Compare commits
41 Commits
fix/system
...
feature-me
| Author | SHA1 | Date | |
|---|---|---|---|
| e6a155a532 | |||
| d455d4ef54 | |||
| 8f8ac99dae | |||
| 0be7db94ad | |||
| ae80359b48 | |||
| 81281855a1 | |||
| a5174c6931 | |||
| a3cc74afb3 | |||
| 84e78de6fc | |||
| 9bf4c73250 | |||
| 57a222b87a | |||
| 3e125b90a2 | |||
| 1809265d4f | |||
| 3b3774596d | |||
| bded49c366 | |||
| 841711b5f1 | |||
| 7a080115a7 | |||
| 337c4724a7 | |||
| 2119691bf6 | |||
| caf50055c9 | |||
| 3ee3c2453f | |||
| 5e431e8a61 | |||
| ff72c7cac8 | |||
| 047325e9bc | |||
| afbb758740 | |||
| 5de629cfdd | |||
| f026623600 | |||
| 2f5ee0eb91 | |||
| e7651e8092 | |||
| 82d51d6375 | |||
| 6080edfd8a | |||
| d9713571c9 | |||
| b466525e8b | |||
| 2a25675dce | |||
| 5486ad8818 | |||
| 5552fcf7bc | |||
| 782a0af13c | |||
| c6c2d9cd12 | |||
| f929a08e46 | |||
| e48f96d7d7 | |||
| 3cc95dbc08 |
184
.gitlab-ci.yml
184
.gitlab-ci.yml
@ -1,159 +1,35 @@
|
||||
# commit_sha 文件记录上一次成功流水线的commit sha,用于定时计划检测是否有新代码提交,有就执行流水线,没有就终止流水线
|
||||
cache:
|
||||
# 不同的分支采用不同的 cache,防止分支之间相互影响
|
||||
key: "${CI_COMMIT_REF_SLUG}_commit_sha"
|
||||
paths:
|
||||
- commit_sha
|
||||
policy: pull
|
||||
|
||||
# 将打包&发送apk包邮件job 和代码分析job 并行执行
|
||||
stages:
|
||||
- build&analyze
|
||||
- oss-upload&send-email
|
||||
- ci_sonar_mail
|
||||
- docker-build && sendmail
|
||||
- deploy-trigger
|
||||
|
||||
# 阻止了 合并请求 或 push(分支和标签)的流水线。 最后的 when: always 规则运行所有其他流水线类型,包括定时计划流水线。
|
||||
workflow:
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "push"'
|
||||
when: always
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
when: never
|
||||
- when: always
|
||||
|
||||
before_script:
|
||||
# 检查是否存在 commit_sha 文件
|
||||
- if [ -f commit_sha ]; then cat commit_sha; else echo "0000000" > commit_sha; fi
|
||||
- export BEFORE_COMMIT_SHA=$(cat commit_sha)
|
||||
# 比较commit sha ,若与上一次成功流水线的commit sha 相同,则退出流水线
|
||||
- if [ "$CI_COMMIT_SHA" == "$BEFORE_COMMIT_SHA" ] && [ "$CI_PIPELINE_SOURCE" != "web" ]; then exit 137; fi
|
||||
|
||||
# 使用 .post 阶段使作业在流水线的末尾运行。.post 始终是流水线的最后阶段。
|
||||
change_commit:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: .post
|
||||
# 此job 跳过拉取git代码
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
# 更新 commit_sha
|
||||
- if [ "$CI_COMMIT_SHA" != "$BEFORE_COMMIT_SHA" ]; then echo $CI_COMMIT_SHA > commit_sha; fi
|
||||
cache:
|
||||
# 不同的分支采用不同的 cache,防止分支之间相互影响
|
||||
key: "${CI_COMMIT_REF_SLUG}_commit_sha"
|
||||
paths:
|
||||
- commit_sha
|
||||
policy: pull-push
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
|
||||
android_build:
|
||||
tags:
|
||||
# - local-runner
|
||||
- offline-test
|
||||
stage: build&analyze
|
||||
image: hub.shanqu.cc/library/ci-android:jdk11-sdk31-33
|
||||
resource_group: android_build
|
||||
variables:
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
KUBERNETES_CPU_LIMIT: "10"
|
||||
script:
|
||||
- export GRADLE_USER_HOME=/home/gitlab-runner/ci-build-cache/$CI_PROJECT_PATH/.gradle
|
||||
- chmod +x ./gradlew
|
||||
- ./scripts/jenkins_build.sh $CI_COMMIT_REF_NAME $BEFORE_COMMIT_SHA $CI_COMMIT_SHA
|
||||
#设置打包后的产物,用于job之间共享
|
||||
artifacts:
|
||||
paths:
|
||||
- app/build/tmp/*.apk
|
||||
expire_in: 48 hrs # 指定附件上载后保存的时间24h,默认永久在Gitlab保存
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: build&analyze
|
||||
image: hub.shanqu.cc/library/sonar-scanner-cli:latest
|
||||
dependencies: [] #禁止传递来的artifact
|
||||
script:
|
||||
## 获取项目的一级组和二级组和项目名作为projectKey,例如projectKey=platform-backend-eci-monitor
|
||||
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- sonar-scanner
|
||||
-Dsonar.host.url=http://sonarqube-server.sonarqube:9000/
|
||||
-Dsonar.login=be43de7264ce4c4766eb0c020373c3e74e6df257
|
||||
-Dsonar.jacoco.reportPaths=target/jacoco.exec
|
||||
-Dsonar.projectKey=$group
|
||||
-Dsonar.projectName=$CI_PROJECT_PATH
|
||||
-Dsonar.sourceEncoding=UTF-8
|
||||
-Dsonar.exclusions=**/vendor/**,**/errcode/**
|
||||
-Dsonar.gitlab.project_id=$CI_PROJECT_ID
|
||||
-Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA
|
||||
-Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
|
||||
-Dsonar.gitlab.ci_merge_request_iid=$CI_MERGE_REQUEST_IID
|
||||
-Dsonar.gitlab.merge_request_discussion=true
|
||||
-Dsonar.java.binaries=.
|
||||
-Dsonar.branch.name=$CI_COMMIT_REF_NAME
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
|
||||
## 发送简易检测结果报告
|
||||
send_sonar_report:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: ci_sonar_mail
|
||||
image: hub.shanqu.cc/library/docker:latest
|
||||
# 此job 跳过拉取git代码
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- docker run -e PROJECTKEY=$group -e EMAIL=$GITLAB_USER_EMAIL -e BRANCH=$CI_COMMIT_REF_NAME --name send-email --rm hub.shanqu.cc/platform/send-sonar-report:latest
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
|
||||
oss-upload&send-email:
|
||||
# 构建推送docker镜像
|
||||
docker-build:
|
||||
tags:
|
||||
- sysadm-devops
|
||||
stage: oss-upload&send-email
|
||||
image: hub.shanqu.cc/devops/android-apk-oss-upload:latest
|
||||
id_tokens:
|
||||
VAULT_ID_TOKEN:
|
||||
aud: https://vault.shanqu.cc
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
VAULT_ADDR: https://vault.shanqu.cc # 固定值
|
||||
VAULT_SECRET_PATH: prod/devops/android-apk-oss-upload # 固定值
|
||||
VAULT_ROLE: android-apk-oss-upload # 固定值
|
||||
ENDPOINT: "tos-cn-guangzhou.ivolces.com" # 固定值
|
||||
BUCKET: "sysadm-public" # 固定值
|
||||
FILE_PATH: "app/build/tmp/" # APK 存放路径
|
||||
Email_To_List: $EMAIL_TO_LIST # 邮件接受人列表
|
||||
Email_Title: "光环助手 $CI_COMMIT_BRANCH" # 邮件标题
|
||||
PIPELINE_ID: $CI_PIPELINE_ID # 流水线id
|
||||
COMMIT_BRANCH: $CI_COMMIT_BRANCH # 提交分支
|
||||
MAIL_MESSAGE: "[$CI_COMMIT_AUTHOR] $CI_COMMIT_MESSAGE"
|
||||
needs:
|
||||
- job: android_build
|
||||
artifacts: true
|
||||
- offline-test
|
||||
stage: docker-build && sendmail
|
||||
image: hub.shanqu.cc/library/docker:latest
|
||||
script:
|
||||
### 绑定上传参数 ###
|
||||
|
||||
- export OSS_PATH="release/dev/${CI_PROJECT_NAME}/$(date "+%Y/%m/%d")"
|
||||
### 开启上传 ###
|
||||
- /usr/local/bin/python /upload.py
|
||||
### 发送邮件
|
||||
- /usr/local/bin/python /ci-android-mail-jira-comment.py
|
||||
- projectPath=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- date
|
||||
- rm -rf /home/gitlab-runner/ci-build-cache/$CI_PROJECT_PATH/.gradle/caches/build-cache-1
|
||||
- cp -R /home/gitlab-runner/ci-build-cache/$CI_PROJECT_PATH/.gradle .
|
||||
- date
|
||||
- docker build -t hub-vol.shanqu.cc/ghzs/$projectPath:latest .
|
||||
- date
|
||||
- docker push hub-vol.shanqu.cc/ghzs/$projectPath:latest
|
||||
- date
|
||||
- docker run -e PROJECTKEY=$projectPath -e EMAIL=$GITLAB_USER_EMAIL -e BRANCH=$CI_COMMIT_REF_NAME --name send-email --rm hub.shanqu.cc/platform/send-sonar-report:latest
|
||||
resource_group: android_build
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
- feature-meta_build
|
||||
|
||||
## 触发多项目构建
|
||||
trigger_job:
|
||||
stage: deploy-trigger
|
||||
variables:
|
||||
BUILD_PROJECT_NAME: $CI_PROJECT_PATH
|
||||
trigger:
|
||||
project: devops/automation/build-eci
|
||||
branch: dev
|
||||
only:
|
||||
- feature-meta_build
|
||||
10
Dockerfile
10
Dockerfile
@ -1,15 +1,21 @@
|
||||
FROM openjdk:11-jdk
|
||||
FROM hub.shanqu.cc/library/openjdk:11-jdk
|
||||
|
||||
WORKDIR /project
|
||||
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
#配置SDK环境变量
|
||||
ENV ANDROID_SDK_ROOT /usr/lib/sdk
|
||||
ENV ANDROID_HOME /usr/lib/sdk
|
||||
ENV PATH $ANDROID_SDK_ROOT:$PATH
|
||||
ENV PATH=$PATH:${ANDROID_HOME}/cmdline-tools/cmdline-tools/bin/
|
||||
ENV GRADLE_USER_HOME /project/.gradle
|
||||
|
||||
RUN source ~/.bashrc
|
||||
|
||||
RUN sed -i "s@http://\(deb\|security\).debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list \
|
||||
&& apt-get --quiet update --yes \
|
||||
&& apt-get --quiet install --yes lib32stdc++6 lib32z1 libncurses5 util-linux bash tzdata librdkafka-dev pkgconf \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY .gradle /project/.gradle
|
||||
|
||||
COPY .gradle /project/.gradle
|
||||
@ -101,6 +101,8 @@ android {
|
||||
buildConfigField "String", "NEW_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "LOG_HUB_PROJECT", "\"${LOG_HUB_PROJECT}\""
|
||||
buildConfigField "String", "VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
buildConfigField "String", "WGAME_CPM_BUSIAPPID", "\"${WGAME_CPM_BUSIAPPID}\""
|
||||
buildConfigField "String", "WGAME_CPM_API_HOST", "\"${WGAME_CPM_API_HOST}\""
|
||||
buildConfigField "String", "WECHAT_APPID", "\"${WECHAT_APPID}\""
|
||||
buildConfigField "String", "WECHAT_SECRET", "\"${WECHAT_SECRET}\""
|
||||
buildConfigField "String", "TENCENT_APPID", "\"${TENCENT_APPID}\""
|
||||
|
||||
@ -588,7 +588,7 @@ document.addEventListener("selectionchange", function(e) {
|
||||
});
|
||||
|
||||
document.addEventListener("selectionchange", function(e) {
|
||||
RE.enabledEditingItems(e)
|
||||
setTimeout(() => RE.enabledEditingItems(e), 10)
|
||||
});
|
||||
|
||||
RE.recursion = function(dom) {
|
||||
|
||||
@ -374,7 +374,7 @@ object DefaultUrlHandler {
|
||||
val iconSubscript = uri.getQueryParameter("game_icon_subscript") ?: ""
|
||||
val gameEntity =
|
||||
if (forumType == BbsType.OFFICIAL_BBS.value && gameId.isNotEmpty() && gameName.isNotEmpty() && icon.isNotEmpty()) {
|
||||
GameEntity(id = gameId, mName = gameName, mIcon = icon, mIconSubscript = iconSubscript)
|
||||
GameEntity(_id = gameId, mName = gameName, mIcon = icon, mIconSubscript = iconSubscript)
|
||||
} else null
|
||||
val activityLabelEntity = if (activityId.isNotEmpty() && activityName.isNotEmpty()) {
|
||||
ActivityLabelEntity(
|
||||
|
||||
@ -63,6 +63,9 @@ public class Config {
|
||||
public static final String NEW_API_HOST = EnvHelper.getNewHost();
|
||||
public static final String VAPI_HOST = EnvHelper.getVHost();
|
||||
|
||||
public static final String WGAME_CPM_BUSIAPPID = BuildConfig.WGAME_CPM_BUSIAPPID;
|
||||
public static final String WGAME_CPM_API_HOST = EnvHelper.getWGameCPMHost();
|
||||
|
||||
// Third-Party confs
|
||||
public static final String WECHAT_APPID = BuildConfig.WECHAT_APPID;
|
||||
public static final String WECHAT_SECRET = BuildConfig.WECHAT_SECRET;
|
||||
|
||||
@ -6,6 +6,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.LayoutManager
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import io.reactivex.functions.Consumer
|
||||
|
||||
@ -16,8 +17,9 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
|
||||
|
||||
val throttleBus: ExposureThrottleBus by lazy {
|
||||
ExposureThrottleBus(
|
||||
Consumer { commitExposure(it) },
|
||||
Consumer(Throwable::printStackTrace)
|
||||
{ commitExposure(it) },
|
||||
Consumer(Throwable::printStackTrace),
|
||||
{ commitWXCPMExposure(it) }
|
||||
)
|
||||
}
|
||||
var layoutManager: LayoutManager? = null
|
||||
@ -93,4 +95,32 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
|
||||
ExposureManager.log(eventList)
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信小游戏CPM曝光事件接口上报,由于普通曝光事件的上报通道存在节流特性,不符合CPM接口对于数据上报的实时性和准确性的要求,所以使用额外的通道进行上报
|
||||
*/
|
||||
private fun commitWXCPMExposure(visibleState: ExposureThrottleBus.VisibleState) {
|
||||
|
||||
val eventList = arrayListOf<ExposureEvent>()
|
||||
|
||||
for (pos in visibleState.firstVisiblePosition..visibleState.lastVisiblePosition) {
|
||||
try {
|
||||
exposable.getEventByPosition(pos)?.let {
|
||||
if (it.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM) {
|
||||
eventList.add(it)
|
||||
}
|
||||
}
|
||||
exposable.getEventListByPosition(pos)?.let { list ->
|
||||
list.forEach {
|
||||
if (it.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM) {
|
||||
eventList.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ignore: Exception) {
|
||||
// Just ignore the error.
|
||||
}
|
||||
}
|
||||
ExposureManager.logCPM(eventList)
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,11 +1,13 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.loghub.TLogHubHelper
|
||||
import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet
|
||||
import com.gh.gamecenter.common.utils.toJson
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.minigame.wechat.WGameSubjectCPMListReportHelper
|
||||
import com.lightgame.utils.Utils
|
||||
import com.volcengine.model.tls.LogItem
|
||||
|
||||
@ -32,6 +34,9 @@ object ExposureManager {
|
||||
*/
|
||||
fun log(event: ExposureEvent) {
|
||||
AppExecutor.logExecutor.execute {
|
||||
if (event.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM) {
|
||||
WGameSubjectCPMListReportHelper.reportExposure(event)
|
||||
}
|
||||
if (!exposureCache.contains(event.id)) {
|
||||
exposureSet.add(event)
|
||||
exposureCache.add(event.id)
|
||||
@ -58,6 +63,17 @@ object ExposureManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a wechat mini game cpm collection of exposure event.
|
||||
*/
|
||||
fun logCPM(eventList: List<ExposureEvent>) {
|
||||
AppExecutor.logExecutor.execute {
|
||||
if (eventList.isNotEmpty()) {
|
||||
WGameSubjectCPMListReportHelper.reportExposure(eventList.toSet())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forcedUpload Ignore all restrictions.
|
||||
*/
|
||||
|
||||
@ -3,16 +3,20 @@ package com.gh.common.exposure
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.functions.Consumer
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import io.reactivex.subjects.PublishSubject
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class ExposureThrottleBus(var onSuccess: Consumer<VisibleState>, var onError: Consumer<Throwable>) {
|
||||
class ExposureThrottleBus(
|
||||
var onSuccess: Consumer<VisibleState>,
|
||||
var onError: Consumer<Throwable>,
|
||||
onPreSuccess: Consumer<VisibleState>
|
||||
) {
|
||||
|
||||
companion object {
|
||||
private const val THRESHOLD_TIME = 300L
|
||||
}
|
||||
|
||||
private val mPublishSubject: PublishSubject<VisibleState> = PublishSubject.create()
|
||||
private val mPublishSubject: BehaviorSubject<VisibleState> = BehaviorSubject.create()
|
||||
private val mCompositeDisposable: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
init {
|
||||
@ -24,6 +28,7 @@ class ExposureThrottleBus(var onSuccess: Consumer<VisibleState>, var onError: Co
|
||||
*/
|
||||
val disposable = mPublishSubject
|
||||
.distinctUntilChanged()
|
||||
.doOnNext(onPreSuccess)
|
||||
.throttleWithTimeout(THRESHOLD_TIME, TimeUnit.MILLISECONDS)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(onSuccess, onError)
|
||||
|
||||
@ -33,5 +33,9 @@ class BuildConfigImpl : IBuildConfigProvider {
|
||||
|
||||
override fun getVDevApiHost(): String = BuildConfig.DEV_VAPI_HOST
|
||||
|
||||
override fun getWGameCPMApiHost(): String = BuildConfig.WGAME_CPM_API_HOST
|
||||
|
||||
override fun getWGameCPMBusiAppId(): String = BuildConfig.WGAME_CPM_BUSIAPPID
|
||||
|
||||
override fun getLogProducerProject(): String = BuildConfig.LOG_HUB_PROJECT
|
||||
}
|
||||
@ -62,7 +62,13 @@ class DirectProviderImpl : IDirectProvider {
|
||||
DirectUtils.directToCommunityArticle(context, articleId, communityId, entrance, path, sourceEntrance)
|
||||
}
|
||||
|
||||
override fun directToVideoDetail(context: Context, videoId: String, entrance: String?, path: String?, sourceEntrance: String) {
|
||||
override fun directToVideoDetail(
|
||||
context: Context,
|
||||
videoId: String,
|
||||
entrance: String?,
|
||||
path: String?,
|
||||
sourceEntrance: String
|
||||
) {
|
||||
DirectUtils.directToVideoDetail(context, videoId, entrance, path, sourceEntrance)
|
||||
}
|
||||
|
||||
@ -78,8 +84,13 @@ class DirectProviderImpl : IDirectProvider {
|
||||
DirectUtils.directToQQGameById(activity, qqAppId)
|
||||
}
|
||||
|
||||
override fun directToWechatGameById(activity: Activity, qqAppId: String) {
|
||||
DirectUtils.directToWechatGameById(activity, qqAppId)
|
||||
override fun directToWechatGameById(
|
||||
activity: Activity,
|
||||
wechatAppId: String,
|
||||
wechatAppPath: String,
|
||||
wechatAppExtData: String
|
||||
) {
|
||||
DirectUtils.directToWechatGameById(activity, wechatAppId, wechatAppPath, wechatAppExtData)
|
||||
}
|
||||
|
||||
override fun directToExternalBrowser(context: Context, url: String) {
|
||||
|
||||
@ -485,11 +485,13 @@ object DirectUtils {
|
||||
ColumnCollectionDetailFragment.TYPE_QQ_MINI_GAME_COLUMN -> directToQGameHome(context)
|
||||
|
||||
// QQ游戏专题详情页
|
||||
ViewPagerFragmentHelper.TYPE_QQ_MINI_GAME_COLUMN, ViewPagerFragmentHelper.TYPE_WECHAT_GAME_COLUMN -> {
|
||||
val subjectType = if (linkEntity.type == ViewPagerFragmentHelper.TYPE_QQ_MINI_GAME_COLUMN) {
|
||||
SubjectData.SubjectType.QQ_GAME
|
||||
} else {
|
||||
SubjectData.SubjectType.WECHAT_GAME
|
||||
ViewPagerFragmentHelper.TYPE_QQ_MINI_GAME_COLUMN,
|
||||
ViewPagerFragmentHelper.TYPE_WECHAT_GAME_COLUMN,
|
||||
ViewPagerFragmentHelper.TYPE_WECHAT_GAME_CPM_COLUMN -> {
|
||||
val subjectType = when (linkEntity.type) {
|
||||
ViewPagerFragmentHelper.TYPE_QQ_MINI_GAME_COLUMN -> SubjectData.SubjectType.QQ_GAME
|
||||
ViewPagerFragmentHelper.TYPE_WECHAT_GAME_CPM_COLUMN -> SubjectData.SubjectType.WECHAT_GAME_CPM
|
||||
else -> SubjectData.SubjectType.WECHAT_GAME
|
||||
}
|
||||
directToSubject(
|
||||
context = context,
|
||||
@ -2009,6 +2011,8 @@ object DirectUtils {
|
||||
fun directToWechatGameById(
|
||||
activity: Activity,
|
||||
wechatAppId: String,
|
||||
wechatAppPath: String = "",
|
||||
wechatAppExtData: String = ""
|
||||
) {
|
||||
|
||||
val wxApiProxy = WXAPIFactory.createWXAPI(
|
||||
@ -2023,8 +2027,9 @@ object DirectUtils {
|
||||
wxApiProxy.sendReq(
|
||||
WXLaunchMiniProgram.Req().apply {
|
||||
userName = wechatAppId
|
||||
path = Constants.WECHAT_MINI_GAME_PCS
|
||||
miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE;
|
||||
path = wechatAppPath.ifEmpty { Constants.WECHAT_MINI_GAME_PCS }
|
||||
extData = wechatAppExtData
|
||||
miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@ -880,7 +880,7 @@ object DownloadItemUtils {
|
||||
}
|
||||
if (gameEntity.isMiniGame()) {
|
||||
downloadBtn.setOnClickListener {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
clickCallback?.onCallback()
|
||||
allStateClickCallback?.onCallback()
|
||||
}
|
||||
|
||||
@ -494,7 +494,7 @@ object DownloadObserver {
|
||||
java.lang.Boolean.parseBoolean(downloadEntity.getMetaExtra(Constants.IS_PLATFORM_RECOMMEND))
|
||||
val exposureEvent = ExposureUtils.logADownloadCompleteExposureEvent(
|
||||
GameEntity(
|
||||
id = downloadEntity.gameId,
|
||||
_id = downloadEntity.gameId,
|
||||
mName = downloadEntity.name.removeSuffix(Constants.GAME_NAME_DECORATOR),
|
||||
gameVersion = downloadEntity.versionName ?: "",
|
||||
isPlatformRecommend = isPlatformRecommend,
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@ -19,10 +16,8 @@ import org.greenrobot.eventbus.EventBus;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 下载完成跳安装,
|
||||
*/
|
||||
@ -49,15 +44,15 @@ public class InstallUtils {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.what == INSTALL_WHAT && packageManager != null) {
|
||||
List<String> packageNameList = PackageHelper.INSTANCE.getInstalledPackageNameList(context, 0);
|
||||
ArrayList<String> list = new ArrayList<>(packageNameList);
|
||||
if (installMap != null && installMap.size() != 0) {
|
||||
ArrayList<String> keys = new ArrayList<>();
|
||||
for (String packageName : installMap.keySet()) {
|
||||
if (TextUtils.isEmpty(packageName)) continue;
|
||||
|
||||
long time = installMap.get(packageName);
|
||||
if (System.currentTimeMillis() - time >= MAX_TIME) {
|
||||
keys.add(packageName);
|
||||
} else if (list.contains(packageName)) {
|
||||
} else if (PackageUtils.isInstalled(context, packageName)) {
|
||||
keys.add(packageName);
|
||||
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntityByPackageName(packageName);
|
||||
@ -80,7 +75,7 @@ public class InstallUtils {
|
||||
long time = uninstallMap.get(packageName);
|
||||
if (System.currentTimeMillis() - time >= MAX_TIME) {
|
||||
keys.add(packageName);
|
||||
} else if (!list.contains(packageName)) {
|
||||
} else if (!PackageUtils.isInstalled(context, packageName)) {
|
||||
keys.add(packageName);
|
||||
EventBus.getDefault().post(new EBPackage("卸载", packageName, "", false));
|
||||
}
|
||||
@ -105,6 +100,8 @@ public class InstallUtils {
|
||||
}
|
||||
|
||||
public void addInstall(String packageName) {
|
||||
if (TextUtils.isEmpty(packageName)) return;
|
||||
|
||||
if (installMap == null) {
|
||||
installMap = Collections.synchronizedMap(new HashMap<String, Long>());
|
||||
}
|
||||
|
||||
@ -814,7 +814,7 @@ object PackageHelper {
|
||||
uploadUIDGapLog = false
|
||||
|
||||
val uidGap = (android.os.Process.LAST_APPLICATION_UID - lastValidUid) / 100 * 100
|
||||
SentryHelper.onEvent("UID_GAP", "gap", uidGap.toString())
|
||||
// SentryHelper.onEvent("UID_GAP", "gap", uidGap.toString())
|
||||
}
|
||||
|
||||
return packageList
|
||||
|
||||
@ -225,17 +225,6 @@ public class PackageUtils {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_META_DATA_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -497,7 +486,6 @@ public class PackageUtils {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
SentryHelper.INSTANCE.onEvent("GET_PACKAGE_INFO_ERROR", "path", path);
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -640,17 +628,6 @@ public class PackageUtils {
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_VERSION_NAME_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -664,16 +641,6 @@ public class PackageUtils {
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionCode;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_VERSION_CODE_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -688,16 +655,6 @@ public class PackageUtils {
|
||||
return packageManager.getApplicationIcon(packageName);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_ICON_ERROR",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -731,17 +688,6 @@ public class PackageUtils {
|
||||
return jsonObject;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (e instanceof AndroidException) {
|
||||
// 有些设备会出现 DeadSystemException
|
||||
SentryHelper.INSTANCE.onEvent(
|
||||
"GET_APP_BASIC_INFO_BY_PACKAGE_NAME",
|
||||
"packageName",
|
||||
packageName,
|
||||
"exception_digest",
|
||||
e.getLocalizedMessage()
|
||||
);
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +27,9 @@ import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
@ -176,7 +178,7 @@ object UsageStatsHelper {
|
||||
return
|
||||
}
|
||||
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), postBody.toString())
|
||||
val body = postBody.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
mApi.postUsageStatus(body, UserManager.getInstance().userId)
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
|
||||
@ -65,6 +65,7 @@ object ViewPagerFragmentHelper {
|
||||
const val TYPE_COLUMN = "column" // 游戏专题详情页
|
||||
const val TYPE_QQ_MINI_GAME_COLUMN = "qq_mini_game_column_detail" // QQ小游戏专题详情页
|
||||
const val TYPE_WECHAT_GAME_COLUMN = "wechat_game_column_detail" // 微信小游戏专题详情页
|
||||
const val TYPE_WECHAT_GAME_CPM_COLUMN = "wechat_game_cpm_column_detail" // 微信小游戏CPM专题详情页
|
||||
const val TYPE_COLUMN_COLLECTION = "column_collection" // 专题合集详情页
|
||||
const val TYPE_SERVER = "server" // 开服表
|
||||
const val TYPE_COLUMN_TEST = "column_test_v2" // 新游开测
|
||||
@ -163,10 +164,11 @@ object ViewPagerFragmentHelper {
|
||||
className = GameCollectionSquareFragment::class.java.name
|
||||
}
|
||||
// 游戏专题详情页/QQ游戏专题详情页
|
||||
TYPE_COLUMN, TYPE_QQ_MINI_GAME_COLUMN, TYPE_WECHAT_GAME_COLUMN -> {
|
||||
TYPE_COLUMN, TYPE_QQ_MINI_GAME_COLUMN, TYPE_WECHAT_GAME_COLUMN, TYPE_WECHAT_GAME_CPM_COLUMN -> {
|
||||
val subjectType = when(entity.type) {
|
||||
TYPE_QQ_MINI_GAME_COLUMN -> SubjectData.SubjectType.QQ_GAME
|
||||
TYPE_WECHAT_GAME_COLUMN -> SubjectData.SubjectType.WECHAT_GAME
|
||||
TYPE_WECHAT_GAME_CPM_COLUMN -> SubjectData.SubjectType.WECHAT_GAME_CPM
|
||||
else -> SubjectData.SubjectType.NORMAL
|
||||
}
|
||||
className = SubjectFragment::class.java.name
|
||||
|
||||
@ -34,7 +34,9 @@ import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
@ -216,7 +218,7 @@ object PackageObserver {
|
||||
try {
|
||||
jsonObject.put("game_id", gameId)
|
||||
jsonObject.put("package", packageName)
|
||||
val rBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val rBody = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
RetrofitManager.getInstance().api
|
||||
.postPlayedGame(UserManager.getInstance().userId, rBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@ -94,8 +94,8 @@ object ExoCacheManager {
|
||||
response =
|
||||
OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS).build()
|
||||
.newCall(request).execute()
|
||||
if (response!!.isSuccessful && response.body() != null) {
|
||||
val length = response.body()!!.contentLength()
|
||||
if (response!!.isSuccessful && response.body != null) {
|
||||
val length = response.body!!.contentLength()
|
||||
contentLength = if (length == 0L) -1L else length
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
||||
@ -27,12 +27,24 @@ object SimpleDownloadManager {
|
||||
val downloadStatus = mDownloadQueue.getStatus(config.uniqueId)
|
||||
|
||||
if (downloadStatus != DownloadStatus.PAUSED) {
|
||||
ExecutorProvider.getInstance().backgroundExecutor.execute {
|
||||
DownloadMessageHandler.insertDownloadToDatabase(getDownloadEntity(config))
|
||||
mDownloadQueue.submitNewTask(config)
|
||||
}
|
||||
createNewTaskAndDownload(config)
|
||||
} else {
|
||||
resume(config.uniqueId)
|
||||
try {
|
||||
resume(config.uniqueId)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
createNewTaskAndDownload(config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新任务并下载
|
||||
*/
|
||||
private fun createNewTaskAndDownload(config: DownloadConfig) {
|
||||
ExecutorProvider.getInstance().backgroundExecutor.execute {
|
||||
mDownloadQueue.cancel(config.uniqueId)
|
||||
DownloadMessageHandler.insertDownloadToDatabase(getDownloadEntity(config))
|
||||
mDownloadQueue.submitNewTask(config)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -408,7 +408,7 @@ public class SkipActivity extends BaseActivity {
|
||||
try {
|
||||
JSONObject extJsonObject = new JSONObject(extJson);
|
||||
String qqGameId = extJsonObject.optString("aid");
|
||||
MiniGameItemHelper.INSTANCE.launchMiniGame(qqGameId, Constants.QQ_MINI_GAME);
|
||||
MiniGameItemHelper.INSTANCE.launchMiniGame(qqGameId, Constants.QQ_MINI_GAME, "", "");
|
||||
} catch (JSONException ignored) {
|
||||
}
|
||||
break;
|
||||
|
||||
@ -27,7 +27,7 @@ open class BaseCloudArchiveViewModel(application: Application, private val mConf
|
||||
)
|
||||
.enqueue(object : Callback {
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
mArchiveConfigStr = response.body()?.string() ?: ""
|
||||
mArchiveConfigStr = response.body?.string() ?: ""
|
||||
callback?.invoke(mArchiveConfigStr)
|
||||
}
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ class AdGameBannerAdapter(
|
||||
it.name ?: ""
|
||||
)
|
||||
if (it.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(it.miniGameAppId, it.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(it)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
|
||||
@ -9,14 +9,16 @@ import kotlinx.parcelize.Parcelize
|
||||
@Parcelize
|
||||
data class SearchSubjectEntity(
|
||||
val name: String = "",
|
||||
val games: List<GameEntity> = listOf(),
|
||||
var games: List<GameEntity> = listOf(),
|
||||
val location: Int = 0,
|
||||
@SerializedName("column_id")
|
||||
val columnId: String = "",
|
||||
val adId: String = "", // 广告ID(本地字段),不为空时为广告专题
|
||||
val codeId: String = "", // 广告CODE_ID(本地字段),不为空时为广告专题
|
||||
@SerializedName("ad_icon_active")
|
||||
val adIconActive: Boolean = false
|
||||
val adIconActive: Boolean = false,
|
||||
// 本地字段,标记是否为微信小游戏CPM专题
|
||||
var isWGameSubjectCPM: Boolean = false
|
||||
) : Parcelable {
|
||||
fun getFilterGame() = RegionSettingHelper.filterGame(games)
|
||||
}
|
||||
@ -63,6 +63,11 @@ class SubjectData(
|
||||
/**
|
||||
* 微信小游戏专题
|
||||
*/
|
||||
WECHAT_GAME
|
||||
WECHAT_GAME,
|
||||
|
||||
/**
|
||||
* 微信小游戏CPM专题
|
||||
*/
|
||||
WECHAT_GAME_CPM,
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,6 +104,8 @@ data class SubjectEntity(
|
||||
@SerializedName("is_wechat_column")
|
||||
var isWechatColumn: Boolean = false,
|
||||
|
||||
var isWechatColumnCPM: Boolean = false,
|
||||
|
||||
var explain: String = "", // 游戏单合集说明
|
||||
|
||||
@SerializedName("show_star")
|
||||
@ -130,6 +132,7 @@ data class SubjectEntity(
|
||||
|
||||
val subjectType: SubjectData.SubjectType get() = when {
|
||||
isQQColumn -> SubjectData.SubjectType.QQ_GAME
|
||||
isWechatColumnCPM -> SubjectData.SubjectType.WECHAT_GAME_CPM
|
||||
isWechatColumn -> SubjectData.SubjectType.WECHAT_GAME
|
||||
else -> SubjectData.SubjectType.NORMAL
|
||||
}
|
||||
|
||||
@ -611,7 +611,7 @@ class GameFragmentAdapter(
|
||||
val subjectData = gameEntity.subjectData
|
||||
DataCollectionUtils.uploadClick(mContext, subjectData?.name + "-列表", "游戏-专题", gameEntity.name)
|
||||
if (gameEntity.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext, gameEntity,
|
||||
@ -1322,7 +1322,7 @@ class GameFragmentAdapter(
|
||||
DataCollectionUtils.uploadClick(mContext, subjectData.name + "-列表", "游戏-专题", gameEntity.name)
|
||||
|
||||
if (gameEntity.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
} else if (gameEntity.isPluggable) {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
|
||||
@ -135,7 +135,7 @@ class GameGallerySlideViewHolder(val binding: GameGallerySlideItemBinding) : Bas
|
||||
binding.iconIv.displayGameIcon(gameEntity)
|
||||
binding.iconIv.setOnClickListener {
|
||||
if (gameEntity.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
binding.root.context,
|
||||
|
||||
@ -55,7 +55,7 @@ class GameGalleryViewHolder(val cell: GameGalleryItemCell) :
|
||||
|
||||
if (subjectEntity.isMiniGame) {
|
||||
gameIcon.setOnClickListener {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
}
|
||||
} else {
|
||||
gameIcon.setOnClickListener(null)
|
||||
|
||||
@ -140,7 +140,7 @@ class GameHorizontalAdapter(
|
||||
}
|
||||
|
||||
if (gameEntity.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
mContext,
|
||||
|
||||
@ -68,7 +68,7 @@ class GameHorizontalSlideAdapter(
|
||||
holder.bindGameHorizontalItem(gameEntity, mSubjectEntity)
|
||||
holder.itemView.setOnClickListener {
|
||||
if (gameEntity.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
} else {
|
||||
val exposureEvent = exposureEventList?.safelyGetInRelease(position)
|
||||
if (exposureEvent != null) {
|
||||
|
||||
@ -45,7 +45,9 @@ import com.zhihu.matisse.Matisse
|
||||
import com.zhihu.matisse.internal.utils.PathUtils
|
||||
import io.reactivex.disposables.Disposable
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.io.File
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
@ -420,10 +422,8 @@ class GameUploadFragment : ToolbarFragment() {
|
||||
requestMap["type"] = mGameType
|
||||
}
|
||||
|
||||
val body = RequestBody.create(
|
||||
MediaType.parse("application/json"),
|
||||
GsonUtils.toJson(requestMap)
|
||||
)
|
||||
val body = GsonUtils.toJson(requestMap)
|
||||
.toRequestBody("application/json".toMediaTypeOrNull())
|
||||
mViewModel.uploadGames(body)
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,9 @@ import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.gh.common.util.DirectUtils
|
||||
@ -21,6 +24,17 @@ class GameCollectionAmwayViewHolder(var binding: GameCollectionSquareAmwayItemBi
|
||||
private val mAdapter = GameCollectionAmwayAdapter(binding.root.context)
|
||||
private val mLooperHandle = LooperHandle(this)
|
||||
private val mSlideLooperKey = 333
|
||||
private val mLifecycleObserver = object : DefaultLifecycleObserver {
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
super.onResume(owner)
|
||||
startAutoPlay()
|
||||
}
|
||||
|
||||
override fun onPause(owner: LifecycleOwner) {
|
||||
super.onPause(owner)
|
||||
stopAutoPlay()
|
||||
}
|
||||
}
|
||||
|
||||
fun bindAmway(amwayList: List<AmwayCommentEntity>, viewModel: GameCollectionSquareViewModel) {
|
||||
mAdapter.setAmwayList(amwayList)
|
||||
@ -54,6 +68,14 @@ class GameCollectionAmwayViewHolder(var binding: GameCollectionSquareAmwayItemBi
|
||||
mLooperHandle.removeMessages(mSlideLooperKey)
|
||||
}
|
||||
|
||||
fun onViewAttach(lifecycle: Lifecycle) {
|
||||
lifecycle.addObserver(mLifecycleObserver)
|
||||
}
|
||||
|
||||
fun onViewDetach(lifecycle: Lifecycle) {
|
||||
lifecycle.removeObserver(mLifecycleObserver)
|
||||
}
|
||||
|
||||
fun ViewPager2.setCurrentItem(
|
||||
item: Int,
|
||||
duration: Long,
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.gamecenter.gamecollection.square
|
||||
|
||||
import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.util.DirectUtils
|
||||
@ -23,6 +24,7 @@ import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
class GameCollectionBannerAdapter(
|
||||
context: Context,
|
||||
private val mLifecycleOwner: LifecycleOwner,
|
||||
private val mViewModel: GameCollectionSquareViewModel,
|
||||
var mBannerList: List<CarouselEntity> = emptyList(),
|
||||
private var mAmwayListItem: List<AmwayCommentEntity>? = null,
|
||||
@ -78,6 +80,20 @@ class GameCollectionBannerAdapter(
|
||||
return index
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
|
||||
super.onViewAttachedToWindow(holder)
|
||||
if (holder is GameCollectionAmwayViewHolder) {
|
||||
holder.onViewAttach(mLifecycleOwner.lifecycle)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
||||
super.onViewDetachedFromWindow(holder)
|
||||
if (holder is GameCollectionAmwayViewHolder) {
|
||||
holder.onViewDetach(mLifecycleOwner.lifecycle)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_AMWAY = 100
|
||||
const val ITEM_BANNER = 101
|
||||
|
||||
@ -12,6 +12,9 @@ import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.PagerSnapHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@ -47,6 +50,7 @@ import java.lang.ref.WeakReference
|
||||
|
||||
class GameCollectionSquareAdapter(
|
||||
context: Context,
|
||||
private val mLifecycleOwner: LifecycleOwner,
|
||||
private val mIsHome: Boolean = false,
|
||||
private val mFragment: GameCollectionSquareFragment,
|
||||
private val mViewModel: GameCollectionSquareViewModel,
|
||||
@ -157,7 +161,7 @@ class GameCollectionSquareAdapter(
|
||||
when (holder) {
|
||||
is GameCollectionHeaderItemViewHolder -> {
|
||||
val itemData = mEntityList[position]
|
||||
holder.bindHeader(itemData, mBasicExposureSource, mViewModel)
|
||||
holder.bindHeader(mLifecycleOwner, itemData, mBasicExposureSource, mViewModel)
|
||||
}
|
||||
|
||||
is GameCollectionFilterItemViewHolder -> holder.bindFilter(mFragment, mViewModel, mRefreshCallback)
|
||||
@ -211,6 +215,20 @@ class GameCollectionSquareAdapter(
|
||||
override fun getItemCount() =
|
||||
if (mEntityList.isNullOrEmpty()) 0 else if (mIsHome && mEntityList.size == 2) mEntityList.size else mEntityList.size + 1
|
||||
|
||||
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
|
||||
super.onViewAttachedToWindow(holder)
|
||||
if (holder is GameCollectionHeaderItemViewHolder) {
|
||||
holder.onViewAttach(mLifecycleOwner.lifecycle)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
||||
super.onViewDetachedFromWindow(holder)
|
||||
if (holder is GameCollectionHeaderItemViewHolder) {
|
||||
holder.onViewDetach(mLifecycleOwner.lifecycle)
|
||||
}
|
||||
}
|
||||
|
||||
class GameCollectionHeaderItemViewHolder(val binding: ItemGameCollectionHeaderBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
private lateinit var mBannerAdapter: GameCollectionBannerAdapter
|
||||
@ -218,8 +236,20 @@ class GameCollectionSquareAdapter(
|
||||
private lateinit var mBannerLayoutManager: LinearLayoutManager
|
||||
private val mLooperHandle = LooperHandle(this)
|
||||
private val mSlideLooperKey = 111
|
||||
private val mLifecycleObserver = object : DefaultLifecycleObserver {
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
super.onResume(owner)
|
||||
startAutoPlay()
|
||||
}
|
||||
|
||||
override fun onPause(owner: LifecycleOwner) {
|
||||
super.onPause(owner)
|
||||
stopAutoPlay()
|
||||
}
|
||||
}
|
||||
|
||||
fun bindHeader(
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
itemData: GameCollectionListItemData,
|
||||
mBasicExposureSource: List<ExposureSource>,
|
||||
viewModel: GameCollectionSquareViewModel
|
||||
@ -249,6 +279,7 @@ class GameCollectionSquareAdapter(
|
||||
mBannerLayoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
|
||||
mBannerAdapter = GameCollectionBannerAdapter(
|
||||
context,
|
||||
lifecycleOwner,
|
||||
viewModel,
|
||||
bannerList,
|
||||
amwayListItem,
|
||||
@ -345,6 +376,14 @@ class GameCollectionSquareAdapter(
|
||||
mLooperHandle.removeMessages(mSlideLooperKey)
|
||||
}
|
||||
|
||||
fun onViewAttach(lifecycle: Lifecycle) {
|
||||
lifecycle.addObserver(mLifecycleObserver)
|
||||
}
|
||||
|
||||
fun onViewDetach(lifecycle: Lifecycle) {
|
||||
lifecycle.removeObserver(mLifecycleObserver)
|
||||
}
|
||||
|
||||
class LooperHandle(viewHolder: GameCollectionHeaderItemViewHolder) : Handler(Looper.getMainLooper()) {
|
||||
private val mWeakReference: WeakReference<GameCollectionHeaderItemViewHolder> = WeakReference(viewHolder)
|
||||
|
||||
|
||||
@ -138,6 +138,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
mGuideContainer?.visibility = View.GONE
|
||||
} else {
|
||||
if (mExposureEventList.isNotEmpty()) ExposureManager.log(mExposureEventList)
|
||||
stopAutoPlay()
|
||||
}
|
||||
val stayTime = (System.currentTimeMillis() - startPageTime) / 1000
|
||||
NewFlatLogUtils.logGameCollectSquareStayTime(stayTime, if (mUseAlternativeLayout) "首页tab栏" else "游戏单广场")
|
||||
@ -175,6 +176,8 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
startAutoPlay()
|
||||
}
|
||||
mElapsedHelper.resetCounting()
|
||||
mElapsedHelper.resumeCounting()
|
||||
@ -270,6 +273,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
mAdapter =
|
||||
GameCollectionSquareAdapter(
|
||||
requireContext(),
|
||||
viewLifecycleOwner,
|
||||
mUseAlternativeLayout,
|
||||
this,
|
||||
mViewModel,
|
||||
@ -382,6 +386,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
|
||||
val bannerAdapter = GameCollectionBannerAdapter(
|
||||
requireContext(),
|
||||
viewLifecycleOwner,
|
||||
mViewModel,
|
||||
mEntrance = "游戏单广场",
|
||||
mBasicExposureSource = mBasicExposureSourceList
|
||||
@ -515,7 +520,8 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
|
||||
}
|
||||
|
||||
private fun startAutoPlay() {
|
||||
if ((mDefaultBinding.headerContainer.bannerRv.adapter as GameCollectionBannerAdapter).getActualSize() <= 1) return
|
||||
val bannerAdapter = mDefaultBinding.headerContainer.bannerRv.adapter as? GameCollectionBannerAdapter
|
||||
if (bannerAdapter == null || bannerAdapter.getActualSize() <= 1) return
|
||||
stopAutoPlay()
|
||||
mLooperHandle.sendEmptyMessageDelayed(mSlideLooperKey, BANNER_LOOP_TIME)
|
||||
}
|
||||
|
||||
@ -45,7 +45,9 @@ import com.gh.gamecenter.login.user.UserManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
|
||||
@ -541,7 +543,7 @@ class RatingEditActivity : ToolBarActivity(), KeyboardHeightObserver {
|
||||
jsonObject.put("rom", MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName)
|
||||
jsonObject.put("again", again)
|
||||
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
|
||||
CheckLoginUtils.checkLogin(this, mEntrance) {
|
||||
mViewModel.postGameComment(mComment?.id ?: "", body)
|
||||
|
||||
@ -97,7 +97,7 @@ class HomeGameItemViewHolder(val binding: HomeGameItemBinding) : BaseRecyclerVie
|
||||
}
|
||||
holder.itemView.setOnClickListener {
|
||||
if (game.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(game.miniGameAppId, game.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(game)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
binding.root.context,
|
||||
|
||||
@ -140,7 +140,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
|
||||
searchToolbarTabWrapperViewModel =
|
||||
viewModelProviderFromParent(
|
||||
SearchToolbarTabWrapperViewModel.Factory(multiTabNavId, noTabLinkId),
|
||||
multiTabNavId
|
||||
multiTabNavId + noTabLinkId
|
||||
)
|
||||
}
|
||||
if (bottomTabId.isNotEmpty()) {
|
||||
@ -292,7 +292,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
|
||||
|
||||
gameDetailDestination.observe(viewLifecycleOwner, EventObserver { (entrance, game) ->
|
||||
if (game.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(game.miniGameAppId, game.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(game)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
requireContext(),
|
||||
|
||||
@ -78,6 +78,7 @@ class CustomPageViewModel(
|
||||
addSource(repository.customDiscoverItemLiveData, ::notifyItemChanged)
|
||||
addSource(repository.recentGamesItemLiveData, ::notifyItemChanged)
|
||||
addSource(repository.customPluginItemLiveData, ::notifyItemChanged)
|
||||
addSource(repository.wechatMiniGameCPMItemLiveData, ::notifyWechatMiniGameCPMSubjectItemChanged)
|
||||
}
|
||||
|
||||
val dataList: LiveData<List<CustomPageItem>> = _dataList
|
||||
@ -357,11 +358,11 @@ class CustomPageViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChangeABatch(subjectEntity: SubjectEntity, position: Int) {
|
||||
override fun onChangeABatch(subjectEntity: SubjectEntity) {
|
||||
val subjectId = subjectEntity.id ?: return
|
||||
val gameList = subjectChangedMap[subjectId]
|
||||
if (gameList != null) {
|
||||
changeSubjectCustomPageItem(position, getRandomGameList(subjectEntity.data, ArrayList(gameList)))
|
||||
changeSubjectCustomPageItem(subjectId, getRandomGameList(subjectEntity.data, ArrayList(gameList)))
|
||||
} else {
|
||||
repository.loadChangeSubjectGame(subjectEntity)
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -370,7 +371,7 @@ class CustomPageViewModel(
|
||||
override fun onResponse(response: List<GameEntity>?) {
|
||||
if (response != null) {
|
||||
subjectChangedMap[subjectId] = response
|
||||
onChangeABatch(subjectEntity, position)
|
||||
onChangeABatch(subjectEntity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -396,21 +397,32 @@ class CustomPageViewModel(
|
||||
return resultGameList
|
||||
}
|
||||
|
||||
private fun changeSubjectCustomPageItem(position: Int, newGameList: MutableList<GameEntity>) {
|
||||
private fun changeSubjectCustomPageItem(id: String, newGameList: MutableList<GameEntity>) {
|
||||
val oldData = _dataList.value as? MutableList<CustomPageItem>
|
||||
if (!oldData.isNullOrEmpty() && newGameList.isNotEmpty()) {
|
||||
val newData = oldData?.toMutableList()
|
||||
if (!newData.isNullOrEmpty() && newGameList.isNotEmpty()) {
|
||||
// 替换当前专题游戏数据
|
||||
val customPageItem = oldData.getOrNull(position)
|
||||
val position = newData.indexOfFirst {
|
||||
when(it) {
|
||||
is CustomSubjectItem -> it.data.id == id
|
||||
is CustomSplitSubjectItem -> it.data.id == id
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
if (position == -1) return
|
||||
|
||||
val customPageItem = newData[position]
|
||||
if (customPageItem is CustomSubjectItem) {
|
||||
val newCustomPageItem = customPageItem.copy(data = customPageItem.data.copy(mData = newGameList))
|
||||
oldData[position] = newCustomPageItem
|
||||
val newCustomPageItem =
|
||||
customPageItem.copy(data = customPageItem.data.copy(mData = newGameList), _position = position)
|
||||
newData[position] = newCustomPageItem
|
||||
gamePositionAndPackageHelper.putAll(getPositionAndPackageMap(newCustomPageItem, newGameList))
|
||||
}
|
||||
|
||||
if (customPageItem is CustomSplitSubjectItem) {
|
||||
|
||||
// 移除所有旧数据
|
||||
oldData.removeAll {
|
||||
newData.removeAll {
|
||||
it.componentPosition == customPageItem.componentPosition
|
||||
}
|
||||
|
||||
@ -433,21 +445,15 @@ class CustomPageViewModel(
|
||||
)
|
||||
|
||||
// 将新的 items 添加到列表集合
|
||||
if (position >= oldData.size) {
|
||||
oldData.addAll(newItems)
|
||||
} else {
|
||||
oldData.addAll(position, newItems)
|
||||
}
|
||||
|
||||
newData.addAll(position, newItems)
|
||||
|
||||
// 修正集合中 item 的position 取值
|
||||
oldData.forEachIndexed { index, item ->
|
||||
newData.forEachIndexed { index, item ->
|
||||
item.position = index
|
||||
}
|
||||
|
||||
}
|
||||
// 通知更新
|
||||
_dataList.value = oldData
|
||||
_dataList.value = newData
|
||||
}
|
||||
}
|
||||
|
||||
@ -467,6 +473,40 @@ class CustomPageViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过CPM接口异步请求获取的微信小游戏数据插入
|
||||
*/
|
||||
private fun notifyWechatMiniGameCPMSubjectItemChanged(result: Pair<String, List<GameEntity>>) {
|
||||
val oldData = _dataList.value ?: return
|
||||
val index = oldData.indexOfFirst {
|
||||
it is CustomWeChatMiniGamesCPMSubjectItem && it.data.id == result.first
|
||||
}
|
||||
if (index == -1) return
|
||||
val subjectItem = (oldData[index] as CustomWeChatMiniGamesCPMSubjectItem).apply {
|
||||
data.data = result.second.toMutableList()
|
||||
data.isWechatColumnCPM = true
|
||||
}
|
||||
val position = subjectItem.position
|
||||
val componentPosition = subjectItem.componentPosition
|
||||
val newData = oldData.toMutableList()
|
||||
val customPageItemList = repository.convertColumnDetailSubjectItems(
|
||||
position,
|
||||
componentPosition,
|
||||
subjectItem.link,
|
||||
subjectItem.data
|
||||
)
|
||||
if (customPageItemList.isEmpty()) return
|
||||
newData[index] = customPageItemList[0]
|
||||
newData.addAll(index + 1, customPageItemList.subList(1, customPageItemList.size))
|
||||
newData.forEachIndexed { pos, customPageItem ->
|
||||
customPageItem.position = pos
|
||||
}
|
||||
repository.notifyPositionChanged(newData.size)
|
||||
gamePositionAndPackageHelper.clear()
|
||||
gamePositionAndPackageHelper.putAll(getPositionAndPackageMap(newData))
|
||||
_dataList.value = newData
|
||||
}
|
||||
|
||||
private fun notifyItemRemoved(removeItem: CustomPageItem) {
|
||||
val oldData = _dataList.value ?: return
|
||||
val newData = oldData.toMutableList()
|
||||
@ -476,7 +516,7 @@ class CustomPageViewModel(
|
||||
for (i in removeItem.position until newData.size) {
|
||||
newData[i].position--
|
||||
}
|
||||
repository.notifyPositionChanged(-1)
|
||||
repository.notifyPositionAdded(-1)
|
||||
gamePositionAndPackageHelper.clear()
|
||||
gamePositionAndPackageHelper.putAll(getPositionAndPackageMap(newData))
|
||||
_dataList.value = newData
|
||||
|
||||
@ -134,7 +134,7 @@ class CustomGameHorizontalAdapter(
|
||||
}
|
||||
|
||||
if (gameEntity.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(
|
||||
context,
|
||||
|
||||
@ -29,7 +29,7 @@ interface OnCustomPageEventListener {
|
||||
/**
|
||||
* 换一批
|
||||
*/
|
||||
fun onChangeABatch(subjectEntity: SubjectEntity, position: Int)
|
||||
fun onChangeABatch(subjectEntity: SubjectEntity)
|
||||
|
||||
fun onChangeAppBarColor(color: Int)
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ class SubjectEventHelper(viewModel: CustomPageViewModel) : CustomPageItemChildEv
|
||||
|
||||
fun onChangeABatch(subject: SubjectEntity) {
|
||||
tracker.trackColumnClick(_item, null, "右上角", "换一批")
|
||||
viewModel.onChangeABatch(subject, _item.position)
|
||||
viewModel.onChangeABatch(subject)
|
||||
}
|
||||
|
||||
fun onMoreClick(link: LinkEntity) {
|
||||
|
||||
@ -73,6 +73,8 @@ class CustomPageData(
|
||||
val qqMiniGameColumn: SubjectEntity? = null,
|
||||
@SerializedName("link_wechat_game_column_detail")
|
||||
val wechatMiniGameColumn: SubjectEntity? = null,
|
||||
@SerializedName("link_wechat_game_cpm_column_detail")
|
||||
val wechatMiniGameCPMColumn: SubjectEntity? = null,
|
||||
@SerializedName("link_common_collection")
|
||||
val linkCommonCollection: CommonContentCollection? = null,
|
||||
@SerializedName("link_qq_game_recently_played")
|
||||
@ -83,6 +85,7 @@ class CustomPageData(
|
||||
get() = when (link.type) {
|
||||
CustomPageItem.CUSTOM_LINK_TYPE_QQ_MINI_GAME_COLUMN_DETAIL -> qqMiniGameColumn
|
||||
CustomPageItem.CUSTOM_LINK_TYPE_WECHAT_MINI_GAME_COLUMN_DETAIL -> wechatMiniGameColumn
|
||||
CustomPageItem.CUSTOM_LINK_TYPE_WECHAT_WECHAT_GAME_CPM_COLUMN_DETAIL -> wechatMiniGameCPMColumn
|
||||
else -> linkColumn
|
||||
}
|
||||
|
||||
@ -672,7 +675,7 @@ class CustomPageData(
|
||||
@SerializedName("home")
|
||||
private val _home: String? = null,
|
||||
@SerializedName("more_link")
|
||||
val moreLink: LinkEntity? = null
|
||||
val moreLink: LinkEntity? = null
|
||||
) {
|
||||
|
||||
val home: String
|
||||
|
||||
@ -4,10 +4,7 @@ import com.gh.common.util.ViewPagerFragmentHelper
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.exposure.ExposureSource
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.entity.AmwayCommentEntity
|
||||
import com.gh.gamecenter.entity.DiscoveryCardEntity
|
||||
import com.gh.gamecenter.entity.HomeItemTestV2Entity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.vspace.VGameItemData
|
||||
@ -84,6 +81,7 @@ abstract class CustomPageItem(
|
||||
const val CUSTOM_LINK_TYPE_WECHAT_GAME_RECENTLY_PLAYED = "wechat_game_recently_played"
|
||||
const val CUSTOM_LINK_TYPE_QQ_MINI_GAME_COLUMN_DETAIL = ViewPagerFragmentHelper.TYPE_QQ_MINI_GAME_COLUMN
|
||||
const val CUSTOM_LINK_TYPE_WECHAT_MINI_GAME_COLUMN_DETAIL = ViewPagerFragmentHelper.TYPE_WECHAT_GAME_COLUMN
|
||||
const val CUSTOM_LINK_TYPE_WECHAT_WECHAT_GAME_CPM_COLUMN_DETAIL = ViewPagerFragmentHelper.TYPE_WECHAT_GAME_CPM_COLUMN
|
||||
const val CUSTOM_LINK_TYPE_HALO_RECOMMEND = "halo_recommend"
|
||||
const val CUSTOM_LINK_TYPE_COLUMN_COLLECTION = "column_collection" // 专题合集
|
||||
const val CUSTOM_LINK_TYPE_GAME_LIST_COLLECTION = "game_list_collection"
|
||||
@ -300,6 +298,7 @@ abstract class CustomPageItem(
|
||||
CUSTOM_LINK_TYPE_WECHAT_GAME_RECENTLY_PLAYED to "最近在玩",
|
||||
CUSTOM_LINK_TYPE_QQ_MINI_GAME_COLUMN_DETAIL to "QQ小游戏专题",
|
||||
CUSTOM_LINK_TYPE_WECHAT_MINI_GAME_COLUMN_DETAIL to "微信小游戏专题",
|
||||
CUSTOM_LINK_TYPE_WECHAT_WECHAT_GAME_CPM_COLUMN_DETAIL to "微信小游戏专题",
|
||||
CUSTOM_LINK_TYPE_HALO_RECOMMEND to "光环推荐",
|
||||
CUSTOM_LINK_TYPE_COLUMN_COLLECTION to "专题合集",
|
||||
CUSTOM_LINK_TYPE_GAME_LIST_COLLECTION to "游戏单合集",
|
||||
@ -623,6 +622,25 @@ data class CustomRecentWeChatMiniGamesItem(
|
||||
}
|
||||
}
|
||||
|
||||
// 微信小游戏CPM专题组件
|
||||
data class CustomWeChatMiniGamesCPMSubjectItem(
|
||||
private val _link: LinkEntity,
|
||||
val data: SubjectEntity,
|
||||
private val _position: Int,
|
||||
private val _componentPosition: Int
|
||||
) : CustomPageItem(_link, _position, _componentPosition) {
|
||||
|
||||
override val itemType: Int
|
||||
get() = CUSTOM_PAGE_ITEM_TYPE_MINI_GAME_RECENT_PLAY
|
||||
|
||||
override fun doAreContentsTheSames(other: CustomPageItem): Boolean {
|
||||
return other is CustomWeChatMiniGamesCPMSubjectItem
|
||||
&& data == other.data
|
||||
&& position == other.position
|
||||
&& componentPosition == other.componentPosition
|
||||
}
|
||||
}
|
||||
|
||||
// qq小游戏-最近在玩
|
||||
data class CustomRecentQqMiniGamesItem(
|
||||
private val _link: LinkEntity,
|
||||
|
||||
@ -3,12 +3,12 @@ package com.gh.gamecenter.home.custom.model
|
||||
import android.graphics.Paint
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.util.GameSubstituteRepositoryHelper
|
||||
import com.gh.common.util.HomePluggableHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.entity.LinkEntity
|
||||
import com.gh.gamecenter.common.utils.TextHelper
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.sp2px
|
||||
@ -18,11 +18,11 @@ import com.gh.gamecenter.entity.DiscoveryCardEntity
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity
|
||||
import com.gh.gamecenter.entity.PullDownPush
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.FloatingWindowEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.PluginLocation
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity
|
||||
import com.gh.gamecenter.feature.utils.ApkActiveUtils
|
||||
import com.gh.gamecenter.feature.entity.FloatingWindowEntity
|
||||
import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_BANNER
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_DOUBLE_ROW_BANNER
|
||||
@ -47,7 +47,6 @@ import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_S
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL_SLIDE
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_TIMELINE_HORIZONTAL_SLIDE
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_SLIDE
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_SINGLE_GAME_CARD
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_COLUMN
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_GAME
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_HALO_RECOMMEND
|
||||
@ -55,7 +54,11 @@ import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_QQ_MINI_GAME_COLUMN_DETAIL
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_WECHAT_GAME_RECENTLY_PLAYED
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_WECHAT_MINI_GAME_COLUMN_DETAIL
|
||||
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_WECHAT_WECHAT_GAME_CPM_COLUMN_DETAIL
|
||||
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayUseCase
|
||||
import com.gh.gamecenter.minigame.wechat.WGameSubjectCPMListRepository
|
||||
import com.gh.gamecenter.minigame.wechat.WGameSubjectCPMListUseCase
|
||||
import com.gh.gamecenter.minigame.wechat.WGameSubjectCPMRemoteDataSource
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.wrapper.MainWrapperRepository
|
||||
@ -63,12 +66,14 @@ import com.gh.vspace.VHelper
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.regex.Pattern
|
||||
|
||||
|
||||
class CustomPageRepository private constructor(
|
||||
private val remoteDataSource: CustomPageRemoteDataSource,
|
||||
private val localDataSource: CustomPageLocalDataSource
|
||||
private val localDataSource: CustomPageLocalDataSource,
|
||||
private val wGameSubjectCPMRemoteDataSource: WGameSubjectCPMRemoteDataSource
|
||||
) {
|
||||
|
||||
private val pageInfo = PageInfo()
|
||||
@ -77,6 +82,10 @@ class CustomPageRepository private constructor(
|
||||
|
||||
private val shareRepository = CustomPageShareRepository.instance
|
||||
|
||||
private val wGameSubjectCPMListUseCase = WGameSubjectCPMListUseCase(
|
||||
WGameSubjectCPMListRepository(wGameSubjectCPMRemoteDataSource)
|
||||
)
|
||||
|
||||
private var recentItem: CustomRecentGamesItem? = null
|
||||
|
||||
private var recentQQItem: CustomRecentQqMiniGamesItem? = null
|
||||
@ -91,14 +100,13 @@ class CustomPageRepository private constructor(
|
||||
|
||||
private var displayingGameIdSet = hashSetOf<String>() // 当前正在显示的游戏 id 列表
|
||||
|
||||
private val _customPluginItemLiveData = MediatorLiveData<CustomPluginItem>().apply {
|
||||
val customPluginItemLiveData: LiveData<CustomPluginItem> = MediatorLiveData<CustomPluginItem>().apply {
|
||||
addSource(PackageRepository.gameUpdateLiveData) {
|
||||
refreshPluginIfNeed(it)?.let(this::setValue)
|
||||
}
|
||||
}
|
||||
val customPluginItemLiveData: LiveData<CustomPluginItem> = _customPluginItemLiveData
|
||||
|
||||
private val _recentGamesItemLiveData = MediatorLiveData<CustomRecentGamesItem>().apply {
|
||||
val recentGamesItemLiveData: LiveData<CustomRecentGamesItem> = MediatorLiveData<CustomRecentGamesItem>().apply {
|
||||
addSource(DownloadManager.getInstance().downloadEntityLiveData) {
|
||||
refreshRecentVGameIfNeed()?.let(this::setValue)
|
||||
}
|
||||
@ -106,29 +114,30 @@ class CustomPageRepository private constructor(
|
||||
refreshRecentVGameIfNeed()?.let(this::setValue)
|
||||
}
|
||||
}
|
||||
val recentGamesItemLiveData: LiveData<CustomRecentGamesItem> = _recentGamesItemLiveData
|
||||
|
||||
private val _recentMiniGamesItemLiveData = MediatorLiveData<CustomRecentWeChatMiniGamesItem>().apply {
|
||||
addSource(MiniGameRecentlyPlayUseCase.wechatRecentGamesItemLiveData) {
|
||||
refreshRecentWechatMiniGameIfNeed(it)?.let(this::setValue)
|
||||
val recentMiniGamesItemLiveData: LiveData<CustomRecentWeChatMiniGamesItem> =
|
||||
MediatorLiveData<CustomRecentWeChatMiniGamesItem>().apply {
|
||||
addSource(MiniGameRecentlyPlayUseCase.wechatRecentGamesItemLiveData) {
|
||||
refreshRecentWechatMiniGameIfNeed(it)?.let(this::setValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val recentMiniGamesItemLiveData: LiveData<CustomRecentWeChatMiniGamesItem> = _recentMiniGamesItemLiveData
|
||||
|
||||
private val _recentQqMiniGamesItemLiveData = MediatorLiveData<CustomRecentQqMiniGamesItem>().apply {
|
||||
addSource(MiniGameRecentlyPlayUseCase.qqRecentGamesItemLiveData) {
|
||||
refreshRecentQQMiniGameIfNeed(it)?.let(this::setValue)
|
||||
val recentQqMiniGamesItemLiveData: LiveData<CustomRecentQqMiniGamesItem> =
|
||||
MediatorLiveData<CustomRecentQqMiniGamesItem>().apply {
|
||||
addSource(MiniGameRecentlyPlayUseCase.qqRecentGamesItemLiveData) {
|
||||
refreshRecentQQMiniGameIfNeed(it)?.let(this::setValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
val recentQqMiniGamesItemLiveData: LiveData<CustomRecentQqMiniGamesItem> = _recentQqMiniGamesItemLiveData
|
||||
|
||||
private val _customDiscoverItemLiveData = MediatorLiveData<CustomDiscoverCardItem>().apply {
|
||||
addSource(shareRepository.discoverData) {
|
||||
refreshDiscoverDataIfNeed(it)?.let(this::setValue)
|
||||
val customDiscoverItemLiveData: LiveData<CustomDiscoverCardItem> =
|
||||
MediatorLiveData<CustomDiscoverCardItem>().apply {
|
||||
addSource(shareRepository.discoverData) {
|
||||
refreshDiscoverDataIfNeed(it)?.let(this::setValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
val customDiscoverItemLiveData: LiveData<CustomDiscoverCardItem> = _customDiscoverItemLiveData
|
||||
|
||||
val wechatMiniGameCPMItemLiveData: LiveData<Pair<String, List<GameEntity>>> =
|
||||
wGameSubjectCPMListUseCase.wechatMiniGameCPMListLiveData
|
||||
|
||||
val hiddenNotifications: LiveData<HashMap<String, MutableSet<String>>>
|
||||
get() = shareRepository.hiddenNotifications
|
||||
@ -224,6 +233,7 @@ class CustomPageRepository private constructor(
|
||||
|
||||
private fun transformRawDataIntoItemData(data: CustomPageData, reloadDiscoverData: Boolean): List<CustomPageItem> {
|
||||
val list = arrayListOf<CustomPageItem>()
|
||||
|
||||
data.customsComponents
|
||||
.forEachIndexed { _, item ->
|
||||
// 如果当前item不是展开大图,并且上一个item为展开大图,则说明展开大图组件已结束
|
||||
@ -265,112 +275,24 @@ class CustomPageRepository private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
item.link.type == CUSTOM_LINK_TYPE_COLUMN || item.link.type == CUSTOM_LINK_TYPE_QQ_MINI_GAME_COLUMN_DETAIL || item.link.type == CUSTOM_LINK_TYPE_WECHAT_MINI_GAME_COLUMN_DETAIL -> {
|
||||
// 游戏专题
|
||||
val gameSubject = item.gameSubjectEntity?.also {
|
||||
if (item.link.type == CUSTOM_LINK_TYPE_COLUMN) {
|
||||
it.data?.forEach { game ->
|
||||
game.gameLocation = GameEntity.GameLocation.INDEX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isAdded = false
|
||||
if (gameSubject != null && !gameSubject.data.isNullOrEmpty()) {
|
||||
// 记录已显示的游戏 id
|
||||
for (game in gameSubject.data!!) {
|
||||
displayingGameIdSet.add(game.id)
|
||||
}
|
||||
|
||||
// 替换游戏
|
||||
substituteGameIfNeeded(gameSubject)
|
||||
|
||||
if (gameSubject.tag == "update") {
|
||||
// 优先显示更新标签
|
||||
gameSubject.data?.forEach {
|
||||
it.tagStyle.clear()
|
||||
it.tagStyle.add(
|
||||
TagStyleEntity(
|
||||
id = "local_generated",
|
||||
name = TimeUtils.getFormatTime(it.updateTime, "MM-dd") + " 更新",
|
||||
color = "1383EB",
|
||||
background = "E8F3FF",
|
||||
column = "1383EB"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
when (gameSubject.type) {
|
||||
COMPONENTS_GAME_SUBJECT_TYPE_DOUBLE_CARD, COMPONENTS_SUBJECT_TYPE_DOUBLE_GAME_WELFARE_CARD -> {
|
||||
// 双列卡片 双列福利卡片
|
||||
val gameCount = gameSubject.data?.size ?: 0
|
||||
if (gameCount >= COMPONENT_TYPE_COLUMN_LIMIT_TWO_COUNT) {
|
||||
val subjectItems = convertSplitSubjectItems(item, 2, false)
|
||||
list.addAll(subjectItems)
|
||||
isAdded = true
|
||||
}
|
||||
}
|
||||
|
||||
COMPONENTS_GAME_SUBJECT_TYPE_GAME_VERTICAL -> {
|
||||
// 长列表式
|
||||
val subjectItems = convertSplitSubjectItems(item, 1, false)
|
||||
list.addAll(subjectItems)
|
||||
isAdded = true
|
||||
}
|
||||
|
||||
COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL -> {
|
||||
// 图标矩阵
|
||||
val subjectItems = convertSplitSubjectItems(item, 4, true)
|
||||
list.addAll(subjectItems)
|
||||
isAdded = true
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (gameSubject.type == COMPONENTS_GAME_SUBJECT_TYPE_GAME_VIDEO_HORIZONTAL_SLIDE ||
|
||||
gameSubject.type == COMPONENTS_SUBJECT_TYPE_GAME_FOLD_SLIDE
|
||||
) {
|
||||
val gameCount = gameSubject.data?.size ?: 0
|
||||
if (gameCount >= COMPONENT_TYPE_COLUMN_LIMIT_TWO_COUNT) {
|
||||
list.add(
|
||||
CustomSubjectItem(
|
||||
item.link,
|
||||
gameSubject,
|
||||
pageInfo.position,
|
||||
pageInfo.componentPosition
|
||||
)
|
||||
)
|
||||
pageInfo.positionIncrement()
|
||||
isAdded = true
|
||||
}
|
||||
|
||||
} else {
|
||||
val gameCount = gameSubject.data?.size ?: 0
|
||||
if (gameCount > 0) {
|
||||
list.add(
|
||||
CustomSubjectItem(
|
||||
item.link,
|
||||
gameSubject,
|
||||
pageInfo.position,
|
||||
pageInfo.componentPosition
|
||||
)
|
||||
)
|
||||
pageInfo.positionIncrement()
|
||||
isAdded = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (isAdded) {
|
||||
pageInfo.componentPositionIncrement()
|
||||
}
|
||||
item.link.type == CUSTOM_LINK_TYPE_COLUMN
|
||||
|| item.link.type == CUSTOM_LINK_TYPE_QQ_MINI_GAME_COLUMN_DETAIL
|
||||
|| item.link.type == CUSTOM_LINK_TYPE_WECHAT_MINI_GAME_COLUMN_DETAIL -> {
|
||||
val subItems = convertColumnDetailSubjectItems(
|
||||
pageInfo.position,
|
||||
pageInfo.componentPosition,
|
||||
item.link,
|
||||
item.gameSubjectEntity
|
||||
)
|
||||
if (subItems.isNotEmpty()) {
|
||||
list.addAll(subItems)
|
||||
pageInfo.positionGetAndAdd(subItems.size)
|
||||
pageInfo.componentPositionIncrement()
|
||||
}
|
||||
}
|
||||
|
||||
//QQ小游戏-最近在玩(需要用户登录才显示)
|
||||
item.link.type == CUSTOM_LINK_TYPE_QQ_GAME_RECENTLY_PLAYED -> {
|
||||
//QQ小游戏-最近在玩(需要用户登录才显示)
|
||||
val linkQqGameRecentlyPlayed = item.linkQqGameRecentlyPlayed
|
||||
if (linkQqGameRecentlyPlayed != null) {
|
||||
recentQQItem = CustomRecentQqMiniGamesItem(
|
||||
@ -386,8 +308,8 @@ class CustomPageRepository private constructor(
|
||||
|
||||
}
|
||||
|
||||
// 微信小游戏-最近在玩
|
||||
item.link.type == CUSTOM_LINK_TYPE_WECHAT_GAME_RECENTLY_PLAYED -> {
|
||||
// 微信小游戏-最近在玩
|
||||
recentWechatItem = CustomRecentWeChatMiniGamesItem(
|
||||
item.link,
|
||||
MiniGameRecentlyPlayUseCase.getRecentlyPlayedMiniGameList(Constants.WECHAT_MINI_GAME),
|
||||
@ -398,6 +320,23 @@ class CustomPageRepository private constructor(
|
||||
pageInfo.componentPositionIncrement()
|
||||
}
|
||||
|
||||
// 微信小游戏CPM专题
|
||||
item.link.type == CUSTOM_LINK_TYPE_WECHAT_WECHAT_GAME_CPM_COLUMN_DETAIL -> {
|
||||
item.gameSubjectEntity?.let { subject ->
|
||||
list.add(
|
||||
CustomWeChatMiniGamesCPMSubjectItem(
|
||||
item.link,
|
||||
subject,
|
||||
pageInfo.position,
|
||||
pageInfo.componentPosition
|
||||
)
|
||||
)
|
||||
wGameSubjectCPMListUseCase.getWechatMiniGameCPMList(subject.id)
|
||||
pageInfo.positionIncrement()
|
||||
pageInfo.componentPositionIncrement()
|
||||
}
|
||||
}
|
||||
|
||||
item.linkColumnCollection != null -> {
|
||||
// 专题合集
|
||||
val linkColumnCollection = item.linkColumnCollection
|
||||
@ -475,7 +414,9 @@ class CustomPageRepository private constructor(
|
||||
|| layout == COMMON_CONTENT_COLLECTION_LAYOUT_DOUBLE_ROW_VERTICAL_CARD
|
||||
|| layout == COMMON_CONTENT_COLLECTION_LAYOUT_VERTICAL_IMAGE_TEXT
|
||||
) {
|
||||
list.addAll(convertSplitCommonContentCollection(item))
|
||||
val subItems = convertSplitCommonContentCollection(item)
|
||||
list.addAll(subItems)
|
||||
pageInfo.positionGetAndAdd(subItems.size)
|
||||
pageInfo.componentPositionIncrement()
|
||||
} else {
|
||||
var show = true
|
||||
@ -528,12 +469,16 @@ class CustomPageRepository private constructor(
|
||||
// 最近在玩
|
||||
val entities = VHelper.getSortedRecentlyPlayedList()
|
||||
recentItem =
|
||||
CustomRecentGamesItem(item.link, entities, pageInfo.position, pageInfo.componentPosition)
|
||||
.also {
|
||||
list.add(it)
|
||||
pageInfo.positionIncrement()
|
||||
pageInfo.componentPositionIncrement()
|
||||
}
|
||||
CustomRecentGamesItem(
|
||||
item.link,
|
||||
entities,
|
||||
pageInfo.position,
|
||||
pageInfo.componentPosition
|
||||
).also {
|
||||
list.add(it)
|
||||
pageInfo.positionIncrement()
|
||||
pageInfo.componentPositionIncrement()
|
||||
}
|
||||
}
|
||||
|
||||
item.link.type == "plugin_area" -> {
|
||||
@ -666,45 +611,155 @@ class CustomPageRepository private constructor(
|
||||
}
|
||||
|
||||
pageInfo.nextPage()
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
fun convertColumnDetailSubjectItems(
|
||||
position: Int,
|
||||
componentPosition: Int,
|
||||
link: LinkEntity,
|
||||
subjectEntity: SubjectEntity?,
|
||||
): List<CustomPageItem> {
|
||||
|
||||
var currentPosition = position
|
||||
val list = mutableListOf<CustomPageItem>()
|
||||
|
||||
// 游戏专题
|
||||
val gameSubject = subjectEntity?.also {
|
||||
if (link.type == CUSTOM_LINK_TYPE_COLUMN) {
|
||||
it.data?.forEach { game ->
|
||||
game.gameLocation = GameEntity.GameLocation.INDEX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gameSubject != null && !gameSubject.data.isNullOrEmpty()) {
|
||||
// 记录已显示的游戏 id
|
||||
for (game in gameSubject.data!!) {
|
||||
displayingGameIdSet.add(game.id)
|
||||
}
|
||||
|
||||
// 替换游戏
|
||||
substituteGameIfNeeded(gameSubject)
|
||||
|
||||
if (gameSubject.tag == "update") {
|
||||
// 优先显示更新标签
|
||||
gameSubject.data?.forEach {
|
||||
it.tagStyle.clear()
|
||||
it.tagStyle.add(
|
||||
TagStyleEntity(
|
||||
id = "local_generated",
|
||||
name = TimeUtils.getFormatTime(it.updateTime, "MM-dd") + " 更新",
|
||||
color = "1383EB",
|
||||
background = "E8F3FF",
|
||||
column = "1383EB"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
when (gameSubject.type) {
|
||||
COMPONENTS_GAME_SUBJECT_TYPE_DOUBLE_CARD, COMPONENTS_SUBJECT_TYPE_DOUBLE_GAME_WELFARE_CARD -> {
|
||||
// 双列卡片 双列福利卡片
|
||||
val gameCount = gameSubject.data?.size ?: 0
|
||||
if (gameCount >= COMPONENT_TYPE_COLUMN_LIMIT_TWO_COUNT) {
|
||||
val subjectItems =
|
||||
convertSplitSubjectItems(link, subjectEntity, currentPosition, componentPosition, 2, false)
|
||||
list.addAll(subjectItems)
|
||||
currentPosition += subjectItems.size
|
||||
}
|
||||
}
|
||||
|
||||
COMPONENTS_GAME_SUBJECT_TYPE_GAME_VERTICAL -> {
|
||||
// 长列表式
|
||||
val subjectItems =
|
||||
convertSplitSubjectItems(link, subjectEntity, currentPosition, componentPosition, 1, false)
|
||||
list.addAll(subjectItems)
|
||||
currentPosition += subjectItems.size
|
||||
}
|
||||
|
||||
COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL -> {
|
||||
// 图标矩阵
|
||||
val subjectItems =
|
||||
convertSplitSubjectItems(link, subjectEntity, currentPosition, componentPosition, 4, true)
|
||||
list.addAll(subjectItems)
|
||||
currentPosition += subjectItems.size
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (gameSubject.type == COMPONENTS_GAME_SUBJECT_TYPE_GAME_VIDEO_HORIZONTAL_SLIDE ||
|
||||
gameSubject.type == COMPONENTS_SUBJECT_TYPE_GAME_FOLD_SLIDE
|
||||
) {
|
||||
val gameCount = gameSubject.data?.size ?: 0
|
||||
if (gameCount >= COMPONENT_TYPE_COLUMN_LIMIT_TWO_COUNT) {
|
||||
list.add(
|
||||
CustomSubjectItem(
|
||||
link,
|
||||
gameSubject,
|
||||
currentPosition,
|
||||
componentPosition
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
} else {
|
||||
val gameCount = gameSubject.data?.size ?: 0
|
||||
if (gameCount > 0) {
|
||||
list.add(
|
||||
CustomSubjectItem(
|
||||
link,
|
||||
gameSubject,
|
||||
currentPosition,
|
||||
componentPosition
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
|
||||
private fun convertSplitSubjectItems(
|
||||
item: CustomPageData.CustomsComponent,
|
||||
link: LinkEntity,
|
||||
subjectEntity: SubjectEntity?,
|
||||
position: Int,
|
||||
componentPosition: Int,
|
||||
stepNum: Int,
|
||||
isMustFullyCover: Boolean
|
||||
): List<CustomPageItem> {
|
||||
val gameSubject = item.gameSubjectEntity ?: return emptyList()
|
||||
val gameSubject = subjectEntity ?: return emptyList()
|
||||
val items = arrayListOf<CustomPageItem>()
|
||||
val games = gameSubject.data ?: emptyList()
|
||||
var currentPosition = position
|
||||
(games.indices step stepNum).forEach { start ->
|
||||
if (isMustFullyCover) {
|
||||
if (start + stepNum - 1 < games.size) {
|
||||
items.add(
|
||||
CustomSplitSubjectItem(
|
||||
item.link,
|
||||
link,
|
||||
gameSubject,
|
||||
pageInfo.position,
|
||||
pageInfo.componentPosition,
|
||||
currentPosition++,
|
||||
componentPosition,
|
||||
stepNum,
|
||||
start
|
||||
)
|
||||
)
|
||||
pageInfo.positionIncrement()
|
||||
}
|
||||
} else {
|
||||
items.add(
|
||||
CustomSplitSubjectItem(
|
||||
item.link,
|
||||
link,
|
||||
gameSubject,
|
||||
pageInfo.position,
|
||||
pageInfo.componentPosition,
|
||||
currentPosition++,
|
||||
componentPosition,
|
||||
stepNum,
|
||||
start
|
||||
)
|
||||
)
|
||||
pageInfo.positionIncrement()
|
||||
}
|
||||
}
|
||||
items.forEach {
|
||||
@ -729,7 +784,6 @@ class CustomPageRepository private constructor(
|
||||
left
|
||||
)
|
||||
)
|
||||
pageInfo.positionIncrement()
|
||||
}
|
||||
return items
|
||||
}
|
||||
@ -742,12 +796,20 @@ class CustomPageRepository private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyPositionChanged(offset: Int) {
|
||||
pageInfo.position += offset
|
||||
fun notifyPositionAdded(offset: Int) {
|
||||
pageInfo.positionGetAndAdd(offset)
|
||||
}
|
||||
|
||||
fun notifyPositionChanged(value: Int) {
|
||||
pageInfo.position = value
|
||||
}
|
||||
|
||||
fun loadChangeSubjectGame(subjectEntity: SubjectEntity): Observable<List<GameEntity>> =
|
||||
remoteDataSource.loadChangeSubjectGame(subjectEntity)
|
||||
if (subjectEntity.isWechatColumnCPM) {// 微信小游戏CPM专题的“换一批”接口
|
||||
wGameSubjectCPMRemoteDataSource.getRecommendCPMList(2, 10).toObservable()
|
||||
} else {
|
||||
remoteDataSource.loadChangeSubjectGame(subjectEntity)
|
||||
}
|
||||
.map(RegionSettingHelper.filterGame)
|
||||
.map(ApkActiveUtils.filterMapperList)
|
||||
|
||||
@ -798,16 +860,16 @@ class CustomPageRepository private constructor(
|
||||
val page: Int
|
||||
get() = _page
|
||||
|
||||
private var _position: Int = 0
|
||||
private var _position: AtomicInteger = AtomicInteger(0)
|
||||
var position: Int
|
||||
get() = _position
|
||||
get() = _position.get()
|
||||
set(value) {
|
||||
_position = value
|
||||
_position.set(value)
|
||||
}
|
||||
|
||||
private var _componentPosition = 0
|
||||
private var _componentPosition: AtomicInteger = AtomicInteger(0)
|
||||
val componentPosition: Int
|
||||
get() = _componentPosition
|
||||
get() = _componentPosition.get()
|
||||
|
||||
|
||||
fun nextPage() {
|
||||
@ -815,17 +877,25 @@ class CustomPageRepository private constructor(
|
||||
}
|
||||
|
||||
fun positionIncrement() {
|
||||
_position++
|
||||
positionGetAndAdd(1)
|
||||
}
|
||||
|
||||
fun componentPositionIncrement() {
|
||||
_componentPosition++
|
||||
componentPositionGetAndAdd(1)
|
||||
}
|
||||
|
||||
fun positionGetAndAdd(value: Int) {
|
||||
_position.getAndAdd(value)
|
||||
}
|
||||
|
||||
fun componentPositionGetAndAdd(value: Int) {
|
||||
_componentPosition.getAndAdd(value)
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
_page = 1
|
||||
_position = 0
|
||||
_componentPosition = 0
|
||||
_position.set(0)
|
||||
_componentPosition.set(0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -844,7 +914,8 @@ class CustomPageRepository private constructor(
|
||||
RetrofitManager.getInstance().newApi,
|
||||
MainWrapperRepository.getInstance()
|
||||
),
|
||||
CustomPageLocalDataSource()
|
||||
CustomPageLocalDataSource(),
|
||||
WGameSubjectCPMRemoteDataSource()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ class MiniGameRecentlyPlayListAdapter(
|
||||
if (onItemClick != null) {
|
||||
onItemClick.invoke(entity, position)
|
||||
} else {
|
||||
MiniGameItemHelper.launchMiniGame(entity.miniGameAppId, entity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ class MiniGameSearchDefaultRankAdapter(
|
||||
|
||||
// 转成Game实体比较好处理数据
|
||||
val trackGame = GameEntity(
|
||||
id = rank.id,
|
||||
_id = rank.id,
|
||||
mName = rank.name,
|
||||
miniGameAppId = rank.link.link ?: "",
|
||||
miniGameType = Constants.WECHAT_MINI_GAME,
|
||||
|
||||
@ -2,14 +2,16 @@ package com.gh.gamecenter.minigame
|
||||
|
||||
import com.gh.gamecenter.entity.SearchSubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.minigame.wechat.WGameSubjectCPMRemoteDataSource
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import com.gh.gamecenter.search.ISearchGameResultRepository
|
||||
import io.reactivex.Observable
|
||||
import java.net.URLEncoder
|
||||
import io.reactivex.Single
|
||||
|
||||
class MiniGameSearchResultRepository(
|
||||
private val api: ApiService = RetrofitManager.getInstance().newApi
|
||||
private val api: ApiService = RetrofitManager.getInstance().newApi,
|
||||
private val mWGameSubjectCPMDataSource: WGameSubjectCPMRemoteDataSource = WGameSubjectCPMRemoteDataSource()
|
||||
) : ISearchGameResultRepository {
|
||||
|
||||
override fun getSearchGame(
|
||||
@ -22,4 +24,8 @@ class MiniGameSearchResultRepository(
|
||||
override fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>> {
|
||||
return Observable.just(emptyList())
|
||||
}
|
||||
|
||||
override fun getWGameCPMGameList(): Single<MutableList<GameEntity>> {
|
||||
return mWGameSubjectCPMDataSource.getRecommendCPMList(1)
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,9 @@ import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import com.gh.gamecenter.subject.ISubjectRepository
|
||||
import io.reactivex.Observable
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.ResponseBody
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
|
||||
class QGameSubjectRepository(
|
||||
private val api: ApiService = RetrofitManager.getInstance().newApi
|
||||
@ -17,7 +19,7 @@ class QGameSubjectRepository(
|
||||
}
|
||||
|
||||
override fun getSubjectName(column_id: String?): Observable<ResponseBody> {
|
||||
return Observable.just(ResponseBody.create(MediaType.parse("application/json"), "{\"name\": \"专题\"}"))
|
||||
return Observable.just("{\"name\": \"专题\"}".toResponseBody("application/json".toMediaTypeOrNull()))
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.gh.gamecenter.minigame.wechat
|
||||
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.subject.ISubjectListRepository
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
class WGameSubjectCPMListRepository(
|
||||
private val dataSource: WGameSubjectCPMRemoteDataSource = WGameSubjectCPMRemoteDataSource()
|
||||
) : ISubjectListRepository {
|
||||
|
||||
override fun getColumn(column_id: String?, page: Int, sort: String?, order: String?): Single<MutableList<GameEntity>> {
|
||||
return dataSource.getRecommendCPMList(page)
|
||||
}
|
||||
|
||||
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {
|
||||
return Observable.just(SubjectSettingEntity())
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.gh.gamecenter.minigame.wechat
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.gh.gamecenter.common.livedata.NonStickyMutableLiveData
|
||||
import com.gh.gamecenter.common.retrofit.BiResponse
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
/**
|
||||
* 微信小游戏CPM-网域层
|
||||
*/
|
||||
class WGameSubjectCPMListUseCase(
|
||||
private val repository: WGameSubjectCPMListRepository = WGameSubjectCPMListRepository()
|
||||
) {
|
||||
|
||||
/**
|
||||
* 微信专题CPM请求记录,用于避免重复请求,以专题ID作为Key
|
||||
*/
|
||||
private val requestKeyList = mutableListOf<String>()
|
||||
|
||||
/**
|
||||
* 微信小游戏CPM列表,这里的LiveData充当类似于EventBus的角色,因此使用NonStickyMutableLiveData
|
||||
*/
|
||||
private val _wechatMiniGameCPMListLiveData = NonStickyMutableLiveData<Pair<String, List<GameEntity>>>()
|
||||
val wechatMiniGameCPMListLiveData: LiveData<Pair<String, List<GameEntity>>> = _wechatMiniGameCPMListLiveData
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun getWechatMiniGameCPMList(subjectId: String?) {
|
||||
if (subjectId.isNullOrEmpty() || requestKeyList.contains(subjectId)) {
|
||||
return
|
||||
}
|
||||
|
||||
requestKeyList.add(subjectId)
|
||||
repository.getColumn(null, 1, null, null)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<List<GameEntity>>() {
|
||||
override fun onSuccess(data: List<GameEntity>) {
|
||||
requestKeyList.remove(subjectId)
|
||||
_wechatMiniGameCPMListLiveData.value = subjectId to data
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.gh.gamecenter.minigame.wechat
|
||||
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
import com.gh.gamecenter.common.utils.toRequestBody
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.entity.TagStyleEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.feature.retrofit.WGameCPMApiService
|
||||
import io.reactivex.Single
|
||||
|
||||
class WGameSubjectCPMRemoteDataSource(
|
||||
private val api: WGameCPMApiService = RetrofitManager.getInstance().wGameCPMApi
|
||||
) {
|
||||
|
||||
fun getRecommendCPMList(page: Int, pageSize: Int = 10): Single<MutableList<GameEntity>> {
|
||||
val meta = MetaUtil.getMeta()
|
||||
val request = mapOf(
|
||||
"head" to mapOf(
|
||||
"busiAppid" to Config.WGAME_CPM_BUSIAPPID,
|
||||
"oaid" to (meta.oaid ?: ""),
|
||||
"manufacturer" to (meta.manufacturer ?: ""),
|
||||
"mode" to (meta.model ?: ""),
|
||||
"androidId" to (MetaUtil.getAndroidId()),
|
||||
"imei" to (MetaUtil.getIMEI())
|
||||
),
|
||||
"body" to mapOf(
|
||||
"page" to page - 1,
|
||||
"pageSize" to pageSize,
|
||||
)
|
||||
)
|
||||
return api.getUserRecommendList(request.toRequestBody())
|
||||
.map {
|
||||
if (it.ret == 0) {
|
||||
it.appInfoList.map { info ->
|
||||
GameEntity(
|
||||
mName = info.appName,
|
||||
mIcon = info.logo,
|
||||
mBrief = info.briefIntro,
|
||||
miniGameUid = info.appID,
|
||||
miniGameAppId = info.userName,
|
||||
miniGameType = Constants.WECHAT_MINI_GAME_CPM,
|
||||
miniGameAppStatus = 2,
|
||||
miniGameAppPath = info.wechatAppPath,
|
||||
miniGameExtData = info.extData,
|
||||
miniGameRecommendId = info.recommendID,
|
||||
mTagStyle = arrayListOf(
|
||||
TagStyleEntity(name = info.categoryName),
|
||||
TagStyleEntity(name = info.subcategoryName)
|
||||
)
|
||||
)
|
||||
}.toMutableList()
|
||||
} else {
|
||||
mutableListOf()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.gh.gamecenter.minigame.wechat
|
||||
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.gh.gamecenter.subject.ISubjectRepository
|
||||
import io.reactivex.Observable
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.ResponseBody
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
|
||||
class WGameSubjectCPMRepository : ISubjectRepository {
|
||||
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {
|
||||
return Observable.just(SubjectSettingEntity())
|
||||
}
|
||||
|
||||
override fun getSubjectName(column_id: String?): Observable<ResponseBody> {
|
||||
return Observable.just("{\"name\": \"专题\"}".toResponseBody("application/json".toMediaTypeOrNull()))
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,9 @@ import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import com.gh.gamecenter.subject.ISubjectRepository
|
||||
import io.reactivex.Observable
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.ResponseBody
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
|
||||
class WGameSubjectRepository(
|
||||
private val api: ApiService = RetrofitManager.getInstance().newApi
|
||||
@ -16,6 +18,6 @@ class WGameSubjectRepository(
|
||||
}
|
||||
|
||||
override fun getSubjectName(column_id: String?): Observable<ResponseBody> {
|
||||
return Observable.just(ResponseBody.create(MediaType.parse("application/json"), "{\"name\": \"专题\"}"))
|
||||
return Observable.just("{\"name\": \"专题\"}".toResponseBody("application/json".toMediaTypeOrNull()))
|
||||
}
|
||||
}
|
||||
@ -374,12 +374,14 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
}
|
||||
|
||||
mSuperiorChain?.registerInferiorChain(mPriorityChain)
|
||||
startBannerAutoPlay()
|
||||
}
|
||||
|
||||
override fun onFragmentPause() {
|
||||
super.onFragmentPause()
|
||||
|
||||
mSuperiorChain?.unregisterInferiorChain(mPriorityChain)
|
||||
stopBannerAutoPlay()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult", "SetTextI18n")
|
||||
@ -1011,7 +1013,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
|
||||
}
|
||||
|
||||
private fun startBannerAutoPlay() {
|
||||
if (mPersonalBannerAdapter.getActualSize() < 2) return
|
||||
if (!::mPersonalBannerAdapter.isInitialized || mPersonalBannerAdapter.getActualSize() < 2) return
|
||||
stopBannerAutoPlay()
|
||||
mLooperHandle.sendEmptyMessageDelayed(mSlideLooperKey, BANNER_LOOP_TIME)
|
||||
}
|
||||
|
||||
@ -20,7 +20,9 @@ import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
@ -75,7 +77,7 @@ class InstalledGameDialog(
|
||||
jsonObject.put("package", game.packageName)
|
||||
objects.put(jsonObject)
|
||||
}
|
||||
val requestBody = RequestBody.create(MediaType.parse("application/json"), objects.toString())
|
||||
val requestBody = objects.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
RetrofitManager.getInstance().api
|
||||
.postPlayedGames(UserManager.getInstance().userId, requestBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@ -25,7 +25,9 @@ import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.json.JSONObject
|
||||
@ -259,10 +261,8 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
|
||||
fun toggleComment(answerId: String, isCommentable: Boolean) {
|
||||
val params = HashMap<String, Boolean>()
|
||||
params["commentable"] = isCommentable
|
||||
val body = RequestBody.create(
|
||||
MediaType.parse("application/json"),
|
||||
JSONObject(params as Map<*, *>).toString()
|
||||
)
|
||||
val body = JSONObject(params as Map<*, *>).toString()
|
||||
.toRequestBody("application/json".toMediaTypeOrNull())
|
||||
|
||||
RetrofitManager.getInstance()
|
||||
.api
|
||||
|
||||
@ -26,7 +26,9 @@ import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.json.JSONArray
|
||||
@ -144,7 +146,7 @@ class ArticleEditViewModel(application: Application) : BaseRichEditorViewModel(a
|
||||
if (draftEntity?.id != null) {
|
||||
articleBody.put("draft_id", draftEntity?.id)
|
||||
}
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), articleBody.toString())
|
||||
val body = articleBody.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
val observable = if (detailEntity == null) {
|
||||
mApi.postCommunityArticle(mSelectCommunityData?.id, body)
|
||||
} else {
|
||||
@ -226,7 +228,7 @@ class ArticleEditViewModel(application: Application) : BaseRichEditorViewModel(a
|
||||
if (mSelectCommunityData != null && mSelectCommunityData!!.id.isNotEmpty()) {
|
||||
articleBody.put("community_id", mSelectCommunityData!!.id)
|
||||
}
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), articleBody.toString())
|
||||
val body = articleBody.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
val observable = if (draftEntity?.id != null) {
|
||||
mApi.patchCommunityArticleDrafts(UserManager.getInstance().userId, draftEntity?.id, body)
|
||||
} else {
|
||||
|
||||
@ -40,7 +40,7 @@ class GameDefaultAdapter(
|
||||
val intent = Intent()
|
||||
intent.putExtra(
|
||||
GameEntity::class.java.simpleName,
|
||||
GameEntity(id = entity.gameId, mIcon = entity.gameIcon, mName = entity.gameName, mCategory = entity.category)
|
||||
GameEntity(_id = entity.gameId, mIcon = entity.gameIcon, mName = entity.gameName, mCategory = entity.category)
|
||||
)
|
||||
(mContext as Activity).setResult(Activity.RESULT_OK, intent)
|
||||
(mContext as Activity).finish()
|
||||
|
||||
@ -28,7 +28,9 @@ import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.json.JSONArray
|
||||
@ -266,7 +268,7 @@ class QuestionEditViewModel(application: Application) : BaseRichEditorViewModel(
|
||||
}
|
||||
|
||||
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), bodyJson)
|
||||
val body = bodyJson.toRequestBody("application/json".toMediaTypeOrNull())
|
||||
mApi.moderatorsPatchQuestion(body, UserManager.getInstance().userId, questionEntity?.id)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
@ -15,7 +15,9 @@ import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
@ -59,7 +61,7 @@ class QuestionsInviteViewModel(application: Application, var questionId: String?
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
RetrofitManager.getInstance().api
|
||||
.postInvite(body, questionId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@ -30,7 +30,9 @@ import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
@ -114,7 +116,7 @@ class VideoPublishViewModel(application: Application) : AndroidViewModel(applica
|
||||
when {
|
||||
isDraft -> {
|
||||
val draftData = JSONObject(videoEntity.toJson()).put("local_path", videoPath).toString()
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), draftData)
|
||||
val body = draftData.toRequestBody("application/json".toMediaTypeOrNull())
|
||||
postDraft(body)
|
||||
}
|
||||
videoPatch != null -> {
|
||||
@ -150,7 +152,7 @@ class VideoPublishViewModel(application: Application) : AndroidViewModel(applica
|
||||
|
||||
private fun patchVideo(jsonObject: JSONObject, videoId: String) {
|
||||
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
mApi.patchBbsVideo(videoId, body)
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
@ -208,7 +210,7 @@ class VideoPublishViewModel(application: Application) : AndroidViewModel(applica
|
||||
|
||||
private fun postVideo(jsonObject: JSONObject) {
|
||||
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
mApi.postBbsVideo(body)
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<JsonObject>() {
|
||||
|
||||
@ -4,6 +4,7 @@ import android.content.Context;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.gamecenter.common.retrofit.BaseRetrofitManager;
|
||||
import com.gh.gamecenter.feature.retrofit.WGameCPMApiService;
|
||||
import com.gh.gamecenter.retrofit.service.ApiService;
|
||||
import com.gh.gamecenter.retrofit.service.VApiService;
|
||||
import com.halo.assistant.HaloApp;
|
||||
@ -20,6 +21,7 @@ public class RetrofitManager extends BaseRetrofitManager {
|
||||
private final ApiService mNewApiService;
|
||||
private final ApiService mUploadApiService;
|
||||
private final VApiService mVApiService;
|
||||
private final WGameCPMApiService mWGameCPMApiService;
|
||||
|
||||
private RetrofitManager() {
|
||||
Context context = HaloApp.getInstance().getApplicationContext();
|
||||
@ -27,7 +29,8 @@ public class RetrofitManager extends BaseRetrofitManager {
|
||||
mApiService = provideService(okHttpNormalConfig, Config.API_HOST, ApiService.class);
|
||||
mNewApiService = provideService(okHttpNormalConfig, Config.NEW_API_HOST, ApiService.class);
|
||||
mUploadApiService = provideService(getOkHttpConfig(context, UPLOAD_CALL_TIME_OUT, 1), Config.API_HOST, ApiService.class);
|
||||
mVApiService = provideService(okHttpNormalConfig, Config.VAPI_HOST, VApiService.class);;
|
||||
mVApiService = provideService(okHttpNormalConfig, Config.VAPI_HOST, VApiService.class);
|
||||
mWGameCPMApiService = provideService(okHttpNormalConfig, Config.WGAME_CPM_API_HOST, WGameCPMApiService.class);
|
||||
}
|
||||
|
||||
public static RetrofitManager getInstance() {
|
||||
@ -50,6 +53,10 @@ public class RetrofitManager extends BaseRetrofitManager {
|
||||
return mVApiService;
|
||||
}
|
||||
|
||||
public WGameCPMApiService getWGameCPMApi() {
|
||||
return mWGameCPMApiService;
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
private static final RetrofitManager INSTANCE = new RetrofitManager();
|
||||
}
|
||||
|
||||
@ -3153,7 +3153,7 @@ public interface ApiService {
|
||||
/**
|
||||
* QQ小游戏-专题-换一换
|
||||
*/
|
||||
@GET("games/qq_mini/columns/{column_id}/games?page=1&page_size=30")
|
||||
@GET("games/qq_mini/columns/{column_id}/games?page=2&page_size=30")
|
||||
Observable<List<GameEntity>> getSubjectQGame(@Path("column_id") String columnId);
|
||||
|
||||
/**
|
||||
@ -3186,7 +3186,7 @@ public interface ApiService {
|
||||
/**
|
||||
* 微信小游戏-专题-换一换
|
||||
*/
|
||||
@GET("wechat_game/columns/{column_id}/games?page=1&page_size=30")
|
||||
@GET("wechat_game/columns/{column_id}/games?page=2&page_size=30")
|
||||
Observable<List<GameEntity>> getSubjectWGame(@Path("column_id") String columnId);
|
||||
|
||||
/**
|
||||
|
||||
@ -3,9 +3,12 @@ package com.gh.gamecenter.search
|
||||
import com.gh.gamecenter.entity.SearchSubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
|
||||
interface ISearchGameResultRepository {
|
||||
fun getSearchGame(key: String?, page: Int): Observable<List<GameEntity>>
|
||||
|
||||
fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>>
|
||||
|
||||
fun getWGameCPMGameList(): Single<MutableList<GameEntity>>
|
||||
}
|
||||
@ -13,6 +13,7 @@ import com.gh.gamecenter.common.view.DrawableView
|
||||
import com.gh.gamecenter.databinding.SearchGameIndexItemBinding
|
||||
import com.gh.gamecenter.databinding.SearchSubjectItemBinding
|
||||
import com.gh.gamecenter.db.ISearchHistoryDao
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.feature.databinding.GameItemBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
@ -85,7 +86,7 @@ class SearchSubjectItemViewHolder(var binding: SearchSubjectItemBinding) : Recyc
|
||||
|
||||
binding.run {
|
||||
subjectRv.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
|
||||
subjectRv.adapter = SearchSubjectAdapter(context, entity.getFilterGame(), "($type-专题)") {
|
||||
subjectRv.adapter = SearchSubjectAdapter(context, entity.getFilterGame(), "($type-专题)", key) {
|
||||
dao?.add(key)
|
||||
if (itemData.adConfig != null) {
|
||||
NewFlatLogUtils.logClickGameAd(
|
||||
@ -119,7 +120,17 @@ class SearchSubjectItemViewHolder(var binding: SearchSubjectItemBinding) : Recyc
|
||||
headContainer.headActionTv.setOnClickListener {
|
||||
dao?.add(key)
|
||||
if (entity.columnId.isNotEmpty()) {
|
||||
DirectUtils.directToSubject(context, entity.columnId, entity.name, "($type-专题)")
|
||||
DirectUtils.directToSubject(
|
||||
context,
|
||||
entity.columnId,
|
||||
entity.name,
|
||||
"($type-专题)",
|
||||
subjectType = if (entity.isWGameSubjectCPM) {
|
||||
SubjectData.SubjectType.WECHAT_GAME_CPM
|
||||
} else {
|
||||
SubjectData.SubjectType.NORMAL
|
||||
}
|
||||
)
|
||||
} else if (entity.adId.isNotEmpty() && entity.codeId.isNotEmpty()) {
|
||||
SubjectActivity.startAdSubjectActivity(
|
||||
context,
|
||||
|
||||
@ -752,7 +752,7 @@ class SearchGameResultAdapter(
|
||||
gameEntity.name ?: "",
|
||||
gameEntity.categoryChinese
|
||||
)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
MiniGameItemHelper.trackMiniGameClick(
|
||||
gameEntity = gameEntity,
|
||||
location = "小游戏搜索结果列表",
|
||||
|
||||
@ -4,14 +4,17 @@ import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.entity.SearchSubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.minigame.wechat.WGameSubjectCPMRemoteDataSource
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.retrofit.service.ApiService
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import java.net.URLEncoder
|
||||
|
||||
class SearchGameResultRepository(
|
||||
private val mApi: ApiService = RetrofitManager.getInstance().api
|
||||
private val mApi: ApiService = RetrofitManager.getInstance().api,
|
||||
private val mWGameSubjectCPMDataSource: WGameSubjectCPMRemoteDataSource = WGameSubjectCPMRemoteDataSource()
|
||||
) : ISearchGameResultRepository {
|
||||
|
||||
override fun getSearchGame(
|
||||
@ -31,4 +34,8 @@ class SearchGameResultRepository(
|
||||
override fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>> {
|
||||
return mApi.getSearchSubject(key, page)
|
||||
}
|
||||
|
||||
override fun getWGameCPMGameList(): Single<MutableList<GameEntity>> {
|
||||
return mWGameSubjectCPMDataSource.getRecommendCPMList(1)
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import com.gh.ad.AdDelegateHelper
|
||||
import com.gh.common.filter.RegionSettingHelper
|
||||
import com.gh.common.util.PackageHelper
|
||||
import com.gh.gamecenter.SearchActivity
|
||||
import com.gh.gamecenter.common.base.GlobalActivityManager
|
||||
import com.gh.gamecenter.common.baselist.ListViewModel
|
||||
import com.gh.gamecenter.common.baselist.LoadParams
|
||||
@ -22,7 +23,6 @@ import com.gh.gamecenter.entity.SearchSubjectEntity
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.minigame.MiniGameSearchResultRepository
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.SearchActivity
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
@ -58,10 +58,6 @@ class SearchGameResultViewModel(
|
||||
mSearchSubjects.clear()
|
||||
}
|
||||
|
||||
override fun loadData() {
|
||||
super.loadData()
|
||||
}
|
||||
|
||||
override fun mergeResultLiveData() {
|
||||
mResultLiveData.addSource(mListLiveData) { list ->
|
||||
mGameEntityList = ArrayList(list)
|
||||
@ -80,31 +76,40 @@ class SearchGameResultViewModel(
|
||||
refreshWrongInstallStatus()
|
||||
|
||||
repository.getSearchSubject(mSearchKey, mPage)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ mutableList ->
|
||||
mSearchSubjects.addAll(mutableList)
|
||||
.map { dataList ->
|
||||
mSearchSubjects.addAll(dataList)
|
||||
var cpmSearchSubject: SearchSubjectEntity? = null
|
||||
mSearchSubjects.forEach {
|
||||
val item = SearchItemData(subject = it)
|
||||
if (it.location <= 0 || it.location > itemDataList.size) {
|
||||
itemDataList.add(item)
|
||||
// 微信小游戏CPM专题需要等搜索广告位插入完成后再插入
|
||||
if (it.location == WGAME_CPM_SUBJECT_POSITION) {
|
||||
cpmSearchSubject = it.apply { isWGameSubjectCPM = true }
|
||||
} else {
|
||||
itemDataList.add(it.location - 1, item)
|
||||
val item = SearchItemData(subject = it)
|
||||
if (it.location <= 0 || it.location > itemDataList.size) {
|
||||
itemDataList.add(item)
|
||||
} else {
|
||||
itemDataList.add(it.location - 1, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
cpmSearchSubject to dataList
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ result ->
|
||||
// 处理初始化列表且游戏列表size为0的情况
|
||||
handleLoadStatusWhenGameListIsEmpty(list, itemDataList)
|
||||
|
||||
if (mIsManuallySearch) {
|
||||
if (mSearchKey == AdDelegateHelper.gameSearchKeyword) {
|
||||
updateAdConfigAndDecorateList(itemDataList, list)
|
||||
updateAdConfigAndDecorateList(itemDataList, list, result.first)
|
||||
} else {
|
||||
AdDelegateHelper.requestAdConfig(false, mSearchKey ?: "") {
|
||||
updateAdConfigAndDecorateList(itemDataList, list)
|
||||
updateAdConfigAndDecorateList(itemDataList, list, result.first)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
postResultList(itemDataList, list)
|
||||
decorateWithWGameSubjectCPM(itemDataList, list, result.first)
|
||||
}
|
||||
}, {
|
||||
it.printStackTrace()
|
||||
@ -114,7 +119,11 @@ class SearchGameResultViewModel(
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun updateAdConfigAndDecorateList(itemDataList: ArrayList<SearchItemData>, list: MutableList<GameEntity>) {
|
||||
private fun updateAdConfigAndDecorateList(
|
||||
itemDataList: ArrayList<SearchItemData>,
|
||||
list: MutableList<GameEntity>,
|
||||
cpmSubjectEntity: SearchSubjectEntity?
|
||||
) {
|
||||
mGameSearchAdList =
|
||||
AdDelegateHelper.getGameSearchAdList().filter { AdDelegateHelper.shouldShowGameSearchAd(it) }.toArrayList()
|
||||
.apply { sortBy { it.position } }
|
||||
@ -166,18 +175,18 @@ class SearchGameResultViewModel(
|
||||
Single.zip(requestSingleList) {}
|
||||
.compose(singleToMain())
|
||||
.subscribe({
|
||||
decorateListWithAd(itemDataList, decoratedItemDataList, list)
|
||||
decorateListWithAd(itemDataList, decoratedItemDataList, list, cpmSubjectEntity)
|
||||
}, {
|
||||
decorateListWithAd(itemDataList, decoratedItemDataList, list)
|
||||
decorateListWithAd(itemDataList, decoratedItemDataList, list, cpmSubjectEntity)
|
||||
})
|
||||
} else {
|
||||
decorateListWithAd(itemDataList, decoratedItemDataList, list)
|
||||
decorateListWithAd(itemDataList, decoratedItemDataList, list, cpmSubjectEntity)
|
||||
}
|
||||
} else {
|
||||
decorateListWithThirdPartyAdOnly(decoratedItemDataList, thirdPartyAdList, list)
|
||||
decorateListWithThirdPartyAdOnly(decoratedItemDataList, thirdPartyAdList, list, cpmSubjectEntity)
|
||||
}
|
||||
} else {
|
||||
postResultList(itemDataList, list)
|
||||
decorateWithWGameSubjectCPM(itemDataList, list, cpmSubjectEntity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,19 +199,21 @@ class SearchGameResultViewModel(
|
||||
private fun decorateListWithThirdPartyAdOnly(
|
||||
decoratedItemDataList: ArrayList<SearchItemData>,
|
||||
thirdPartyAdList: List<AdConfig>,
|
||||
list: List<GameEntity>
|
||||
list: List<GameEntity>,
|
||||
cpmSubjectEntity: SearchSubjectEntity?
|
||||
) {
|
||||
thirdPartyAdList.forEach {
|
||||
decoratedItemDataList.add(it.position - 1, SearchItemData(ad = it.thirdPartyAd, adConfig = it))
|
||||
SPUtils.setLong(Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + it.position, System.currentTimeMillis())
|
||||
}
|
||||
postResultList(decoratedItemDataList, list)
|
||||
decorateWithWGameSubjectCPM(decoratedItemDataList, list, cpmSubjectEntity)
|
||||
}
|
||||
|
||||
private fun decorateListWithAd(
|
||||
itemDataList: ArrayList<SearchItemData>,
|
||||
decoratedItemDataList: ArrayList<SearchItemData>,
|
||||
list: List<GameEntity>
|
||||
list: List<GameEntity>,
|
||||
cpmSubjectEntity: SearchSubjectEntity?
|
||||
) {
|
||||
val adGameOneIdSet = HashSet<String>() // 展示样式为单个游戏时记录游戏ID,避免重复
|
||||
for ((index, position) in mAdPositionSet!!.withIndex()) {
|
||||
@ -270,7 +281,41 @@ class SearchGameResultViewModel(
|
||||
break
|
||||
}
|
||||
}
|
||||
postResultList(decoratedItemDataList, list)
|
||||
decorateWithWGameSubjectCPM(decoratedItemDataList, list, cpmSubjectEntity)
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun decorateWithWGameSubjectCPM(
|
||||
resultList: ArrayList<SearchItemData>,
|
||||
list: List<GameEntity>,
|
||||
cpmSubjectEntity: SearchSubjectEntity?
|
||||
) {
|
||||
// 微信小游戏CPM专题搜索结果存在,则请求CPM接口获取微信小游戏列表数据,并将列表数据插入缓存的CPM专题中,
|
||||
// 再根据location的值(固定为4)将CPM专题插入搜索结果列表中
|
||||
// 相关需求:https://jira.shanqu.cc/browse/GHZSCY-6710
|
||||
cpmSubjectEntity?.let { subject ->
|
||||
if (subject.games.isNotEmpty()) {
|
||||
Single.just(subject.games.toMutableList())
|
||||
} else {
|
||||
repository.getWGameCPMGameList()
|
||||
.onErrorReturnItem(mutableListOf())
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
val cpmSearchItemData = SearchItemData(subject = subject.apply { games = it })
|
||||
if (subject.location <= 0 || subject.location > resultList.size) {
|
||||
resultList.add(cpmSearchItemData)
|
||||
} else {
|
||||
resultList.add(subject.location - 1, cpmSearchItemData)
|
||||
}
|
||||
postResultList(resultList, list)
|
||||
},
|
||||
{
|
||||
postResultList(resultList, list)
|
||||
})
|
||||
} ?: postResultList(resultList, list)
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@ -386,6 +431,7 @@ class SearchGameResultViewModel(
|
||||
|
||||
companion object {
|
||||
const val AD_SUBJECT_GAME_MAX_COUNT = 8
|
||||
const val WGAME_CPM_SUBJECT_POSITION = 4
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,6 +6,7 @@ import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
import com.gh.gamecenter.feature.entity.GameEntity
|
||||
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
|
||||
import com.gh.gamecenter.game.horizontal.GameHorizontalSimpleItemViewHolder
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
|
||||
@ -13,6 +14,7 @@ class SearchSubjectAdapter(
|
||||
context: Context,
|
||||
private val mList: List<GameEntity>,
|
||||
private val mEntrance: String,
|
||||
private val mKey: String,
|
||||
private val clickCallback: ((GameEntity) -> Unit)
|
||||
) : BaseRecyclerAdapter<GameHorizontalSimpleItemViewHolder>(context) {
|
||||
|
||||
@ -34,7 +36,16 @@ class SearchSubjectAdapter(
|
||||
GameHorizontalSimpleItemViewHolder.setHorizontalNameAndGravity(gameName, gameEntity.name)
|
||||
root.setOnClickListener {
|
||||
clickCallback.invoke(gameEntity)
|
||||
GameDetailActivity.startGameDetailActivity(mContext, gameEntity.id, mEntrance, gameEntity.exposureEvent)
|
||||
if (gameEntity.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
MiniGameItemHelper.trackMiniGameClick(
|
||||
gameEntity = gameEntity,
|
||||
location = "小游戏搜索结果列表",
|
||||
searchContent = mKey,
|
||||
)
|
||||
} else {
|
||||
GameDetailActivity.startGameDetailActivity(mContext, gameEntity.id, mEntrance, gameEntity.exposureEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,9 @@ import com.lightgame.utils.Utils.toast
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import retrofit2.HttpException
|
||||
|
||||
class AddKaiFuViewModel(application: Application) : AndroidViewModel(application) {
|
||||
@ -266,7 +268,7 @@ class AddKaiFuViewModel(application: Application) : AndroidViewModel(application
|
||||
|
||||
|
||||
private fun postData(postList: ArrayList<ServerCalendarEntity>) {
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), GsonUtils.toJson(postList))
|
||||
val body = GsonUtils.toJson(postList).toRequestBody("application/json".toMediaTypeOrNull())
|
||||
RetrofitManager.getInstance().api.addKaifu(body, mGameId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
@ -11,7 +11,9 @@ import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
@ -35,7 +37,7 @@ class PatchKaifuViewModel(application: Application) : AndroidViewModel(applicati
|
||||
val jsonObject = JSONObject()
|
||||
jsonObject.put("note", patchName)
|
||||
jsonObject.put("remark", patchRemark)
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
apiService.patchKaifu(body, gameId, serverEntity!!.id)
|
||||
} else {
|
||||
apiService.deleteKaifu(gameId, serverEntity!!.id)
|
||||
|
||||
@ -228,7 +228,7 @@ class SubjectAdapter(
|
||||
DataCollectionUtils.uploadClick(mContext, "列表", subjectData.subjectName, gameEntity.name)
|
||||
|
||||
if (gameEntity.isMiniGame()) {
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
|
||||
MiniGameItemHelper.launchMiniGame(gameEntity)
|
||||
val pageLocation = mViewModel.pageLocation
|
||||
MiniGameItemHelper.trackMiniGameClick(
|
||||
gameEntity = gameEntity,
|
||||
|
||||
@ -3,6 +3,8 @@ package com.gh.gamecenter.subject
|
||||
import com.gh.gamecenter.entity.SubjectData
|
||||
import com.gh.gamecenter.minigame.qq.QGameSubjectListRepository
|
||||
import com.gh.gamecenter.minigame.qq.QGameSubjectRepository
|
||||
import com.gh.gamecenter.minigame.wechat.WGameSubjectCPMListRepository
|
||||
import com.gh.gamecenter.minigame.wechat.WGameSubjectCPMRepository
|
||||
import com.gh.gamecenter.minigame.wechat.WGameSubjectListRepository
|
||||
import com.gh.gamecenter.minigame.wechat.WGameSubjectRepository
|
||||
|
||||
@ -10,12 +12,14 @@ object SubjectRepositoryFactory {
|
||||
fun createRepo(subjectType: SubjectData.SubjectType): ISubjectRepository = when(subjectType) {
|
||||
SubjectData.SubjectType.QQ_GAME -> QGameSubjectRepository()
|
||||
SubjectData.SubjectType.WECHAT_GAME -> WGameSubjectRepository()
|
||||
SubjectData.SubjectType.WECHAT_GAME_CPM -> WGameSubjectCPMRepository()
|
||||
else -> SubjectRepository()
|
||||
}
|
||||
|
||||
fun createListRepo(subjectType: SubjectData.SubjectType): ISubjectListRepository = when(subjectType) {
|
||||
SubjectData.SubjectType.QQ_GAME -> QGameSubjectListRepository()
|
||||
SubjectData.SubjectType.WECHAT_GAME -> WGameSubjectListRepository()
|
||||
SubjectData.SubjectType.WECHAT_GAME_CPM -> WGameSubjectCPMListRepository()
|
||||
else -> SubjectListRepository()
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,9 @@ import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
@ -57,7 +59,7 @@ class UploadVideoViewModel(application: Application) : AndroidViewModel(applicat
|
||||
|
||||
private fun postVideo(jsonObject: JSONObject) {
|
||||
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
mApi.postVideo(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -121,7 +123,7 @@ class UploadVideoViewModel(application: Application) : AndroidViewModel(applicat
|
||||
|
||||
private fun patchVideo(jsonObject: JSONObject, videoId: String) {
|
||||
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
mApi.patchVideo(body, videoId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -188,7 +190,7 @@ class UploadVideoViewModel(application: Application) : AndroidViewModel(applicat
|
||||
patchVideo(JSONObject(GsonUtils.toJson(videoEntity)), videoEntity.id)
|
||||
} else if (isDraft) {
|
||||
val draftData = JSONObject(videoEntity.toJson()).put("local_path", videoPath).toString()
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), draftData)
|
||||
val body = draftData.toRequestBody("application/json".toMediaTypeOrNull())
|
||||
postDraft(body)
|
||||
} else {
|
||||
var videoHeight = 0
|
||||
|
||||
@ -19,7 +19,9 @@ import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import io.reactivex.subjects.PublishSubject
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
@ -66,7 +68,7 @@ class VoteViewModel(application: Application, private val mGameId: String = "")
|
||||
requestMap["version_code"] = installGameEntity.versionCode
|
||||
|
||||
val body = RequestBody.create(
|
||||
MediaType.parse("application/json"),
|
||||
"application/json".toMediaTypeOrNull(),
|
||||
GsonUtils.toJson(requestMap)
|
||||
)
|
||||
RetrofitManager.getInstance().api.postPlatformRequestApk(installGameEntity.platformRequestsId, body)
|
||||
@ -99,7 +101,7 @@ class VoteViewModel(application: Application, private val mGameId: String = "")
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
val responseBodyObservable = if (isNewVote) {
|
||||
RetrofitManager.getInstance().api.addVersionVote(body, mGameId)
|
||||
} else if (isVoted) {
|
||||
|
||||
@ -22,7 +22,9 @@ import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.transformWhile
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
@ -93,7 +95,7 @@ class MainWrapperViewModel(application: Application, private val mRepository: Ma
|
||||
fun postMessageRead(messageId: String) {
|
||||
val jsonObject = JSONObject()
|
||||
jsonObject.put("type", "system_message")
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
RetrofitManager.getInstance().api.postMessageRead(UserManager.getInstance().userId, messageId, body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
@ -99,7 +99,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
|
||||
private val viewModel: SearchToolbarTabWrapperViewModel by lazy {
|
||||
viewModelProviderFromParent(
|
||||
SearchToolbarTabWrapperViewModel.Factory(multiTabNavId, noTabLinkEntity?.link ?: ""),
|
||||
multiTabNavId
|
||||
multiTabNavId + (noTabLinkEntity?.link ?: "")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import androidx.recyclerview.widget.*
|
||||
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
||||
import androidx.viewpager2.widget.ViewPager2.PageTransformer
|
||||
@ -80,6 +81,26 @@ class VGameInstalledLaunchDialog : DialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun show(manager: FragmentManager?, tag: String?) {
|
||||
try {
|
||||
val clazz: Class<*> = DialogFragment::class.java
|
||||
val dismissed = clazz.getDeclaredField("mDismissed")
|
||||
dismissed.isAccessible = true
|
||||
dismissed[this] = false
|
||||
|
||||
val shownByMe = clazz.getDeclaredField("mShownByMe")
|
||||
shownByMe.isAccessible = true
|
||||
shownByMe[this] = true
|
||||
val transaction = manager!!.beginTransaction()
|
||||
transaction.add(this, tag)
|
||||
transaction.commitAllowingStateLoss()
|
||||
} catch (e: Exception) {
|
||||
super.show(manager, tag)
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
return super.onCreateDialog(savedInstanceState).apply {
|
||||
|
||||
@ -145,7 +145,7 @@ class WebFragment : LazyFragment(), IScrollable {
|
||||
}
|
||||
} else if (requestCode == REQUEST_PICK_IMAGE) {
|
||||
if (mSelectPicCallback == null && mSelectPicCallbackAboveL == null) return
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val uriList = Matisse.obtainResult(data)
|
||||
if (uriList.size == 0) return
|
||||
if (mSelectPicCallbackAboveL != null) {
|
||||
|
||||
@ -15,7 +15,9 @@ import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
@ -52,9 +54,8 @@ class ManuallyRealNameViewModel(application: Application) : AndroidViewModel(app
|
||||
fun postCertificationReview(idCardEntity: IdCardEntity) {
|
||||
val userInfoEntity = UserInfoEntity()
|
||||
userInfoEntity.idCard = idCardEntity
|
||||
val body = RequestBody.create(
|
||||
MediaType.parse("application/json"), GsonUtils.toJson(userInfoEntity)
|
||||
)
|
||||
val body = GsonUtils.toJson(userInfoEntity)
|
||||
.toRequestBody("application/json".toMediaTypeOrNull())
|
||||
RetrofitManager.getInstance().api.postCertificationReview(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
||||
@ -19,7 +19,9 @@ import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import retrofit2.HttpException
|
||||
@ -39,7 +41,7 @@ class VerifyPhoneViewModel(application: Application) : AndroidViewModel(applicat
|
||||
params["mobile"] = phoneNum
|
||||
val jsonObject = JSONObject(params as Map<*, *>)
|
||||
jsonObject.put("device", device)
|
||||
val body: RequestBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body: RequestBody = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
|
||||
api.verifyPhone(1, body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -80,7 +82,7 @@ class VerifyPhoneViewModel(application: Application) : AndroidViewModel(applicat
|
||||
params["code"] = code
|
||||
val jsonObject = JSONObject(params as Map<*, *>)
|
||||
jsonObject.put("device", device)
|
||||
val body: RequestBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
|
||||
val body: RequestBody = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
|
||||
api.verifyPhone(2, body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@ -7,8 +7,8 @@ ext {
|
||||
targetSdkVersion = 30
|
||||
|
||||
// application info (每个大版本之间的 versionCode 增加 20)
|
||||
versionCode = 1110
|
||||
versionName = "5.38.0"
|
||||
versionCode = 1112
|
||||
versionName = "5.38.2"
|
||||
applicationId = "com.gh.gamecenter"
|
||||
applicationIdGat = "com.gh.gamecenter.intl"
|
||||
|
||||
@ -49,7 +49,7 @@ ext {
|
||||
rxAndroid2 = "2.1.1"
|
||||
rxBinding2 = "2.1.1"
|
||||
retrofit = "2.3.0"
|
||||
okHttp = "3.12.13"
|
||||
okHttp = "4.11.0"
|
||||
gson = "2.8.2"
|
||||
zxing = "3.2.1"
|
||||
fresco = "2.6.0"
|
||||
|
||||
@ -150,7 +150,7 @@ class HelpAndFeedbackFragment : BaseLazyFragment() {
|
||||
|
||||
val layoutManager = FixLinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
|
||||
mSnapHelper = LeftPagerSnapHelper()
|
||||
mHelpVideoAdapter = HelpVideoAdapter(requireContext(), mSnapHelper!!, layoutManager, helpVideoRv)
|
||||
mHelpVideoAdapter = HelpVideoAdapter(requireContext(), viewLifecycleOwner, mSnapHelper!!, layoutManager, helpVideoRv)
|
||||
(helpVideoRv.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
|
||||
helpVideoRv.layoutManager = layoutManager
|
||||
helpVideoRv.adapter = mHelpVideoAdapter
|
||||
|
||||
@ -5,6 +5,8 @@ import android.os.Handler
|
||||
import android.os.Message
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
@ -20,6 +22,7 @@ import java.lang.ref.WeakReference
|
||||
|
||||
class HelpVideoAdapter(
|
||||
context: Context,
|
||||
private val mLifecycleOwner: LifecycleOwner,
|
||||
private val mSnapHelper: LeftPagerSnapHelper,
|
||||
private val mLayoutManager: LinearLayoutManager,
|
||||
private val mRecyclerView: RecyclerView
|
||||
@ -27,6 +30,17 @@ class HelpVideoAdapter(
|
||||
private var mHelpVideoList = arrayListOf<HelpVideo>()
|
||||
private val mLooperHandle = LooperHandle(this)
|
||||
private val mSlideLooperKey = 102
|
||||
private val mLifecycleObserver = object : DefaultLifecycleObserver {
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
super.onResume(owner)
|
||||
startScroll()
|
||||
}
|
||||
|
||||
override fun onPause(owner: LifecycleOwner) {
|
||||
super.onPause(owner)
|
||||
stopScroll()
|
||||
}
|
||||
}
|
||||
|
||||
fun submitList(helpVideoList: List<HelpVideo>) {
|
||||
mHelpVideoList = ArrayList(helpVideoList)
|
||||
@ -122,6 +136,16 @@ class HelpVideoAdapter(
|
||||
mLooperHandle.removeMessages(mSlideLooperKey)
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
|
||||
super.onViewAttachedToWindow(holder)
|
||||
mLifecycleOwner.lifecycle.addObserver(mLifecycleObserver)
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
||||
super.onViewDetachedFromWindow(holder)
|
||||
mLifecycleOwner.lifecycle.removeObserver(mLifecycleObserver)
|
||||
}
|
||||
|
||||
class LooperHandle(adapter: HelpVideoAdapter) : Handler() {
|
||||
private val mWeakReference: WeakReference<HelpVideoAdapter> = WeakReference(adapter)
|
||||
|
||||
|
||||
@ -480,6 +480,8 @@ open class SuggestAppFragment : ToolbarFragment() {
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (data == null) return
|
||||
|
||||
if (requestCode == MEDIA_STORE_REQUEST || requestCode == MEDIA_STORE_CREDENTIALS_REQUEST || requestCode == MEDIA_STORE_SCREENSHOT_REQUEST) {
|
||||
val selectedPaths = Matisse.obtainResult(data) ?: return
|
||||
val picturePath = PathUtils.getPath(requireContext(), selectedPaths[0])
|
||||
|
||||
@ -59,6 +59,9 @@ LOG_HUB_PROJECT_GAT=ghzs-global
|
||||
DEV_CSJ_APPID=5410486
|
||||
CSJ_APPID=5429125
|
||||
|
||||
WGAME_CPM_BUSIAPPID=dl5b0ccbd8
|
||||
WGAME_CPM_API_HOST=https://mrj.20130123.com/dlwxgame/api/
|
||||
|
||||
# hosts
|
||||
DEV_API_HOST=https\://dev-and-api.ghzs6.com/v5d5d0/
|
||||
API_HOST=https\://and-api.ghzs6.com/v5d5d0/
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Mon Oct 30 17:29:06 CST 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-7.2-bin.zip
|
||||
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-7.4-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@ -63,6 +63,11 @@ class CustomLayoutInflaterFactory(
|
||||
view.dimOnDarkMode()
|
||||
}
|
||||
|
||||
// 为每个Fragment的子view添加对应Fragment的Tag
|
||||
parent?.getTag(androidx.fragment.R.id.fragment_container_view_tag)?.let {
|
||||
view?.setTag(androidx.fragment.R.id.fragment_container_view_tag, it)
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
|
||||
@ -78,6 +78,7 @@ public class Constants {
|
||||
|
||||
public static final String QQ_MINI_GAME = "qq";
|
||||
public static final String WECHAT_MINI_GAME = "wechat";
|
||||
public static final String WECHAT_MINI_GAME_CPM = "wechat_cpm";
|
||||
/**
|
||||
* <a href="https://developers.weixin.qq.com/community/minigame/doc/000c461a17c6486f0641e27176b401">微信小游戏PCS参数</a>
|
||||
*/
|
||||
|
||||
@ -30,10 +30,14 @@ data class ExposureEntity(
|
||||
val displayType: String? = "",
|
||||
@SerializedName("is_platform_recommend")
|
||||
val isPlatformRecommend: Boolean? = false,
|
||||
@SerializedName("mini_game_uid")
|
||||
val miniGameUid: String? = "",
|
||||
@SerializedName("mini_game_id")
|
||||
val miniGameId: String? = "",// 小游戏ID
|
||||
@SerializedName("mini_game_type")
|
||||
val miniGameType: String? = "",// 小游戏类型:QQ小游戏:qq 微信小游戏:wechat
|
||||
@SerializedName("mini_game_recommend_id")
|
||||
val miniGameRecommendId: String? = "",
|
||||
var speed: Long = 0,
|
||||
var certification: Int? = null, // 0表示未实名,1表示未成年,2表示成年
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.Cache;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.brotli.BrotliInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
@ -38,6 +39,7 @@ public abstract class BaseRetrofitManager {
|
||||
final Cache cache = new Cache(new File(OkHttpCache.getCachePath(context)), 10 * 1024 * 1024); // 10Mb
|
||||
|
||||
return Injection.provideRetrofitBuilder()
|
||||
.addInterceptor(BrotliInterceptor.INSTANCE)
|
||||
.addInterceptor(new OkHttpCacheInterceptor(context))
|
||||
.addInterceptor(new OkHttpRetryInterceptor(context, maxRetryCount))
|
||||
.addInterceptor(new ChuckerInterceptor(context, new ChuckerCollector(context, true, RetentionManager.Period.ONE_DAY)))
|
||||
|
||||
@ -13,7 +13,9 @@ import com.gh.gamecenter.core.provider.IUserManagerProvider
|
||||
import com.gh.gamecenter.core.utils.MtaHelper
|
||||
import com.lightgame.config.CommonDebug
|
||||
import okhttp3.*
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.Response
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
@ -43,12 +45,12 @@ class OkHttpRetryInterceptor constructor(context: Context, val maxRetryCount: In
|
||||
|
||||
var tryCount = 0
|
||||
val token = chain.request().header("token")
|
||||
val url = request.url().toString()
|
||||
while ((response == null || (token != null && response.code() == 401 && (!url.contains("refresh")))) // 排除刷新token接口,避免进入死循环
|
||||
val url = request.url.toString()
|
||||
while ((response == null || (token != null && response.code == 401 && (!url.contains("refresh")))) // 排除刷新token接口,避免进入死循环
|
||||
&& ++tryCount <= maxRetryCount
|
||||
) {
|
||||
if (CommonDebug.IS_DEBUG) {
|
||||
CommonDebug.logMethodWithParams(this, "Retrying ${request.url()} for $tryCount")
|
||||
CommonDebug.logMethodWithParams(this, "Retrying ${request.url} for $tryCount")
|
||||
}
|
||||
|
||||
if (url.contains("users:validate") && !TextUtils.isEmpty(request.header("retry"))
|
||||
@ -70,7 +72,7 @@ class OkHttpRetryInterceptor constructor(context: Context, val maxRetryCount: In
|
||||
tryCount = maxRetryCount + 1 // 只要token刷新异常直接主动退出登录
|
||||
if (e != null && e.isNotEmpty()) {
|
||||
response =
|
||||
response?.newBuilder()?.body(ResponseBody.create(MediaType.parse("application/json"), e))
|
||||
response?.newBuilder()?.body(e.toResponseBody("application/json".toMediaTypeOrNull()))
|
||||
?.build()
|
||||
}
|
||||
})
|
||||
@ -81,9 +83,9 @@ class OkHttpRetryInterceptor constructor(context: Context, val maxRetryCount: In
|
||||
val buildConfig =
|
||||
ARouter.getInstance().build(RouteConsts.provider.buildConfig).navigation() as IBuildConfigProvider
|
||||
// 上报网络错误,过滤 404 以及非用户可感知的请求
|
||||
val api = pathSegmentsToString(request.url().pathSegments())
|
||||
val api = pathSegmentsToString(request.url.pathSegments)
|
||||
if (tryCount == maxRetryCount + 1
|
||||
&& (response == null || response?.code() != 404)
|
||||
&& (response == null || response?.code != 404)
|
||||
&& isUserAwareApi(api)
|
||||
) {
|
||||
MtaHelper.onEvent(
|
||||
|
||||
@ -92,6 +92,21 @@ object EnvHelper {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getWGameCPMHost(): String {
|
||||
val buildConfig =
|
||||
ARouter.getInstance().build(RouteConsts.provider.buildConfig).navigation() as? IBuildConfigProvider
|
||||
return buildConfig?.getWGameCPMApiHost() ?: ""
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getWGameCPMBusiAppId(): String {
|
||||
val buildConfig =
|
||||
ARouter.getInstance().build(RouteConsts.provider.buildConfig).navigation() as? IBuildConfigProvider
|
||||
return buildConfig?.getWGameCPMBusiAppId() ?: ""
|
||||
}
|
||||
|
||||
|
||||
fun showChangeChannelDialog(context: Context, restartAfterChanges: Boolean = false) {
|
||||
val appProvider = ARouter.getInstance().build(RouteConsts.provider.app).navigation() as? IAppProvider
|
||||
val layout = LinearLayout(context).apply {
|
||||
|
||||
@ -68,7 +68,9 @@ import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.*
|
||||
@ -652,25 +654,25 @@ fun String.copyTextAndToast(toastText: String = "复制成功") {
|
||||
|
||||
fun Map<String, String>.createRequestBody(): RequestBody {
|
||||
val json = GsonUtils.toJson(this)
|
||||
return RequestBody.create(MediaType.parse("application/json"), json)
|
||||
return json.toRequestBody("application/json".toMediaTypeOrNull())
|
||||
}
|
||||
|
||||
fun Map<String, Any>.createRequestBodyAny(): RequestBody {
|
||||
val json = GsonUtils.toJson(this)
|
||||
return RequestBody.create(MediaType.parse("application/json"), json)
|
||||
return json.toRequestBody("application/json".toMediaTypeOrNull())
|
||||
}
|
||||
|
||||
fun Any.toRequestBody(): RequestBody {
|
||||
val json = GsonUtils.toJson(this)
|
||||
return RequestBody.create(MediaType.parse("application/json"), json)
|
||||
return json.toRequestBody("application/json".toMediaTypeOrNull())
|
||||
}
|
||||
|
||||
fun JSONObject.toRequestBody(): RequestBody {
|
||||
return RequestBody.create(MediaType.parse("application/json"), this.toString())
|
||||
return this.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
}
|
||||
|
||||
fun JSONArray.toRequestBody(): RequestBody {
|
||||
return RequestBody.create(MediaType.parse("application/json"), this.toString())
|
||||
return this.toString().toRequestBody("application/json".toMediaTypeOrNull())
|
||||
}
|
||||
|
||||
// 对在浏览器(WebView)显示的路径进行转码
|
||||
|
||||
@ -8,8 +8,14 @@ import android.graphics.drawable.ColorDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.alibaba.android.arouter.launcher.ARouter
|
||||
import com.facebook.common.executors.CallerThreadExecutor
|
||||
import com.facebook.common.references.CloseableReference
|
||||
@ -406,6 +412,23 @@ object ImageUtils {
|
||||
return modifiedUrl
|
||||
}
|
||||
|
||||
private fun View.findFragment(): Fragment? {
|
||||
var view: View? = this
|
||||
val addTagViewList = ArrayList<View>()
|
||||
while (view != null) {
|
||||
val tag = view.getTag(androidx.fragment.R.id.fragment_container_view_tag)
|
||||
if (tag is Fragment) {
|
||||
addTagViewList.forEach {
|
||||
it.setTag(androidx.fragment.R.id.fragment_container_view_tag, tag)
|
||||
}
|
||||
return tag
|
||||
}
|
||||
addTagViewList.add(view)
|
||||
view = view.parent as? View
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun loadImage(
|
||||
view: SimpleDraweeView?,
|
||||
highResUrl: String,
|
||||
@ -414,6 +437,20 @@ object ImageUtils {
|
||||
shouldNotSaveMemoryCache: Boolean,
|
||||
controllerListener: BaseControllerListener<ImageInfo>? = null,
|
||||
) {
|
||||
val lifecycleObserver = view?.getTag(R.id.lifecycle_observer) as? LifecycleObserver
|
||||
val lifecycle = if (lifecycleObserver != null) {
|
||||
try {
|
||||
view.findFragment()?.viewLifecycleOwner?.lifecycle
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
} else null
|
||||
lifecycleObserver?.let {
|
||||
lifecycle?.removeObserver(it)
|
||||
view.setTag(R.id.lifecycle_observer, null)
|
||||
}
|
||||
|
||||
val listener = getFinalControllerListener(view, controllerListener, lifecycle)
|
||||
val imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(highResUrl))
|
||||
.apply {
|
||||
if (shouldNotSaveMemoryCache) {
|
||||
@ -424,7 +461,7 @@ object ImageUtils {
|
||||
.build()
|
||||
val controller = Fresco.newDraweeControllerBuilder()
|
||||
.setImageRequest(imageRequest)
|
||||
.setControllerListener(controllerListener)
|
||||
.setControllerListener(listener)
|
||||
.apply {
|
||||
if (lowResUrl.isNotEmpty()
|
||||
&& lowResUrl != highResUrl
|
||||
@ -443,6 +480,64 @@ object ImageUtils {
|
||||
view?.setTag(R.string.highResImageTag, highResUrl)
|
||||
}
|
||||
|
||||
private fun getFinalControllerListener(
|
||||
view: SimpleDraweeView?,
|
||||
controllerListener: BaseControllerListener<ImageInfo>?,
|
||||
lifecycle: Lifecycle?
|
||||
) = object : BaseControllerListener<ImageInfo>() {
|
||||
override fun onSubmit(id: String?, callerContext: Any?) {
|
||||
super.onSubmit(id, callerContext)
|
||||
controllerListener?.onSubmit(id, callerContext)
|
||||
}
|
||||
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
|
||||
super.onFinalImageSet(id, imageInfo, animatable)
|
||||
controllerListener?.onFinalImageSet(id, imageInfo, animatable)
|
||||
animatable?.let {
|
||||
val viewLifecycle = try {
|
||||
lifecycle ?: view?.findFragment()?.viewLifecycleOwner?.lifecycle
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
viewLifecycle?.run {
|
||||
val observer = object : DefaultLifecycleObserver {
|
||||
override fun onPause(owner: LifecycleOwner) {
|
||||
super.onPause(owner)
|
||||
it.stop()
|
||||
}
|
||||
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
super.onResume(owner)
|
||||
it.start()
|
||||
}
|
||||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
super.onDestroy(owner)
|
||||
removeObserver(this)
|
||||
}
|
||||
}
|
||||
view?.setTag(R.id.lifecycle_observer, observer)
|
||||
addObserver(observer)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun onIntermediateImageSet(id: String?, imageInfo: ImageInfo?) {
|
||||
super.onIntermediateImageSet(id, imageInfo)
|
||||
controllerListener?.onIntermediateImageSet(id, imageInfo)
|
||||
}
|
||||
override fun onIntermediateImageFailed(id: String?, throwable: Throwable?) {
|
||||
super.onIntermediateImageFailed(id, throwable)
|
||||
controllerListener?.onIntermediateImageFailed(id, throwable)
|
||||
}
|
||||
override fun onFailure(id: String?, throwable: Throwable?) {
|
||||
super.onFailure(id, throwable)
|
||||
controllerListener?.onFailure(id, throwable)
|
||||
}
|
||||
override fun onRelease(id: String?) {
|
||||
super.onRelease(id)
|
||||
controllerListener?.onRelease(id)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addCachedUrl(url: String) {
|
||||
imageDecorationThread.execute {
|
||||
if (url.startsWith("http")) {
|
||||
|
||||
@ -18,13 +18,7 @@ class NavigationBarView @JvmOverloads constructor(
|
||||
val height = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
0
|
||||
} else {
|
||||
val navigationHeight = DisplayUtils.retrieveNavigationHeight(context)
|
||||
// 小于 100px 的其实不是按键形式的 navigationBar 而是条状的 navigationBar,把它当成是 0 处理
|
||||
if (navigationHeight > 100) {
|
||||
navigationHeight
|
||||
} else {
|
||||
0
|
||||
}
|
||||
DisplayUtils.retrieveNavigationHeight(context)
|
||||
}
|
||||
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user