Compare commits
136 Commits
v5.25.3-85
...
delete
| Author | SHA1 | Date | |
|---|---|---|---|
| 684dbcfd87 | |||
| 4f8b961e2c | |||
| 58a7f7c3fa | |||
| ae8267d96d | |||
| e20af462b7 | |||
| e2773ed8c7 | |||
| c77e5ca56b | |||
| e78c23ca4f | |||
| b790d71aa5 | |||
| 5c91023a68 | |||
| 2eae71bc96 | |||
| 909477ec7f | |||
| a5da376f62 | |||
| d084cb1c34 | |||
| 411bf3561f | |||
| 610c006aeb | |||
| ffa81bc4c1 | |||
| 67477ac20a | |||
| a6a16e4694 | |||
| 8f8352dc12 | |||
| 1bbbe575f2 | |||
| 5975d9850f | |||
| ef001b0a77 | |||
| fd49ecbc8a | |||
| d683969eda | |||
| f8527da9df | |||
| f50d901171 | |||
| 71db870bd2 | |||
| b4c550f71b | |||
| 91bde61054 | |||
| d7940121ee | |||
| ef9c473301 | |||
| 2c82437449 | |||
| 311e5e4225 | |||
| 91864e3681 | |||
| 5e66db7435 | |||
| e7c74d3f39 | |||
| d0fa02b221 | |||
| 70e4378ef0 | |||
| f8ee943678 | |||
| 918aa17fbd | |||
| 0a7a3d9878 | |||
| b6a823e793 | |||
| 9a95a4623d | |||
| 206bc1bfcc | |||
| 4045e42a7b | |||
| 15f283d330 | |||
| 97bafee09e | |||
| e32745d9d7 | |||
| c37a54ac89 | |||
| 607d514ae9 | |||
| 62ee0b4a6e | |||
| 11ff054520 | |||
| e96fc0f3b4 | |||
| a7875b21c9 | |||
| e53154c810 | |||
| e1d89725bc | |||
| 1d3ec9eff6 | |||
| 0403743533 | |||
| 1f25b932d5 | |||
| d3545bc766 | |||
| b2b858c403 | |||
| debbe08262 | |||
| 4e746a2b16 | |||
| b86e372e5b | |||
| f65e76a94a | |||
| 05c8de827e | |||
| 78eb10fa3c | |||
| 23dfb7378b | |||
| 0e2e175194 | |||
| 9050a04c3a | |||
| 4ff21914c1 | |||
| 0dec30ff56 | |||
| 8668b2b4ec | |||
| b758658ea6 | |||
| 4ca9c32762 | |||
| af8fdd5d65 | |||
| 36dd4f5a82 | |||
| c7161e3483 | |||
| bffaaffc56 | |||
| 3257dd4c53 | |||
| 6793945606 | |||
| 52be14a4ef | |||
| e2cb5a31cf | |||
| d807b7973b | |||
| 1fb0d13646 | |||
| 68a3eadfeb | |||
| a2d904c634 | |||
| 56cd1bdad7 | |||
| 8b4f71bc75 | |||
| aa069b7a21 | |||
| fb0db2feee | |||
| 4c531b40b0 | |||
| bd11481c2d | |||
| a3f1b09da1 | |||
| 1798dfb64d | |||
| 8e5814d389 | |||
| 14c01cf171 | |||
| 2ee4ad6752 | |||
| 73d7a38886 | |||
| e1f70ce788 | |||
| fe5b93c35a | |||
| 74c3e7a10d | |||
| deb2b07644 | |||
| c6b433d09c | |||
| c556a127f5 | |||
| bdfd88a4c3 | |||
| 2697fd57b4 | |||
| 06e238b2d5 | |||
| a4c323b5e0 | |||
| fdfb03348e | |||
| ba65c5e23a | |||
| 0f2fcdba68 | |||
| 548156c159 | |||
| ea08a52750 | |||
| 4c51ca7670 | |||
| d1277aa1aa | |||
| 2381550e08 | |||
| e57017f5f2 | |||
| 6506a18d6f | |||
| ed79b230aa | |||
| ac56650ce5 | |||
| 0e988b2b49 | |||
| 1b3c2da6d3 | |||
| 48209b05e7 | |||
| 2da42d48e6 | |||
| f6b1813e88 | |||
| 9abd0de3fe | |||
| 25cb0de6c0 | |||
| 4db1147c4f | |||
| 7802082797 | |||
| 81400a37f1 | |||
| 228a786f6c | |||
| 690c2e53d9 | |||
| 5a72c12233 | |||
| 74f41404ef |
@ -71,7 +71,8 @@ android_build:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- dev-5.25.0
|
||||
- dev-5.26.0
|
||||
- dev-5.27.0
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
@ -102,7 +103,8 @@ sonarqube_analysis:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- dev-5.25.0
|
||||
- dev-5.26.0
|
||||
- dev-5.27.0
|
||||
|
||||
## 发送简易检测结果报告
|
||||
send_sonar_report:
|
||||
@ -120,7 +122,8 @@ send_sonar_report:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- dev-5.25.0
|
||||
- dev-5.26.0
|
||||
- dev-5.27.0
|
||||
|
||||
oss-upload&send-email:
|
||||
tags:
|
||||
@ -152,4 +155,5 @@ oss-upload&send-email:
|
||||
- /usr/local/bin/python /ci-android-mail.py
|
||||
only:
|
||||
- dev
|
||||
- dev-5.25.0
|
||||
- dev-5.26.0
|
||||
- dev-5.27.0
|
||||
|
||||
@ -163,7 +163,7 @@ android {
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
// internal test dev host
|
||||
// internal, 内部测试包使用的 flavor,接口包含包括测试和正式环境
|
||||
internal {
|
||||
dimension "env"
|
||||
versionNameSuffix "-debug"
|
||||
@ -175,7 +175,7 @@ android {
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${DEV_QUICK_LOGIN_APPKEY}\""
|
||||
}
|
||||
|
||||
// publish release host
|
||||
// publish, 发布时候使用的 flavor,接口仅包含正式环境
|
||||
publish {
|
||||
dimension "env"
|
||||
|
||||
@ -201,11 +201,17 @@ android {
|
||||
kuaishou {
|
||||
dimension "env"
|
||||
|
||||
String KUAI_SHOU_APP_ID = ""
|
||||
String KUAI_SHOU_APP_NAME = ""
|
||||
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
|
||||
buildConfigField "String", "KUAI_SHOU_APP_ID", "\"${KUAI_SHOU_APP_ID}\""
|
||||
buildConfigField "String", "KUAI_SHOU_APP_NAME", "\"${KUAI_SHOU_APP_NAME}\""
|
||||
}
|
||||
|
||||
gdt {
|
||||
@ -325,6 +331,7 @@ dependencies {
|
||||
}
|
||||
// implementation(project(':feature:vpn'))
|
||||
implementation(project(':feature:pkg'))
|
||||
implementation(project(':feature:oaid'))
|
||||
implementation(project(':feature:floating-window'))
|
||||
implementation(project(':feature:beizi_startup_ad'))
|
||||
}
|
||||
|
||||
Binary file not shown.
BIN
app/src/gdt/libs/GDTActionSDK.min.1.8.6.aar
Normal file
BIN
app/src/gdt/libs/GDTActionSDK.min.1.8.6.aar
Normal file
Binary file not shown.
@ -5,15 +5,15 @@ import com.kwai.monitor.log.TurboAgent
|
||||
import com.kwai.monitor.log.TurboConfig
|
||||
|
||||
object KuaishouHelper {
|
||||
private const val APP_ID = "80655"
|
||||
private const val APP_NAME = "guanghuanzhushou_1"
|
||||
private val mAppId by lazy { BuildConfig.KUAI_SHOU_APP_ID.ifEmpty { "81537" } }
|
||||
private val mAppName by lazy { BuildConfig.KUAI_SHOU_APP_NAME.ifEmpty { "guanghuanzhushou_1" } }
|
||||
|
||||
@JvmStatic
|
||||
fun init(context: Context, channel: String) {
|
||||
TurboAgent.init(
|
||||
TurboConfig.TurboConfigBuilder.create(context)
|
||||
.setAppId(APP_ID)
|
||||
.setAppName(APP_NAME)
|
||||
.setAppId(mAppId)
|
||||
.setAppName(mAppName)
|
||||
.setAppChannel(channel)
|
||||
.build()
|
||||
)
|
||||
|
||||
@ -8,7 +8,7 @@ import com.gh.gamecenter.core.provider.IFlavorProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.leon.channel.helper.ChannelReaderUtil
|
||||
import com.kwai.monitor.payload.TurboHelper
|
||||
|
||||
class FlavorProviderImp : IFlavorProvider {
|
||||
|
||||
@ -31,7 +31,7 @@ class FlavorProviderImp : IFlavorProvider {
|
||||
}
|
||||
|
||||
override fun getChannelStr(application: Application): String {
|
||||
var channel = ChannelReaderUtil.getChannel(application)
|
||||
var channel = TurboHelper.getChannel(application)
|
||||
if (channel == null || TextUtils.isEmpty(channel.trim())) {
|
||||
channel = KUAISHOU_CHANNEL
|
||||
}
|
||||
|
||||
BIN
app/src/kuaishou/libs/channelsdk-0.2.1-beta.aar
Normal file
BIN
app/src/kuaishou/libs/channelsdk-0.2.1-beta.aar
Normal file
Binary file not shown.
Binary file not shown.
BIN
app/src/kuaishou/libs/monitorsdk-1.0.13.aar
Normal file
BIN
app/src/kuaishou/libs/monitorsdk-1.0.13.aar
Normal file
Binary file not shown.
@ -112,6 +112,10 @@
|
||||
tools:replace="android:name,android:allowBackup"
|
||||
tools:targetApi="n">
|
||||
|
||||
<meta-data
|
||||
android:name="EasyGoClient"
|
||||
android:value="true" />
|
||||
|
||||
<meta-data
|
||||
android:name="io.sentry.auto-init"
|
||||
android:value="false" />
|
||||
|
||||
27
app/src/main/assets/easygo.json
Normal file
27
app/src/main/assets/easygo.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"easyGoVersion": "1.0",
|
||||
"client": "com.gh.gamecenter",
|
||||
"logicEntities": [
|
||||
{
|
||||
"head": {
|
||||
"function": "magicwindow",
|
||||
"required": "true"
|
||||
},
|
||||
"body": {
|
||||
"mode":"1",
|
||||
"activityPairs":[
|
||||
{"from":"com.gh.gamecenter.MainActivity","to":"*"}
|
||||
],
|
||||
"defaultDualActivities": {
|
||||
"mainPages": "com.gh.gamecenter.MainActivity"
|
||||
},
|
||||
"UX": {
|
||||
"supportRotationUxCompat": "false",
|
||||
"isDraggable": "true"
|
||||
},
|
||||
"transActivities":[
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -209,7 +209,7 @@ class DefaultJsApi(
|
||||
runOnUiThread {
|
||||
// 若畅玩列表中安装了,优先启动畅玩游戏
|
||||
if (VHelper.isInstalled(packageName)) {
|
||||
if (!VHelper.showDialogIfVSpaceIsNeeded(context, "", "")) {
|
||||
if (!VHelper.showDialogIfVSpaceIsNeeded(context, "", "", "", "")) {
|
||||
VHelper.launch(context, packageName)
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -9,7 +9,7 @@ class CheckDownloadHandler : ChainHandler() {
|
||||
|
||||
override fun handleRequest(context: Context, gameEntity: GameEntity) {
|
||||
val apk = gameEntity.getApk().safelyGetInRelease(0) ?: return
|
||||
DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
|
||||
DialogUtils.checkDownload(context, apk.size, gameEntity.id, gameEntity.name) { isSubscribe: Boolean ->
|
||||
if (hasNext()) {
|
||||
getNext()?.handleRequest(context, gameEntity)
|
||||
} else {
|
||||
|
||||
@ -122,17 +122,6 @@ public class Config {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否启用畅玩游戏
|
||||
*/
|
||||
public static boolean isVGameEnabled() {
|
||||
if (getSettings() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !"off".equals(getSettings().getGameSmooth());
|
||||
}
|
||||
|
||||
/**
|
||||
* VPN 开关选项是否开启
|
||||
*/
|
||||
@ -229,6 +218,8 @@ public class Config {
|
||||
if (!TextUtils.isEmpty(json)) {
|
||||
mSettingsEntity = GsonUtils.fromJson(json, SettingsEntity.class);
|
||||
}
|
||||
|
||||
mSettingsEntity.setGameSmooth("off");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ import com.gh.common.chain.CertificationHandler;
|
||||
import com.gh.common.chain.ChainBuilder;
|
||||
import com.gh.common.chain.ChainHandler;
|
||||
import com.gh.common.chain.CheckDownloadHandler;
|
||||
import com.gh.common.chain.CheckStoragePermissionHandler;
|
||||
import com.gh.common.chain.DownloadDialogHelperHandler;
|
||||
import com.gh.common.chain.GamePermissionHandler;
|
||||
import com.gh.common.chain.OverseaDownloadHandler;
|
||||
@ -397,8 +398,9 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
ChainBuilder builder = new ChainBuilder();
|
||||
builder.addHandler(new ValidateVSpaceHandler());
|
||||
builder.addHandler(new GamePermissionHandler());
|
||||
builder.addHandler(new CheckStoragePermissionHandler());
|
||||
builder.addHandler(new ValidateVSpaceHandler());
|
||||
builder.addHandler(new BrowserInstallHandler());
|
||||
builder.addHandler(new PackageCheckHandler());
|
||||
builder.addHandler(new DownloadDialogHelperHandler());
|
||||
|
||||
@ -3,6 +3,7 @@ package com.gh.common.exposure
|
||||
import android.text.TextUtils
|
||||
import com.g00fy2.versioncompare.Version
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.util.RealNameHelper
|
||||
import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet
|
||||
import com.gh.gamecenter.common.utils.toObject
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity
|
||||
@ -42,7 +43,9 @@ object ExposureUtils {
|
||||
source = traceEvent?.source ?: ArrayList(),
|
||||
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
|
||||
event = ExposureType.DOWNLOAD
|
||||
)
|
||||
).apply {
|
||||
this.payload.certification = RealNameHelper.getCertificationStatus()
|
||||
}
|
||||
if (!TextUtils.isEmpty(entity.id)) {
|
||||
ExposureManager.log(exposureEvent)
|
||||
}
|
||||
@ -78,7 +81,9 @@ object ExposureUtils {
|
||||
source = traceEvent?.source ?: ArrayList(),
|
||||
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
|
||||
event = ExposureType.DOWNLOAD_COMPLETE
|
||||
)
|
||||
).apply {
|
||||
this.payload.certification = RealNameHelper.getCertificationStatus()
|
||||
}
|
||||
exposureEvent.payload.host = host
|
||||
exposureEvent.payload.path = path
|
||||
exposureEvent.payload.speed = speed
|
||||
|
||||
@ -49,7 +49,7 @@ object ArchiveDownloadButtonHelper {
|
||||
downloadBtn.setOnClickListener {
|
||||
when {
|
||||
// 检查是否已安装畅玩助手
|
||||
!VHelper.isVSpaceInstalled(context) -> showVspaceTipDialog(context, gameEntity)
|
||||
!VHelper.isVSpaceInstalled(context) -> showVSpaceTipDialog(context, gameEntity)
|
||||
// 检查是否已安装游戏
|
||||
!VHelper.isInstalled(packageName) -> {
|
||||
// 检查游戏是否在安装中
|
||||
@ -82,7 +82,7 @@ object ArchiveDownloadButtonHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showVspaceTipDialog(context: Context, gameEntity: GameEntity?) {
|
||||
private fun showVSpaceTipDialog(context: Context, gameEntity: GameEntity?) {
|
||||
NewFlatLogUtils.logCloudArchiveVSpaceDownloadDialogShow()
|
||||
DialogHelper.showDialog(
|
||||
context,
|
||||
@ -92,7 +92,7 @@ object ArchiveDownloadButtonHelper {
|
||||
R.string.cancel.toResString(),
|
||||
{
|
||||
NewFlatLogUtils.logCloudArchiveVSpaceDownloadDialogClick(R.string.archive_vspace_dialog_confirm.toResString())
|
||||
VHelper.showVspaceDialog(context, gameEntity)
|
||||
VHelper.showVSpaceDialog(context, gameEntity)
|
||||
},
|
||||
{
|
||||
NewFlatLogUtils.logCloudArchiveVSpaceDownloadDialogClick(R.string.cancel.toResString())
|
||||
|
||||
@ -3,11 +3,15 @@ package com.gh.common.util;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@ -19,6 +23,7 @@ import com.gh.gamecenter.adapter.viewholder.CommentViewHolder;
|
||||
import com.gh.gamecenter.common.callback.SimpleCallback;
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.common.utils.DialogHelper;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
@ -45,6 +50,7 @@ import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
@ -102,17 +108,27 @@ public class CommentUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void showReportDialog(final CommentEntity commentEntity,
|
||||
final Context context,
|
||||
final boolean showConversation,
|
||||
final String patch) {
|
||||
final Dialog dialog = new Dialog(context);
|
||||
|
||||
LinearLayout container = new LinearLayout(context);
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
container.setBackgroundColor(ContextCompat.getColor(context, R.color.background_white));
|
||||
container.setPadding(0, DisplayUtils.dip2px(context, 12), 0, DisplayUtils.dip2px(context, 12));
|
||||
public static void showMorePopupWindow(
|
||||
final View anchor,
|
||||
final CommentEntity commentEntity,
|
||||
final boolean showConversation,
|
||||
final String patch,
|
||||
final OnCommentDeleteListener onCommentDeleteListener
|
||||
) {
|
||||
Context context = anchor.getContext();
|
||||
LayoutInflater inflater = LayoutInflater.from(context);
|
||||
View contentView = inflater.inflate(R.layout.layout_popup_container, null);
|
||||
PopupWindow popupWindow = new PopupWindow(
|
||||
contentView,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
popupWindow.setBackgroundDrawable(new ColorDrawable(0));
|
||||
popupWindow.setTouchable(true);
|
||||
popupWindow.setFocusable(true);
|
||||
popupWindow.setOutsideTouchable(true);
|
||||
|
||||
LinearLayout container = contentView.findViewById(R.id.container);
|
||||
List<String> dialogType = new ArrayList<>();
|
||||
dialogType.add("复制");
|
||||
dialogType.add("投诉");
|
||||
@ -121,21 +137,23 @@ public class CommentUtils {
|
||||
dialogType.add("查看对话");
|
||||
}
|
||||
|
||||
String commentUserId = commentEntity.getUser().getId();
|
||||
String userId = UserManager.getInstance().getUserId();
|
||||
MeEntity me = commentEntity.getMe();
|
||||
boolean isCommentedByUser = Objects.equals(commentUserId, userId);
|
||||
boolean isContentAuthorOrModerator = me != null && (me.isModerator() || me.isContentAuthor());
|
||||
if (isCommentedByUser || isContentAuthorOrModerator) {
|
||||
dialogType.add("删除");
|
||||
}
|
||||
|
||||
for (String s : dialogType) {
|
||||
final TextView reportTv = new TextView(context);
|
||||
View itemView = inflater.inflate(R.layout.layout_popup_option_item, container, false);
|
||||
TextView reportTv = itemView.findViewById(R.id.hint_text);
|
||||
reportTv.setText(s);
|
||||
reportTv.setTextSize(17);
|
||||
reportTv.setTextColor(ContextCompat.getColor(context, R.color.title));
|
||||
reportTv.setBackgroundResource(R.drawable.textview_white_style);
|
||||
int widthPixels = context.getResources().getDisplayMetrics().widthPixels;
|
||||
reportTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
reportTv.setPadding(DisplayUtils.dip2px(context, 20), DisplayUtils.dip2px(context, 12),
|
||||
0, DisplayUtils.dip2px(context, 12));
|
||||
container.addView(reportTv);
|
||||
container.addView(itemView);
|
||||
|
||||
reportTv.setOnClickListener(v -> {
|
||||
dialog.cancel();
|
||||
popupWindow.dismiss();
|
||||
switch (reportTv.getText().toString()) {
|
||||
case "复制":
|
||||
copyText(commentEntity.getContent(), context);
|
||||
@ -143,19 +161,30 @@ public class CommentUtils {
|
||||
case "投诉":
|
||||
CheckLoginUtils.checkLogin(context, patch + "-投诉",
|
||||
() -> showReportTypeDialog(commentEntity, context));
|
||||
|
||||
break;
|
||||
case "查看对话":
|
||||
context.startActivity(CommentDetailActivity.getIntent(context, commentEntity.getId(), null));
|
||||
break;
|
||||
case "删除":
|
||||
DialogHelper.INSTANCE.showDialog(
|
||||
context,
|
||||
"提示",
|
||||
"删除评论后,评论下所有的回复都将被删除",
|
||||
"删除",
|
||||
"取消",
|
||||
() -> {
|
||||
deleteComment(context, commentEntity, onCommentDeleteListener);
|
||||
return null;
|
||||
},
|
||||
null,
|
||||
new DialogHelper.Config("", false, true, true, false, -1)
|
||||
);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(container);
|
||||
dialog.show();
|
||||
|
||||
ExtensionsKt.showAutoOrientation(popupWindow, anchor, 0, 0);
|
||||
}
|
||||
|
||||
private static void showReportTypeDialog(final CommentEntity commentEntity, final Context context) {
|
||||
@ -430,6 +459,28 @@ public class CommentUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public static void deleteComment(
|
||||
final Context context,
|
||||
final CommentEntity commentEntity,
|
||||
final OnCommentDeleteListener listener
|
||||
) {
|
||||
Dialog dialog = DialogUtils.showWaitDialog(
|
||||
context,
|
||||
context.getString(R.string.post_dialog_hint)
|
||||
);
|
||||
RetrofitManager.getInstance().getApi()
|
||||
.deleteComment(commentEntity.getId())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doFinally(dialog::cancel)
|
||||
.subscribe(new Response<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(@Nullable ResponseBody response) {
|
||||
listener.onCommentDelete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 设置评论item 用户相关的view(点赞/头像/用户名)
|
||||
public static void setCommentUserView(Context mContext, CommentViewHolder holder, CommentEntity entity) {
|
||||
@ -540,4 +591,8 @@ public class CommentUtils {
|
||||
public interface OnVoteListener {
|
||||
void onVote();
|
||||
}
|
||||
|
||||
public interface OnCommentDeleteListener {
|
||||
void onCommentDelete();
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,14 +171,25 @@ public class DataUtils {
|
||||
IdCardEntity idCardEntity = data.getIdCard();
|
||||
|
||||
if (idCardEntity != null) {
|
||||
values.put(GhContentProvider.KEY_IS_CERTIFICATED, !TextUtils.isEmpty(data.getIdCard().getId())); // 是否认证
|
||||
values.put(GhContentProvider.KEY_IS_ADULT,
|
||||
data.getIdCard().getMinor() == null
|
||||
|| !data.getIdCard().getMinor()
|
||||
);
|
||||
boolean isCertificated = !TextUtils.isEmpty(data.getIdCard().getId());
|
||||
boolean isAdult = data.getIdCard().getMinor() == null || !data.getIdCard().getMinor();
|
||||
|
||||
values.put(GhContentProvider.KEY_IS_CERTIFICATED, isCertificated); // 是否认证
|
||||
values.put(GhContentProvider.KEY_IS_ADULT, isAdult); // 是否成年
|
||||
|
||||
if (!isCertificated) {
|
||||
RealNameHelper.updateCertificationStatus(0);
|
||||
} else {
|
||||
if (isAdult) {
|
||||
RealNameHelper.updateCertificationStatus(2);
|
||||
} else {
|
||||
RealNameHelper.updateCertificationStatus(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
values.put(GhContentProvider.KEY_IS_CERTIFICATED, false);
|
||||
values.put(GhContentProvider.KEY_IS_ADULT, false);
|
||||
RealNameHelper.updateCertificationStatus(0);
|
||||
}
|
||||
|
||||
EventBus.getDefault().post(new EBReuse(Constants.EB_REALNAME_RESULT));
|
||||
|
||||
@ -121,7 +121,7 @@ public class DialogUtils {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static void checkDownload(Context context, String size, CheckDownloadCallBack callBack) {
|
||||
public static void checkDownload(Context context, String size, String gameId, String gameName, CheckDownloadCallBack callBack) {
|
||||
if (!NetworkUtils.isNetworkConnected(context)) {
|
||||
showNoConnectionDownloadDialog(context, () -> {
|
||||
},
|
||||
@ -136,7 +136,9 @@ public class DialogUtils {
|
||||
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "出现弹窗提示");
|
||||
showDownloadDialog(context,
|
||||
() -> callBack.onResponse(false),
|
||||
() -> callBack.onResponse(true));
|
||||
() -> callBack.onResponse(true),
|
||||
gameId,
|
||||
gameName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,9 +167,11 @@ public class DialogUtils {
|
||||
DialogHelper.showDialog(context, "下载提示", "网络异常,请检查手机网络状态", "知道了", "WiFi自动下载", listener::onConfirm, cancelListener::onCancel, false, "", "");
|
||||
}
|
||||
|
||||
public static void showDownloadDialog(Context context, ConfirmListener listener, CancelListener cancelListener) {
|
||||
public static void showDownloadDialog(Context context, ConfirmListener listener, CancelListener cancelListener, String gameId, String gameName) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
NewFlatLogUtils.logDownloadMobileDataDialogShow(gameId, gameName);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_download_traffic, null);
|
||||
@ -177,6 +181,7 @@ public class DialogUtils {
|
||||
|
||||
Context finalContext = context;
|
||||
allowOnce.setOnClickListener(v -> {
|
||||
NewFlatLogUtils.logDownloadMobileDataDialogClick(gameId, gameName, "允许一次");
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
Utils.toast(finalContext, "已使用移动网络下载,请注意流量消耗");
|
||||
}, 500);
|
||||
@ -185,11 +190,13 @@ public class DialogUtils {
|
||||
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "本次允许");
|
||||
});
|
||||
wifiAuto.setOnClickListener(v -> {
|
||||
NewFlatLogUtils.logDownloadMobileDataDialogClick(gameId, gameName, "WiFi自动下载");
|
||||
cancelListener.onCancel();
|
||||
dialog.dismiss();
|
||||
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "连上WiFi后自动下载");
|
||||
});
|
||||
allowAlways.setOnClickListener(v -> {
|
||||
NewFlatLogUtils.logDownloadMobileDataDialogClick(gameId, gameName, "总是允许");
|
||||
SPUtils.setBoolean(getTrafficDownloadHintKey(), false);
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
// 显示了弹窗以后,即便下面这个 toast 放在 listener.onConfirm 后调用也是显示 listener.onConfirm 里的 toast
|
||||
@ -201,6 +208,8 @@ public class DialogUtils {
|
||||
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "总是允许");
|
||||
});
|
||||
|
||||
dialog.setOnCancelListener(downloadDialog -> NewFlatLogUtils.logDownloadMobileDataDialogClick(gameId, gameName, "关闭弹窗"));
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
|
||||
@ -800,8 +800,11 @@ object DirectUtils {
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 畅玩助手反馈跳转
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToFeedbackCompat(
|
||||
fun directToVGameFeedback(
|
||||
context: Context,
|
||||
content: String? = null,
|
||||
hintType: String? = null,
|
||||
@ -816,14 +819,14 @@ object DirectUtils {
|
||||
if (isQaFeedback) {
|
||||
bundle.putBoolean(KEY_IS_QA_FEEDBACK, true)
|
||||
bundle.putString(KEY_QA_CONTENT_ID, qaContentId)
|
||||
bundle.putSerializable(KEY_SUGGESTTYPE, SuggestType.normal)
|
||||
bundle.putSerializable(KEY_SUGGESTTYPE, SuggestType.cwzsQuestion)
|
||||
} else {
|
||||
bundle.putString(KEY_CONTENT, content)
|
||||
if (TextUtils.isEmpty(hintType)) {
|
||||
bundle.putSerializable(KEY_SUGGESTTYPE, SuggestType.gameQuestion)
|
||||
bundle.putString(KEY_SUGGEST_HINT_TYPE, KEY_PLUGIN)
|
||||
} else {
|
||||
bundle.putSerializable(KEY_SUGGESTTYPE, SuggestType.normal)
|
||||
bundle.putSerializable(KEY_SUGGESTTYPE, SuggestType.cwzsQuestion)
|
||||
bundle.putString(KEY_SUGGEST_HINT_TYPE, hintType)
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.collection.ArrayMap
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.common.chain.*
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.dialog.DeviceRemindDialog
|
||||
@ -25,6 +24,7 @@ import com.gh.download.dialog.DownloadDialog
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.callback.CancelListener
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
@ -836,6 +836,7 @@ object DownloadItemUtils {
|
||||
addHandler(CertificationHandler())
|
||||
addHandler(VersionNumberHandler())
|
||||
addHandler(OverseaDownloadHandler())
|
||||
addHandler(CheckStoragePermissionHandler())
|
||||
addHandler(ValidateVSpaceHandler())
|
||||
addHandler(CheckDownloadHandler())
|
||||
}
|
||||
@ -927,7 +928,12 @@ object DownloadItemUtils {
|
||||
}
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
|
||||
DialogUtils.checkDownload(
|
||||
context,
|
||||
apk.size,
|
||||
gameEntity.id,
|
||||
gameEntity.name
|
||||
) { isSubscribe: Boolean ->
|
||||
update(context, gameEntity, entrance, location, isSubscribe, traceEvent)
|
||||
}
|
||||
}
|
||||
@ -1070,6 +1076,7 @@ object DownloadItemUtils {
|
||||
"game_type", gameEntity.categoryChinese,
|
||||
"download_status", gameEntity.downloadStatusChinese,
|
||||
"button_name", buttonName,
|
||||
"game_schema_type", gameEntity.gameBitChinese,
|
||||
"page_name", GlobalActivityManager.getCurrentPageEntity().pageName,
|
||||
"page_id", GlobalActivityManager.getCurrentPageEntity().pageId,
|
||||
"page_business_id", GlobalActivityManager.getCurrentPageEntity().pageBusinessId,
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager.getCurrentPageEntity
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager.getLastPageEntity
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.exposure.ExposureUtils
|
||||
import com.gh.common.simulator.SimulatorDownloadManager
|
||||
@ -10,6 +8,8 @@ import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.download.DownloadDataHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager.getCurrentPageEntity
|
||||
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
|
||||
@ -18,7 +18,6 @@ import com.gh.gamecenter.common.entity.SuggestType
|
||||
import com.gh.gamecenter.common.eventbus.EBShowDialog
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.utils.SensorsBridge
|
||||
import com.gh.gamecenter.core.utils.*
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
@ -235,17 +234,13 @@ object DownloadObserver {
|
||||
downloadEntity.name + " - " + platform + " - 下载完成"
|
||||
)
|
||||
else -> {
|
||||
if (downloadEntity.isVGame()) {
|
||||
VHelper.showFloatingWindow(downloadEntity.packageName)
|
||||
} else {
|
||||
if (!downloadEntity.isVGame()) {
|
||||
Utils.toast(mApplication, downloadEntity.name + " - 下载完成")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (downloadEntity.isVGame()) {
|
||||
VHelper.showFloatingWindow(downloadEntity.packageName)
|
||||
} else {
|
||||
if (!downloadEntity.isVGame()) {
|
||||
Utils.toast(mApplication, downloadEntity.name + " - 下载完成")
|
||||
}
|
||||
}
|
||||
@ -281,7 +276,7 @@ object DownloadObserver {
|
||||
val downloadType = downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE)
|
||||
// 是否是自动安装
|
||||
val isAutoInstall = SPUtils.getBoolean(Constants.SP_AUTO_INSTALL, true)
|
||||
if (downloadType == Constants.SIMULATOR_DOWNLOAD || isAutoInstall) {
|
||||
if (downloadType != Constants.VSPACE_32_DOWNLOAD_ONLY && (downloadType == Constants.SIMULATOR_DOWNLOAD || isAutoInstall)) {
|
||||
if (FileUtils.isEmptyFile(downloadEntity.path)) {
|
||||
Utils.toast(mApplication, R.string.install_failure_hint)
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
@ -317,9 +312,6 @@ object DownloadObserver {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 统计下载完成
|
||||
uploadData(gameId, downloadEntity.platform)
|
||||
}
|
||||
|
||||
// 下载过程分析统计
|
||||
@ -386,16 +378,22 @@ object DownloadObserver {
|
||||
SensorsBridge.trackEvent(
|
||||
"HaloFunGameDownloadDone",
|
||||
"game_name", downloadEntity.name,
|
||||
"game_id", downloadEntity.gameId
|
||||
"game_id", downloadEntity.gameId,
|
||||
"game_schema_type", if (downloadEntity.getMetaExtra(VHelper.KEY_BIT) == "32") "32位" else "64位"
|
||||
)
|
||||
} else if (downloadEntity.gameId == Constants.HALO_FUN_GAME_ID) {
|
||||
SensorsBridge.trackEvent("HaloFunDownloadDone")
|
||||
SensorsBridge.trackEvent(
|
||||
"HaloFunDownloadDone",
|
||||
"space_schema_type",
|
||||
if (downloadEntity.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) "32位" else "64位"
|
||||
)
|
||||
} else if (downloadEntity.gameId != Constants.GHZS_GAME_ID && downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) != Constants.SIMULATOR_DOWNLOAD) {
|
||||
SensorsBridge.trackEvent(
|
||||
"DownloadProcessFinish",
|
||||
"game_id", downloadEntity.gameId,
|
||||
"game_name", downloadEntity.meta[Constants.GAME_NAME] ?: "",
|
||||
"game_type", downloadEntity.meta[Constants.GAME_TYPE] ?: "",
|
||||
"game_schema_type", if (downloadEntity.getMetaExtra(VHelper.KEY_BIT) == "32") "32位" else "64位",
|
||||
"page_name", getCurrentPageEntity().pageName,
|
||||
"page_id", getCurrentPageEntity().pageId,
|
||||
"page_business_id", getCurrentPageEntity().pageBusinessId,
|
||||
@ -454,19 +452,4 @@ object DownloadObserver {
|
||||
DataLogUtils.uploadHijack(mApplication, downloadEntity)
|
||||
}
|
||||
|
||||
// 统计下载
|
||||
private fun uploadData(id: String, platform: String?) {
|
||||
val params = HashMap<String, String>()
|
||||
params["game"] = id
|
||||
params["platform"] = platform ?: ""
|
||||
val body = RequestBody.create(
|
||||
MediaType.parse("application/json"),
|
||||
JSONObject(params as Map<*, *>).toString()
|
||||
)
|
||||
RetrofitManager.getInstance().api.postDownload(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(Response())
|
||||
}
|
||||
|
||||
}
|
||||
@ -221,7 +221,7 @@ object GameActivityDownloadHelper {
|
||||
) {
|
||||
GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity) {
|
||||
DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
|
||||
DialogUtils.checkDownload(context, apk.size, gameEntity.id, gameEntity.name) { isSubscribe: Boolean ->
|
||||
download(context, gameEntity, apk, isSubscribe, entrance, location, traceEvent)
|
||||
}
|
||||
}
|
||||
@ -241,7 +241,12 @@ object GameActivityDownloadHelper {
|
||||
VHelper.validateVSpaceBeforeAction(context, gameEntity) {
|
||||
GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity) {
|
||||
DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
|
||||
DialogUtils.checkDownload(
|
||||
context,
|
||||
apk.size,
|
||||
gameEntity.id,
|
||||
gameEntity.name
|
||||
) { isSubscribe: Boolean ->
|
||||
download(context, gameEntity, apk, isSubscribe, entrance, location, traceEvent)
|
||||
}
|
||||
}
|
||||
@ -262,7 +267,7 @@ object GameActivityDownloadHelper {
|
||||
DownloadDialog.showDownloadDialog(context, gameEntity, traceEvent, entrance, location)
|
||||
} else {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity) {
|
||||
DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
|
||||
DialogUtils.checkDownload(context, apk.size, gameEntity.id, gameEntity.name) { isSubscribe: Boolean ->
|
||||
plugin(context, gameEntity, apk, entrance, location, isSubscribe, traceEvent)
|
||||
}
|
||||
}
|
||||
@ -355,7 +360,7 @@ object GameActivityDownloadHelper {
|
||||
location: String,
|
||||
traceEvent: ExposureEvent
|
||||
) {
|
||||
DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
|
||||
DialogUtils.checkDownload(context, apk.size, gameEntity.id, gameEntity.name) { isSubscribe: Boolean ->
|
||||
update(context, gameEntity, apk, entrance, location, isSubscribe, traceEvent)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@ import com.gh.gamecenter.common.json.JsonObjectBuilder
|
||||
import com.gh.gamecenter.common.json.json
|
||||
import com.gh.gamecenter.common.loghub.LoghubUtils
|
||||
import com.gh.gamecenter.common.utils.LogUtils
|
||||
import com.gh.gamecenter.common.utils.NewFlatLogUtils
|
||||
import com.gh.gamecenter.entity.HomeSubSlide
|
||||
import com.lightgame.utils.Utils
|
||||
import org.json.JSONArray
|
||||
@ -54,6 +53,66 @@ object NewFlatLogUtils {
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 畅玩助手下载弹窗展示事件
|
||||
@JvmStatic
|
||||
fun logHaloFunDownloadDialogShow(gameId: String, gameName: String, gameArchitecture: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "halo_fun_download_dialog_show"
|
||||
"game_id" to gameId
|
||||
"game_name" to gameName
|
||||
"game_architecture" to gameArchitecture
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 畅玩助手下载点击事件
|
||||
@JvmStatic
|
||||
fun logHaloFunDownloadDialogDownloadClick(architecture: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "halo_fun_download_dialog_download_click"
|
||||
"architecture" to architecture
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 畅玩助手安装提示弹窗展示事件
|
||||
@JvmStatic
|
||||
fun logHaloFunInstallTipDialogShow(architecture: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "halo_fun_install_tip_dialog_show"
|
||||
"architecture" to architecture
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 畅玩助手更新弹窗展示事件
|
||||
@JvmStatic
|
||||
fun logHaloFunUpdateDialogShow(gameId: String, gameName: String, gameArchitecture: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "halo_fun_update_dialog_show"
|
||||
"game_id" to gameId
|
||||
"game_name" to gameName
|
||||
"game_architecture" to gameArchitecture
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 畅玩助手(32位)弹窗事件
|
||||
@JvmStatic
|
||||
fun logHaloFun32DialogEvent(event: String, gameId: String, gameName: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to event
|
||||
"game_id" to gameId
|
||||
"game_name" to gameName
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 关联游戏跳转icon点击事件
|
||||
@JvmStatic
|
||||
fun logHaloFunGameDetailJumpClick(downloadStatus: String, gameId: String) {
|
||||
@ -80,11 +139,12 @@ object NewFlatLogUtils {
|
||||
|
||||
// 畅玩助手更新弹窗点击事件
|
||||
@JvmStatic
|
||||
fun logHaloFunUpdateDialogClick(dialogType: String, buttonType: String) {
|
||||
fun logHaloFunUpdateDialogClick(dialogType: String, buttonType: String, architecture: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "halo_fun_update_dialog_click"
|
||||
"dialog_type" to dialogType
|
||||
KEY_BUTTON_TYPE to buttonType
|
||||
"architecture" to architecture
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json)
|
||||
@ -2100,4 +2160,29 @@ object NewFlatLogUtils {
|
||||
}
|
||||
log(json)
|
||||
}
|
||||
|
||||
// 下载流量提示弹窗展示事件
|
||||
@JvmStatic
|
||||
fun logDownloadMobileDataDialogShow(gameId: String, gameName: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "download_mobile_data_dialog_show"
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
|
||||
// 下载流量提示弹窗点击事件
|
||||
@JvmStatic
|
||||
fun logDownloadMobileDataDialogClick(gameId: String, gameName: String, button: String) {
|
||||
val json = json {
|
||||
KEY_EVENT to "download_mobile_data_dialog_click"
|
||||
KEY_GAME_ID to gameId
|
||||
KEY_GAME_NAME to gameName
|
||||
"button" to button
|
||||
parseAndPutMeta().invoke(this)
|
||||
}
|
||||
log(json, "event", false)
|
||||
}
|
||||
}
|
||||
@ -38,6 +38,7 @@ import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.gh.vspace.VHelper;
|
||||
import com.gh.vspace.db.VGameEntity;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lg.vspace.VirtualAppManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import net.dongliu.apk.parser.ApkFile;
|
||||
@ -554,9 +555,32 @@ public class PackageUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据包名,判断是否已安装该游戏
|
||||
* 不区分是否有桌面图标
|
||||
*/
|
||||
public static boolean isInstalledFromAllPackage(Context context, String packageName) {
|
||||
ArrayList<String> allPackageName = getAllPackageName(context);
|
||||
return allPackageName.contains(packageName);
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
context.getPackageManager().getPackageInfo(
|
||||
packageName,
|
||||
PackageManager.PackageInfoFlags.of(0)
|
||||
);
|
||||
} else {
|
||||
context.getPackageManager().getPackageInfo(packageName, 0);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
ArrayList<String> allPackageName = getAllPackageName(context);
|
||||
boolean isInstalled = allPackageName.contains(packageName);
|
||||
|
||||
if (isInstalled) {
|
||||
// 能进这里说明上面的 try {} 结果有问题,记录一下
|
||||
SentryHelper.INSTANCE.onEvent("CHECK_INSTALLED_CONFLICT", "packageName", packageName);
|
||||
}
|
||||
|
||||
return isInstalled;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -16,6 +16,9 @@ object RealNameHelper {
|
||||
|
||||
var pendingInstallPkgPath = ""
|
||||
|
||||
// 0表示未实名,1表示未成年,2表示成年
|
||||
private var mCertificationStatus: Int = 0
|
||||
|
||||
/**
|
||||
* 弹未成年人不能下载游戏弹窗
|
||||
*/
|
||||
@ -124,7 +127,21 @@ object RealNameHelper {
|
||||
DownloadManager.getInstance()
|
||||
.addInvisiblePendingTask(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实名状态 0表示未实名,1表示未成年,2表示成年
|
||||
*/
|
||||
fun getCertificationStatus(): Int {
|
||||
return mCertificationStatus
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新实名状态 0表示未实名,1表示未成年,2表示成年
|
||||
*/
|
||||
@JvmStatic
|
||||
fun updateCertificationStatus(newCertificationStatus: Int) {
|
||||
mCertificationStatus = newCertificationStatus
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.gh.download
|
||||
import android.content.pm.PackageInfo
|
||||
import android.text.TextUtils
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.util.RealNameHelper
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
@ -125,6 +126,7 @@ object DownloadDataHelper {
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("certification", RealNameHelper.getCertificationStatus())
|
||||
payloadObject.put("filename", getFileName(downloadEntity))
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTasks.size)
|
||||
jsonObject.put("payload", payloadObject)
|
||||
@ -209,6 +211,7 @@ object DownloadDataHelper {
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("certification", RealNameHelper.getCertificationStatus())
|
||||
payloadObject.put("filename", getFileName(downloadEntity))
|
||||
payloadObject.put("launch_ms", startupTime)
|
||||
payloadObject.put("task_num", NDataChanger.downloadingTasks.size)
|
||||
@ -247,6 +250,7 @@ object DownloadDataHelper {
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("certification", RealNameHelper.getCertificationStatus())
|
||||
payloadObject.put("filename", getFileName(downloadEntity))
|
||||
payloadObject.put("total_size", sizeInMB)
|
||||
if (parallel != null) {
|
||||
@ -317,6 +321,7 @@ object DownloadDataHelper {
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("certification", RealNameHelper.getCertificationStatus())
|
||||
payloadObject.put("filename", getFileName(downloadEntity))
|
||||
payloadObject.put("speed_progress", JSONArray(averageSpeedList))
|
||||
payloadObject.put("is_finished", downloadEntity.status == DownloadStatus.done)
|
||||
@ -356,6 +361,7 @@ object DownloadDataHelper {
|
||||
sheet.put("game_id", downloadEntity.gameId)
|
||||
sheet.put("platform", downloadEntity.platform)
|
||||
sheet.put("package", downloadEntity.packageName)
|
||||
sheet.put("certification", RealNameHelper.getCertificationStatus())
|
||||
sheet.put("filename", getFileName(downloadEntity))
|
||||
sheet.put("total_size", downloadEntity.size / 1024 / 1024)
|
||||
sheet.put("current_progress_size", downloadEntity.progress / 1024)
|
||||
|
||||
@ -341,15 +341,18 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.EXTRA_DOWNLOAD_TYPE, Constants.SMOOTH_GAME);
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200");
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, VHelper.KEY_REQUIRED_G_APPS, gameEntity.getGAppsSwitch());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, VHelper.KEY_BIT, apkEntity.getBit());
|
||||
|
||||
SensorsBridge.trackEvent("HaloFunGameDownloadClick",
|
||||
"game_name", gameEntity.getName(),
|
||||
"game_id", gameEntity.getId());
|
||||
"game_id", gameEntity.getId(),
|
||||
"game_schema_type", gameEntity.getGameBitChinese());
|
||||
} else {
|
||||
SensorsBridge.trackEvent("DownloadProcessBegin",
|
||||
"game_id", gameEntity.getId(),
|
||||
"game_name", gameEntity.getName(),
|
||||
"game_type", gameEntity.getCategoryChinese(),
|
||||
"game_schema_type", gameEntity.getGameBitChinese(),
|
||||
"page_name", GlobalActivityManager.getCurrentPageEntity().getPageName(),
|
||||
"page_id", GlobalActivityManager.getCurrentPageEntity().getPageId(),
|
||||
"page_business_id", GlobalActivityManager.getCurrentPageEntity().getPageBusinessId(),
|
||||
|
||||
@ -373,7 +373,9 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
override fun onConfirm() {
|
||||
DialogUtils.checkDownload(
|
||||
context,
|
||||
apkEntity.size
|
||||
apkEntity.size,
|
||||
gameEntity.id,
|
||||
gameEntity.name
|
||||
) { isSubscribe ->
|
||||
DownloadManager.createDownload(
|
||||
context,
|
||||
|
||||
@ -30,7 +30,6 @@ import com.ethanhua.skeleton.ViewSkeletonScreen;
|
||||
import com.gh.base.DownloadToolbarActivity;
|
||||
import com.gh.common.filter.RegionSettingHelper;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
import com.gh.gamecenter.feature.utils.ApkActiveUtils;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.CollectionUtils;
|
||||
import com.gh.common.util.DataCollectionUtils;
|
||||
@ -41,6 +40,8 @@ import com.gh.gamecenter.adapter.viewholder.DetailViewHolder;
|
||||
import com.gh.gamecenter.common.callback.OnRequestCallBackListener;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts;
|
||||
import com.gh.gamecenter.common.eventbus.EBNetworkState;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||||
import com.gh.gamecenter.common.utils.ShareUtils;
|
||||
@ -49,15 +50,16 @@ import com.gh.gamecenter.common.view.VerticalItemDecoration;
|
||||
import com.gh.gamecenter.core.utils.ClickUtils;
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.gamecenter.entity.NewsDetailEntity;
|
||||
import com.gh.gamecenter.eventbus.EBConcernChanged;
|
||||
import com.gh.gamecenter.eventbus.EBAddComment;
|
||||
import com.gh.gamecenter.eventbus.EBDeleteComment;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.eventbus.EBPackage;
|
||||
import com.gh.gamecenter.feature.entity.GameEntity;
|
||||
import com.gh.gamecenter.feature.entity.MeEntity;
|
||||
import com.gh.gamecenter.entity.NewsDetailEntity;
|
||||
import com.gh.gamecenter.feature.entity.NewsEntity;
|
||||
import com.gh.gamecenter.eventbus.EBConcernChanged;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.common.eventbus.EBNetworkState;
|
||||
import com.gh.gamecenter.eventbus.EBPackage;
|
||||
import com.gh.gamecenter.common.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.feature.utils.ApkActiveUtils;
|
||||
import com.gh.gamecenter.newsdetail.NewsDetailAdapter;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.lightgame.download.DataWatcher;
|
||||
@ -557,6 +559,17 @@ public class NewsDetailActivity extends DownloadToolbarActivity implements OnCli
|
||||
});
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onDeleteComment(EBDeleteComment event) {
|
||||
adapter.getNewsCommentNum();
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onAddComment(EBAddComment event) {
|
||||
adapter.getNewsCommentNum();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
switch (ev.getAction() & MotionEventCompat.ACTION_MASK) {
|
||||
|
||||
@ -149,7 +149,7 @@ public class SkipActivity extends BaseActivity {
|
||||
if (!TextUtils.isEmpty(qaId)) {
|
||||
DirectUtils.directToQa(this, qaTitle, qaId);
|
||||
} else if ("vgame".equals(suggestionType)) {
|
||||
DirectUtils.directToFeedbackCompat(this, content, "game", isQaFeedback, qaContentId, EntranceConsts.ENTRANCE_BROWSER);
|
||||
DirectUtils.directToVGameFeedback(this, content, "game", isQaFeedback, qaContentId, EntranceConsts.ENTRANCE_BROWSER);
|
||||
} else {
|
||||
DirectUtils.directToFeedback(this, content, null, isQaFeedback, qaContentId, EntranceConsts.ENTRANCE_BROWSER);
|
||||
}
|
||||
|
||||
@ -164,9 +164,11 @@ class SplashScreenActivity : BaseActivity() {
|
||||
val signatureHash = packageUtilsConfig?.getApkSignatureByPackageName(this, packageName)?.get(0)
|
||||
val sideLoadInfo = packageUtilsConfig?.getSideLoadedInfo()
|
||||
val trackEvent = JSONObject()
|
||||
// 是否首次使用神策
|
||||
val isFirstTime = SPUtils.getBoolean(Constants.SP_SENSORS_IS_FIRST_TIME, true)
|
||||
tryCatchInRelease {
|
||||
trackEvent.run {
|
||||
put("\$is_first_time", SPUtils.getBoolean(Constants.SP_SENSORS_IS_FIRST_TIME, true))
|
||||
put("\$is_first_time", isFirstTime)
|
||||
put("is_side_loaded", sideLoadInfo?.get("is_side_loaded").toBoolean())
|
||||
put("installer_store", sideLoadInfo?.get("installer_store") ?: "")
|
||||
put("package_name", packageName)
|
||||
@ -176,6 +178,10 @@ class SplashScreenActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
SensorsBridge.trackEvent("AppLaunch", trackEvent)
|
||||
if (!isFirstTime && HaloApp.getInstance().isBrandNewInstall) {
|
||||
// 神策不是第一次使用,但是全局标志为全新安装,有问题,上报数据供后续确认
|
||||
SentryHelper.onEvent("WRONG_LAUNCH_LOG", "a_id", MetaUtil.getBase64EncodedAndroidId())
|
||||
}
|
||||
SPUtils.setBoolean(Constants.SP_SENSORS_IS_FIRST_TIME, false)
|
||||
}
|
||||
|
||||
@ -306,7 +312,7 @@ class SplashScreenActivity : BaseActivity() {
|
||||
private fun doFlavorInit() {
|
||||
HaloApp.getInstance().flavorProvider.init(HaloApp.getInstance(), this, PkgHelper.getActivateRatio())
|
||||
|
||||
val whiteListChannel = arrayListOf<String>(
|
||||
val whiteListChannel = arrayListOf(
|
||||
"GH_206",
|
||||
"KS-GHZS-KY1",
|
||||
"KS-GHZS-MC1",
|
||||
@ -326,12 +332,6 @@ class SplashScreenActivity : BaseActivity() {
|
||||
private fun initStartUpAdSDK() {
|
||||
mStartUpAdProvider?.run {
|
||||
if (shouldEnableSDK(HaloApp.getInstance().channel)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
initOAID(applicationContext) {
|
||||
HaloApp.getInstance().oaid = it
|
||||
MetaUtil.refreshMeta()
|
||||
}
|
||||
}
|
||||
initSDK(applicationContext)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,27 +8,31 @@ import android.view.ViewGroup;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.gh.gamecenter.common.constant.ItemViewType;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.CommentUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.gamecenter.common.utils.TextHelper;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.CommentViewHolder;
|
||||
import com.gh.gamecenter.common.constant.ItemViewType;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||||
import com.gh.gamecenter.common.utils.TextHelper;
|
||||
import com.gh.gamecenter.common.viewholder.FooterViewHolder;
|
||||
import com.gh.gamecenter.core.utils.MtaHelper;
|
||||
import com.gh.gamecenter.entity.ArticleCommentParent;
|
||||
import com.gh.gamecenter.entity.CommentEntity;
|
||||
import com.gh.gamecenter.common.retrofit.Response;
|
||||
import com.gh.gamecenter.eventbus.EBDeleteComment;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
@ -68,22 +72,34 @@ public class CommentDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
mDataExceptionView = dataExceptionView;
|
||||
mRecyclerView = recyclerView;
|
||||
|
||||
loadData();
|
||||
mOnCommentCallBackListener.onCommentCallback(null);
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
public void loadData() {
|
||||
public void refresh() {
|
||||
loadData(1);
|
||||
}
|
||||
|
||||
public void loadMore() {
|
||||
loadData(mPage + 1);
|
||||
}
|
||||
|
||||
public void loadData(int page) {
|
||||
if (mIsLoading) return;
|
||||
mIsLoading = true;
|
||||
RetrofitManager.getInstance().getApi()
|
||||
.getCommentTrace(mCommentId, mPage)
|
||||
.getCommentTrace(mCommentId, page)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<List<CommentEntity>>() {
|
||||
@Override
|
||||
public void onResponse(List<CommentEntity> response) {
|
||||
super.onResponse(response);
|
||||
if (page == 1) {
|
||||
mCommentList.clear();
|
||||
}
|
||||
mCommentList.addAll(response);
|
||||
|
||||
if (response.size() < 20) {
|
||||
mIsOver = true;
|
||||
}
|
||||
@ -91,7 +107,7 @@ public class CommentDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
mDataExceptionView.setVisibility(View.GONE);
|
||||
mRecyclerView.setVisibility(View.VISIBLE);
|
||||
notifyItemRangeChanged(0, getItemCount() - 1);
|
||||
mPage++;
|
||||
mPage = page;
|
||||
mIsLoading = false;
|
||||
}
|
||||
|
||||
@ -201,8 +217,14 @@ public class CommentDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
});
|
||||
|
||||
holder.commentMore.setOnClickListener(v ->
|
||||
CommentUtils.showReportDialog(commentEntity,
|
||||
mContext, false, "资讯文章-评论"));
|
||||
CommentUtils.showMorePopupWindow(
|
||||
holder.commentMore,
|
||||
commentEntity,
|
||||
false,
|
||||
"资讯文章-评论",
|
||||
() -> EventBus.getDefault().post(new EBDeleteComment(commentEntity))
|
||||
)
|
||||
);
|
||||
|
||||
holder.commentUserIconDv.setOnClickListener(v -> DirectUtils.directToHomeActivity(mContext, commentEntity.getUser().getId(), "", "文章-评论详情"));
|
||||
holder.commentUserNameTv.setOnClickListener(v -> DirectUtils.directToHomeActivity(mContext, commentEntity.getUser().getId(), "", "文章-评论详情"));
|
||||
@ -254,4 +276,24 @@ public class CommentDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
public boolean isLoading() {
|
||||
return mIsLoading;
|
||||
}
|
||||
|
||||
public void notifyCommentRemoved(final CommentEntity entity) {
|
||||
int positionInComments = getCommentIndexByEntity(mCommentList, entity);
|
||||
if (positionInComments != -1) {
|
||||
mCommentList.remove(positionInComments);
|
||||
notifyItemRemoved(positionInComments);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getCommentIndexByEntity(
|
||||
final List<CommentEntity> commentList,
|
||||
final CommentEntity comment
|
||||
) {
|
||||
for (int i = 0; i < commentList.size();i++) {
|
||||
if (Objects.equals(comment.getId(), commentList.get(i).getId())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ import com.gh.gamecenter.databinding.NewsDigestItemBinding;
|
||||
import com.gh.gamecenter.entity.ArticleCommentParent;
|
||||
import com.gh.gamecenter.entity.CommentEntity;
|
||||
import com.gh.gamecenter.entity.ConcernEntity;
|
||||
import com.gh.gamecenter.eventbus.EBDeleteComment;
|
||||
import com.gh.gamecenter.manager.VisitManager;
|
||||
import com.gh.gamecenter.common.retrofit.JSONObjectResponse;
|
||||
import com.gh.gamecenter.common.retrofit.OkHttpCache;
|
||||
@ -50,12 +51,14 @@ import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@ -151,6 +154,7 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
return;
|
||||
}
|
||||
if (isRefresh) {
|
||||
isOver = false;
|
||||
mNormalCommentList.clear();
|
||||
mPage = 1;
|
||||
}
|
||||
@ -467,8 +471,14 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
});
|
||||
|
||||
holder.commentMore.setOnClickListener(v ->
|
||||
CommentUtils.showReportDialog(finalCommentEntity,
|
||||
mContext, true, "资讯文章详情-评论详情"));
|
||||
CommentUtils.showMorePopupWindow(
|
||||
holder.commentMore,
|
||||
finalCommentEntity,
|
||||
true,
|
||||
"资讯文章详情-评论详情",
|
||||
() -> EventBus.getDefault().post(new EBDeleteComment(finalCommentEntity))
|
||||
)
|
||||
);
|
||||
|
||||
holder.commentUserNameTv.setOnClickListener(v -> DirectUtils.directToHomeActivity(mContext, finalCommentEntity.getUser().getId(), mEntrance, "文章-评论详情"));
|
||||
holder.commentUserIconDv.setOnClickListener(v -> DirectUtils.directToHomeActivity(mContext, finalCommentEntity.getUser().getId(), mEntrance, "文章-评论详情"));
|
||||
@ -524,6 +534,42 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
});
|
||||
}
|
||||
|
||||
public void notifyCommentRemoved(final CommentEntity entity) {
|
||||
|
||||
if (mHotCommentList.size() > 0) {
|
||||
int positionInHotComments = getCommentIndexByEntity(mHotCommentList, entity);
|
||||
if (positionInHotComments != -1) {// 如果在热门评论中存在要被删除的评论,则将此评论移除
|
||||
mHotCommentList.remove(positionInHotComments);
|
||||
}
|
||||
}
|
||||
|
||||
if (mNormalCommentList.size() > 0) {
|
||||
int positionInNormalComments = getCommentIndexByEntity(mNormalCommentList, entity);
|
||||
if (positionInNormalComments != -1) {// 如果在热门评论中存在要被删除的评论,则将此评论移除
|
||||
mNormalCommentList.remove(positionInNormalComments);
|
||||
}
|
||||
}
|
||||
|
||||
if (mConcernEntity != null) {
|
||||
int commentNum = mConcernEntity.getCommentnum();
|
||||
mConcernEntity.setCommentnum(commentNum - 1);
|
||||
}
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private static int getCommentIndexByEntity(
|
||||
final List<CommentEntity> commentList,
|
||||
final CommentEntity comment
|
||||
) {
|
||||
for (int i = 0; i < commentList.size();i++) {
|
||||
if (Objects.equals(comment.getId(), commentList.get(i).getId())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void statNewsViews(final String news_id) {
|
||||
RetrofitManager.getInstance().getApi().postArticleVisit(news_id)
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -587,7 +633,7 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
}
|
||||
|
||||
public void addCommentCount() {
|
||||
mConcernEntity.setCommentnum(mConcernEntity.getCommentnum());
|
||||
mConcernEntity.setCommentnum(mConcernEntity.getCommentnum() + 1);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
||||
@ -166,6 +166,7 @@ public class DetailViewHolder {
|
||||
"game_type", mGameEntity.getCategoryChinese(),
|
||||
"download_status", mGameEntity.getDownloadStatusChinese(),
|
||||
"button_name", mViewHolder.mDownloadPb.getText(),
|
||||
"game_schema_type", mGameEntity.getGameBitChinese(),
|
||||
"page_name", GlobalActivityManager.getCurrentPageEntity().getPageName(),
|
||||
"page_id", GlobalActivityManager.getCurrentPageEntity().getPageId(),
|
||||
"page_business_id", GlobalActivityManager.getCurrentPageEntity().getPageBusinessId(),
|
||||
@ -285,9 +286,9 @@ public class DetailViewHolder {
|
||||
|
||||
ChainBuilder builder = new ChainBuilder();
|
||||
builder.addHandler(new UpdateNewSimulatorHandler());
|
||||
builder.addHandler(new ValidateVSpaceHandler());
|
||||
builder.addHandler(new GamePermissionHandler());
|
||||
builder.addHandler(new CheckStoragePermissionHandler());
|
||||
builder.addHandler(new ValidateVSpaceHandler());
|
||||
|
||||
if (mGameEntity.getApk().size() == 1) {
|
||||
builder.addHandler(new BrowserInstallHandler());
|
||||
|
||||
@ -32,6 +32,11 @@ class CloudArchiveManagerViewModel(
|
||||
) :
|
||||
ListViewModel<ArchiveEntity, ArchiveEntity>(application) {
|
||||
|
||||
companion object {
|
||||
private const val SORT_TYPE_CREATE = "time.create:-1"
|
||||
private const val SORT_TYPE_SHARE_AND_CREATE = "time.share:-1,time.create:-1"
|
||||
}
|
||||
|
||||
var archiveConfigStr = ""
|
||||
private val mNewApi = RetrofitManager.getInstance().newApi
|
||||
private val mApi = RetrofitManager.getInstance().api
|
||||
@ -54,10 +59,10 @@ class CloudArchiveManagerViewModel(
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<List<ArchiveEntity>>? = when (mType) {
|
||||
MyArchiveFragment.Type.MY_ARCHIVE -> {
|
||||
mNewApi.getMyArchives(gameId, page)
|
||||
mNewApi.getMyArchives(gameId, page, SORT_TYPE_CREATE)
|
||||
}
|
||||
MyArchiveFragment.Type.MY_DOWNLOAD_ARCHIVE -> null
|
||||
MyArchiveFragment.Type.MY_SHARE_ARCHIVE -> mNewApi.getMyShareArchives(gameId, page)
|
||||
MyArchiveFragment.Type.MY_SHARE_ARCHIVE -> mNewApi.getMyShareArchives(gameId, page, SORT_TYPE_SHARE_AND_CREATE)
|
||||
}
|
||||
|
||||
override fun provideDataSingle(page: Int): Single<MutableList<ArchiveEntity>>? {
|
||||
@ -77,7 +82,7 @@ class CloudArchiveManagerViewModel(
|
||||
url = vArchiveEntity.url,
|
||||
configUrl = vArchiveEntity.configUrl,
|
||||
md5 = vArchiveEntity.md5,
|
||||
time = ArchiveEntity.Time(update = vArchiveEntity.time),
|
||||
time = ArchiveEntity.Time(create = vArchiveEntity.time),
|
||||
gameVersion = vArchiveEntity.gameVersion
|
||||
)
|
||||
)
|
||||
|
||||
@ -48,7 +48,7 @@ class MyArchiveAdapter(
|
||||
val entity = mEntityList[position]
|
||||
holder.binding.run {
|
||||
titleTv.text = entity.name
|
||||
timeTv.text = entity.time.update.formatTime("yyyy-MM-dd HH:mm")
|
||||
timeTv.text = entity.time.create.formatTime("yyyy-MM-dd HH:mm")
|
||||
versionTv.text = "版本:${entity.gameVersion}"
|
||||
optionsIv.setOnClickListener {
|
||||
MyArchiveOptionDialogFragment.show(
|
||||
|
||||
@ -17,7 +17,7 @@ class MyShareArchiveFragment : MyArchiveFragment() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mBinding.tipsTv.visibility = View.GONE
|
||||
mBinding.reuseNoneData.reuseNoneDataTv.text = "还没有您分享存档噢~"
|
||||
mBinding.reuseNoneData.reuseNoneDataTv.text = "您还没有分享存档噢~"
|
||||
mBinding.reuseNoneData.reuseNoneDataDescTv.text = "快快把您的有趣存档分享给大家吧!"
|
||||
}
|
||||
|
||||
|
||||
@ -100,9 +100,6 @@ class CommunityArticleAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.bbs == CommunityEntity()) {
|
||||
entity.bbs = entity.community
|
||||
}
|
||||
holder.binding.selectIv.goneIf(mCurrentOption == ManageOption.OPTION_MANAGER)
|
||||
holder.binding.selectIv.isChecked = selectItems.contains(entity.id)
|
||||
holder.binding.imageContainer.setOffset(if (mCurrentOption == ManageOption.OPTION_MANAGER) 40f else 76f)
|
||||
|
||||
@ -294,7 +294,7 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
case subscribe:
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(mContext, () -> {
|
||||
// 下载管理不用判断是否大于50M
|
||||
DialogUtils.checkDownload(mContext, Float.toString(100F), isSubscribe -> {
|
||||
DialogUtils.checkDownload(mContext, Float.toString(100F), downloadEntity.getGameId(), downloadEntity.getName(), isSubscribe -> {
|
||||
if (isSubscribe) {
|
||||
DownloadManager.getInstance().subscribe(downloadEntity);
|
||||
statusMap.put(url, DownloadStatus.subscribe.getStatus());
|
||||
|
||||
@ -127,11 +127,12 @@ class InstalledGameViewModel(application: Application) : AndroidViewModel(applic
|
||||
}
|
||||
if (newEntity.getApk().size > 1) {
|
||||
for (apkEntity in newEntity.getApk()) {
|
||||
val packageName: String = sortedList.get(i).packageName
|
||||
val packageName: String = sortedList[i].packageName
|
||||
if (packageName == apkEntity.packageName) {
|
||||
val list = ArrayList<ApkEntity>()
|
||||
list.add(apkEntity)
|
||||
newEntity.setApk(list)
|
||||
newEntity.dropOtherApk()
|
||||
if (PackageUtils.isCanPluggable(apkEntity)) {
|
||||
val pluggableCollection =
|
||||
GameUtils.getPluggableCollectionFromGameEntity(
|
||||
|
||||
@ -343,7 +343,9 @@ class UpdatableGameAdapter(private var mViewModel: UpdatableGameViewModel) :
|
||||
(CurrentActivityHolder.getCurrentActivity() as? FragmentActivity)?.checkStoragePermissionBeforeAction {
|
||||
DialogUtils.checkDownload(
|
||||
updateBtn.context,
|
||||
update.size
|
||||
update.size,
|
||||
downloadEntity?.gameId ?: "",
|
||||
downloadEntity?.name ?: ""
|
||||
) { isSubscribe: Boolean ->
|
||||
if (str.contains("化")) {
|
||||
if (update.pluggableCollection != null) {
|
||||
|
||||
@ -11,6 +11,8 @@ class AppEntity(
|
||||
@SerializedName("version_code")
|
||||
var versionCode: Int = 0,
|
||||
|
||||
var category: String? = "",
|
||||
|
||||
var url: String? = null,
|
||||
|
||||
var size: String? = null,
|
||||
@ -31,6 +33,8 @@ class AppEntity(
|
||||
* EVERY_TIME_OPEN(每次打开)
|
||||
*/
|
||||
var alert: String? = null,
|
||||
// 关联64位更新
|
||||
var relation: AppEntity? = null
|
||||
) : Parcelable {
|
||||
fun isAlertEveryTime() = alert == "EVERY_TIME_OPEN"
|
||||
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
package com.gh.gamecenter.eventbus;
|
||||
|
||||
public class EBAddComment {}
|
||||
@ -0,0 +1,3 @@
|
||||
package com.gh.gamecenter.eventbus
|
||||
|
||||
class EBTopCommunityChanged(val communityId: String)
|
||||
@ -40,7 +40,7 @@ class ForumArticleAskListAdapter(
|
||||
|
||||
private var mDefOrderList = listOf("回复", "发布")
|
||||
private var mVideoOrderList = listOf("推荐", "发布")
|
||||
private var mFilterPosition = 0
|
||||
private var mFilterPosition = if (path == "视频") 1 else 0
|
||||
|
||||
override fun areItemsTheSame(oldItem: AnswerEntity?, newItem: AnswerEntity?): Boolean {
|
||||
return oldItem?.id == newItem?.id
|
||||
|
||||
@ -21,7 +21,7 @@ class ForumArticleAskListViewModel(application: Application, val bbsId: String =
|
||||
var sort: String = "time.reply"
|
||||
var filter: String = "section_id"
|
||||
var selectedSection = ForumDetailEntity.Section("", "全部")
|
||||
var videoSort: String = "recommend"
|
||||
var videoSort: String = "time.upload"
|
||||
var videoList = arrayListOf<ForumVideoEntity>()
|
||||
|
||||
override fun provideDataObservable(page: Int): Observable<MutableList<AnswerEntity>> {
|
||||
|
||||
@ -59,6 +59,7 @@ import com.gh.gamecenter.databinding.ItemForumSectionBinding
|
||||
import com.gh.gamecenter.databinding.PopupForumDetailSectionsBinding
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.eventbus.EBForumFollowChange
|
||||
import com.gh.gamecenter.eventbus.EBTopCommunityChanged
|
||||
import com.gh.gamecenter.eventbus.EBTypeChange
|
||||
import com.gh.gamecenter.feature.entity.AnswerEntity
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
@ -1226,6 +1227,13 @@ class ForumDetailFragment : BaseLazyTabFragment(), IScrollable {
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onTopCommunityChanged(event: EBTopCommunityChanged) {
|
||||
if (event.communityId == mBbsId) {
|
||||
mViewModel?.getForumDetail(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun scrollToTop() {
|
||||
val fragment = mFragmentsList.safelyGetInRelease(mViewPager.currentItem)
|
||||
if (fragment is IScrollable && fragment.isAdded) {
|
||||
|
||||
@ -50,8 +50,12 @@ class ForumDetailViewModel(application: Application, val bbsId: String) : Androi
|
||||
.subscribe(EmptyResponse())
|
||||
}
|
||||
|
||||
fun getForumDetail() {
|
||||
mApi.getForumDetail(bbsId)
|
||||
/**
|
||||
* 获取论坛详情
|
||||
* @param refresh 是否刷新后台缓存
|
||||
*/
|
||||
fun getForumDetail(refresh: Boolean = false) {
|
||||
mApi.getForumDetail(bbsId, refresh)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ForumDetailEntity>() {
|
||||
|
||||
@ -67,7 +67,7 @@ class CommunityHomeViewModel(application: Application) : AndroidViewModel(applic
|
||||
articleEntity.count = articleDetailEntity.count
|
||||
articleDetailEntity.community.id = articleDetailEntity.communityId
|
||||
articleEntity.community = articleDetailEntity.community
|
||||
articleEntity.bbs = articleDetailEntity.community
|
||||
articleEntity.community = articleDetailEntity.community
|
||||
articleEntity.time = articleDetailEntity.time
|
||||
articleEntity.title = articleDetailEntity.title
|
||||
articleEntity.user = articleDetailEntity.user
|
||||
@ -89,7 +89,7 @@ class CommunityHomeViewModel(application: Application) : AndroidViewModel(applic
|
||||
?: ""
|
||||
articleEntity.count = questionDetailEntity.count
|
||||
articleEntity.community = questionDetailEntity.community
|
||||
articleEntity.bbs = questionDetailEntity.community
|
||||
articleEntity.community = questionDetailEntity.community
|
||||
articleEntity.time = questionDetailEntity.time
|
||||
articleEntity.title = questionDetailEntity.title ?: ""
|
||||
articleEntity.user = questionDetailEntity.user
|
||||
@ -114,7 +114,7 @@ class CommunityHomeViewModel(application: Application) : AndroidViewModel(applic
|
||||
articleEntity.length = forumVideoEntity.length
|
||||
articleEntity.videoInfo = forumVideoEntity.videoInfo
|
||||
articleEntity.count = forumVideoEntity.count
|
||||
articleEntity.bbs = forumVideoEntity.bbs ?: CommunityEntity()
|
||||
articleEntity.community = forumVideoEntity.bbs ?: CommunityEntity()
|
||||
articleEntity.time = TimeEntity(upload = forumVideoEntity.time.upload)
|
||||
articleEntity.title = forumVideoEntity.title
|
||||
forumVideoEntity.user.run {
|
||||
|
||||
@ -62,7 +62,6 @@ class ForumArticleListAdapter(
|
||||
ItemViewType.ITEM_BODY -> {
|
||||
val viewHolder = holder as ForumArticleAskItemViewHolder
|
||||
val articleEntity = mEntityList[position]
|
||||
articleEntity.community = CommunityEntity(articleEntity.bbs.id, articleEntity.bbs.name)
|
||||
|
||||
if (articleEntity.type == "bbs_article") articleEntity.type = "community_article"
|
||||
if (articleEntity.type == "bbs_question") articleEntity.type = "question"
|
||||
@ -102,13 +101,13 @@ class ForumArticleListAdapter(
|
||||
"question" -> "提问帖"
|
||||
else -> "提问帖评论"
|
||||
}
|
||||
val bbsType = if (bbs.type == "official_bbs") "综合论坛" else "游戏论坛"
|
||||
val bbsType = if (community.type == "official_bbs") "综合论坛" else "游戏论坛"
|
||||
NewLogUtils.logRecommendFeedContentClick(
|
||||
"click_for_you_content",
|
||||
contentType,
|
||||
id,
|
||||
position + 1,
|
||||
bbs.id,
|
||||
community.id,
|
||||
bbsType,
|
||||
user.id ?: ""
|
||||
)
|
||||
|
||||
@ -1264,6 +1264,8 @@ class HomeSearchToolWrapperFragment : SearchToolWrapperFragment() {
|
||||
tabViewBinding.titleTv.visibility = View.GONE
|
||||
tabViewBinding.invisibleTitleTv.visibility = View.GONE
|
||||
tabViewBinding.titleIv.setFixedHeight(16)
|
||||
// 部分设备加载图片时会获取到错误的最小宽度,这里为它做个 64DP 的保底尺寸
|
||||
tabViewBinding.titleIv.setTag(ImageUtils.TAG_TARGET_WIDTH, 64F.dip2px())
|
||||
tabViewBinding.titleIv.display(tabEntity.img)
|
||||
tabViewBinding.titleIv.registerLoadingCallback(object : WrapContentDraweeView.LoadingCallback {
|
||||
override fun loaded() {
|
||||
|
||||
@ -59,14 +59,34 @@ class GameGallerySlideViewHolder(val binding: GameGallerySlideItemBinding) : Bas
|
||||
binding.cardView.setCardBackgroundColor(R.color.text_FAFAFA.toColor(binding.root.context))
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分割好的游戏列表数据
|
||||
*/
|
||||
private fun getDividedGameList(): ArrayList<ArrayList<GameEntity>> {
|
||||
val containerList = arrayListOf<ArrayList<GameEntity>>()
|
||||
val gameDataList = mCachedSubject!!.data!!
|
||||
val gameListSize = gameDataList.size
|
||||
|
||||
val bestNumber = mCachedSubject!!.data!!.size / 3
|
||||
// 分割大小
|
||||
val splitSize = gameDataList.size / 3
|
||||
|
||||
containerList.add(ArrayList(mCachedSubject!!.data!!.subList(0, bestNumber - 1)))
|
||||
containerList.add(ArrayList(mCachedSubject!!.data!!.subList(bestNumber, bestNumber * 2 - 1)))
|
||||
containerList.add(ArrayList(mCachedSubject!!.data!!.subList(bestNumber * 2, mCachedSubject!!.data!!.size - 1)))
|
||||
if (splitSize > 1) {
|
||||
containerList.add(ArrayList(gameDataList.subList(0, splitSize)))
|
||||
containerList.add(ArrayList(gameDataList.subList(splitSize, splitSize * 2)))
|
||||
containerList.add(ArrayList(gameDataList.subList(splitSize * 2, gameListSize)))
|
||||
} else if (splitSize == 1) {
|
||||
containerList.add(ArrayList(gameDataList.subList(0, 1)))
|
||||
containerList.add(ArrayList(gameDataList.subList(1, 2)))
|
||||
containerList.add(ArrayList(gameDataList.subList(2, 3)))
|
||||
} else {
|
||||
val tempGameList = arrayListOf<GameEntity>()
|
||||
if (gameListSize != 0) {
|
||||
tempGameList.add(gameDataList.first())
|
||||
}
|
||||
containerList.add(tempGameList)
|
||||
containerList.add(tempGameList)
|
||||
containerList.add(tempGameList)
|
||||
}
|
||||
return containerList
|
||||
}
|
||||
|
||||
@ -88,6 +108,8 @@ class GameGallerySlideViewHolder(val binding: GameGallerySlideItemBinding) : Bas
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: GameGallerySlideItemViewHolder, position: Int) {
|
||||
if (gameList.isEmpty()) return
|
||||
|
||||
val gameEntity = gameList[position % gameList.size]
|
||||
|
||||
runOnIoThread(true) {
|
||||
|
||||
@ -159,18 +159,19 @@ class GameVerticalAdapter(
|
||||
|
||||
fun checkResetData(updateData: SubjectEntity) {
|
||||
var dataIds = ""
|
||||
mSubjectEntity = updateData
|
||||
mSubjectEntity.data?.forEach {
|
||||
dataIds += it.id
|
||||
}
|
||||
|
||||
mSubjectEntity = updateData
|
||||
if ((countAndKey?.first == updateData.data?.size && countAndKey?.second != dataIds) || mDarkMode != DarkModeUtils.isDarkModeOn(
|
||||
mContext
|
||||
)
|
||||
) { // 数量不变,内容发生改变
|
||||
if ((countAndKey?.first == updateData.data?.size && countAndKey?.second != dataIds)
|
||||
|| mDarkMode != DarkModeUtils.isDarkModeOn(mContext)
|
||||
) {
|
||||
// 数量不变,内容发生改变
|
||||
notifyItemRangeChanged(0, itemCount)
|
||||
mDarkMode = DarkModeUtils.isDarkModeOn(mContext)
|
||||
} else if (countAndKey?.first != updateData.data?.size) { // 数量发生改变
|
||||
} else if (countAndKey?.first != updateData.data?.size) {
|
||||
// 数量发生改变
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
|
||||
@ -56,8 +56,8 @@ class CloudArchiveListViewModel(
|
||||
|
||||
private fun getSortTypeFilter(): String {
|
||||
return when (mSortType) {
|
||||
SortType.NEWEST -> "time.create:-1"
|
||||
else -> "hot:-1"
|
||||
SortType.NEWEST -> "time.share:-1"
|
||||
else -> "count.usage:-1,time.share:-1"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -60,11 +60,11 @@ class GameLibaoAdapter(
|
||||
when (holder) {
|
||||
is LibaoViewHolder -> {
|
||||
val libaoEntity = libaos[position]
|
||||
val isTypeCopy = libaoEntity.receiveMethod == "copy"
|
||||
|
||||
holder.binding.libaoNameTv.text = libaoEntity.name
|
||||
holder.binding.contentTv.text = libaoEntity.content?.fromHtml()
|
||||
|
||||
val isTypeCopy = libaoEntity.receiveMethod == "copy"
|
||||
if (isTypeCopy) {
|
||||
// 类型为复制,不需要登录也能直接领取
|
||||
holder.binding.libaoSchedulePb.visibility = View.GONE
|
||||
@ -93,10 +93,7 @@ class GameLibaoAdapter(
|
||||
holder.binding.libaoCodeTv.text = "礼包码:-"
|
||||
} else {
|
||||
when (libaoEntity.status) {
|
||||
"ling" -> {
|
||||
holder.binding.libaoCodeTv.text = "礼包码:-"
|
||||
}
|
||||
"linged", "repeatLing", "repeatLinged" -> {
|
||||
"linged", "repeatLing", "repeatLinged", "taoed", "repeatTao", "repeatTaoed" -> {
|
||||
val size = libaoEntity.me?.userDataLibaoList?.size ?: 0
|
||||
val code = libaoEntity.me?.userDataLibaoList?.get(size - 1)?.code ?: ""
|
||||
val text = "礼包码:$code"
|
||||
@ -125,14 +122,7 @@ class GameLibaoAdapter(
|
||||
initProgressUI(libaoEntity, holder)
|
||||
} else {
|
||||
when (libaoEntity.status) {
|
||||
"ling" -> {
|
||||
holder.binding.libaoSchedulePb.visibility = View.VISIBLE
|
||||
holder.binding.remainingTv.visibility = View.VISIBLE
|
||||
holder.binding.libaoCodeTv.visibility = View.GONE
|
||||
|
||||
initProgressUI(libaoEntity, holder)
|
||||
}
|
||||
"linged", "repeatLing", "repeatLinged" -> {
|
||||
"linged", "repeatLing", "repeatLinged", "taoed", "repeatTao", "repeatTaoed" -> {
|
||||
holder.binding.libaoSchedulePb.visibility = View.GONE
|
||||
holder.binding.remainingTv.visibility = View.GONE
|
||||
holder.binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
@ -152,10 +142,11 @@ class GameLibaoAdapter(
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
holder.binding.libaoSchedulePb.visibility = View.GONE
|
||||
holder.binding.remainingTv.visibility = View.GONE
|
||||
holder.binding.libaoCodeTv.visibility = View.VISIBLE
|
||||
holder.binding.libaoCodeTv.text = "礼包码:-"
|
||||
holder.binding.libaoSchedulePb.visibility = View.VISIBLE
|
||||
holder.binding.remainingTv.visibility = View.VISIBLE
|
||||
holder.binding.libaoCodeTv.visibility = View.GONE
|
||||
|
||||
initProgressUI(libaoEntity, holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +67,7 @@ class HomeGameCollectionAdapter(
|
||||
val gamesCollectionEntity = itemData.gameCollectionItem
|
||||
root.layoutParams.width = DisplayUtils.getScreenWidth() - 50F.dip2px()
|
||||
if (gamesCollectionEntity != null) {
|
||||
poster.setTag(ImageUtils.TAG_TARGET_WIDTH, DisplayUtils.getScreenWidth() - 50F.dip2px())
|
||||
ImageUtils.display(poster, gamesCollectionEntity.cover)
|
||||
ImageUtils.display(userIv, gamesCollectionEntity.user?.icon)
|
||||
titleTv.text = gamesCollectionEntity.title
|
||||
|
||||
@ -127,7 +127,12 @@ class HomeItemGameTestV2ViewHolder(
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
Utils.log("onScrollStateChanged: newState = $newState")
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
recyclerView.handler.removeCallbacksAndMessages(null)
|
||||
// 高速滑动时可能触发空指针闪退
|
||||
try {
|
||||
recyclerView.handler.removeCallbacksAndMessages(null)
|
||||
} catch (e: NullPointerException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
recyclerView.postDelayed(300) { // 解决动画没结束时候条目和时间轴不对应问题
|
||||
onRecyclerViewChanged(true)
|
||||
}
|
||||
|
||||
@ -263,7 +263,7 @@ class ConcernAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
}
|
||||
|
||||
// 获取新闻评论数
|
||||
private void getNewsCommentnum(final List<ConcernEntity> list) {
|
||||
public void getNewsCommentnum(final List<ConcernEntity> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@ -508,6 +508,10 @@ class ConcernAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<ConcernEntity> getConcernList() {
|
||||
return concernList;
|
||||
}
|
||||
|
||||
public List<LibaoStatusEntity> getLibaoStatusList() {
|
||||
return libaoStatusList;
|
||||
}
|
||||
|
||||
@ -20,6 +20,8 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import com.gh.gamecenter.common.callback.OnRequestCallBackListener;
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity;
|
||||
import com.gh.common.filter.RegionSettingHelper;
|
||||
import com.gh.gamecenter.eventbus.EBAddComment;
|
||||
import com.gh.gamecenter.eventbus.EBDeleteComment;
|
||||
import com.gh.gamecenter.feature.utils.ApkActiveUtils;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.DataCollectionUtils;
|
||||
@ -386,6 +388,16 @@ public class ConcernFragment extends ToolbarFragment implements SwipeRefreshLayo
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onAddComment(EBAddComment event) {
|
||||
mAdapter.getNewsCommentnum(mAdapter.getConcernList());
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onDeleteComment(EBDeleteComment event) {
|
||||
mAdapter.getNewsCommentnum(mAdapter.getConcernList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
postDelayedRunnable(mRunnable, 1000);
|
||||
|
||||
@ -44,24 +44,32 @@ import com.gh.gamecenter.entity.CommentEntity;
|
||||
import com.gh.gamecenter.entity.CommentnumEntity;
|
||||
import com.gh.gamecenter.entity.ConcernEntity;
|
||||
import com.gh.gamecenter.entity.ViewsEntity;
|
||||
import com.gh.gamecenter.eventbus.EBAddComment;
|
||||
import com.gh.gamecenter.eventbus.EBDeleteComment;
|
||||
import com.gh.gamecenter.login.entity.UserInfoEntity;
|
||||
import com.gh.gamecenter.login.user.UserManager;
|
||||
import com.gh.gamecenter.manager.CommentManager;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.gamecenter.retrofit.service.ApiService;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.listeners.OnBackPressedListener;
|
||||
import com.lightgame.utils.Util_System_Keyboard;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.functions.Function3;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import retrofit2.HttpException;
|
||||
|
||||
@ -199,46 +207,34 @@ public class MessageDetailFragment extends ToolbarFragment implements OnCommentC
|
||||
mBinding.shadowView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void getCommentNum() {
|
||||
RetrofitManager.getInstance().getApi()
|
||||
.getNewsCommentnum(newsId, Utils.getTime(getContext()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<List<CommentnumEntity>>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(List<CommentnumEntity> response) {
|
||||
super.onResponse(response);
|
||||
if (response.size() > 0) {
|
||||
if (!TextUtils.isEmpty(mConcernEntity.getId())) {
|
||||
commentNum = response.get(0).getNum();
|
||||
mConcernEntity.setCommentnum(commentNum);
|
||||
adapter.notifyItemChanged(0);
|
||||
}
|
||||
private void getConcernDigest() {
|
||||
ApiService apiService = RetrofitManager.getInstance().getApi();
|
||||
Observable.zip(
|
||||
apiService.getNewsRichDigest(newsId),
|
||||
apiService.getArticlesVisits(UrlFilterUtils.getFilterQuery("article_ids", newsId)),
|
||||
apiService.getNewsCommentnum(newsId, Utils.getTime(getContext())),
|
||||
(concernEntity, viewsEntities, commentNumEntities) -> {
|
||||
if (commentNumEntities.size() > 0) {
|
||||
if (!TextUtils.isEmpty(concernEntity.getId())) {
|
||||
concernEntity.setCommentnum(commentNumEntities.get(0).getNum());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void getConcernDigest() {
|
||||
RetrofitManager.getInstance().getApi().getNewsRichDigest(newsId)
|
||||
if (viewsEntities.size() > 0) {
|
||||
concernEntity.setViews(viewsEntities.get(0).getViews());
|
||||
}
|
||||
|
||||
return concernEntity;
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ConcernEntity>() {
|
||||
@Override
|
||||
public void onResponse(ConcernEntity response) {
|
||||
mConcernEntity = response;
|
||||
if (commentNum == -1) {
|
||||
getCommentNum();
|
||||
} else {
|
||||
mConcernEntity.setCommentnum(commentNum);
|
||||
}
|
||||
|
||||
commentNum = mConcernEntity.getCommentnum();
|
||||
adapter.addConcernEntity(mConcernEntity);
|
||||
adapter.notifyDataSetChanged();
|
||||
adapter.addHotComment();
|
||||
getNewsViews();
|
||||
|
||||
if (commentNum == 0) {
|
||||
setSoftInput(true);
|
||||
}
|
||||
@ -251,22 +247,6 @@ public class MessageDetailFragment extends ToolbarFragment implements OnCommentC
|
||||
});
|
||||
}
|
||||
|
||||
private void getNewsViews() {
|
||||
RetrofitManager.getInstance().getApi()
|
||||
.getArticlesVisits(UrlFilterUtils.getFilterQuery("article_ids", newsId))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<List<ViewsEntity>>() {
|
||||
@Override
|
||||
public void onResponse(List<ViewsEntity> viewsEntities) {
|
||||
if (viewsEntities.size() > 0) {
|
||||
mConcernEntity.setViews(viewsEntities.get(0).getViews());
|
||||
adapter.notifyItemChanged(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//软键盘控制
|
||||
private void setSoftInput(boolean isShow) {
|
||||
if (isShow) {
|
||||
@ -297,6 +277,17 @@ public class MessageDetailFragment extends ToolbarFragment implements OnCommentC
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onDeleteComment(EBDeleteComment event) {
|
||||
adapter.notifyCommentRemoved(event.commentEntity);
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onAddComment(EBAddComment event) {
|
||||
commentNum = -1;
|
||||
getConcernDigest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
@ -375,6 +366,8 @@ public class MessageDetailFragment extends ToolbarFragment implements OnCommentC
|
||||
//修改评论缓存
|
||||
CommentManager.updateOkhttpCacheForId(getContext(), newsId);
|
||||
CommentManager.updateOkhttpCache(getContext(), newsId);
|
||||
// 发送评论更新通知
|
||||
EventBus.getDefault().post(new EBAddComment());
|
||||
adapter.notifyItemInserted(adapter.getHotCommentListSize() + 2);
|
||||
adapter.notifyItemChanged(adapter.getItemCount() - 1); //刷新脚布局高度
|
||||
} else {
|
||||
|
||||
@ -64,6 +64,7 @@ import com.gh.gamecenter.databinding.GamedetailItemNewsBinding;
|
||||
import com.gh.gamecenter.databinding.NewsDetailCommentBinding;
|
||||
import com.gh.gamecenter.databinding.NewsdetailItemContentBinding;
|
||||
import com.gh.gamecenter.databinding.NewsdetailItemGameBinding;
|
||||
import com.gh.gamecenter.eventbus.EBDeleteComment;
|
||||
import com.gh.gamecenter.feature.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.ArticleCommentParent;
|
||||
import com.gh.gamecenter.feature.entity.ColorEntity;
|
||||
@ -77,9 +78,12 @@ import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
@ -579,8 +583,16 @@ public class NewsDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
return true;
|
||||
});
|
||||
viewHolder.commentMore.setOnClickListener(v ->
|
||||
CommentUtils.showReportDialog(commentEntity,
|
||||
mContext, true, "资讯文章详情-评论"));
|
||||
CommentUtils.showMorePopupWindow(
|
||||
viewHolder.commentMore,
|
||||
commentEntity,
|
||||
true,
|
||||
"资讯文章详情-评论",
|
||||
() -> {
|
||||
EventBus.getDefault().post(new EBDeleteComment(commentEntity));
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
viewHolder.commentUserNameTv.setOnClickListener(v -> DirectUtils.directToHomeActivity(mContext, commentEntity.getUser().getId(), mEntrance, "文章-评论列表"));
|
||||
viewHolder.commentUserIconDv.setOnClickListener(v -> DirectUtils.directToHomeActivity(mContext, commentEntity.getUser().getId(), mEntrance, "文章-评论列表"));
|
||||
@ -679,10 +691,8 @@ public class NewsDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
|
||||
@Override
|
||||
public void onResponse(List<CommentnumEntity> response) {
|
||||
if (response.size() > 0 && response.get(0).getNum() > 0) {
|
||||
mCommentNum = response.get(0).getNum();
|
||||
getNewsHotComment();
|
||||
}
|
||||
mCommentNum = response.get(0).getNum();
|
||||
getNewsHotComment();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -726,9 +736,9 @@ public class NewsDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
public void onResponse(List<CommentEntity> response) {
|
||||
if (response.size() >= 1) {
|
||||
mIsHotComment = false;
|
||||
mCommentEntityList = response;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
mCommentEntityList = response;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
22
app/src/main/java/com/gh/gamecenter/oaid/OAIDHelper.kt
Normal file
22
app/src/main/java/com/gh/gamecenter/oaid/OAIDHelper.kt
Normal file
@ -0,0 +1,22 @@
|
||||
package com.gh.gamecenter.oaid
|
||||
|
||||
import android.content.Context
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.gh.gamecenter.common.constant.RouteConsts
|
||||
import com.gh.gamecenter.core.provider.IOAIDProvider
|
||||
|
||||
object OAIDHelper {
|
||||
|
||||
fun doSystemLoad() {
|
||||
val oaidProvider = ARouter.getInstance().build(RouteConsts.provider.oaid).navigation() as? IOAIDProvider
|
||||
|
||||
oaidProvider?.doSystemLoad()
|
||||
}
|
||||
|
||||
fun getOAID(context: Context, callback: (String) -> Unit) {
|
||||
val oaidProvider = ARouter.getInstance().build(RouteConsts.provider.oaid).navigation() as? IOAIDProvider
|
||||
|
||||
oaidProvider?.getOAID(context, callback)
|
||||
}
|
||||
|
||||
}
|
||||
@ -132,13 +132,13 @@ open class BaseAnswerOrArticleItemViewHolder(itemView: View) : BaseRecyclerViewH
|
||||
open fun bindCommendAndVote(entity: ArticleEntity, entrance: String, position: Int? = null) {
|
||||
binNormalView(entity.transformAnswerEntity())
|
||||
|
||||
if (entity.bbs.type == "official_bbs") {
|
||||
forumIcon?.displayGameIcon(entity.bbs.icon, null)
|
||||
if (entity.community.type == "official_bbs") {
|
||||
forumIcon?.displayGameIcon(entity.community.icon, null)
|
||||
} else {
|
||||
forumIcon?.displayGameIcon(
|
||||
entity.bbs.game?.getIcon(),
|
||||
entity.bbs.game?.iconSubscript,
|
||||
entity.bbs.game?.iconFloat
|
||||
entity.community.game?.getIcon(),
|
||||
entity.community.game?.iconSubscript,
|
||||
entity.community.game?.iconFloat
|
||||
)
|
||||
}
|
||||
|
||||
@ -148,17 +148,17 @@ open class BaseAnswerOrArticleItemViewHolder(itemView: View) : BaseRecyclerViewH
|
||||
"question" -> "提问帖"
|
||||
else -> "提问帖评论"
|
||||
}
|
||||
val bbsType = if (entity.bbs.type == "official_bbs") "综合论坛" else "游戏论坛"
|
||||
val bbsType = if (entity.community.type == "official_bbs") "综合论坛" else "游戏论坛"
|
||||
|
||||
forumNameTv.setOnClickListener {
|
||||
if (entrance == "社区+(推荐)") {
|
||||
NewLogUtils.logRecommendFeedForumClick(contentType, entity.id, entity.bbs.id, bbsType)
|
||||
NewLogUtils.logRecommendFeedForumClick(contentType, entity.id, entity.community.id, bbsType)
|
||||
}
|
||||
|
||||
MtaHelper.onEvent(
|
||||
getEventId(entrance),
|
||||
getKey(entrance),
|
||||
if (entity.bbs.name.isEmpty()) entity.community.name else entity.bbs.name
|
||||
if (entity.community.name.isEmpty()) entity.community.name else entity.community.name
|
||||
)
|
||||
itemView.context.startActivity(
|
||||
ForumDetailActivity.getIntent(
|
||||
@ -207,7 +207,7 @@ open class BaseAnswerOrArticleItemViewHolder(itemView: View) : BaseRecyclerViewH
|
||||
contentType,
|
||||
id,
|
||||
(position + 1),
|
||||
bbs.id,
|
||||
community.id,
|
||||
bbsType,
|
||||
user.id ?: "",
|
||||
commentType
|
||||
@ -266,7 +266,7 @@ open class BaseAnswerOrArticleItemViewHolder(itemView: View) : BaseRecyclerViewH
|
||||
contentType,
|
||||
id,
|
||||
position + 1,
|
||||
bbs.id,
|
||||
community.id,
|
||||
bbsType,
|
||||
user.id ?: ""
|
||||
)
|
||||
|
||||
@ -70,7 +70,7 @@ class MyArticleAdapter(
|
||||
mContext.startActivity(
|
||||
ArticleDetailActivity.getIntent(
|
||||
mContext,
|
||||
entity.bbs,
|
||||
entity.community,
|
||||
entity.id,
|
||||
mEntrance,
|
||||
mPath
|
||||
|
||||
@ -38,6 +38,7 @@ import com.gh.gamecenter.databinding.FragmentArticleDetailBinding
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.eventbus.EBDeleteCommentDetail
|
||||
import com.gh.gamecenter.eventbus.EBDeleteDetail
|
||||
import com.gh.gamecenter.eventbus.EBTopCommunityChanged
|
||||
import com.gh.gamecenter.feature.entity.ArticleDraftEntity
|
||||
import com.gh.gamecenter.feature.entity.Permissions
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
@ -453,6 +454,22 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
}
|
||||
}
|
||||
|
||||
mViewModel.top.observeNonNull(this) { top ->
|
||||
val topSuccessToast = if(top) {
|
||||
R.string.article_detail_top_success_toast
|
||||
} else {
|
||||
R.string.article_detail_cancel_top_success_toast
|
||||
}
|
||||
toast(getString(topSuccessToast))
|
||||
mViewModel.detailEntity?.let {
|
||||
EventBus.getDefault().post(
|
||||
EBTopCommunityChanged(
|
||||
it.communityId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
mViewModel.dislike.observeNonNull(this) { disliked ->
|
||||
if (disliked) {
|
||||
toast("已反对")
|
||||
@ -508,58 +525,82 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
private fun showMoreItemDialog() {
|
||||
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) || mViewModel.detailEntity != null) {
|
||||
val entities = ArrayList<MenuItemEntity>()
|
||||
// 申请加精
|
||||
if (mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId && !mViewModel.detailEntity?.me!!.isModerator && mViewModel.detailEntity?.status == "pass") {
|
||||
val isEnable =
|
||||
mViewModel.detailEntity?.getSimplifyChoicenessStatus() != "pass"
|
||||
mViewModel.detailEntity?.getSimplifyChoicenessStatus() != ArticleDetailEntity.STATUS_PASS
|
||||
entities.add(
|
||||
MenuItemEntity(
|
||||
"申请加精",
|
||||
getString(R.string.article_detail_more_apply_select_title),
|
||||
if (isEnable)
|
||||
R.drawable.icon_more_panel_essence else R.drawable.icon_more_panel_essence_unenable,
|
||||
isEnable = isEnable
|
||||
)
|
||||
)
|
||||
}
|
||||
if (mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId && mViewModel.detailEntity?.status == "pass") {
|
||||
entities.add(MenuItemEntity("修改", R.drawable.icon_more_panel_edit))
|
||||
|
||||
// 修改
|
||||
if (mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId
|
||||
&& mViewModel.detailEntity?.status == ArticleDetailEntity.STATUS_PASS) {
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_edit_title), R.drawable.icon_more_panel_edit))
|
||||
}
|
||||
|
||||
// 举报
|
||||
if (mViewModel.detailEntity?.user?.id != UserManager.getInstance().userId) {
|
||||
entities.add(MenuItemEntity("投诉", R.drawable.icon_gamedetail_copyright))
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_complaint_title), R.drawable.icon_gamedetail_copyright))
|
||||
}
|
||||
|
||||
val moderatorPermissions = mViewModel.detailEntity?.me?.moderatorPermissions
|
||||
if (mViewModel.detailEntity?.me?.isModerator == true && mViewModel.detailEntity?.status == "pass") {
|
||||
if (mViewModel.detailEntity?.getSimplifyChoicenessStatus() == "pass") {
|
||||
// 取消精选
|
||||
if (mViewModel.detailEntity?.me?.isModerator == true
|
||||
&& mViewModel.detailEntity?.status == ArticleDetailEntity.STATUS_PASS) {
|
||||
if (mViewModel.detailEntity?.getSimplifyChoicenessStatus() == ArticleDetailEntity.STATUS_PASS) {
|
||||
if ((moderatorPermissions?.cancelHighlightCommunityArticle
|
||||
?: Permissions.GUEST) > Permissions.GUEST
|
||||
) {
|
||||
entities.add(MenuItemEntity("取消精选", R.drawable.icon_more_panel_essence_cancel))
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_unselect_title), R.drawable.icon_more_panel_essence_cancel))
|
||||
}
|
||||
} else {
|
||||
if ((moderatorPermissions?.highlightCommunityArticle
|
||||
?: Permissions.GUEST) > Permissions.GUEST
|
||||
) {
|
||||
entities.add(MenuItemEntity("加精选", R.drawable.icon_more_panel_essence))
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_select_title), R.drawable.icon_more_panel_essence))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 修改活动标签
|
||||
if (mViewModel.detailEntity?.me?.isModerator == true &&
|
||||
(moderatorPermissions?.updateArticleActivityTag
|
||||
?: Permissions.GUEST) > Permissions.GUEST &&
|
||||
mViewModel.detailEntity?.status == "pass"
|
||||
mViewModel.detailEntity?.status == ArticleDetailEntity.STATUS_PASS
|
||||
) {
|
||||
entities.add(MenuItemEntity("修改活动标签", R.drawable.icon_more_panel_modify_label))
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_edit_activity_tag_title), R.drawable.icon_more_panel_modify_label))
|
||||
}
|
||||
|
||||
// 隐藏/删除
|
||||
if (mViewModel.detailEntity?.me?.isModerator == true &&
|
||||
(moderatorPermissions?.hideCommunityArticle
|
||||
?: Permissions.GUEST) > Permissions.GUEST
|
||||
) {
|
||||
entities.add(MenuItemEntity("隐藏", R.drawable.icon_more_panel_delete))
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_hide_title), R.drawable.icon_more_panel_delete))
|
||||
} else {
|
||||
if (mViewModel.detailEntity?.user?.id == UserManager.getInstance().userId) {
|
||||
entities.add(MenuItemEntity("删除", R.drawable.icon_more_panel_delete))
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_delete_title), R.drawable.icon_more_panel_delete))
|
||||
}
|
||||
}
|
||||
|
||||
// 置顶/取消置顶
|
||||
if (mViewModel.detailEntity?.me?.isModerator == true
|
||||
&& mViewModel.detailEntity?.me?.isCommunityTop == false
|
||||
&& (moderatorPermissions?.topCommunityArticle ?: Permissions.GUEST) > Permissions.GUEST) {
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_top_title), R.drawable.icon_more_panel_top))
|
||||
} else if (mViewModel.detailEntity?.me?.isModerator == true
|
||||
&& mViewModel.detailEntity?.me?.isCommunityTop == true
|
||||
&& (moderatorPermissions?.cancelTopCommunityArticle ?: Permissions.GUEST) > Permissions.GUEST) {
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_cancel_top_title), R.drawable.icon_more_panel_top_cancel))
|
||||
}
|
||||
|
||||
MoreFunctionPanelDialog.showMoreDialog(
|
||||
requireActivity() as AppCompatActivity, entities, mViewModel.detailEntity?.title
|
||||
?: "", getShareEntity(), mViewModel.detailEntity?.status ?: "", tag ?: ""
|
||||
@ -597,7 +638,7 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
return {
|
||||
val bbsType = if (mViewModel.detailEntity?.type == "game_bbs") "游戏论坛" else "综合论坛"
|
||||
when (it?.text) {
|
||||
"修改" -> {
|
||||
getString(R.string.article_detail_more_edit_title) -> {
|
||||
startActivityForResult(
|
||||
ArticleEditActivity.getPatchIntent(
|
||||
requireContext(),
|
||||
@ -610,7 +651,7 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
?: "", mViewModel.detailEntity?.community?.id ?: "", bbsType
|
||||
)
|
||||
}
|
||||
"投诉" -> {
|
||||
getString(R.string.article_detail_more_complaint_title) -> {
|
||||
ifLogin("帖子详情") {
|
||||
BbsReportHelper.showReportDialog(mViewModel.detailEntity?.id ?: "")
|
||||
}
|
||||
@ -620,7 +661,7 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
?: "", mViewModel.detailEntity?.community?.id ?: "", bbsType
|
||||
)
|
||||
}
|
||||
"申请加精" -> {
|
||||
getString(R.string.article_detail_more_apply_select_title) -> {
|
||||
if (mViewModel.detailEntity?.getSimplifyChoicenessStatus() == "apply") {
|
||||
ToastUtils.showToast("申请加精审核中")
|
||||
} else {
|
||||
@ -632,7 +673,7 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
)
|
||||
}
|
||||
}
|
||||
"加精选" -> {
|
||||
getString(R.string.article_detail_more_select_title) -> {
|
||||
if (mViewModel.detailEntity?.getSimplifyChoicenessStatus() == "apply") {
|
||||
ToastUtils.showToast("加精审核中")
|
||||
} else {
|
||||
@ -644,10 +685,10 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
)
|
||||
}
|
||||
}
|
||||
"取消精选" -> {
|
||||
getString(R.string.article_detail_more_unselect_title) -> {
|
||||
showHighlightDialog(false)
|
||||
}
|
||||
"修改活动标签" -> {
|
||||
getString(R.string.article_detail_more_edit_activity_tag_title) -> {
|
||||
ChooseActivityDialogFragment.show(
|
||||
requireActivity() as AppCompatActivity,
|
||||
ChooseActivityDialogFragment.ActivityLabelLocation.BBS_ARTICLE,
|
||||
@ -656,7 +697,8 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
tag ?: ""
|
||||
)
|
||||
}
|
||||
"删除", "隐藏" -> {
|
||||
getString(R.string.article_detail_more_delete_title),
|
||||
getString(R.string.article_detail_more_hide_title) -> {
|
||||
DialogHelper.showDialog(
|
||||
requireContext(),
|
||||
"提示",
|
||||
@ -673,6 +715,26 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
|
||||
?: "", mViewModel.detailEntity?.community?.id ?: "", bbsType
|
||||
)
|
||||
}
|
||||
getString(R.string.article_detail_more_top_title) -> {
|
||||
TopCommunityCategoryDialog.show(
|
||||
childFragmentManager
|
||||
) { category ->
|
||||
mViewModel.topCommunityArticle(category.id)
|
||||
}
|
||||
}
|
||||
getString(R.string.article_detail_more_cancel_top_title) -> {
|
||||
DialogHelper.showDialog(
|
||||
requireContext(),
|
||||
getString(R.string.article_detail_cancel_top_dialog_title),
|
||||
getString(R.string.article_detail_cancel_top_dialog_hint),
|
||||
getString(R.string.article_detail_cancel_top_dialog_confirm),
|
||||
getString(R.string.article_detail_cancel_top_dialog_cancel),
|
||||
confirmClickCallback = {
|
||||
mViewModel.cancelTopCommunityArticle()
|
||||
},
|
||||
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,6 +57,7 @@ class ArticleDetailViewModel(
|
||||
val mFollowLiveData = MutableLiveData<Boolean>()
|
||||
|
||||
val hide = MutableLiveData<Boolean>()
|
||||
val top = MutableLiveData<Boolean>()
|
||||
val like = MutableLiveData<VoteEntity>()
|
||||
val dislike = MutableLiveData<Boolean>()
|
||||
val highlight = MutableLiveData<Boolean>()
|
||||
@ -377,6 +378,52 @@ class ArticleDetailViewModel(
|
||||
})
|
||||
}
|
||||
|
||||
fun topCommunityArticle(topCategoryId: String) {
|
||||
detailEntity?.let {articleDetail ->
|
||||
mApi.topCommunityArticle(
|
||||
articleDetail.id,
|
||||
articleDetail.communityId,
|
||||
mapOf(
|
||||
"title" to articleDetail.title,
|
||||
"top_category_id" to topCategoryId
|
||||
).toRequestBody()
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
getArticleDetail()
|
||||
top.postValue(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun cancelTopCommunityArticle() {
|
||||
detailEntity?.also {articleDetail ->
|
||||
articleDetail.top?.let { communityTop ->
|
||||
mApi.cancelTopCommunityArticle(
|
||||
articleDetail.id,
|
||||
communityId,
|
||||
mapOf(
|
||||
"community_article_top_id" to communityTop.id
|
||||
).toRequestBody()
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
getArticleDetail()
|
||||
top.postValue(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun modifyArticleActivityTag(
|
||||
articleId: String,
|
||||
label: ActivityLabelEntity?
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
package com.gh.gamecenter.qa.article.detail
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil.ItemCallback
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView.NO_POSITION
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.gh.gamecenter.common.utils.layoutInflater
|
||||
import com.gh.gamecenter.databinding.ItemTopCommunityCategoryBinding
|
||||
import com.gh.gamecenter.qa.entity.TopCommunityCategory
|
||||
|
||||
class TopCommunityCategoryAdapter(
|
||||
private val callback: (TopCommunityCategory) -> Unit
|
||||
) : ListAdapter<TopCommunityCategory, TopCommunityCategoryAdapter.ArticleDetailTopCategoryViewHolder>(COMPARATOR) {
|
||||
|
||||
private var selectedPosition = -1
|
||||
|
||||
companion object {
|
||||
private val COMPARATOR = object: ItemCallback<TopCommunityCategory>() {
|
||||
override fun areItemsTheSame(
|
||||
oldItem: TopCommunityCategory,
|
||||
newItem: TopCommunityCategory
|
||||
) : Boolean = oldItem == newItem
|
||||
|
||||
override fun areContentsTheSame(
|
||||
oldItem: TopCommunityCategory,
|
||||
newItem: TopCommunityCategory
|
||||
) : Boolean = oldItem == newItem
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleDetailTopCategoryViewHolder =
|
||||
ArticleDetailTopCategoryViewHolder(
|
||||
ItemTopCommunityCategoryBinding.inflate(
|
||||
parent.layoutInflater,
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(holder: ArticleDetailTopCategoryViewHolder, position: Int) {
|
||||
val titleView = holder.binding.root
|
||||
|
||||
titleView.text = getItem(position).title
|
||||
titleView.isSelected = selectedPosition == position
|
||||
|
||||
titleView.setOnClickListener {
|
||||
val pos = holder.bindingAdapterPosition
|
||||
if (pos == NO_POSITION) return@setOnClickListener
|
||||
|
||||
it.isSelected = true
|
||||
|
||||
val oldPos = selectedPosition
|
||||
selectedPosition = pos
|
||||
notifyItemChanged(oldPos)
|
||||
callback.invoke(getItem(pos))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ArticleDetailTopCategoryViewHolder(
|
||||
val binding: ItemTopCommunityCategoryBinding
|
||||
) : ViewHolder(binding.root)
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package com.gh.gamecenter.qa.article.detail
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.gh.gamecenter.common.utils.observeNonNull
|
||||
import com.gh.gamecenter.common.view.GridSpacingItemDecoration
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.databinding.DialogTopCommunityCategoryBinding
|
||||
import com.gh.gamecenter.qa.entity.TopCommunityCategory
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
|
||||
/**
|
||||
* 版主帖子置顶-置顶类型
|
||||
*/
|
||||
class TopCommunityCategoryDialog private constructor(): BottomSheetDialogFragment() {
|
||||
|
||||
private val viewModel: TopCommunityCategoryViewModel by viewModels()
|
||||
|
||||
private lateinit var viewBinding: DialogTopCommunityCategoryBinding
|
||||
|
||||
private lateinit var topCommunityCategoryAdapter: TopCommunityCategoryAdapter
|
||||
|
||||
private lateinit var callback: (TopCommunityCategory) -> Unit
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
viewModel.getTopCommunityCategory()
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View = DialogTopCommunityCategoryBinding
|
||||
.inflate(
|
||||
inflater,
|
||||
container,
|
||||
false
|
||||
).also {
|
||||
viewBinding = it
|
||||
}.root
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
with(viewBinding) {
|
||||
rv.adapter = TopCommunityCategoryAdapter{
|
||||
viewModel.submitTopCommunityCategory(it)
|
||||
}.also {
|
||||
topCommunityCategoryAdapter = it
|
||||
}
|
||||
rv.layoutManager = GridLayoutManager(context, 2)
|
||||
rv.addItemDecoration(GridSpacingItemDecoration(2, DisplayUtils.dip2px(8F), false))
|
||||
}
|
||||
|
||||
viewModel.topCommunityCategoryList.observeNonNull(viewLifecycleOwner) {
|
||||
topCommunityCategoryAdapter.submitList(it)
|
||||
}
|
||||
|
||||
viewModel.selectTopCommunityCategory.observe(viewLifecycleOwner) {
|
||||
if (it == null) {
|
||||
viewBinding.tvSubmit.isEnabled = false
|
||||
viewBinding.tvSubmit.alpha = 0.4F
|
||||
} else {
|
||||
viewBinding.tvSubmit.isEnabled = true
|
||||
viewBinding.tvSubmit.alpha = 1.0F
|
||||
}
|
||||
}
|
||||
|
||||
viewBinding.ivClose.setOnClickListener {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
viewBinding.tvSubmit.setOnClickListener {
|
||||
callback.invoke(viewModel.selectTopCommunityCategory.value!!)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun show(
|
||||
fragmentManager: FragmentManager,
|
||||
callback: (TopCommunityCategory) -> Unit
|
||||
) = TopCommunityCategoryDialog().also {
|
||||
it.callback = callback
|
||||
}.show(fragmentManager, null)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.gh.gamecenter.qa.article.detail
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.gh.gamecenter.common.retrofit.Response
|
||||
import com.gh.gamecenter.qa.entity.TopCommunityCategory
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
/**
|
||||
* 论坛置顶类型
|
||||
*/
|
||||
class TopCommunityCategoryViewModel: ViewModel() {
|
||||
|
||||
private val mApi: ApiService = RetrofitManager.getInstance().api
|
||||
|
||||
val topCommunityCategoryList = MutableLiveData<List<TopCommunityCategory>>()
|
||||
|
||||
val selectTopCommunityCategory = MutableLiveData<TopCommunityCategory?>(null)
|
||||
|
||||
fun getTopCommunityCategory() {
|
||||
mApi.topCommunityCategory
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<List<TopCommunityCategory>>() {
|
||||
override fun onResponse(response: List<TopCommunityCategory>?) {
|
||||
response?.let {
|
||||
topCommunityCategoryList.value = it
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun submitTopCommunityCategory(category: TopCommunityCategory) {
|
||||
selectTopCommunityCategory.value = category
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@ import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.LayoutInflater
|
||||
@ -13,6 +14,8 @@ import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.*
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@ -305,8 +308,22 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
|
||||
commentContainer?.layoutParams = layoutParams
|
||||
}
|
||||
|
||||
mKeyboardHeightProvider = KeyboardHeightProvider(activity)
|
||||
view.post { mKeyboardHeightProvider?.start() }
|
||||
// 判断是否处于平板的平行视界模式
|
||||
val configString = requireContext().resources.configuration.toString()
|
||||
val isMagicMode = configString.contains("magic-window") || configString.contains("window-magic")
|
||||
|
||||
// 平板上的导航方式改成按键时,使用 KeyboardHeightProvider 的 PopupWindow 会拦截掉所有的触摸事件
|
||||
// 根据测试 Android 11 以前的系统用 WindowInsetsCompat.Type.ime()).bottom 获取不到正确的值
|
||||
// 所以仅在系统为大于 10 且处于平行视界模式时才切换实现
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && isMagicMode) {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(requireActivity().window.decorView) { _: View?, insets: WindowInsetsCompat ->
|
||||
onKeyboardHeightChanged(insets.getInsets(WindowInsetsCompat.Type.ime()).bottom, 0)
|
||||
insets
|
||||
}
|
||||
} else {
|
||||
mKeyboardHeightProvider = KeyboardHeightProvider(activity)
|
||||
view.post { mKeyboardHeightProvider?.start() }
|
||||
}
|
||||
val emptyHint = mCachedView?.findViewById<TextView>(R.id.reuseNoneDataTv)
|
||||
emptyHint?.text = "这里还没有人评论噢~"
|
||||
emptyHint?.setTextColor(R.color.background_white.toColor(requireContext()))
|
||||
|
||||
@ -7,6 +7,7 @@ import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
@ -151,8 +152,14 @@ class MoreFunctionPanelDialog : BaseDraggableDialogFragment() {
|
||||
}
|
||||
|
||||
private fun addActionItem() {
|
||||
mMenuItems.forEachIndexed { _, menuItemEntity ->
|
||||
val itemView = createItemView(menuItemEntity)
|
||||
mMenuItems.forEachIndexed { index, menuItemEntity ->
|
||||
val itemView = createItemView(menuItemEntity).apply {
|
||||
if (index == mMenuItems.lastIndex) {
|
||||
(layoutParams as MarginLayoutParams).apply {
|
||||
rightMargin = 16F.dip2px()
|
||||
}
|
||||
}
|
||||
}
|
||||
itemView.setOnClickListener {
|
||||
debounceActionWithInterval(it.id, 2000) {
|
||||
if (menuItemEntity.isEnable) {
|
||||
|
||||
@ -3,7 +3,6 @@ package com.gh.gamecenter.qa.entity
|
||||
import android.os.Parcelable
|
||||
import com.gh.gamecenter.common.entity.CommunityEntity
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.entity.ForumEntity
|
||||
import com.gh.gamecenter.feature.entity.UserEntity
|
||||
import com.gh.gamecenter.feature.entity.*
|
||||
import com.google.gson.annotations.SerializedName
|
||||
@ -48,7 +47,9 @@ class ArticleDetailEntity(
|
||||
val activityTag: ActivityTagEntity? = null,
|
||||
var sections: List<SectionEntity> = ArrayList(),
|
||||
@SerializedName("section_id")
|
||||
var sectionIdList: List<String> = ArrayList()
|
||||
var sectionIdList: List<String> = ArrayList(),
|
||||
@SerializedName("community_article_top")
|
||||
var top: CommunityTopEntity? = null
|
||||
) : Parcelable {
|
||||
|
||||
fun getSimplifyChoicenessStatus(): String {
|
||||
@ -58,6 +59,10 @@ class ArticleDetailEntity(
|
||||
else -> choicenessStatus ?: ""
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val STATUS_PASS = "pass"
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
|
||||
@ -36,7 +36,7 @@ class EditorInsertEntity(
|
||||
fun transform(article: ArticleEntity): EditorInsertEntity {
|
||||
val entity = EditorInsertEntity()
|
||||
entity.id = article.id
|
||||
entity.communityId = article.bbs.id
|
||||
entity.communityId = article.community.id
|
||||
entity.type = "community_article"
|
||||
entity.title = article.title.eliminateDoubleQuote()
|
||||
entity.brief = article.brief.eliminateDoubleQuote()
|
||||
|
||||
@ -56,7 +56,9 @@ class QuestionsDetailEntity(
|
||||
val source: SourceEntity? = null,
|
||||
@SerializedName("activity_tag")
|
||||
val activityTag: ActivityTagEntity? = null,
|
||||
var sections: List<SectionEntity> = ArrayList()
|
||||
var sections: List<SectionEntity> = ArrayList(),
|
||||
@SerializedName("question_top")
|
||||
var top: CommunityTopEntity? = null
|
||||
) : Parcelable {
|
||||
|
||||
fun getFollowCount(): Int {
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
package com.gh.gamecenter.qa.entity
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class TopCommunityCategory(
|
||||
@SerializedName("_id")
|
||||
val id: String, // 置顶类型ID
|
||||
val title: String, // 置顶类型名称
|
||||
val style: Style
|
||||
): Parcelable {
|
||||
@Parcelize
|
||||
data class Style(
|
||||
val color: String,
|
||||
val fontColor: String
|
||||
): Parcelable
|
||||
}
|
||||
@ -32,9 +32,11 @@ import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.databinding.FragmentArticleDetailBinding
|
||||
import com.gh.gamecenter.entity.MenuItemEntity
|
||||
import com.gh.gamecenter.eventbus.EBDeleteDetail
|
||||
import com.gh.gamecenter.eventbus.EBTopCommunityChanged
|
||||
import com.gh.gamecenter.feature.entity.Permissions
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.qa.article.detail.CommentItemData
|
||||
import com.gh.gamecenter.qa.article.detail.TopCommunityCategoryDialog
|
||||
import com.gh.gamecenter.qa.comment.CommentActivity
|
||||
import com.gh.gamecenter.qa.comment.base.BaseCommentAdapter
|
||||
import com.gh.gamecenter.qa.comment.base.BaseCommentFragment
|
||||
@ -367,6 +369,22 @@ class NewQuestionDetailFragment :
|
||||
mViewModel.updateDetailLiveData.observeNonNull(this) {
|
||||
mAdapter?.questionDetailVH?.bindView(it)
|
||||
}
|
||||
mViewModel.top.observeNonNull(this) { top ->
|
||||
val topSuccessToast = if(top) {
|
||||
R.string.article_detail_top_success_toast
|
||||
} else {
|
||||
R.string.article_detail_cancel_top_success_toast
|
||||
}
|
||||
toast(getString(topSuccessToast))
|
||||
mListViewModel.questionDetail?.let {
|
||||
EventBus.getDefault().post(
|
||||
EBTopCommunityChanged(
|
||||
it.community.id
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateStartButton() {
|
||||
@ -545,6 +563,17 @@ class NewQuestionDetailFragment :
|
||||
}
|
||||
}
|
||||
|
||||
// 置顶/取消置顶
|
||||
if (questionEntity.me.isModerator
|
||||
&& !questionEntity.me.isCommunityTop
|
||||
&& moderatorPermissions.topQuestion > Permissions.GUEST) {
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_top_title), R.drawable.icon_more_panel_top))
|
||||
} else if (questionEntity.me.isModerator
|
||||
&& questionEntity.me.isCommunityTop
|
||||
&& moderatorPermissions.cancelTopQuestion > Permissions.GUEST) {
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_cancel_top_title), R.drawable.icon_more_panel_top_cancel))
|
||||
}
|
||||
|
||||
MoreFunctionPanelDialog.showMoreDialog(
|
||||
requireActivity() as AppCompatActivity, entities, questionEntity.title
|
||||
?: "", getShareEntity(questionEntity), questionEntity.status, tag ?: ""
|
||||
@ -655,6 +684,29 @@ class NewQuestionDetailFragment :
|
||||
bbsType
|
||||
)
|
||||
}
|
||||
getString(R.string.article_detail_more_top_title) -> {
|
||||
TopCommunityCategoryDialog.show(
|
||||
childFragmentManager
|
||||
) { category ->
|
||||
mViewModel.topCommunityQuestion(category.id)
|
||||
}
|
||||
}
|
||||
getString(R.string.article_detail_more_cancel_top_title) -> {
|
||||
DialogHelper.showDialog(
|
||||
requireContext(),
|
||||
getString(R.string.article_detail_cancel_top_dialog_title),
|
||||
getString(R.string.article_detail_cancel_top_dialog_hint),
|
||||
getString(R.string.article_detail_cancel_top_dialog_confirm),
|
||||
getString(R.string.article_detail_cancel_top_dialog_cancel),
|
||||
confirmClickCallback = {
|
||||
mViewModel.questionDetail?.top?.let { top ->
|
||||
mViewModel.cancelTopCommunityQuestion()
|
||||
}
|
||||
|
||||
},
|
||||
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,6 +57,7 @@ class NewQuestionDetailViewModel(
|
||||
val moderatorsHideLiveData = MutableLiveData<Boolean>()
|
||||
val favoriteLiveData = MutableLiveData<Boolean>()
|
||||
val mFollowLiveData = MutableLiveData<Boolean>()
|
||||
val top = MutableLiveData<Boolean>()
|
||||
val updateDetailLiveData = MutableLiveData<QuestionsDetailEntity>()
|
||||
var questionDetail: QuestionsDetailEntity? = null
|
||||
val followLiveData = mFollowLiveData
|
||||
@ -226,6 +227,49 @@ class NewQuestionDetailViewModel(
|
||||
})
|
||||
}
|
||||
|
||||
fun topCommunityQuestion(topCategoryId: String) {
|
||||
questionDetail?.let { questionDetail ->
|
||||
mApi.topCommunityQuestion(
|
||||
questionDetail.id,
|
||||
mapOf(
|
||||
"title" to questionDetail.title,
|
||||
"top_category_id" to topCategoryId
|
||||
).toRequestBody()
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
getQuestionDetail()
|
||||
top.postValue(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun cancelTopCommunityQuestion() {
|
||||
questionDetail?.also {questionDetail ->
|
||||
questionDetail.top?.let { communityTop ->
|
||||
mApi.cancelTopCommunityQuestion(
|
||||
questionDetail.id,
|
||||
mapOf(
|
||||
"question_top_id" to communityTop.id
|
||||
).toRequestBody()
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
getQuestionDetail()
|
||||
top.postValue(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getFirstAnswer() = mListLiveData.value?.safelyGetInRelease(0)
|
||||
|
||||
class Factory(
|
||||
|
||||
@ -41,12 +41,14 @@ import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.eventbus.EBDeleteDetail
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.eventbus.EBTopCommunityChanged
|
||||
import com.gh.gamecenter.feature.entity.ForumVideoEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.Permissions
|
||||
import com.gh.gamecenter.forum.home.ForumScrollCalculatorHelper
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.login.user.UserManager
|
||||
import com.gh.gamecenter.qa.article.detail.TopCommunityCategoryDialog
|
||||
import com.gh.gamecenter.qa.dialog.ChooseActivityDialogFragment
|
||||
import com.gh.gamecenter.qa.dialog.MoreFunctionPanelDialog
|
||||
import com.gh.gamecenter.qa.video.detail.comment.VideoCommentFragment
|
||||
@ -309,6 +311,21 @@ class ForumVideoDetailFragment : BaseFragment_TabLayout() {
|
||||
toast("提交失败")
|
||||
}
|
||||
}
|
||||
mViewModel.top.observeNonNull(this) { top ->
|
||||
val topSuccessToast = if(top) {
|
||||
R.string.article_detail_top_success_toast
|
||||
} else {
|
||||
R.string.article_detail_cancel_top_success_toast
|
||||
}
|
||||
toast(getString(topSuccessToast))
|
||||
mForumVideoEntity?.let {
|
||||
EventBus.getDefault().post(
|
||||
EBTopCommunityChanged(
|
||||
it.bbsId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setGameInfo(entity: ForumVideoEntity) {
|
||||
@ -535,6 +552,17 @@ class ForumVideoDetailFragment : BaseFragment_TabLayout() {
|
||||
}
|
||||
}
|
||||
|
||||
// 置顶/取消置顶
|
||||
if (mForumVideoEntity?.me?.isModerator == true
|
||||
&& mForumVideoEntity?.me?.isCommunityTop == false
|
||||
&& (moderatorPermissions?.topVideo ?: Permissions.GUEST) > Permissions.GUEST) {
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_top_title), R.drawable.icon_more_panel_top))
|
||||
} else if (mForumVideoEntity?.me?.isModerator == true
|
||||
&& mForumVideoEntity?.me?.isCommunityTop == true
|
||||
&& (moderatorPermissions?.cancelTopVideo ?: Permissions.GUEST) > Permissions.GUEST) {
|
||||
entities.add(MenuItemEntity(getString(R.string.article_detail_more_cancel_top_title), R.drawable.icon_more_panel_top_cancel))
|
||||
}
|
||||
|
||||
MoreFunctionPanelDialog.showMoreDialog(
|
||||
requireActivity() as AppCompatActivity, entities, mForumVideoEntity?.title
|
||||
?: "", getShareEntity(), mForumVideoEntity?.status ?: "", tag ?: ""
|
||||
@ -647,6 +675,27 @@ class ForumVideoDetailFragment : BaseFragment_TabLayout() {
|
||||
?: "", mForumVideoEntity?.bbs?.id ?: "", bbsType
|
||||
)
|
||||
}
|
||||
getString(R.string.article_detail_more_top_title) -> {
|
||||
TopCommunityCategoryDialog.show(
|
||||
childFragmentManager
|
||||
) { category ->
|
||||
mViewModel.topCommunityVideo(category.id)
|
||||
}
|
||||
}
|
||||
getString(R.string.article_detail_more_cancel_top_title) -> {
|
||||
DialogHelper.showDialog(
|
||||
requireContext(),
|
||||
getString(R.string.article_detail_cancel_top_dialog_title),
|
||||
getString(R.string.article_detail_cancel_top_dialog_hint),
|
||||
getString(R.string.article_detail_cancel_top_dialog_confirm),
|
||||
getString(R.string.article_detail_cancel_top_dialog_cancel),
|
||||
confirmClickCallback = {
|
||||
mViewModel.cancelTopCommunityVideo()
|
||||
|
||||
},
|
||||
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ import com.gh.gamecenter.feature.entity.Permissions
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.google.gson.JsonObject
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.HttpException
|
||||
@ -43,6 +44,7 @@ class ForumVideoDetailViewModel(
|
||||
val highlight = MutableLiveData<Boolean>()
|
||||
val cancelHighlight = MutableLiveData<Boolean>()
|
||||
val applyHighlight = MutableLiveData<Boolean>()
|
||||
val top = MutableLiveData<Boolean>()
|
||||
var currentToolbarStatus = true
|
||||
|
||||
init {
|
||||
@ -200,6 +202,49 @@ class ForumVideoDetailViewModel(
|
||||
runOnIoThread { tryCatchInRelease { HistoryDatabase.instance.videoHistoryDao().addVideo(videoHistory) } }
|
||||
}
|
||||
|
||||
fun topCommunityVideo(topCategoryId: String) {
|
||||
detailLiveData.value?.data?.let { videoDetail ->
|
||||
mApi.topCommunityVideo(
|
||||
videoDetail.id,
|
||||
mapOf(
|
||||
"title" to videoDetail.title,
|
||||
"top_category_id" to topCategoryId
|
||||
).toRequestBody()
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
getVideoDetail()
|
||||
top.postValue(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun cancelTopCommunityVideo() {
|
||||
detailLiveData.value?.data
|
||||
?.also {videoDetail ->
|
||||
videoDetail.top?.let { communityTop ->
|
||||
mApi.cancelTopCommunityVideo(
|
||||
videoDetail.id,
|
||||
mapOf(
|
||||
"video_top_id" to communityTop.id
|
||||
).toRequestBody()
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
getVideoDetail()
|
||||
top.postValue(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun isTopVideoPartlyCached(topVideoUrl: String): Boolean {
|
||||
val cache = ExoSourceManager.getCacheSingleInstance(HaloApp.getInstance().application, null)
|
||||
val key = Uri.parse(topVideoUrl).toString()
|
||||
|
||||
@ -40,7 +40,6 @@ import com.gh.gamecenter.entity.GameCollectionTagEntity;
|
||||
import com.gh.gamecenter.entity.GameColumnCollection;
|
||||
import com.gh.gamecenter.entity.GameDigestEntity;
|
||||
import com.gh.gamecenter.entity.GameGuidePopupEntity;
|
||||
import com.gh.gamecenter.entity.GameNavigationWrapper;
|
||||
import com.gh.gamecenter.entity.GameServerTestV2Entity;
|
||||
import com.gh.gamecenter.entity.GameVideoInfo;
|
||||
import com.gh.gamecenter.entity.GamesCollectionDetailEntity;
|
||||
@ -114,6 +113,7 @@ import com.gh.gamecenter.gamedetail.entity.BigEvent;
|
||||
import com.gh.gamecenter.gamedetail.entity.NewGameDetailEntity;
|
||||
import com.gh.gamecenter.login.entity.UserInfoEntity;
|
||||
import com.gh.gamecenter.personalhome.rating.MyRating;
|
||||
import com.gh.gamecenter.qa.entity.TopCommunityCategory;
|
||||
import com.gh.gamecenter.qa.entity.AnswerDetailEntity;
|
||||
import com.gh.gamecenter.qa.entity.AnswerDraftEntity;
|
||||
import com.gh.gamecenter.qa.entity.ArticleDetailEntity;
|
||||
@ -193,13 +193,6 @@ public interface ApiService {
|
||||
@GET("region_setting")
|
||||
Single<RegionSetting> getRegionSetting(@Query("channel") String channel);
|
||||
|
||||
/**
|
||||
* 统计下载量
|
||||
*/
|
||||
@Headers({"Content-Type: application/json", "Accept: application/json"})
|
||||
@POST("stat/download")
|
||||
Observable<ResponseBody> postDownload(@Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 根据包名获取游戏摘要
|
||||
*/
|
||||
@ -497,6 +490,12 @@ public interface ApiService {
|
||||
@POST("articles/comments/{comment_id}:vote")
|
||||
Observable<ResponseBody> postCommentVote(@Path("comment_id") String comment_id);
|
||||
|
||||
/**
|
||||
* 评论点赞
|
||||
*/
|
||||
@POST("articles/comments/{comment_id}:hide")
|
||||
Observable<ResponseBody> deleteComment(@Path("comment_id") String comment_id);
|
||||
|
||||
/**
|
||||
* 获取新闻评论
|
||||
*/
|
||||
@ -1348,6 +1347,56 @@ public interface ApiService {
|
||||
@POST("communities/articles/{article_id}:hide")
|
||||
Observable<ResponseBody> hideCommunityArticle(@Path("article_id") String articleId);
|
||||
|
||||
/**
|
||||
* 获取置顶帖子类型
|
||||
*/
|
||||
@GET("communities/top_category")
|
||||
Observable<List<TopCommunityCategory>> getTopCommunityCategory();
|
||||
|
||||
/**
|
||||
* 普通帖-置顶
|
||||
*/
|
||||
@POST("communities/{community_id}/articles/{article_id}:set-top")
|
||||
Observable<ResponseBody> topCommunityArticle(@Path("article_id") String articleId,
|
||||
@Path("community_id") String communityId,
|
||||
@Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 普通帖-取消置顶
|
||||
*/
|
||||
@POST("communities/{community_id}/articles/{article_id}:cancel-top")
|
||||
Observable<ResponseBody> cancelTopCommunityArticle(@Path("article_id") String articleId,
|
||||
@Path("community_id") String communityId,
|
||||
@Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 提问帖-置顶
|
||||
*/
|
||||
@POST("question/{question_id}:set-top")
|
||||
Observable<ResponseBody> topCommunityQuestion(@Path("question_id") String questionId,
|
||||
@Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 提问帖-取消置顶
|
||||
*/
|
||||
@POST("question/{question_id}:cancel-top")
|
||||
Observable<ResponseBody> cancelTopCommunityQuestion(@Path("question_id") String questionId,
|
||||
@Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 视频帖-置顶
|
||||
*/
|
||||
@POST("video/{video_id}:set-top")
|
||||
Observable<ResponseBody> topCommunityVideo(@Path("video_id") String videoId,
|
||||
@Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 视频帖-取消置顶
|
||||
*/
|
||||
@POST("video/{video_id}:cancel-top")
|
||||
Observable<ResponseBody> cancelTopCommunityVideo(@Path("video_id") String videoId,
|
||||
@Body RequestBody body);
|
||||
|
||||
|
||||
/**
|
||||
* 隐藏社区文章评论
|
||||
@ -2062,7 +2111,7 @@ public interface ApiService {
|
||||
* 获取论坛详情
|
||||
*/
|
||||
@GET("bbses/{bbs_id}")
|
||||
Observable<ForumDetailEntity> getForumDetail(@Path("bbs_id") String bbsId);
|
||||
Observable<ForumDetailEntity> getForumDetail(@Path("bbs_id") String bbsId, @Query("refresh") boolean refresh);
|
||||
|
||||
/**
|
||||
* 获取论坛板块列表
|
||||
@ -2967,7 +3016,7 @@ public interface ApiService {
|
||||
* 获取我的存档列表
|
||||
*/
|
||||
@GET("users/games/{game_id}/archives")
|
||||
Observable<List<ArchiveEntity>> getMyArchives(@Path("game_id") String gameId, @Query("page") int page);
|
||||
Observable<List<ArchiveEntity>> getMyArchives(@Path("game_id") String gameId, @Query("page") int page, @Query("sort") String sort);
|
||||
|
||||
/**
|
||||
* 创建我的存档
|
||||
@ -2985,7 +3034,7 @@ public interface ApiService {
|
||||
* 获取我的分享存档列表
|
||||
*/
|
||||
@GET("users/games/{game_id}/archives/share")
|
||||
Observable<List<ArchiveEntity>> getMyShareArchives(@Path("game_id") String gameId, @Query("page") int page);
|
||||
Observable<List<ArchiveEntity>> getMyShareArchives(@Path("game_id") String gameId, @Query("page") int page, @Query("sort") String sort);
|
||||
|
||||
/**
|
||||
* 编辑我的存档
|
||||
|
||||
@ -12,6 +12,7 @@ import com.gh.gamecenter.adapter.viewholder.GameViewHolder
|
||||
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.common.view.DrawableView
|
||||
import com.gh.gamecenter.core.utils.DisplayUtils
|
||||
import com.gh.gamecenter.core.utils.RandomUtils
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.databinding.ItemGameServerTestBigImageBinding
|
||||
@ -31,6 +32,7 @@ class GameBigImageViewHolder(val binding: ItemGameServerTestBigImageBinding) :
|
||||
) {
|
||||
holder.bindGameInfo(gameEntity, adapter, exposureEvent, entrance)
|
||||
holder.binding.gameImage.goneIf(gameEntity.topVideo != null || gameEntity.homeSetting.image.isEmpty()) {
|
||||
binding.gameImage.setTag(ImageUtils.TAG_TARGET_WIDTH, DisplayUtils.getScreenWidth() - 32F.dip2px())
|
||||
ImageUtils.display(binding.gameImage, gameEntity.homeSetting.image)
|
||||
val hierarchy = binding.gameImage.hierarchy
|
||||
try {
|
||||
@ -40,6 +42,10 @@ class GameBigImageViewHolder(val binding: ItemGameServerTestBigImageBinding) :
|
||||
}
|
||||
}
|
||||
holder.binding.autoVideoView.goneIf(gameEntity.topVideo == null) {
|
||||
binding.autoVideoView.thumbImage.setTag(
|
||||
ImageUtils.TAG_TARGET_WIDTH,
|
||||
DisplayUtils.getScreenWidth() - 32F.dip2px()
|
||||
)
|
||||
if (!holder.binding.autoVideoView.isInPlayingState) {
|
||||
GSYVideoOptionBuilder()
|
||||
.setIsTouchWiget(false)
|
||||
|
||||
@ -83,7 +83,12 @@ class VFeedbackDialogFragment : BaseDialogFragment() {
|
||||
}
|
||||
mBinding.submitTv.setOnClickListener {
|
||||
mGame?.run {
|
||||
mViewModel.postFeedback(this, mBinding.feedbackEt.text.toString(), getSelectedTagString())
|
||||
mViewModel.postFeedback(
|
||||
this,
|
||||
mBinding.feedbackEt.text.toString(),
|
||||
VHelper.getVersionName(it.context),
|
||||
getSelectedTagString()
|
||||
)
|
||||
}
|
||||
NewFlatLogUtils.logHaloFunGameExitDialogSubmitClick(
|
||||
mGame?.id ?: "",
|
||||
@ -194,12 +199,17 @@ class VFeedbackDialogFragment : BaseDialogFragment() {
|
||||
|
||||
class VFeedbackViewModel : ViewModel() {
|
||||
|
||||
fun postFeedback(game: GameEntity, message: String, tags: ArrayList<String>) {
|
||||
fun postFeedback(game: GameEntity, message: String, vSpaceVersion: String?, tags: ArrayList<String>) {
|
||||
val processedMessage = StringBuilder().apply {
|
||||
append(game.name)
|
||||
game.getApk().safelyGetInRelease(0)?.version?.run {
|
||||
append("-$this")
|
||||
}
|
||||
|
||||
vSpaceVersion?.apply {
|
||||
append("-$this")
|
||||
}
|
||||
|
||||
if (message.isNotBlank()) {
|
||||
append("-$message")
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.database.sqlite.SQLiteFullException
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
@ -58,15 +59,14 @@ import org.greenrobot.eventbus.EventBus
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
object VHelper {
|
||||
|
||||
// 畅玩游戏是否已被使用过
|
||||
private const val KEY_V_IS_USED = "v_is_used"
|
||||
private const val KEY_LAST_PLAYED_TIME = "last_played_time"
|
||||
private const val KEY_LAST_ALERT_UPDATE_URL = "last_alert_update_url"
|
||||
private const val KEY_LAST_ALERT_64_UPDATE_URL = "last_alert_64_update_url"
|
||||
private const val KEY_LAST_ALERT_32_UPDATE_URL = "last_alert_32_update_url"
|
||||
private const val KEY_TOTAL_PLAYED_TIME = "total_played_time"
|
||||
|
||||
private const val G_GMS_PACKAGE_NAME = "com.google.android.gms"
|
||||
@ -79,8 +79,12 @@ object VHelper {
|
||||
"https://dev-and-static.ghzs.com/game/apk/smooth_google/google_play_services.zip"
|
||||
const val G_APPS_DOWNLOAD_URL = "https://and-static.ghzs.com/game/apk/smooth_google/google_play_services.zip"
|
||||
|
||||
// 畅玩游戏位数
|
||||
const val KEY_BIT = "bit"
|
||||
|
||||
const val LOG_TAG = "VSPACE"
|
||||
const val DEFAULT_VSPACE_PACKAGENAME = "com.lg.vspace"
|
||||
const val VSPACE_32BIT_PACKAGENAME = "$DEFAULT_VSPACE_PACKAGENAME.addon"
|
||||
const val PLATFORM_V = "畅玩版"
|
||||
|
||||
private val mDelegateManager by lazy { VirtualAppManager.get() }
|
||||
@ -91,7 +95,8 @@ object VHelper {
|
||||
private val mVGameDao by lazy { VGameDatabase.instance.vGameDao() }
|
||||
private var mVGameSnapshotList = arrayListOf<VGameEntity>()
|
||||
|
||||
private var mUpdateEntity: AppEntity? = null
|
||||
private var m64UpdateEntity: AppEntity? = null
|
||||
private var m32UpdateEntity: AppEntity? = null
|
||||
|
||||
private var mIsInitialized = false // 是否已初始化
|
||||
private var mIsServiceConnected = false // AIDL 服务是否成功连接,不可作为 AIDL 仍然可用的依据
|
||||
@ -109,11 +114,14 @@ object VHelper {
|
||||
// 因为显示下载畅玩弹窗而处于挂起状态的游戏回调,供安装完畅玩组件后自动下载用
|
||||
private var mPendingDownloadCallback: (() -> Unit)? = null
|
||||
|
||||
// 供安装完畅玩组件判断畅玩游戏位数使用
|
||||
private var mBit = ""
|
||||
|
||||
// 批量安装的 map k: 包名, v: 文件
|
||||
private var mBatchInstallMap = hashMapOf<String, File>()
|
||||
|
||||
// 批量安装的监听
|
||||
private var mBatchInstallListener: ((isSuccess: Boolean) -> Unit)? = null
|
||||
private var mBatchInstallListener: ((isSuccess: Boolean, interrupted: Boolean) -> Unit)? = null
|
||||
|
||||
// 批量安装失败的统计
|
||||
private var mBatchInstallFailedCount = 0
|
||||
@ -123,6 +131,7 @@ object VHelper {
|
||||
|
||||
// 下次应用可见时是否需要尝试重连
|
||||
private var mShouldReConnectOnVisible = false
|
||||
|
||||
// 是否已经尝试过重连
|
||||
private var mHasAlreadyTriedReConnect = false
|
||||
|
||||
@ -140,12 +149,22 @@ object VHelper {
|
||||
private val mPackageObserver by lazy {
|
||||
PackageObserver.PackageChangeListener {
|
||||
val vaConfig = Config.getVSettingEntity()?.va ?: return@PackageChangeListener
|
||||
val isVSpace =
|
||||
it.packageName == vaConfig.arch32?.packageName || it.packageName == vaConfig.arch64?.packageName
|
||||
val isVSpace32 = it.packageName == vaConfig.arch32?.packageName
|
||||
val isVSpace64 = it.packageName == vaConfig.arch64?.packageName
|
||||
|
||||
if (!isVSpace) return@PackageChangeListener
|
||||
if (!isVSpace64 && !isVSpace32) return@PackageChangeListener
|
||||
|
||||
// 需要安装32位畅玩时跳过64位畅玩安装成功的回调
|
||||
val skip64VSpaceInstalled = mBit == "32" && isVSpace64 && !PackageUtils.isInstalledFromAllPackage(
|
||||
HaloApp.getInstance(),
|
||||
vaConfig.arch32?.packageName
|
||||
)
|
||||
|
||||
if (it.type == EBPackage.TYPE_INSTALLED) {
|
||||
SensorsBridge.trackEvent("HaloFunInstallDone", "space_schema_type", if (isVSpace32) "32位" else "64位")
|
||||
|
||||
if (skip64VSpaceInstalled) return@PackageChangeListener
|
||||
|
||||
// 帮用户启动因为没有安装畅玩组件而没法进行的下载任务
|
||||
// 因为有可能回调时还在后台,但还要弹窗什么的,所以可能会闪退?先 try catch 一下看看
|
||||
try {
|
||||
@ -155,20 +174,24 @@ object VHelper {
|
||||
}
|
||||
|
||||
mPendingDownloadCallback = null
|
||||
mBit = ""
|
||||
}
|
||||
|
||||
if (!isVIsUsed()) return@PackageChangeListener
|
||||
|
||||
if (it.type == EBPackage.TYPE_INSTALLED) {
|
||||
if (skip64VSpaceInstalled) return@PackageChangeListener
|
||||
|
||||
// 即时调用大概率调不起来,我也不知道为什么,只能延迟大法了
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
connectService()
|
||||
}, 500)
|
||||
SensorsBridge.trackEvent("HaloFunInstallDone")
|
||||
} else if (it.type == EBPackage.TYPE_UNINSTALLED) {
|
||||
// 执行卸载逻辑
|
||||
mIsServiceConnected = false
|
||||
mInstalledInfoList.clear()
|
||||
if (isVSpace64) {
|
||||
// 执行卸载逻辑
|
||||
mIsServiceConnected = false
|
||||
mInstalledInfoList.clear()
|
||||
}
|
||||
} else if (it.type == EBPackage.TYPE_REPLACED) {
|
||||
connectService()
|
||||
}
|
||||
@ -195,8 +218,15 @@ object VHelper {
|
||||
connectService(shouldCheckUpdate = true)
|
||||
}
|
||||
|
||||
// 检查畅玩助手组件更新
|
||||
getVSpaceUpdate(config.arch64)
|
||||
// 检查畅玩助手64位组件更新
|
||||
getVSpaceUpdate(config.arch64, true)
|
||||
}
|
||||
|
||||
if (config?.arch32 != null
|
||||
&& PackageUtils.isInstalledFromAllPackage(context, config.arch32.packageName)
|
||||
) {
|
||||
// 检查畅玩助手32位组件更新
|
||||
getVSpaceUpdate(config.arch32, false)
|
||||
}
|
||||
PackageObserver.registerPackageChangeChangeListener(mPackageObserver)
|
||||
}
|
||||
@ -276,6 +306,9 @@ object VHelper {
|
||||
// 已断开
|
||||
mIsServiceConnected = false
|
||||
|
||||
// 断开时清空正在安装列表
|
||||
mInstallingVaPathSet.clear()
|
||||
|
||||
if (failCode == BinderPool.CONNECT_STATE_NOT_INSTALLED) {
|
||||
Utils.log(LOG_TAG, "未安装畅玩助手")
|
||||
}
|
||||
@ -354,15 +387,19 @@ object VHelper {
|
||||
* 畅玩助手是否已安装
|
||||
*/
|
||||
fun isVSpaceInstalled(context: Context): Boolean {
|
||||
val config = Config.getVSettingEntity()?.va
|
||||
return config?.arch64 != null && PackageUtils.isInstalledFromAllPackage(context, config.arch64.packageName)
|
||||
return PackageUtils.isInstalledFromAllPackage(context, VirtualAppManager.AIDL_SERVER_PACKAGE_NAME)
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示下载畅玩空间弹窗
|
||||
*/
|
||||
fun showVspaceDialog(context: Context, gameEntity: GameEntity?) {
|
||||
VSpaceDialogFragment.showDownloadDialog(context, getVSpaceDownloadEntity(false), gameEntity)
|
||||
fun showVSpaceDialog(context: Context, gameEntity: GameEntity?) {
|
||||
VSpaceDialogFragment.showDownloadDialog(
|
||||
context,
|
||||
appEntity64 = getVSpaceDownloadEntity(true),
|
||||
appEntity32 = getVSpaceDownloadEntity(false),
|
||||
gameEntity = gameEntity
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -404,9 +441,22 @@ object VHelper {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isInstalled(packageName: String?): Boolean {
|
||||
val isInstalled = mInstalledInfoList.any { it.packageName == packageName }
|
||||
var isInstalled = mInstalledInfoList.any { it.packageName == packageName }
|
||||
|
||||
Utils.log(LOG_TAG, "$packageName 已安装列表里 -> $isInstalled")
|
||||
|
||||
// 有可能 mInstalledInfoList 获取异常,导致判断为未安装,手动调用 AIDL 再查一次
|
||||
if (!isInstalled
|
||||
&& mIsServiceConnected
|
||||
&& mDelegateManager.isConnectAidlInterface) {
|
||||
try {
|
||||
isInstalled = mDelegateManager.checkGameInstalled(packageName)
|
||||
Utils.log(LOG_TAG, "手动调用 AIDL 获取安装情况 -> $isInstalled")
|
||||
} catch (e: RuntimeException) {
|
||||
Utils.log(LOG_TAG, "手动调用 AIDL 获取安装情况异常 ${e.localizedMessage}")
|
||||
}
|
||||
}
|
||||
|
||||
return isInstalled
|
||||
}
|
||||
|
||||
@ -449,44 +499,105 @@ object VHelper {
|
||||
fun validateVSpaceBeforeAction(context: Context, gameEntity: GameEntity?, callback: () -> Unit) {
|
||||
// 仅下载类型为畅玩的类型才执行判断
|
||||
if (gameEntity == null || gameEntity.isVGame()) {
|
||||
if (showDialogIfVSpaceIsNeeded(context, gameEntity?.id ?: "", gameEntity?.name ?: "")) {
|
||||
if (showDialogIfVSpaceIsNeeded(
|
||||
context,
|
||||
gameEntity?.id ?: "",
|
||||
gameEntity?.name ?: "",
|
||||
gameEntity?.categoryChinese ?: "",
|
||||
gameEntity?.gameBit ?: ""
|
||||
)
|
||||
) {
|
||||
mBit = gameEntity?.gameBit ?: ""
|
||||
mPendingDownloadCallback = callback
|
||||
return
|
||||
}
|
||||
|
||||
val vaConfig64 = Config.getVSettingEntity()?.va?.arch64
|
||||
val installedSpaceVersionCode = PackageUtils.getVersionCodeByPackageName(vaConfig64?.packageName)
|
||||
val vaConfig32 = Config.getVSettingEntity()?.va?.arch32
|
||||
val installed64SpaceVersionCode = PackageUtils.getVersionCodeByPackageName(vaConfig64?.packageName)
|
||||
val installed32SpaceVersionCode = PackageUtils.getVersionCodeByPackageName(vaConfig32?.packageName)
|
||||
|
||||
// 检查更新
|
||||
val containsUpdate = shouldShowVSpaceUpdate(mUpdateEntity, installedSpaceVersionCode)
|
||||
val contains64Update = shouldShowVSpaceUpdate(m64UpdateEntity, installed64SpaceVersionCode)
|
||||
val contains32Update = if (gameEntity?.gameBit == "32") shouldShowVSpaceUpdate(
|
||||
m32UpdateEntity,
|
||||
installed32SpaceVersionCode
|
||||
) else false
|
||||
|
||||
if (containsUpdate) {
|
||||
val dialogType = if (mUpdateEntity!!.isAlertEveryTime()) "强制更新" else "提示更新"
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_update_dialog_show")
|
||||
SPUtils.setString(KEY_LAST_ALERT_UPDATE_URL, mUpdateEntity!!.url + mUpdateEntity!!.alert)
|
||||
var containsRelated64Update = false
|
||||
|
||||
if (contains32Update) {
|
||||
// 检查关联64位是否需要更新
|
||||
if (m32UpdateEntity?.relation != null) {
|
||||
containsRelated64Update =
|
||||
shouldShowVSpaceUpdate(m32UpdateEntity?.relation, installed64SpaceVersionCode, true)
|
||||
}
|
||||
}
|
||||
|
||||
if (contains32Update || contains64Update) {
|
||||
val gameBit = gameEntity?.gameBit
|
||||
val updateEntity = if (gameBit == "32" && contains32Update) m32UpdateEntity else m64UpdateEntity
|
||||
val dialogType = if (updateEntity!!.isAlertEveryTime()) "强制更新" else "提示更新"
|
||||
NewFlatLogUtils.logHaloFunUpdateDialogShow(
|
||||
gameEntity?.id ?: "",
|
||||
gameEntity?.name ?: "",
|
||||
if (gameBit == "32") "32位" else "64位"
|
||||
)
|
||||
SPUtils.setString(
|
||||
if (updateEntity.category == "32-bit") KEY_LAST_ALERT_32_UPDATE_URL else KEY_LAST_ALERT_64_UPDATE_URL,
|
||||
updateEntity.url + updateEntity.alert
|
||||
)
|
||||
DialogHelper.showDialog(
|
||||
context = context,
|
||||
title = "服务工具更新提示",
|
||||
content = mUpdateEntity!!.content.toString(),
|
||||
content = updateEntity.content.toString(),
|
||||
cancelText = "立即更新",
|
||||
confirmText = "继续游戏",
|
||||
cancelClickCallback = {
|
||||
NewFlatLogUtils.logHaloFunUpdateDialogClick(dialogType, "立即更新")
|
||||
val appEntity64 =
|
||||
if (gameBit == "32" && contains32Update && m32UpdateEntity?.relation != null) {
|
||||
// 32位游戏且包含32位更新和32位关联64位更新
|
||||
// 存在64位单独更新时对比32位关联的64位更新与64位单独更新推送的版本号
|
||||
if (contains64Update && (m64UpdateEntity?.versionCode
|
||||
?: 0) > (m32UpdateEntity?.relation?.versionCode ?: 0)
|
||||
) {
|
||||
// 64位单独更新版本号更高时使用64位单独更新
|
||||
m64UpdateEntity
|
||||
} else if (containsRelated64Update) {
|
||||
// 不存在64位单独更新或32位关联64位更新版本号更高
|
||||
// 对比已安装版本号和32位关联的64位更新版本号,32位关联的64位更新版本号更高时使用32位关联的64位更新
|
||||
m32UpdateEntity?.relation
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else if ((gameBit != "32" && contains64Update) || (gameBit == "32" && contains64Update && !contains32Update)) {
|
||||
// 64位游戏且包含64位单独更新 / 32位游戏无32位更新且包含64位更新
|
||||
m64UpdateEntity
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val appEntity32 = if (contains32Update) updateEntity else null
|
||||
NewFlatLogUtils.logHaloFunUpdateDialogClick(
|
||||
dialogType,
|
||||
"立即更新",
|
||||
if (appEntity64 != null && appEntity32 != null) "32位&64位" else if (appEntity64 != null) "64位" else "32位"
|
||||
)
|
||||
VSpaceDialogFragment.showDownloadDialog(
|
||||
context,
|
||||
getVSpaceDownloadEntity(true),
|
||||
appEntity64,
|
||||
appEntity32,
|
||||
gameEntity,
|
||||
autoDownload = true,
|
||||
isUpdate = true
|
||||
)
|
||||
},
|
||||
confirmClickCallback = {
|
||||
NewFlatLogUtils.logHaloFunUpdateDialogClick(dialogType, "继续游戏")
|
||||
NewFlatLogUtils.logHaloFunUpdateDialogClick(dialogType, "继续游戏", "")
|
||||
callback.invoke()
|
||||
},
|
||||
extraConfig = DialogHelper.Config(centerTitle = true),
|
||||
uiModificationCallback = {
|
||||
if (mUpdateEntity!!.isAlertEveryTime()) {
|
||||
if (updateEntity.isAlertEveryTime()) {
|
||||
it.confirmTv.visibility = View.GONE
|
||||
it.cancelTv.setTextColor(R.color.theme_font.toColor(context))
|
||||
}
|
||||
@ -553,7 +664,14 @@ object VHelper {
|
||||
) {
|
||||
Utils.log(LOG_TAG, "尝试安装新游戏 ${downloadEntity.path}")
|
||||
|
||||
if (showDialogIfVSpaceIsNeeded(context, downloadEntity.gameId, downloadEntity.name)) return
|
||||
if (showDialogIfVSpaceIsNeeded(
|
||||
context,
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.name,
|
||||
downloadEntity.getMetaExtra(Constants.GAME_TYPE),
|
||||
downloadEntity.getMetaExtra(KEY_BIT)
|
||||
)
|
||||
) return
|
||||
|
||||
// 更新此包名对应的 gameId Map
|
||||
mTempPackageNameAndGameIdMap[downloadEntity.packageName] = downloadEntity.gameId
|
||||
@ -586,7 +704,7 @@ object VHelper {
|
||||
|
||||
val path = downloadEntity.path
|
||||
// 正在安装中,忽略重复调用 (手动安装时强行再安装,避免安装结果没有回调时永远卡住,无法安装)
|
||||
if (!mInstallingVaPathSet.contains(path) || isManualInstall) {
|
||||
if (!mInstallingVaPathSet.contains(path)) {
|
||||
try {
|
||||
mInstallingVaPathSet.add(path)
|
||||
|
||||
@ -599,6 +717,8 @@ object VHelper {
|
||||
} catch (e: Exception) {
|
||||
ToastUtils.toast(e.localizedMessage ?: "")
|
||||
}
|
||||
} else {
|
||||
Utils.log(LOG_TAG, "$path 正在安装中,此次安装调用无效")
|
||||
}
|
||||
}
|
||||
|
||||
@ -629,13 +749,13 @@ object VHelper {
|
||||
/**
|
||||
* 注册批量安装结果回调,值为空时为取消注册
|
||||
*/
|
||||
fun registerBatchInstallListener(listener: ((isSuccess: Boolean) -> Unit)? = null) {
|
||||
fun registerBatchInstallListener(listener: ((isSuccess: Boolean, isInterrupted: Boolean) -> Unit)? = null) {
|
||||
mBatchInstallListener = listener
|
||||
}
|
||||
|
||||
/**
|
||||
* 安装新应用
|
||||
* 不会作为游戏存储,目前应用于谷歌框架
|
||||
* 不会作为游戏存储,目前仅应用于谷歌框架
|
||||
* 因为是静默安装,所以不检查其它限制条件
|
||||
*/
|
||||
private fun install(context: Context, file: File) {
|
||||
@ -645,12 +765,19 @@ object VHelper {
|
||||
|
||||
val installClosure: () -> Unit = {
|
||||
val path = file.path
|
||||
// 正在安装中,忽略重复调用 (手动安装时强行再安装,避免安装结果没有回调时永远卡住,无法安装)
|
||||
if (!mInstallingVaPathSet.contains(path)) {
|
||||
try {
|
||||
mInstallingVaPathSet.add(path)
|
||||
|
||||
runOnUiThread {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
|
||||
&& !PackageUtils.isAppOnForeground(context)
|
||||
) {
|
||||
mBatchInstallListener?.invoke(false, true)
|
||||
Utils.log(LOG_TAG, "应用切换至后台,批量安装被打断")
|
||||
return@runOnUiThread
|
||||
}
|
||||
|
||||
mInstallingVaPathSet.add(path)
|
||||
|
||||
val intent = VirtualAppManager.getInstallIntent(context, path, packageName)
|
||||
|
||||
Utils.log(LOG_TAG, "正在安装 $packageName")
|
||||
@ -704,6 +831,9 @@ object VHelper {
|
||||
}
|
||||
)
|
||||
insertInstalledGameToProvider(downloadEntity)
|
||||
runOnUiThread {
|
||||
showFloatingWindow(downloadEntity)
|
||||
}
|
||||
} else {
|
||||
ToastUtils.toast("安装出现异常, ${result.status}")
|
||||
}
|
||||
@ -718,7 +848,7 @@ object VHelper {
|
||||
if (result.status == 0) {
|
||||
updateInstalledList()
|
||||
} else {
|
||||
Utils.log(LOG_TAG, "安装出现异常, ${result.status}")
|
||||
ToastUtils.toast("安装出现异常, ${result.status}")
|
||||
}
|
||||
}
|
||||
|
||||
@ -750,7 +880,7 @@ object VHelper {
|
||||
if (mBatchInstallMap.size == 0) {
|
||||
runOnUiThread {
|
||||
// 批量安装完成后回调成功/失败事件
|
||||
mBatchInstallListener?.invoke(mBatchInstallFailedCount == 0)
|
||||
mBatchInstallListener?.invoke(mBatchInstallFailedCount == 0, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -808,23 +938,50 @@ object VHelper {
|
||||
fun installOrLaunch(context: Context, downloadEntity: DownloadEntity) {
|
||||
Utils.log(LOG_TAG, "检测是需要安装还是启动 ${downloadEntity.gameId}")
|
||||
|
||||
installOrLaunch(context, downloadEntity.packageName, downloadEntity.gameId)
|
||||
installOrLaunch(
|
||||
context,
|
||||
downloadEntity.packageName,
|
||||
downloadEntity.gameId,
|
||||
downloadEntity.name,
|
||||
downloadEntity.getMetaExtra(Constants.GAME_TYPE),
|
||||
downloadEntity.getMetaExtra(KEY_BIT)
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun installOrLaunch(context: Context, gameEntity: GameEntity) {
|
||||
Utils.log(LOG_TAG, "检测是需要安装还是启动 ${gameEntity.id}")
|
||||
|
||||
installOrLaunch(context, gameEntity.getUniquePackageName() ?: "", gameEntity.id)
|
||||
installOrLaunch(
|
||||
context,
|
||||
gameEntity.getUniquePackageName() ?: "",
|
||||
gameEntity.id,
|
||||
gameEntity.name ?: "",
|
||||
gameEntity.category ?: "",
|
||||
gameEntity.gameBit
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 安装或启动应用
|
||||
*/
|
||||
private fun installOrLaunch(context: Context, packageName: String, gameId: String) {
|
||||
private fun installOrLaunch(
|
||||
context: Context,
|
||||
packageName: String,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
gameType: String,
|
||||
bit: String
|
||||
) {
|
||||
Utils.log(LOG_TAG, "检测是需要安装还是启动 $packageName")
|
||||
|
||||
validateVSpaceBeforeAction(context, null) {
|
||||
validateVSpaceBeforeAction(context, GameEntity().apply {
|
||||
id = gameId
|
||||
name = gameName
|
||||
downloadStatus = "smooth"
|
||||
category = gameType
|
||||
setApk(arrayListOf(ApkEntity(packageName = packageName, bit = bit)))
|
||||
}) {
|
||||
if (isInstalled(packageName)) {
|
||||
launch(context, packageName)
|
||||
} else {
|
||||
@ -953,6 +1110,26 @@ object VHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取畅玩助手版本号
|
||||
*/
|
||||
fun getVersionName(context: Context): String? = try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
context.packageManager.getPackageInfo(
|
||||
VirtualAppManager.AIDL_SERVER_PACKAGE_NAME,
|
||||
PackageManager.PackageInfoFlags.of(0)
|
||||
)
|
||||
} else {
|
||||
context.packageManager.getPackageInfo(
|
||||
VirtualAppManager.AIDL_SERVER_PACKAGE_NAME,
|
||||
0
|
||||
)
|
||||
}.versionName
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除游戏数据
|
||||
*/
|
||||
@ -1029,16 +1206,11 @@ object VHelper {
|
||||
*/
|
||||
fun getPackageInstalledLiveData(): LiveData<String> = mPackageInstalledLiveData
|
||||
|
||||
fun showFloatingWindow(packageName: String) {
|
||||
val vDownloadList = DownloadManager.getInstance().allVDownloadTaskSnapshots
|
||||
vDownloadList.firstOrNull {
|
||||
it.packageName == packageName
|
||||
}?.let {
|
||||
val topActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
if (topActivity.isFinishing || topActivity is VSpaceLoadingActivity) return
|
||||
fun showFloatingWindow(downloadEntity: DownloadEntity) {
|
||||
val topActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
if (topActivity.isFinishing || topActivity is VSpaceLoadingActivity) return
|
||||
|
||||
VLoadCompleteWindowHelper.showFloatingWindow(topActivity, toGameEntity(it))
|
||||
}
|
||||
VLoadCompleteWindowHelper.showFloatingWindow(topActivity, toGameEntity(downloadEntity))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1046,7 +1218,13 @@ object VHelper {
|
||||
* 如果已安装或配置为空返回 true
|
||||
* 未安装的情况下会弹弹窗
|
||||
*/
|
||||
fun showDialogIfVSpaceIsNeeded(context: Context, gameId: String, gameName: String): Boolean {
|
||||
fun showDialogIfVSpaceIsNeeded(
|
||||
context: Context,
|
||||
gameId: String,
|
||||
gameName: String,
|
||||
gameType: String,
|
||||
bit: String
|
||||
): Boolean {
|
||||
Utils.log(LOG_TAG, "检测是否已安装畅玩空间")
|
||||
|
||||
val vaConfig = Config.getVSettingEntity()?.va
|
||||
@ -1057,34 +1235,50 @@ object VHelper {
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO 检测 32 位
|
||||
if (!PackageUtils.isInstalledFromAllPackage(context, vaConfig.arch64?.packageName)) {
|
||||
VSpaceDialogFragment.showDownloadDialog(
|
||||
context,
|
||||
getVSpaceDownloadEntity(false),
|
||||
gameId = gameId,
|
||||
gameName = gameName
|
||||
)
|
||||
Utils.log(LOG_TAG, "显示下载畅玩空间弹窗")
|
||||
return true
|
||||
val is64VSpaceInstalled = PackageUtils.isInstalledFromAllPackage(context, vaConfig.arch64?.packageName)
|
||||
val is32VSpaceInstalled = PackageUtils.isInstalledFromAllPackage(context, vaConfig.arch32?.packageName)
|
||||
when {
|
||||
!is64VSpaceInstalled -> {
|
||||
VSpaceDialogFragment.showDownloadDialog(
|
||||
context,
|
||||
appEntity64 = getVSpaceDownloadEntity(true),
|
||||
appEntity32 = getVSpaceDownloadEntity(false),
|
||||
autoDownload = true,
|
||||
gameId = gameId,
|
||||
gameName = gameName,
|
||||
gameType = gameType,
|
||||
bit = bit
|
||||
)
|
||||
Utils.log(LOG_TAG, "显示下载64位畅玩空间弹窗")
|
||||
return true
|
||||
}
|
||||
|
||||
bit == "32" && !is32VSpaceInstalled -> {
|
||||
VSpace32DialogFragment.showDownloadDialog(
|
||||
context,
|
||||
getVSpaceDownloadEntity(false),
|
||||
autoDownload = true,
|
||||
gameId = gameId,
|
||||
gameName = gameName
|
||||
)
|
||||
Utils.log(LOG_TAG, "显示下载32位畅玩空间弹窗")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
Utils.log(LOG_TAG, "畅玩空间已安装")
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getVSpaceDownloadEntity(forUpdate: Boolean): AppEntity {
|
||||
return if (!forUpdate) {
|
||||
val appEntity = AppEntity()
|
||||
val vaConfig64 = Config.getVSettingEntity()?.va?.arch64
|
||||
appEntity.versionCode = vaConfig64?.versionCode ?: 0
|
||||
appEntity.version = vaConfig64?.versionName
|
||||
appEntity.url = vaConfig64?.url
|
||||
private fun getVSpaceDownloadEntity(is64Bit: Boolean): AppEntity {
|
||||
val appEntity = AppEntity()
|
||||
val vaConfig =
|
||||
if (is64Bit) Config.getVSettingEntity()?.va?.arch64 else Config.getVSettingEntity()?.va?.arch32
|
||||
appEntity.versionCode = vaConfig?.versionCode ?: 0
|
||||
appEntity.version = vaConfig?.versionName
|
||||
appEntity.url = vaConfig?.url
|
||||
|
||||
appEntity
|
||||
} else {
|
||||
mUpdateEntity!!
|
||||
}
|
||||
return appEntity
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1173,7 +1367,8 @@ object VHelper {
|
||||
SensorsBridge.trackEvent(
|
||||
"HaloFunGameDownloadClick",
|
||||
"game_name", originDownloadEntity.name,
|
||||
"game_id", originDownloadEntity.gameId
|
||||
"game_id", originDownloadEntity.gameId,
|
||||
"game_schema_type", if (originDownloadEntity.getMetaExtra(KEY_BIT) == "32") "32位" else "64位"
|
||||
)
|
||||
}
|
||||
|
||||
@ -1222,7 +1417,7 @@ object VHelper {
|
||||
* 获取畅玩空间更新
|
||||
*/
|
||||
@SuppressLint("CheckResult")
|
||||
private fun getVSpaceUpdate(config: VSetting.VaArch) {
|
||||
private fun getVSpaceUpdate(config: VSetting.VaArch, is64Bit: Boolean) {
|
||||
val installedVersionName = PackageUtils.getVersionNameByPackageName(config.packageName)
|
||||
val installedVersionCode = PackageUtils.getVersionCodeByPackageName(config.packageName)
|
||||
|
||||
@ -1232,7 +1427,7 @@ object VHelper {
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<AppEntity>() {
|
||||
override fun onSuccess(data: AppEntity) {
|
||||
mUpdateEntity = data
|
||||
if (is64Bit) m64UpdateEntity = data else m32UpdateEntity = data
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1256,7 +1451,8 @@ object VHelper {
|
||||
*/
|
||||
private fun shouldShowVSpaceUpdate(
|
||||
updateEntity: AppEntity?,
|
||||
installedSpaceVersionCode: Int
|
||||
installedSpaceVersionCode: Int,
|
||||
isRelatedUpdate: Boolean = false
|
||||
): Boolean {
|
||||
if (updateEntity == null) return false
|
||||
|
||||
@ -1264,10 +1460,14 @@ object VHelper {
|
||||
|
||||
if (!hasNewerVersion) return false
|
||||
|
||||
// 关联更新忽略检查上次提示更新
|
||||
if (isRelatedUpdate) return true
|
||||
|
||||
if (updateEntity.isAlertEveryTime()) return true
|
||||
|
||||
val lastAlertUpdateUrl = updateEntity.url + updateEntity.alert
|
||||
if (updateEntity.isAlertOnceADay()
|
||||
&& SPUtils.getString(KEY_LAST_ALERT_UPDATE_URL) != (mUpdateEntity!!.url + mUpdateEntity!!.alert)
|
||||
&& SPUtils.getString(if (updateEntity.category == "32-bit") KEY_LAST_ALERT_32_UPDATE_URL else KEY_LAST_ALERT_64_UPDATE_URL) != lastAlertUpdateUrl
|
||||
) {
|
||||
return true
|
||||
}
|
||||
@ -1323,10 +1523,25 @@ object VHelper {
|
||||
|
||||
/**
|
||||
* 畅玩功能是否启用
|
||||
* 设备系统版本大于 7.1 且后台接口开启时才启用畅玩功能
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isVGameOn() = BuildConfig.DEBUG
|
||||
|| (BuildConfig.IS_VGAME_ON && Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1 && Config.isVGameEnabled())
|
||||
|| (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1 && isVGameOnByConfigSettings())
|
||||
|
||||
/**
|
||||
* 后台接口是否启用畅玩功能(若获取不到开关情况时,判断用户是否曾用过畅玩功能)
|
||||
*/
|
||||
private fun isVGameOnByConfigSettings(): Boolean {
|
||||
val configSettings = Config.getSettings()
|
||||
|
||||
// 当 settings 为空时,若曾经用过畅玩,也允许用户继续使用畅玩
|
||||
return if (configSettings == null) {
|
||||
isVIsUsed()
|
||||
} else {
|
||||
"on" == configSettings.gameSmooth
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查畅玩游戏是否满足生成存档要求
|
||||
|
||||
330
app/src/main/java/com/gh/vspace/VSpace32DialogFragment.kt
Normal file
330
app/src/main/java/com/gh/vspace/VSpace32DialogFragment.kt
Normal file
@ -0,0 +1,330 @@
|
||||
package com.gh.vspace
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.gh.common.exposure.ExposureUtils
|
||||
import com.gh.common.exposure.ExposureUtils.DownloadType.DOWNLOAD
|
||||
import com.gh.common.exposure.ExposureUtils.DownloadType.UPDATE
|
||||
import com.gh.common.util.DataCollectionUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.PackageInstaller
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDraggableDialogFragment
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.databinding.DialogVspace32Binding
|
||||
import com.gh.gamecenter.entity.AppEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadConfig
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus.*
|
||||
import com.lightgame.utils.AppManager
|
||||
import java.io.File
|
||||
|
||||
class VSpace32DialogFragment : BaseDraggableDialogFragment() {
|
||||
|
||||
private var mAppEntity: AppEntity? = null
|
||||
private var mGameId: String = ""
|
||||
private var mGameName: String = ""
|
||||
private val mDownloadUrl by lazy { mAppEntity?.url ?: "" }
|
||||
private val mBinding by lazy { DialogVspace32Binding.inflate(layoutInflater) }
|
||||
private var mIsLogInstallShow = false
|
||||
private var mIsLogAutoInstallClick = false
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
if (downloadEntity.url == mDownloadUrl && isAdded) {
|
||||
updateDownloadButton(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDataInit(downloadEntity: DownloadEntity) {
|
||||
onDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRootView(): View = mBinding.root
|
||||
override fun getDragCloseView(): View = mBinding.dragClose
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mAppEntity = arguments?.get(KEY_APP_ENTITY_32) as AppEntity
|
||||
mGameId = arguments?.getString(EntranceConsts.KEY_GAME_ID) ?: ""
|
||||
mGameName = arguments?.getString(EntranceConsts.KEY_GAME_NAME) ?: ""
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
return mBinding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val mViewModel = viewModelProvider<VSpaceDialogFragment.VSpaceDialogViewModel>()
|
||||
mViewModel.packageLiveData.observe(this) {
|
||||
if (it.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
val downloadSnapshot = DownloadManager.getInstance()
|
||||
.getDownloadEntitySnapshotByPackageName(VHelper.VSPACE_32BIT_PACKAGENAME)
|
||||
mBinding.downloadBtn.text = if (downloadSnapshot?.status == done) "安装" else "下载"
|
||||
mBinding.downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
mBinding.descTv.text = "《$mGameName》需安装完整的畅玩服务组件,安装后即可给您带来急速的畅玩体验~"
|
||||
mBinding.privacyPolicyTv.setOnClickListener {
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_privacy_click")
|
||||
DirectUtils.directToWebView(requireContext(), Constants.SMOOTH_GAME_PRIVACY_POLICY_ADDRESS)
|
||||
}
|
||||
|
||||
if (downloadSnapshot?.status == done) {
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_show")
|
||||
SensorsBridge.trackEvent("HaloFunExpandInstallDialogShow")
|
||||
mIsLogInstallShow = true
|
||||
} else {
|
||||
NewFlatLogUtils.logHaloFun32DialogEvent("halo_fun_32_download_tip_dialog_show", mGameId, mGameName)
|
||||
SensorsBridge.trackEvent("HaloFunExpandDownloadDialogShow", "game_id", mGameId, "game_name", mGameName)
|
||||
}
|
||||
|
||||
mBinding.downloadBtn.setOnClickListener {
|
||||
if (downloadSnapshot?.status == done) {
|
||||
if (!File(downloadSnapshot.path).exists()) {
|
||||
ToastUtils.toast("畅玩组件已损坏,即将重新下载")
|
||||
DownloadManager.getInstance().cancel(downloadSnapshot.url)
|
||||
DownloadManager.getInstance().add(downloadSnapshot)
|
||||
} else {
|
||||
PackageInstaller.install(requireContext(), downloadSnapshot)
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_click")
|
||||
SensorsBridge.trackEvent("HaloFunExpandInstallButtonClick")
|
||||
}
|
||||
} else {
|
||||
val downloadEntity = DownloadEntity()
|
||||
|
||||
val name = "畅玩助手V" + mAppEntity?.version + "(32位)"
|
||||
val downloadId = PackageInstaller.createDownloadId(name)
|
||||
|
||||
downloadEntity.url = mDownloadUrl
|
||||
downloadEntity.name = name
|
||||
downloadEntity.platform = "官方版"
|
||||
downloadEntity.gameId = "62bd412bbbf04747cd3de539"
|
||||
downloadEntity.path = PackageInstaller.getDownloadPathWithId(downloadId, "apk")
|
||||
downloadEntity.packageName = VHelper.VSPACE_32BIT_PACKAGENAME
|
||||
downloadEntity.addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200")
|
||||
|
||||
val gameEntity = GameEntity(downloadEntity.gameId, downloadEntity.name)
|
||||
gameEntity.gameVersion = mAppEntity?.version ?: ""
|
||||
|
||||
// 确定下载类型
|
||||
val downloadType =
|
||||
if (arguments?.getBoolean(VSpaceDialogFragment.KEY_IS_UPDATE) == true) UPDATE else DOWNLOAD
|
||||
|
||||
downloadEntity.exposureTrace = ExposureUtils.logADownloadExposureEvent(
|
||||
gameEntity,
|
||||
downloadEntity.platform,
|
||||
null,
|
||||
downloadType
|
||||
).toJson()
|
||||
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
DownloadManager.getInstance().cancel(mDownloadUrl)
|
||||
DownloadManager.getInstance().add(downloadEntity)
|
||||
}, 200)
|
||||
|
||||
DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity, "开始")
|
||||
NewFlatLogUtils.logHaloFun32DialogEvent("halo_fun_32_download_tip_dialog_click", mGameId, mGameName)
|
||||
SensorsBridge.trackEvent("HaloFunExpandDownloadDialogDownloadClick")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
|
||||
// 上面监听安装包名变化的 LiveData 监听有可能被冲掉了
|
||||
// 手动再检查一下安装状态,避免出现已安装但是没有 dismiss 弹窗的问题
|
||||
if (PackageUtils.isInstalled(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
DownloadManager.getInstance().removeObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
private fun updateDownloadButton(downloadEntity: DownloadEntity) {
|
||||
val downloadBtn = mBinding.downloadBtn
|
||||
downloadBtn.progress = (downloadEntity.progress * 10).toInt()
|
||||
when (downloadEntity.status) {
|
||||
downloading -> {
|
||||
downloadBtn.setText(R.string.pause)
|
||||
downloadBtn.progress = (downloadEntity.percent * 10).toInt()
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
|
||||
downloadBtn.setOnClickListener {
|
||||
DownloadManager.getInstance().pause(mDownloadUrl)
|
||||
}
|
||||
}
|
||||
|
||||
pause -> {
|
||||
downloadBtn.setText(R.string.resume)
|
||||
downloadBtn.setOnClickListener {
|
||||
DownloadManager.getInstance().resume(downloadEntity, true)
|
||||
}
|
||||
}
|
||||
|
||||
overflow,
|
||||
timeout,
|
||||
neterror,
|
||||
diskisfull,
|
||||
waiting,
|
||||
subscribe -> {
|
||||
downloadBtn.setText(R.string.waiting)
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
|
||||
downloadBtn.setOnClickListener {
|
||||
DownloadManager.getInstance().resume(downloadEntity, false)
|
||||
}
|
||||
}
|
||||
|
||||
done -> {
|
||||
downloadBtn.setText(R.string.install)
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
|
||||
if (!mIsLogInstallShow) {
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_show")
|
||||
SensorsBridge.trackEvent("HaloFunExpandInstallDialogShow")
|
||||
mIsLogInstallShow = true
|
||||
}
|
||||
|
||||
val isVSpace32DownloadOnly =
|
||||
downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) == Constants.VSPACE_32_DOWNLOAD_ONLY
|
||||
val isAutoInstall = SPUtils.getBoolean(Constants.SP_AUTO_INSTALL, true)
|
||||
if (!isVSpace32DownloadOnly && isAutoInstall && !mIsLogAutoInstallClick) {
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_click")
|
||||
SensorsBridge.trackEvent("HaloFunExpandInstallButtonClick")
|
||||
mIsLogAutoInstallClick = true
|
||||
}
|
||||
|
||||
downloadBtn.setOnClickListener {
|
||||
if (!File(downloadEntity.path).exists()) {
|
||||
ToastUtils.toast("畅玩组件已损坏,即将重新下载")
|
||||
DownloadManager.getInstance().cancel(downloadEntity.url)
|
||||
DownloadManager.getInstance().add(downloadEntity)
|
||||
} else {
|
||||
PackageInstaller.install(requireContext(), downloadEntity)
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_32_install_tip_dialog_click")
|
||||
SensorsBridge.trackEvent("HaloFunExpandInstallButtonClick")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancel,
|
||||
hijack,
|
||||
notfound,
|
||||
uncertificated,
|
||||
unqualified -> {
|
||||
downloadBtn.text = "下载"
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
downloadBtn.setOnClickListener {
|
||||
DownloadManager.getInstance().resume(downloadEntity, true)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_APP_ENTITY_32 = "app_entity_32"
|
||||
const val KEY_AUTO_DOWNLOAD = "auto_download"
|
||||
const val KEY_IS_UPDATE = "is_update"
|
||||
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(
|
||||
context: Context?,
|
||||
appEntity32: AppEntity,
|
||||
autoDownload: Boolean = false,
|
||||
isUpdate: Boolean = false,
|
||||
gameId: String = "",
|
||||
gameName: String = ""
|
||||
) {
|
||||
val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
|
||||
context
|
||||
} else {
|
||||
val currentActivity = AppManager.getInstance().currentActivity()
|
||||
if (currentActivity is FragmentActivity) {
|
||||
currentActivity
|
||||
} else {
|
||||
throw IllegalStateException("current activity context must be FragmentActivity")
|
||||
}
|
||||
}
|
||||
|
||||
// 防止重复弹出
|
||||
if (hasDialogDisplayedInCurrentActivity(fragmentActivity)) return
|
||||
|
||||
val downloadDialog = VSpace32DialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putParcelable(KEY_APP_ENTITY_32, appEntity32)
|
||||
putString(EntranceConsts.KEY_GAME_ID, gameId)
|
||||
putString(EntranceConsts.KEY_GAME_NAME, gameName)
|
||||
putBoolean(KEY_AUTO_DOWNLOAD, autoDownload)
|
||||
putBoolean(KEY_IS_UPDATE, isUpdate)
|
||||
}
|
||||
}
|
||||
downloadDialog.show(
|
||||
fragmentActivity.supportFragmentManager,
|
||||
VSpace32DialogFragment::class.java.name
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(
|
||||
context: Context?,
|
||||
appEntity32: AppEntity,
|
||||
gameEntity: GameEntity?,
|
||||
autoDownload: Boolean = false,
|
||||
isUpdate: Boolean = false
|
||||
) {
|
||||
showDownloadDialog(
|
||||
context,
|
||||
appEntity32,
|
||||
autoDownload,
|
||||
isUpdate,
|
||||
gameEntity?.id ?: "",
|
||||
gameEntity?.name ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
private fun hasDialogDisplayedInCurrentActivity(fragmentActivity: FragmentActivity): Boolean {
|
||||
val fragments: List<Fragment> = fragmentActivity.supportFragmentManager.fragments
|
||||
fragments.forEach { fragment ->
|
||||
if (fragment is VSpace32DialogFragment) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,12 +13,8 @@ import androidx.lifecycle.ViewModel
|
||||
import com.gh.common.exposure.ExposureUtils
|
||||
import com.gh.common.exposure.ExposureUtils.DownloadType.DOWNLOAD
|
||||
import com.gh.common.exposure.ExposureUtils.DownloadType.UPDATE
|
||||
import com.gh.common.util.DataCollectionUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.PackageInstaller
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.download.PackageObserver
|
||||
import com.gh.gamecenter.R
|
||||
@ -28,27 +24,37 @@ import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.databinding.DialogVspaceBinding
|
||||
import com.gh.gamecenter.entity.AppEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.eventbus.EBPackage
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadConfig
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus.*
|
||||
import com.lightgame.utils.AppManager
|
||||
import java.io.File
|
||||
|
||||
class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
|
||||
private var mAppEntity: AppEntity? = null
|
||||
private var mAppEntity64: AppEntity? = null
|
||||
private var mAppEntity32: AppEntity? = null
|
||||
private var mGameId: String = ""
|
||||
private var mGameName: String = ""
|
||||
private val mDownloadUrl by lazy { mAppEntity?.url ?: "" }
|
||||
private var mBit: String = "" // 畅玩游戏位数
|
||||
private var mIsUpdate = false
|
||||
private val mDownloadUrl64 by lazy { mAppEntity64?.url ?: "" }
|
||||
private val mDownloadUrl32 by lazy { mAppEntity32?.url ?: "" }
|
||||
private val mBinding by lazy { DialogVspaceBinding.inflate(layoutInflater) }
|
||||
private var mIsLogInstallShow = false
|
||||
private var mIsLogAutoInstallClick = false
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
if (downloadEntity.url == mDownloadUrl && isAdded) {
|
||||
if (((mAppEntity64 != null && downloadEntity.url == mDownloadUrl64) || (mAppEntity64 == null && downloadEntity.url == mDownloadUrl32)) && isAdded) {
|
||||
updateDownloadButton(downloadEntity)
|
||||
}
|
||||
}
|
||||
@ -64,9 +70,12 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mAppEntity = arguments?.get(KEY_ENTITY) as AppEntity
|
||||
mAppEntity64 = arguments?.get(KEY_APP_ENTITY_64) as? AppEntity
|
||||
mAppEntity32 = arguments?.get(KEY_APP_ENTITY_32) as? AppEntity
|
||||
mGameId = arguments?.getString(EntranceConsts.KEY_GAME_ID) ?: ""
|
||||
mGameName = arguments?.getString(EntranceConsts.KEY_GAME_NAME) ?: ""
|
||||
mBit = arguments?.getString(VHelper.KEY_BIT) ?: ""
|
||||
mIsUpdate = arguments?.getBoolean(KEY_IS_UPDATE) == true
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@ -84,59 +93,95 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
val mViewModel = viewModelProvider<VSpaceDialogViewModel>()
|
||||
mViewModel.packageLiveData.observe(this) {
|
||||
if (it.packageName == VHelper.DEFAULT_VSPACE_PACKAGENAME) {
|
||||
if (mIsUpdate) showVSpace32UpdateDialogIfNeeded() else showVSpace32DownloadDialogIfNeeded()
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
if (it.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
mBinding.downloadBtn.text = "下载畅玩助手服务组件"
|
||||
mBinding.downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
mBinding.descTv.text = "检测到您未安装畅玩64位组件,\n点击下载即可体验急速畅玩~"
|
||||
mBinding.descTv.text = "《$mGameName》需先安装畅玩服务组件,安装后即可进入游戏体验新鲜功能~"
|
||||
mBinding.privacyPolicyTv.setOnClickListener {
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_privacy_click")
|
||||
DirectUtils.directToWebView(requireContext(), Constants.SMOOTH_GAME_PRIVACY_POLICY_ADDRESS)
|
||||
}
|
||||
|
||||
val downloadSnapshot = DownloadManager.getInstance()
|
||||
.getDownloadEntitySnapshotByPackageName(VHelper.DEFAULT_VSPACE_PACKAGENAME)
|
||||
.getDownloadEntitySnapshotByPackageName(if (mAppEntity64 != null) VHelper.DEFAULT_VSPACE_PACKAGENAME else VHelper.VSPACE_32BIT_PACKAGENAME)
|
||||
|
||||
mBinding.downloadBtn.setOnClickListener {
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_download_click")
|
||||
SensorsBridge.trackEvent("HaloFunDownloadDialogDownloadClick", "game_id", mGameId, "game_name", mGameName)
|
||||
|
||||
val name = "畅玩助手V" + mAppEntity?.version
|
||||
val downloadId = PackageInstaller.createDownloadId(name)
|
||||
|
||||
val downloadEntity = DownloadEntity()
|
||||
downloadEntity.url = mDownloadUrl
|
||||
downloadEntity.name = name
|
||||
downloadEntity.platform = "官方版"
|
||||
downloadEntity.gameId = "62bd412bbbf04747cd3de539"
|
||||
downloadEntity.path = PackageInstaller.getDownloadPathWithId(downloadId, "apk")
|
||||
downloadEntity.packageName = VHelper.DEFAULT_VSPACE_PACKAGENAME
|
||||
downloadEntity.addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200")
|
||||
|
||||
// 确定下载类型
|
||||
val downloadType =
|
||||
if (arguments?.getBoolean(KEY_IS_UPDATE) == true) UPDATE else DOWNLOAD
|
||||
val gameEntity = GameEntity(downloadEntity.gameId, downloadEntity.name)
|
||||
gameEntity.gameVersion = mAppEntity?.version ?: ""
|
||||
val downloadType = if (mIsUpdate) UPDATE else DOWNLOAD
|
||||
var downloadEntity64: DownloadEntity? = null
|
||||
var downloadEntity32: DownloadEntity? = null
|
||||
|
||||
val event = ExposureUtils.logADownloadExposureEvent(
|
||||
gameEntity,
|
||||
downloadEntity.platform,
|
||||
null,
|
||||
downloadType
|
||||
)
|
||||
if (mAppEntity64 != null) {
|
||||
downloadEntity64 = getDownloadEntity(true)
|
||||
|
||||
downloadEntity.exposureTrace = event.toJson()
|
||||
val gameEntity64 = GameEntity(downloadEntity64.gameId, downloadEntity64.name)
|
||||
gameEntity64.gameVersion = mAppEntity64?.version ?: ""
|
||||
|
||||
downloadEntity64.exposureTrace = ExposureUtils.logADownloadExposureEvent(
|
||||
gameEntity64,
|
||||
downloadEntity64.platform,
|
||||
null,
|
||||
downloadType
|
||||
).toJson()
|
||||
|
||||
// 收集下载数据
|
||||
DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity64, "开始")
|
||||
}
|
||||
|
||||
val is32VSpaceInstalled = PackageUtils.isInstalledFromAllPackage(context, VHelper.VSPACE_32BIT_PACKAGENAME)
|
||||
if (mBit == "32" && mAppEntity32 != null && !(is32VSpaceInstalled && !mIsUpdate)) {
|
||||
downloadEntity32 = getDownloadEntity(false)
|
||||
|
||||
// 非32位单独下载时下载完成不弹出安装界面
|
||||
if (mAppEntity64 != null) {
|
||||
downloadEntity32.addMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE, Constants.VSPACE_32_DOWNLOAD_ONLY)
|
||||
}
|
||||
|
||||
val gameEntity32 = GameEntity(downloadEntity32.gameId, downloadEntity32.name)
|
||||
gameEntity32.gameVersion = mAppEntity32?.version ?: ""
|
||||
|
||||
downloadEntity32.exposureTrace = ExposureUtils.logADownloadExposureEvent(
|
||||
gameEntity32,
|
||||
downloadEntity32.platform,
|
||||
null,
|
||||
downloadType
|
||||
).toJson()
|
||||
|
||||
DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity32, "开始")
|
||||
}
|
||||
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
DownloadManager.getInstance().cancel(mDownloadUrl)
|
||||
DownloadManager.getInstance().add(downloadEntity)
|
||||
if (downloadEntity64 != null) {
|
||||
DownloadManager.getInstance().cancel(mDownloadUrl64)
|
||||
DownloadManager.getInstance().add(downloadEntity64)
|
||||
}
|
||||
if (downloadEntity32 != null) {
|
||||
DownloadManager.getInstance().cancel(mDownloadUrl32)
|
||||
DownloadManager.getInstance().add(downloadEntity32)
|
||||
}
|
||||
}, 200)
|
||||
|
||||
// 收集下载数据
|
||||
DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity, "开始")
|
||||
val architecture =
|
||||
if (downloadEntity64 != null && downloadEntity32 != null) "32位&64位" else if (downloadEntity64 != null) "64位" else "32位"
|
||||
NewFlatLogUtils.logHaloFunDownloadDialogDownloadClick(architecture)
|
||||
SensorsBridge.trackEvent(
|
||||
"HaloFunDownloadDialogDownloadClick",
|
||||
"game_id",
|
||||
mGameId,
|
||||
"game_name",
|
||||
mGameName,
|
||||
"space_schema_type",
|
||||
architecture,
|
||||
"game_schema_type",
|
||||
if (mBit == "32") "32位" else "64位"
|
||||
)
|
||||
}
|
||||
|
||||
if (arguments?.getBoolean(KEY_AUTO_DOWNLOAD) == true && downloadSnapshot == null) {
|
||||
@ -144,6 +189,17 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDownloadEntity(is64Bit: Boolean) = DownloadEntity().apply {
|
||||
url = if (is64Bit) mDownloadUrl64 else mDownloadUrl32
|
||||
name =
|
||||
"畅玩助手V" + (if (is64Bit) mAppEntity64?.version else mAppEntity32?.version) + "(${if (is64Bit) 64 else 32}位)"
|
||||
platform = "官方版"
|
||||
gameId = "62bd412bbbf04747cd3de539"
|
||||
path = PackageInstaller.getDownloadPathWithId(PackageInstaller.createDownloadId(name), "apk")
|
||||
packageName = if (is64Bit) VHelper.DEFAULT_VSPACE_PACKAGENAME else VHelper.VSPACE_32BIT_PACKAGENAME
|
||||
addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200")
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
@ -151,8 +207,36 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
// 上面监听安装包名变化的 LiveData 监听有可能被冲掉了
|
||||
// 手动再检查一下安装状态,避免出现已安装但是没有 dismiss 弹窗的问题
|
||||
if (PackageUtils.isInstalled(requireContext(), VHelper.DEFAULT_VSPACE_PACKAGENAME)) {
|
||||
if (mIsUpdate) showVSpace32UpdateDialogIfNeeded() else showVSpace32DownloadDialogIfNeeded()
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
if (PackageUtils.isInstalled(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showVSpace32DownloadDialogIfNeeded() {
|
||||
val is32VSpaceInstalled =
|
||||
PackageUtils.isInstalledFromAllPackage(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)
|
||||
if (!is32VSpaceInstalled && mBit == "32" && mAppEntity32 != null && !mAppEntity32?.url.isNullOrEmpty()) {
|
||||
VSpace32DialogFragment.showDownloadDialog(
|
||||
requireContext(),
|
||||
mAppEntity32!!,
|
||||
gameId = mGameId,
|
||||
gameName = mGameName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showVSpace32UpdateDialogIfNeeded() {
|
||||
if (mBit == "32" && mAppEntity32 != null && !mAppEntity32?.url.isNullOrEmpty()) {
|
||||
VSpaceUpdate32DialogFragment.showDownloadDialog(
|
||||
requireContext(),
|
||||
mAppEntity32!!,
|
||||
gameId = mGameId,
|
||||
gameName = mGameName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
@ -169,7 +253,7 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
downloadBtn.progress = (downloadEntity.percent * 10).toInt()
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
|
||||
downloadBtn.setOnClickListener {
|
||||
DownloadManager.getInstance().pause(mDownloadUrl)
|
||||
DownloadManager.getInstance().pause(downloadEntity.url)
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,9 +281,27 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
downloadBtn.setText(R.string.install)
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
|
||||
val vSpaceType = if (downloadEntity.url == mDownloadUrl64) "64位" else "32位"
|
||||
if (!mIsLogInstallShow) {
|
||||
NewFlatLogUtils.logHaloFunInstallTipDialogShow(vSpaceType)
|
||||
SensorsBridge.trackEvent("HaloFunInstallDialogShow", "space_schema_type", vSpaceType)
|
||||
mIsLogInstallShow = true
|
||||
}
|
||||
|
||||
if (SPUtils.getBoolean(Constants.SP_AUTO_INSTALL, true) && !mIsLogAutoInstallClick) {
|
||||
SensorsBridge.trackEvent("HaloFunInstallButtonClick", "space_schema_type", vSpaceType)
|
||||
mIsLogAutoInstallClick = true
|
||||
}
|
||||
|
||||
downloadBtn.setOnClickListener {
|
||||
PackageInstaller.install(requireContext(), downloadEntity)
|
||||
SensorsBridge.trackEvent("HaloFunInstallButtonClick")
|
||||
if (!File(downloadEntity.path).exists()) {
|
||||
ToastUtils.toast("畅玩组件已损坏,即将重新下载")
|
||||
DownloadManager.getInstance().cancel(downloadEntity.url)
|
||||
DownloadManager.getInstance().add(downloadEntity)
|
||||
} else {
|
||||
PackageInstaller.install(requireContext(), downloadEntity)
|
||||
SensorsBridge.trackEvent("HaloFunInstallButtonClick", "space_schema_type", vSpaceType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,18 +323,22 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_ENTITY = "entity"
|
||||
const val KEY_APP_ENTITY_64 = "app_entity_64"
|
||||
const val KEY_APP_ENTITY_32 = "app_entity_32"
|
||||
const val KEY_AUTO_DOWNLOAD = "auto_download"
|
||||
const val KEY_IS_UPDATE = "is_update"
|
||||
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(
|
||||
context: Context?,
|
||||
appEntity: AppEntity,
|
||||
appEntity64: AppEntity?,
|
||||
appEntity32: AppEntity?,
|
||||
autoDownload: Boolean = false,
|
||||
isUpdate: Boolean = false,
|
||||
gameId: String = "",
|
||||
gameName: String = ""
|
||||
gameName: String = "",
|
||||
gameType: String = "",
|
||||
bit: String = ""
|
||||
) {
|
||||
val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
|
||||
context
|
||||
@ -248,11 +354,16 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
// 防止重复弹出
|
||||
if (hasDialogDisplayedInCurrentActivity(fragmentActivity)) return
|
||||
|
||||
NewFlatLogUtils.logHaloFunEvent("halo_fun_download_dialog_show")
|
||||
NewFlatLogUtils.logHaloFunDownloadDialogShow(gameId, gameName, if (bit == "32") "32位" else "64位")
|
||||
|
||||
if (context is BaseActivity) {
|
||||
SensorsBridge.trackEvent(
|
||||
"HaloFunDownloadDialogShow",
|
||||
"game_id", gameId,
|
||||
"game_name", gameName,
|
||||
"game_type", gameType,
|
||||
"game_schema_type", if (bit == "32") "32位" else "64位",
|
||||
"last_page_name", context::class.java.simpleName,
|
||||
"last_page_name", context::class.java.simpleName,
|
||||
"last_page_id", context.getUniqueId(),
|
||||
"last_page_business_id", context.getBusinessId().first,
|
||||
@ -262,9 +373,11 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
|
||||
val downloadDialog = VSpaceDialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putParcelable(KEY_ENTITY, appEntity)
|
||||
if (appEntity64 != null) putParcelable(KEY_APP_ENTITY_64, appEntity64)
|
||||
if (appEntity32 != null) putParcelable(KEY_APP_ENTITY_32, appEntity32)
|
||||
putString(EntranceConsts.KEY_GAME_ID, gameId)
|
||||
putString(EntranceConsts.KEY_GAME_NAME, gameName)
|
||||
putString(VHelper.KEY_BIT, bit)
|
||||
putBoolean(KEY_AUTO_DOWNLOAD, autoDownload)
|
||||
putBoolean(KEY_IS_UPDATE, isUpdate)
|
||||
}
|
||||
@ -278,12 +391,23 @@ class VSpaceDialogFragment : BaseDraggableDialogFragment() {
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(
|
||||
context: Context?,
|
||||
appEntity: AppEntity,
|
||||
appEntity64: AppEntity?,
|
||||
appEntity32: AppEntity?,
|
||||
gameEntity: GameEntity?,
|
||||
autoDownload: Boolean = false,
|
||||
isUpdate: Boolean = false
|
||||
) {
|
||||
showDownloadDialog(context, appEntity, autoDownload, isUpdate, gameEntity?.id ?: "", gameEntity?.name ?: "")
|
||||
showDownloadDialog(
|
||||
context,
|
||||
appEntity64,
|
||||
appEntity32,
|
||||
autoDownload,
|
||||
isUpdate,
|
||||
gameEntity?.id ?: "",
|
||||
gameEntity?.name ?: "",
|
||||
gameEntity?.categoryChinese ?: "",
|
||||
gameEntity?.gameBit ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
private fun hasDialogDisplayedInCurrentActivity(fragmentActivity: FragmentActivity): Boolean {
|
||||
|
||||
300
app/src/main/java/com/gh/vspace/VSpaceUpdate32DialogFragment.kt
Normal file
300
app/src/main/java/com/gh/vspace/VSpaceUpdate32DialogFragment.kt
Normal file
@ -0,0 +1,300 @@
|
||||
package com.gh.vspace
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.gh.common.exposure.ExposureUtils
|
||||
import com.gh.common.exposure.ExposureUtils.DownloadType.DOWNLOAD
|
||||
import com.gh.common.exposure.ExposureUtils.DownloadType.UPDATE
|
||||
import com.gh.common.util.DataCollectionUtils
|
||||
import com.gh.common.util.NewFlatLogUtils
|
||||
import com.gh.common.util.PackageInstaller
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.gamecenter.feature.view.DownloadButton
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
|
||||
import com.gh.gamecenter.common.constant.EntranceConsts
|
||||
import com.gh.gamecenter.common.utils.*
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.databinding.DialogVspaceUpdate32Binding
|
||||
import com.gh.gamecenter.entity.AppEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadConfig
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus.*
|
||||
import com.lightgame.utils.AppManager
|
||||
import java.io.File
|
||||
|
||||
class VSpaceUpdate32DialogFragment : BaseDialogFragment() {
|
||||
|
||||
private var mAppEntity: AppEntity? = null
|
||||
private var mGameId: String = ""
|
||||
private var mGameName: String = ""
|
||||
private val mDownloadUrl by lazy { mAppEntity?.url ?: "" }
|
||||
private val mBinding by lazy { DialogVspaceUpdate32Binding.inflate(layoutInflater) }
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
if (downloadEntity.url == mDownloadUrl && isAdded) {
|
||||
updateDownloadButton(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDataInit(downloadEntity: DownloadEntity) {
|
||||
onDataChanged(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mAppEntity = arguments?.get(KEY_APP_ENTITY_32) as AppEntity
|
||||
mGameId = arguments?.getString(EntranceConsts.KEY_GAME_ID) ?: ""
|
||||
mGameName = arguments?.getString(EntranceConsts.KEY_GAME_NAME) ?: ""
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
return mBinding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val mViewModel = viewModelProvider<VSpaceDialogFragment.VSpaceDialogViewModel>()
|
||||
mViewModel.packageLiveData.observe(this) {
|
||||
if (it.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
val downloadSnapshot = DownloadManager.getInstance()
|
||||
.getDownloadEntitySnapshotByPackageName(VHelper.VSPACE_32BIT_PACKAGENAME)
|
||||
mBinding.downloadBtn.text = if (downloadSnapshot?.status == done) "安装" else "下载"
|
||||
mBinding.downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
mBinding.contentTv.text = "《$mGameName》需安装完整的畅玩服务组件,安装后即可给您带来急速的畅玩体验~"
|
||||
|
||||
mBinding.downloadBtn.setOnClickListener {
|
||||
NewFlatLogUtils.logHaloFun32DialogEvent("halo_fun_32_update_tip_dialog_click", mGameId, mGameName)
|
||||
if (downloadSnapshot?.status == done) {
|
||||
if (!File(downloadSnapshot.path).exists()) {
|
||||
ToastUtils.toast("畅玩组件已损坏,即将重新下载")
|
||||
DownloadManager.getInstance().cancel(downloadSnapshot.url)
|
||||
DownloadManager.getInstance().add(downloadSnapshot)
|
||||
} else {
|
||||
PackageInstaller.install(requireContext(), downloadSnapshot)
|
||||
}
|
||||
} else {
|
||||
val downloadEntity = DownloadEntity()
|
||||
|
||||
val name = "畅玩助手V" + mAppEntity?.version + "(32位)"
|
||||
val downloadId = PackageInstaller.createDownloadId(name)
|
||||
|
||||
downloadEntity.url = mDownloadUrl
|
||||
downloadEntity.name = name
|
||||
downloadEntity.platform = "官方版"
|
||||
downloadEntity.gameId = "62bd412bbbf04747cd3de539"
|
||||
downloadEntity.path = PackageInstaller.getDownloadPathWithId(downloadId, "apk")
|
||||
downloadEntity.packageName = VHelper.VSPACE_32BIT_PACKAGENAME
|
||||
downloadEntity.addMetaExtra(DownloadConfig.KEY_PROGRESS_CALLBACK_INTERVAL, "200")
|
||||
|
||||
val gameEntity = GameEntity(downloadEntity.gameId, downloadEntity.name)
|
||||
gameEntity.gameVersion = mAppEntity?.version ?: ""
|
||||
|
||||
// 确定下载类型
|
||||
val downloadType =
|
||||
if (arguments?.getBoolean(VSpaceDialogFragment.KEY_IS_UPDATE) == true) UPDATE else DOWNLOAD
|
||||
|
||||
downloadEntity.exposureTrace = ExposureUtils.logADownloadExposureEvent(
|
||||
gameEntity,
|
||||
downloadEntity.platform,
|
||||
null,
|
||||
downloadType
|
||||
).toJson()
|
||||
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
DownloadManager.getInstance().cancel(mDownloadUrl)
|
||||
DownloadManager.getInstance().add(downloadEntity)
|
||||
}, 200)
|
||||
|
||||
DataCollectionUtils.uploadDownload(HaloApp.getInstance(), downloadEntity, "开始")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
DownloadManager.getInstance().addObserver(mDataWatcher)
|
||||
|
||||
// 上面监听安装包名变化的 LiveData 监听有可能被冲掉了
|
||||
// 手动再检查一下安装状态,避免出现已安装但是没有 dismiss 弹窗的问题
|
||||
if (PackageUtils.isInstalled(requireContext(), VHelper.VSPACE_32BIT_PACKAGENAME)) {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
DownloadManager.getInstance().removeObserver(mDataWatcher)
|
||||
}
|
||||
|
||||
private fun updateDownloadButton(downloadEntity: DownloadEntity) {
|
||||
val downloadBtn = mBinding.downloadBtn
|
||||
downloadBtn.progress = (downloadEntity.progress * 10).toInt()
|
||||
when (downloadEntity.status) {
|
||||
downloading -> {
|
||||
downloadBtn.setText(R.string.pause)
|
||||
downloadBtn.progress = (downloadEntity.percent * 10).toInt()
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
|
||||
downloadBtn.setOnClickListener {
|
||||
DownloadManager.getInstance().pause(mDownloadUrl)
|
||||
NewFlatLogUtils.logHaloFun32DialogEvent("halo_fun_32_update_tip_dialog_click", mGameId, mGameName)
|
||||
}
|
||||
}
|
||||
|
||||
pause -> {
|
||||
downloadBtn.setText(R.string.resume)
|
||||
downloadBtn.setOnClickListener {
|
||||
DownloadManager.getInstance().resume(downloadEntity, true)
|
||||
NewFlatLogUtils.logHaloFun32DialogEvent("halo_fun_32_update_tip_dialog_click", mGameId, mGameName)
|
||||
}
|
||||
}
|
||||
|
||||
overflow,
|
||||
timeout,
|
||||
neterror,
|
||||
diskisfull,
|
||||
waiting,
|
||||
subscribe -> {
|
||||
downloadBtn.setText(R.string.waiting)
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
|
||||
downloadBtn.setOnClickListener {
|
||||
DownloadManager.getInstance().resume(downloadEntity, false)
|
||||
NewFlatLogUtils.logHaloFun32DialogEvent("halo_fun_32_update_tip_dialog_click", mGameId, mGameName)
|
||||
}
|
||||
}
|
||||
|
||||
done -> {
|
||||
downloadBtn.setText(R.string.install)
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.INSTALL_NORMAL
|
||||
|
||||
downloadBtn.setOnClickListener {
|
||||
if (!File(downloadEntity.path).exists()) {
|
||||
ToastUtils.toast("畅玩组件已损坏,即将重新下载")
|
||||
DownloadManager.getInstance().cancel(downloadEntity.url)
|
||||
DownloadManager.getInstance().add(downloadEntity)
|
||||
} else {
|
||||
PackageInstaller.install(requireContext(), downloadEntity)
|
||||
NewFlatLogUtils.logHaloFun32DialogEvent(
|
||||
"halo_fun_32_update_tip_dialog_click",
|
||||
mGameId,
|
||||
mGameName
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancel,
|
||||
hijack,
|
||||
notfound,
|
||||
uncertificated,
|
||||
unqualified -> {
|
||||
downloadBtn.text = "下载"
|
||||
downloadBtn.buttonStyle = DownloadButton.ButtonStyle.NORMAL
|
||||
downloadBtn.setOnClickListener {
|
||||
DownloadManager.getInstance().resume(downloadEntity, true)
|
||||
NewFlatLogUtils.logHaloFun32DialogEvent("halo_fun_32_update_tip_dialog_click", mGameId, mGameName)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_APP_ENTITY_32 = "app_entity_32"
|
||||
const val KEY_AUTO_DOWNLOAD = "auto_download"
|
||||
const val KEY_IS_UPDATE = "is_update"
|
||||
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(
|
||||
context: Context?,
|
||||
appEntity32: AppEntity,
|
||||
autoDownload: Boolean = false,
|
||||
isUpdate: Boolean = false,
|
||||
gameId: String = "",
|
||||
gameName: String = ""
|
||||
) {
|
||||
val fragmentActivity: FragmentActivity = if (context is FragmentActivity) {
|
||||
context
|
||||
} else {
|
||||
val currentActivity = AppManager.getInstance().currentActivity()
|
||||
if (currentActivity is FragmentActivity) {
|
||||
currentActivity
|
||||
} else {
|
||||
throw IllegalStateException("current activity context must be FragmentActivity")
|
||||
}
|
||||
}
|
||||
|
||||
// 防止重复弹出
|
||||
if (hasDialogDisplayedInCurrentActivity(fragmentActivity)) return
|
||||
|
||||
NewFlatLogUtils.logHaloFun32DialogEvent("halo_fun_32_update_tip_dialog_show", gameId, gameName)
|
||||
|
||||
val downloadDialog = VSpaceUpdate32DialogFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putParcelable(KEY_APP_ENTITY_32, appEntity32)
|
||||
putString(EntranceConsts.KEY_GAME_ID, gameId)
|
||||
putString(EntranceConsts.KEY_GAME_NAME, gameName)
|
||||
putBoolean(KEY_AUTO_DOWNLOAD, autoDownload)
|
||||
putBoolean(KEY_IS_UPDATE, isUpdate)
|
||||
}
|
||||
}
|
||||
downloadDialog.show(
|
||||
fragmentActivity.supportFragmentManager,
|
||||
VSpaceUpdate32DialogFragment::class.java.name
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showDownloadDialog(
|
||||
context: Context?,
|
||||
appEntity32: AppEntity,
|
||||
gameEntity: GameEntity?,
|
||||
autoDownload: Boolean = false,
|
||||
isUpdate: Boolean = false
|
||||
) {
|
||||
showDownloadDialog(
|
||||
context,
|
||||
appEntity32,
|
||||
autoDownload,
|
||||
isUpdate,
|
||||
gameEntity?.id ?: "",
|
||||
gameEntity?.name ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
private fun hasDialogDisplayedInCurrentActivity(fragmentActivity: FragmentActivity): Boolean {
|
||||
val fragments: List<Fragment> = fragmentActivity.supportFragmentManager.fragments
|
||||
fragments.forEach { fragment ->
|
||||
if (fragment is VSpaceUpdate32DialogFragment) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18,7 +18,7 @@ interface VArchiveDao {
|
||||
@Query("DELETE FROM VArchiveEntity")
|
||||
fun clearAllArchives()
|
||||
|
||||
@Query("SELECT * FROM VArchiveEntity")
|
||||
@Query("SELECT * FROM VArchiveEntity ORDER BY time desc")
|
||||
fun getAllLiveData(): LiveData<List<VArchiveEntity>>
|
||||
|
||||
}
|
||||
@ -34,6 +34,7 @@ class GAppsDownloadDialogFragment : BaseBottomDialogFragment<DialogGappsDownload
|
||||
|
||||
private var mIsInstalling = false // 是否正在安装,避免重复触发
|
||||
private var mRequiredAutoInstall = false // 是否需要自动安装(下载完成后自动安装)
|
||||
private var mRequiredReTriggerInstall = false // 是否需要重新触发安装(因为切换到后台被中断)
|
||||
private var mInstallSuccess = false // 安装是否已经成功
|
||||
private var mInstallProgressAnimator: ValueAnimator? = null
|
||||
|
||||
@ -52,22 +53,28 @@ class GAppsDownloadDialogFragment : BaseBottomDialogFragment<DialogGappsDownload
|
||||
File(mGAppsUnZipDestPath).also { if (!it.exists()) it.mkdir() }
|
||||
}
|
||||
|
||||
private val mBatchInstallListener: (isSuccess: Boolean) -> Unit = { isSuccess ->
|
||||
val elapsedTime =
|
||||
(System.currentTimeMillis() - mGAppsDownloadAndInstallStartTimestampMills + mGAppsDownloadAndInstallElapsedTimeMills) / 1000
|
||||
|
||||
mGAppsDownloadAndInstallStartTimestampMills = 0L
|
||||
mGAppsDownloadAndInstallElapsedTimeMills = 0L
|
||||
|
||||
if (isSuccess) {
|
||||
showSuccessStyle()
|
||||
mInstallSuccess = true
|
||||
NewFlatLogUtils.logGAppsInstallSuccess(mGameId, mGameName, elapsedTime.toInt())
|
||||
clearCaches()
|
||||
private val mBatchInstallListener: (isSuccess: Boolean, isInterrupted: Boolean) -> Unit = { isSuccess, isInterrupted ->
|
||||
if (isInterrupted) {
|
||||
// 安装过程被打断
|
||||
mIsInstalling = false
|
||||
mRequiredReTriggerInstall = true
|
||||
} else {
|
||||
mInstallSuccess = false
|
||||
NewFlatLogUtils.logGAppsInstallFailed(mGameId, mGameName, elapsedTime.toInt())
|
||||
resetDownloadStatus(null)
|
||||
val elapsedTime =
|
||||
(System.currentTimeMillis() - mGAppsDownloadAndInstallStartTimestampMills + mGAppsDownloadAndInstallElapsedTimeMills) / 1000
|
||||
|
||||
mGAppsDownloadAndInstallStartTimestampMills = 0L
|
||||
mGAppsDownloadAndInstallElapsedTimeMills = 0L
|
||||
|
||||
if (isSuccess) {
|
||||
showSuccessStyle()
|
||||
mInstallSuccess = true
|
||||
NewFlatLogUtils.logGAppsInstallSuccess(mGameId, mGameName, elapsedTime.toInt())
|
||||
clearCaches()
|
||||
} else {
|
||||
mInstallSuccess = false
|
||||
NewFlatLogUtils.logGAppsInstallFailed(mGameId, mGameName, elapsedTime.toInt())
|
||||
resetDownloadStatus(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,6 +120,16 @@ class GAppsDownloadDialogFragment : BaseBottomDialogFragment<DialogGappsDownload
|
||||
NewFlatLogUtils.logGAppsDialogShowed(mGameId, mGameName)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
// 执行安装重试
|
||||
if (mRequiredReTriggerInstall) {
|
||||
batchInstall(mGAppsUnZipDestFile)
|
||||
mRequiredReTriggerInstall = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateViewByDownload(downloadEntity: SimpleDownloadEntity?) {
|
||||
if (downloadEntity != null) {
|
||||
updateViewByDownloadStatus(downloadEntity.status)
|
||||
@ -291,7 +308,7 @@ class GAppsDownloadDialogFragment : BaseBottomDialogFragment<DialogGappsDownload
|
||||
|
||||
runOnUiThread {
|
||||
mInstallProgressAnimator = ValueAnimator.ofInt(500, 1000)
|
||||
mInstallProgressAnimator?.duration = 10 * 1000L
|
||||
mInstallProgressAnimator?.duration = INSTALL_ANIMATION_DURATION
|
||||
mInstallProgressAnimator?.interpolator = DecelerateInterpolator()
|
||||
mInstallProgressAnimator?.addUpdateListener {
|
||||
mBinding.downloadButton.progress = it.animatedValue as Int
|
||||
@ -333,6 +350,7 @@ class GAppsDownloadDialogFragment : BaseBottomDialogFragment<DialogGappsDownload
|
||||
private const val TRIGGER_PACKAGE_NAME = "trigger_package_name" // 触发弹窗的原始游戏包名
|
||||
private const val GAME_ID = "game_id"
|
||||
private const val GAME_NAME = "game_name"
|
||||
private const val INSTALL_ANIMATION_DURATION = 30 * 1000L // 安装动画时长
|
||||
|
||||
fun getInstance(packageName: String, gameId: String, gameName: String): GAppsDownloadDialogFragment {
|
||||
return GAppsDownloadDialogFragment().also {
|
||||
|
||||
@ -11,6 +11,7 @@ import android.os.Build;
|
||||
import android.os.StrictMode;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.collection.ArrayMap;
|
||||
@ -43,6 +44,7 @@ import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.Injection;
|
||||
import com.gh.gamecenter.common.constant.Config;
|
||||
import com.gh.gamecenter.common.constant.Constants;
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.common.image.EmptyDecoder;
|
||||
import com.gh.gamecenter.common.tracker.Tracker;
|
||||
import com.gh.gamecenter.common.utils.DarkModeUtils;
|
||||
@ -58,6 +60,7 @@ import com.gh.gamecenter.core.utils.SPUtils;
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity;
|
||||
import com.gh.gamecenter.fragment.MainWrapperRepository;
|
||||
import com.gh.gamecenter.login.user.UserRepository;
|
||||
import com.gh.gamecenter.oaid.OAIDHelper;
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository;
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider;
|
||||
import com.gh.gamecenter.provider.FlavorProviderImp;
|
||||
@ -200,10 +203,26 @@ public class HaloApp extends MultiDexApplication {
|
||||
|
||||
mInstance = this;
|
||||
|
||||
// 每个进程都用自己的进程名作为后缀的文件夹来存 WebView cache
|
||||
// https://sentry.shanqu.cc/organizations/lightgame/issues/285063/?project=22&query=is%3Aunresolved
|
||||
// https://stackoverflow.com/a/61748345/4812571 这个无效
|
||||
// WebView.disableWebView() 也无效
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
try {
|
||||
String process = getProcessName();
|
||||
WebView.setDataDirectorySuffix(process);
|
||||
} catch (IllegalStateException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
for (IApplication application : mApplicationList) {
|
||||
application.onCreate(mInstance);
|
||||
}
|
||||
|
||||
// 似乎只是 load SO 不涉及方法调用,所以可以在隐私政策前调用吧?
|
||||
OAIDHelper.INSTANCE.doSystemLoad();
|
||||
|
||||
// 70ms
|
||||
PlayerFactory.setPlayManager(Exo2PlayerManager.class);
|
||||
CacheFactory.setCacheManager(ExoPlayerCacheManager.class);
|
||||
@ -273,6 +292,12 @@ public class HaloApp extends MultiDexApplication {
|
||||
// 获取/更新 GID 和 读 SP 的操作不需要 delay
|
||||
DataUtils.getGid();
|
||||
|
||||
OAIDHelper.INSTANCE.getOAID(this, s -> {
|
||||
setOAID(s);
|
||||
MetaUtil.INSTANCE.refreshMeta();
|
||||
return null;
|
||||
});
|
||||
|
||||
// 获取 settings 配置
|
||||
ExtensionsKt.doOnMainProcessOnly(this, com.gh.common.constant.Config::getGhzsSettings);
|
||||
|
||||
|
||||
@ -173,6 +173,10 @@ class WebFragment : LazyFragment(), IScrollable {
|
||||
closeBtn.visibility = View.VISIBLE
|
||||
closeBtn.setOnClickListener { requireActivity().finish() }
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
mBinding?.fullscreenContainer?.elevation = 10F.dip2px().toFloat()
|
||||
mBinding?.closeBtn?.elevation = 11F.dip2px().toFloat()
|
||||
}
|
||||
} else {
|
||||
initMenu()
|
||||
}
|
||||
@ -461,6 +465,19 @@ class WebFragment : LazyFragment(), IScrollable {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onShowCustomView(view: View, callback: CustomViewCallback) {
|
||||
super.onShowCustomView(view, callback)
|
||||
fullscreenContainer.removeAllViews()
|
||||
fullscreenContainer.visibility = View.VISIBLE
|
||||
fullscreenContainer.addView(view)
|
||||
}
|
||||
|
||||
override fun onHideCustomView() {
|
||||
super.onHideCustomView()
|
||||
fullscreenContainer.visibility = View.GONE
|
||||
fullscreenContainer.removeAllViews()
|
||||
}
|
||||
|
||||
override fun onProgressChanged(view: WebView, newProgress: Int) {
|
||||
webProgressbar.progress = newProgress
|
||||
if (newProgress == 100) {
|
||||
|
||||
@ -35,8 +35,13 @@ import com.gh.gamecenter.adapter.OnCommentCallBackListener;
|
||||
import com.gh.gamecenter.entity.CommentEntity;
|
||||
import com.gh.gamecenter.entity.MessageEntity;
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment;
|
||||
import com.gh.gamecenter.eventbus.EBAddComment;
|
||||
import com.gh.gamecenter.eventbus.EBDeleteComment;
|
||||
import com.lightgame.utils.Util_System_Keyboard;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@ -122,7 +127,7 @@ public class CommentDetailFragment extends ToolbarFragment implements OnCommentC
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||
super.onScrollStateChanged(recyclerView, newState);
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE && !mAdapter.isOver() && !mAdapter.isLoading()) {
|
||||
mAdapter.loadData();
|
||||
mAdapter.loadMore();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -140,6 +145,11 @@ public class CommentDetailFragment extends ToolbarFragment implements OnCommentC
|
||||
requireView().post(() -> mKeyboardHeightProvider.start());
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onDeleteComment(EBDeleteComment event) {
|
||||
mAdapter.notifyCommentRemoved(event.commentEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
@ -180,7 +190,7 @@ public class CommentDetailFragment extends ToolbarFragment implements OnCommentC
|
||||
@Override
|
||||
public void onCommentCallback(CommentEntity entity) {
|
||||
mCommentEntity = entity;
|
||||
setSoftInput(true);
|
||||
setSoftInput(mCommentEntity != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -215,6 +225,8 @@ public class CommentDetailFragment extends ToolbarFragment implements OnCommentC
|
||||
mCommentDetailCommentEt.setText("");
|
||||
|
||||
setSoftInput(false);
|
||||
mAdapter.refresh();
|
||||
EventBus.getDefault().post(new EBAddComment());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="true" android:color="@color/theme_font" />
|
||||
<item android:color="@color/text_subtitle" />
|
||||
</selector>
|
||||
BIN
app/src/main/res/drawable-night-xxxhdpi/icon_more_panel_top.webp
Normal file
BIN
app/src/main/res/drawable-night-xxxhdpi/icon_more_panel_top.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/drawable-xxhdpi/icon_more_panel_top.webp
Normal file
BIN
app/src/main/res/drawable-xxhdpi/icon_more_panel_top.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/drawable-xxhdpi/icon_more_panel_top_cancel.webp
Normal file
BIN
app/src/main/res/drawable-xxhdpi/icon_more_panel_top_cancel.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.3 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user