feat: 微信小游戏接入—客户端 https://jira.shanqu.cc/browse/GHZSCY-5267

This commit is contained in:
曾祥俊
2024-06-11 18:42:15 +08:00
parent 8f8cfb757f
commit efae6cb459
128 changed files with 2089 additions and 679 deletions

View File

@ -747,11 +747,11 @@
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qgame.QGameHomeWrapperActivity"
android:name="com.gh.gamecenter.minigame.qq.QGameHomeWrapperActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qgame.QGameSearchActivity"
android:name="com.gh.gamecenter.minigame.MiniGameSearchActivity"
android:screenOrientation="portrait" />
<activity

View File

@ -1,5 +1,6 @@
package com.gh.common.provider
import android.app.Activity
import android.content.Context
import android.os.Bundle
import com.alibaba.android.arouter.facade.annotation.Route
@ -69,10 +70,18 @@ class DirectProviderImpl : IDirectProvider {
DirectUtils.directToAmway(context, fixedTopAmwayCommentId, entrance, path)
}
override fun directToQGame(context: Context) {
override fun directToQQGameHome(context: Context) {
return DirectUtils.directToQGameHome(context)
}
override fun directToQQGameById(activity: Activity, qqAppId: String) {
DirectUtils.directToQQGameById(activity, qqAppId)
}
override fun directToWechatGameById(activity: Activity, qqAppId: String) {
DirectUtils.directToWechatGameById(activity, qqAppId)
}
override fun directToExternalBrowser(context: Context, url: String) {
DirectUtils.directToExternalBrowser(context, url)
}

View File

@ -43,11 +43,13 @@ import com.gh.gamecenter.feature.entity.MeEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.ExposureEvent.Companion.createEvent
import com.gh.gamecenter.feature.exposure.ExposureType
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.feature.provider.IConcernInfoProvider
import com.gh.gamecenter.forum.detail.ForumDetailActivity
import com.gh.gamecenter.forum.home.CommunityActivity
import com.gh.gamecenter.forum.search.ForumOrUserSearchActivity
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailFragment
import com.gh.gamecenter.game.commoncollection.detail.CustomCommonCollectionDetailActivity
import com.gh.gamecenter.game.upload.GameSubmissionActivity
import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
@ -63,6 +65,9 @@ import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
import com.gh.gamecenter.help.HelpAndFeedbackBridge
import com.gh.gamecenter.libao.LibaoDetailActivity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayUseCase
import com.gh.gamecenter.minigame.MiniGameSearchActivity
import com.gh.gamecenter.minigame.qq.QGameHomeWrapperActivity
import com.gh.gamecenter.newsdetail.NewsDetailActivity
import com.gh.gamecenter.personalhome.UserHomeActivity
import com.gh.gamecenter.personalhome.background.PersonalityBackgroundActivity
@ -73,9 +78,6 @@ import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
import com.gh.gamecenter.qa.questions.newdetail.NewQuestionDetailActivity
import com.gh.gamecenter.qa.subject.CommunitySubjectActivity
import com.gh.gamecenter.qa.video.detail.ForumVideoDetailActivity
import com.gh.gamecenter.qgame.QGameHomeWrapperActivity
import com.gh.gamecenter.qgame.QGameSearchActivity
import com.gh.gamecenter.qgame.QGameViewModel
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.servers.GameServerTestActivity
import com.gh.gamecenter.servers.GameServersActivity
@ -95,6 +97,8 @@ import com.gh.vspace.VDownloadManagerActivity
import com.halo.assistant.HaloApp
import com.halo.assistant.fragment.WebFragment
import com.lightgame.utils.Utils
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import retrofit2.HttpException
@ -108,8 +112,14 @@ import kotlin.math.roundToInt
object DirectUtils {
@JvmStatic
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String, sourceEntrance: String = "") {
directToLinkPage(context, linkEntity, entrance, path, null, sourceEntrance)
fun directToLinkPage(
context: Context,
linkEntity: LinkEntity,
entrance: String,
path: String,
sourceEntrance: String = ""
) {
directToLinkPage(context, linkEntity, entrance, path, null, sourceEntrance)
}
@JvmStatic
@ -475,17 +485,22 @@ object DirectUtils {
)
)
"qq_mini_game_column" -> directToQGameHome(context)
ColumnCollectionDetailFragment.TYPE_QQ_MINI_GAME_COLUMN -> directToQGameHome(context)
// QQ游戏专题详情页
"qq_mini_game_column_detail" -> {
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
}
directToSubject(
context = context,
id = linkEntity.link ?: "",
subjectName = linkEntity.text,
entrance = BaseActivity.mergeEntranceAndPath(entrance, path),
exposureEvent = exposureEvent,
isQQMiniGame = true
subjectType = subjectType
)
}
@ -536,6 +551,10 @@ object DirectUtils {
}
}
"wechat_game" -> linkEntity.link?.let {
MiniGameItemHelper.launchMiniGame(it, Constants.WECHAT_MINI_GAME)
}
"" -> {
// do nothing
}
@ -774,7 +793,12 @@ object DirectUtils {
}
}
if (traceEvent != null) {
val clickEvent = createEvent(GameEntity(id = id, name = name), traceEvent.source, appendTrace(traceEvent), ExposureType.CLICK)
val clickEvent = createEvent(
GameEntity(id = id, name = name),
traceEvent.source,
appendTrace(traceEvent),
ExposureType.CLICK
)
log(clickEvent)
bundle.putParcelable(KEY_TRACE_EVENT, clickEvent)
}
@ -837,12 +861,12 @@ object DirectUtils {
subjectName: String? = "",
entrance: String? = null,
exposureEvent: ExposureEvent? = null,
isQQMiniGame: Boolean = false,
subjectType: SubjectData.SubjectType = SubjectData.SubjectType.NORMAL
) {
if (id.isEmpty()) return
val bundle = Bundle()
val subjectData =
SubjectData(subjectId = id, subjectName = subjectName, isOrder = false, isQQMiniGame = isQQMiniGame)
SubjectData(subjectId = id, subjectName = subjectName, isOrder = false, subjectType = subjectType)
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, SubjectActivity::class.java.name)
bundle.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, subjectData)
@ -991,7 +1015,13 @@ object DirectUtils {
}
@JvmStatic
fun directToQuestionDetail(context: Context, id: String, entrance: String? = null, path: String? = null, sourceEntrance: String = "") {
fun directToQuestionDetail(
context: Context,
id: String,
entrance: String? = null,
path: String? = null,
sourceEntrance: String = ""
) {
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
@ -1935,7 +1965,7 @@ object DirectUtils {
}
@JvmStatic
fun directToQGameSearch(
fun directToMiniGameSearch(
context: Context,
hint: String,
sourceEntrance: String,
@ -1947,7 +1977,7 @@ object DirectUtils {
searchBoxPattern: String = ""
) {
context.startActivity(
QGameSearchActivity.getIntent(
MiniGameSearchActivity.getIntent(
context,
hint,
sourceEntrance,
@ -1963,11 +1993,10 @@ object DirectUtils {
@SuppressLint("CheckResult")
@JvmStatic
fun directToQGameById(
fun directToQQGameById(
activity: Activity,
qqGameId: String
qqAppId: String
) {
if (activity !is AppCompatActivity || activity.supportFragmentManager.isDestroyed) {
ToastUtils.toast("启动QQ小游戏失败请稍后再试")
return
@ -1990,23 +2019,37 @@ object DirectUtils {
.build(RouteConsts.provider.qGame)
.navigation() as IQGameProvider
qGameProvider.setLoginInfo(activity, userId, userName, userToken)
qGameProvider.launchGame(activity, qqGameId) { _, _ ->
RetrofitManager
.getInstance()
.newApi
.postQGamePlay(qqGameId, userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
QGameViewModel.notifyQGameSubjectUpdate() // 通知QQ小游戏首页列表刷新
},
{}
) // 秒玩记录上报
qGameProvider.launchGame(activity, qqAppId) { _, _ ->
MiniGameRecentlyPlayUseCase.submitRecentPlayedQGame(qqAppId, userId)
}
}
}
@SuppressLint("CheckResult")
fun directToWechatGameById(
activity: Activity,
wechatAppId: String,
) {
val wxApiProxy = WXAPIFactory.createWXAPI(
activity,
Config.WECHAT_APPID
)
if (!wxApiProxy.isWXAppInstalled) {
ToastUtils.toast("请安装微信客户端")
return
}
wxApiProxy.sendReq(
WXLaunchMiniProgram.Req().apply {
userName = wechatAppId
miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE;
}
)
MiniGameRecentlyPlayUseCase.submitRecentPlayedWGame(wechatAppId, HaloApp.getInstance().gid)
}
@JvmStatic
fun directToMessageCenter(defaultTabIndex: Int) {
ARouter.getInstance().build(RouteConsts.activity.messageWrapperActivity)
@ -2082,7 +2125,7 @@ object DirectUtils {
)
)
BottomTab.SearchStyle.TYPE_QQ_MINI_GAME -> directToQGameSearch(
BottomTab.SearchStyle.TYPE_MINI_GAME -> directToMiniGameSearch(
context,
"请输入小游戏关键词",
sourceEntrance,

View File

@ -27,7 +27,6 @@ import com.gh.download.server.BrowserInstallHelper
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.callback.CancelListener
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
@ -41,6 +40,7 @@ import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.teenagermode.TeenagerModeActivity
import com.gh.vspace.VHelper
import com.lightgame.download.DownloadConfig
@ -247,9 +247,8 @@ object DownloadItemUtils {
}
return
}
if (gameEntity.isQQMiniGame()) {
val isQQMiniGameOffShelve = gameEntity.qqMiniGameAppStatus == 1 // QQ小游戏是否下架
if (isQQMiniGameOffShelve) {
if (gameEntity.isMiniGame()) {
if (gameEntity.isMiniGameOffShelve()) {
downloadBtn.apply {
isClickable = false
text = context.getString(R.string.off_shelve)
@ -844,12 +843,11 @@ object DownloadItemUtils {
}
return
}
if (gameEntity.isQQMiniGame()) {
if (gameEntity.isMiniGame()) {
downloadBtn.setOnClickListener {
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
GlobalActivityManager.currentActivity?.let { activity ->
DirectUtils.directToQGameById(activity, gameEntity.qqMiniGameAppId)
}
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
clickCallback?.onCallback()
allStateClickCallback?.onCallback()
}
return
}

View File

@ -2600,17 +2600,6 @@ object NewFlatLogUtils {
log(json)
}
@JvmStatic
fun logQGameClick(qqGameId: String, qqGameName: String?) {
val json = json {
KEY_EVENT to "qq_game_click"
"qq_game_id" to qqGameId
"qq_game_name" to qqGameName ?: ""
parseAndPutMeta().invoke(this)
}
log(json)
}
// 点击个人主页的认证文案事件
@JvmStatic
fun logClickAuthText(linkType: String, linkId: String, linkText: String, userId: String, text: String) {

View File

@ -62,7 +62,8 @@ object ViewPagerFragmentHelper {
const val TYPE_GAME_LIST = "game_list" // 游戏单广场
const val TYPE_FEEDBACK = "feedback" // 帮助与反馈
const val TYPE_COLUMN = "column" // 游戏专题详情页
const val TYPE_QQ_MINI_GAME_COLUMN = "qq_mini_game_column_detail" // QQ游戏专题详情页
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_COLUMN_COLLECTION = "column_collection" // 专题合集详情页
const val TYPE_SERVER = "server" // 开服表
const val TYPE_COLUMN_TEST = "column_test_v2" // 新游开测
@ -151,11 +152,16 @@ object ViewPagerFragmentHelper {
className = GameCollectionSquareFragment::class.java.name
}
// 游戏专题详情页/QQ游戏专题详情页
TYPE_COLUMN, TYPE_QQ_MINI_GAME_COLUMN -> {
TYPE_COLUMN, TYPE_QQ_MINI_GAME_COLUMN, TYPE_WECHAT_GAME_COLUMN -> {
val subjectType = when(entity.type) {
TYPE_QQ_MINI_GAME_COLUMN -> SubjectData.SubjectType.QQ_GAME
TYPE_WECHAT_GAME_COLUMN -> SubjectData.SubjectType.WECHAT_GAME
else -> SubjectData.SubjectType.NORMAL
}
className = SubjectFragment::class.java.name
bundle.putParcelable(
EntranceConsts.KEY_SUBJECT_DATA,
SubjectData(entity.link, entity.text, false, isQQMiniGame = entity.type == "qq_mini_game_column_detail")
SubjectData(entity.link, entity.text, false, subjectType = subjectType)
)
bundle.putBoolean(EntranceConsts.KEY_SHOW_DOWNLOAD_MENU, !isTabWrapper)
}

View File

@ -17,6 +17,7 @@ import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.db.SearchHistoryDao
import com.gh.gamecenter.eventbus.EBSearch
import com.gh.gamecenter.search.SearchDefaultFragment
@ -39,7 +40,7 @@ open class SearchActivity : BaseActivity() {
lateinit var backBtn: RelativeLayout
private lateinit var deleteIv: ImageView
private var mDao: SearchHistoryDao? = null
protected val mDao: ISearchHistoryDao by lazy { provideDao() }
protected var mSearchKey: String? = null
protected var mIsAutoSearchDisabled: Boolean = false
@ -78,7 +79,6 @@ open class SearchActivity : BaseActivity() {
val searchImmediately = intent.getBooleanExtra(KEY_SEARCH_IMMEDIATELY, false)
var ignoreTextChanges = savedInstanceState != null
mDao = SearchHistoryDao(this)
mPublishSubject = PublishSubject.create()
mPublishSubject!!
@ -102,7 +102,7 @@ open class SearchActivity : BaseActivity() {
searchEt.hint = hint
if (searchImmediately) {
mDisplayType = GAME_DETAIL
mDao?.add(hint)
mDao.add(hint)
search(SearchType.DEFAULT, hint)
}
} else {
@ -190,12 +190,12 @@ open class SearchActivity : BaseActivity() {
mIsAutoSearchDisabled = false
}
private fun handleAutoSearch(key: String?) {
protected open fun handleAutoSearch(key: String?) {
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
if (newSearchKey.isEmpty()) {
val hint = searchEt.hint.toString()
if (!TextUtils.isEmpty(hint) && HINT_TEXT != hint) {
mDao?.add(hint)
mDao.add(hint)
search(SearchType.DEFAULT, hint)
}
} else {
@ -213,7 +213,7 @@ open class SearchActivity : BaseActivity() {
}
}
private fun handleDefaultSearch(key: String?) {
protected open fun handleDefaultSearch(key: String?) {
mSearchKey = key
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
@ -230,14 +230,14 @@ open class SearchActivity : BaseActivity() {
// MtaHelper.onEvent("游戏搜索", "默认搜索", key)
}
private fun handleHotSearch(key: String?) {
protected open fun handleHotSearch(key: String?) {
mSearchKey = key
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
updateDisplayType(GAME_DETAIL)
}
private fun handleHistorySearch(key: String?) {
protected open fun handleHistorySearch(key: String?) {
mSearchKey = key
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
@ -254,12 +254,12 @@ open class SearchActivity : BaseActivity() {
// MtaHelper.onEvent("游戏搜索", "历史搜索", key)
}
private fun handleManualSearch() {
protected open fun handleManualSearch() {
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
if (newSearchKey.isEmpty()) {
val hint = searchEt.hint.toString()
if (!TextUtils.isEmpty(hint) && HINT_TEXT != hint) {
mDao?.add(hint)
mDao.add(hint)
search(SearchType.DEFAULT, hint)
}
} else if (newSearchKey != mSearchKey || mDisplayType != GAME_DETAIL) {
@ -273,7 +273,7 @@ open class SearchActivity : BaseActivity() {
mSourceEntrance
)
mDao?.add(mSearchKey)
mDao.add(mSearchKey)
updateDisplayType(GAME_DETAIL)
} else {
toast("请输入搜索内容")
@ -283,6 +283,8 @@ open class SearchActivity : BaseActivity() {
// MtaHelper.onEvent("游戏搜索", "主动搜索", newSearchKey)
}
protected open fun provideDao(): ISearchHistoryDao = SearchHistoryDao(this)
open fun updateDisplayType(type: DisplayType) {
val transaction = supportFragmentManager.beginTransaction()
when (type) {

View File

@ -55,15 +55,18 @@ import com.gh.common.util.CheckLoginUtils;
import com.gh.common.util.DirectUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.gamecenter.common.base.activity.BaseActivity;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.constant.EntranceConsts;
import com.gh.gamecenter.common.entity.CommunityEntity;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.entity.SimpleGameEntity;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.ToastUtils;
import com.gh.gamecenter.entity.SubjectData;
import com.gh.gamecenter.entity.SubjectRecommendEntity;
import com.gh.gamecenter.entity.VideoLinkEntity;
import com.gh.gamecenter.feature.utils.PlatformUtils;
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper;
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel;
import com.gh.gamecenter.video.videomanager.VideoManagerActivity;
import com.gh.vspace.shortcut.OnCreateShortcutResult;
@ -152,7 +155,7 @@ public class SkipActivity extends BaseActivity {
DirectUtils.directToGameDetail(this, path, "", entrance, "true".equals(uri.getQueryParameter("auto_download")), to, null);
break;
case HOST_COLUMN:
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), entrance, null, false);
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), entrance, null, SubjectData.SubjectType.NORMAL);
break;
case HOST_SUGGESTION:
if (!TextUtils.isEmpty(qaId)) {
@ -401,7 +404,7 @@ public class SkipActivity extends BaseActivity {
try {
JSONObject extJsonObject = new JSONObject(extJson);
String qqGameId = extJsonObject.optString("aid");
DirectUtils.directToQGameById(this, qqGameId);
MiniGameItemHelper.INSTANCE.launchMiniGame(qqGameId, Constants.QQ_MINI_GAME);
} catch (JSONException ignored) {
}
break;

View File

@ -9,12 +9,12 @@ import com.gh.gamecenter.DisplayType
import com.gh.gamecenter.R
import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.SearchType
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.search.SearchDefaultFragment
class AmwaySearchActivity : SearchActivity() {
private lateinit var mViewModel: AmwaySearchViewModel
private val mSearchHistoryDao by lazy { AmwaySearchDao() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -22,38 +22,43 @@ class AmwaySearchActivity : SearchActivity() {
mViewModel = viewModelProvider()
}
override fun provideDao(): ISearchHistoryDao = AmwaySearchDao()
override fun handleAutoSearch(key: String?) {
mSearchKey = key
updateDisplayType(DisplayType.GAME_DIGEST)
mViewModel.getSearchResult(mSearchKey!!)
}
override fun handleHistorySearch(key: String?) {
mSearchKey = key
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
mViewModel.getSearchResult(mSearchKey!!)
updateDisplayType(DisplayType.GAME_DETAIL)
}
private fun handleOtherSearch() {
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
if (newSearchKey != mSearchKey || mDisplayType != DisplayType.GAME_DETAIL) {
mSearchKey = newSearchKey
if (!TextUtils.isEmpty(mSearchKey)) {
mViewModel.getSearchResult(mSearchKey!!)
mDao.add(mSearchKey!!)
updateDisplayType(DisplayType.GAME_DETAIL)
} else {
toast("请先输入游戏名再搜索~")
}
}
}
override fun search(type: SearchType, key: String?) {
mSearchType = type
mIsAutoSearchDisabled = true
when (type) {
SearchType.AUTO -> {
mSearchKey = key
updateDisplayType(DisplayType.GAME_DIGEST)
mViewModel.getSearchResult(mSearchKey!!)
}
SearchType.HISTORY -> {
mSearchKey = key
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
mViewModel.getSearchResult(mSearchKey!!)
updateDisplayType(DisplayType.GAME_DETAIL)
}
else -> {
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
if (newSearchKey != mSearchKey || mDisplayType != DisplayType.GAME_DETAIL) {
mSearchKey = newSearchKey
if (!TextUtils.isEmpty(mSearchKey)) {
mViewModel.getSearchResult(mSearchKey!!)
mSearchHistoryDao.add(mSearchKey!!)
updateDisplayType(DisplayType.GAME_DETAIL)
} else {
toast("请先输入游戏名再搜索~")
}
}
}
SearchType.AUTO -> handleAutoSearch(key)
SearchType.HISTORY -> handleHistorySearch(key)
else -> handleOtherSearch()
}
mIsAutoSearchDisabled = false
}

View File

@ -1,9 +1,11 @@
package com.gh.gamecenter.amway.search
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.db.ISearchHistoryDao
class AmwaySearchDao {
fun add(keyword: String) {
class AmwaySearchDao : ISearchHistoryDao {
override fun add(keyword: String) {
val originString = SPUtils.getString(SP_KEY)
if (originString.isEmpty()) {
@ -28,16 +30,18 @@ class AmwaySearchDao {
}
}
fun getAll(): ArrayList<String>? {
override fun getAll(): ArrayList<String>? {
val list = SPUtils.getString(SP_KEY).split(SEARCH_KEY_DIVIDER)
return if (list.size == 1 && list[0].isEmpty()) null else ArrayList(list)
}
fun deleteAll() {
override fun deleteAll() {
SPUtils.setString(SP_KEY, "")
}
override fun delete(item: String) {}
companion object {
const val SP_KEY = "amway_key"
const val SEARCH_KEY_DIVIDER = "<-||->"

View File

@ -7,6 +7,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.databinding.FragmentAmwaySearchDefaultBinding
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.eventbus.EBSearch
import com.gh.gamecenter.search.SearchDefaultFragment
import com.lightgame.utils.Util_System_Keyboard
@ -14,7 +15,6 @@ import org.greenrobot.eventbus.EventBus
class AmwaySearchDefaultFragment : SearchDefaultFragment() {
private lateinit var mSearchDao: AmwaySearchDao
private lateinit var mViewModel: AmwaySearchViewModel
private val mAmwayBinding by lazy { FragmentAmwaySearchDefaultBinding.inflate(layoutInflater) }
@ -22,11 +22,15 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
override fun getLayoutId() = 0
override fun getInflatedLayout() = mAmwayBinding.root
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mViewModel = viewModelProviderFromParent()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mViewModel = viewModelProviderFromParent()
mViewModel.playedGames.observeNonNull(this) {
mViewModel.playedGames.observeNonNull(viewLifecycleOwner) {
defaultViewModel?.isExistHotSearch = it.isNotEmpty()
updateView()
mBinding.hotList.run {
@ -38,28 +42,21 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
}
}
override fun initDao() {
mSearchDao = AmwaySearchDao()
mHistoryList = mSearchDao.getAll()
}
override fun provideDao(): ISearchHistoryDao = AmwaySearchDao()
override fun initView() {
mBinding = mAmwayBinding.searchContent
defaultViewModel?.isExistHistory = mHistoryList?.isNotEmpty() == true
updateView()
mBinding.hotHeadContainer.headTitle.text = "最近玩过"
mBinding.historyFlexContainer.setLimitHeight(mFlexMaxHeight)
createFlexContent(mBinding.historyFlex, mHistoryList, clickListener = {
val key = mHistoryList!![it]
mSearchDao.add(key)
EventBus.getDefault().post(EBSearch("history", key))
Util_System_Keyboard.hideSoftKeyboardByIBinder(context, mBinding.historyFlex.windowToken)
})
initHistoryHeadView()
updateHistorySearchView(null)
defaultViewModel?.historySearchLiveData?.observe(this) {
updateHistorySearchView(it)
}
initHeadView()
}
private fun initHistoryHeadView() {
override fun initHeadView() {
mBinding.historyHeadContainer.run {
headTitle.text = getString(R.string.search_history)
headTitle.textSize = 16F
@ -73,17 +70,15 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
)
headActionTv.setOnClickListener {
DialogHelper.showCenterWarningDialog(requireContext(), "清空记录", "确定清空历史搜索记录?", confirmClickCallback = {
mSearchDao.deleteAll()
defaultViewModel?.isExistHistory = false
updateView()
updateNoPlayedGameHint()
defaultViewModel?.deleteAll()
})
}
}
}
private fun updateNoPlayedGameHint() {
if (mSearchDao.getAll() != null && mSearchDao.getAll()?.size != 0) {
val historyList = defaultViewModel?.historySearchLiveData?.value
if (!historyList.isNullOrEmpty()) {
mAmwayBinding.noDataContainer.visibility = View.GONE
return
}
@ -95,4 +90,21 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
}
}
override fun updateHistorySearchView(historyList: List<String>?) {
defaultViewModel?.isExistHistory = historyList?.isNotEmpty() == true
updateView()
updateNoPlayedGameHint()
historyList?.let {
createFlexContent(mBinding.historyFlex, historyList, clickListener = { id ->
val key = it[id]
defaultViewModel?.add(key)
EventBus.getDefault().post(EBSearch("history", key))
Util_System_Keyboard.hideSoftKeyboardByIBinder(
context,
mBinding.historyFlex.windowToken
)
})
}
}
}

View File

@ -0,0 +1,14 @@
package com.gh.gamecenter.db;
import java.util.List;
public interface ISearchHistoryDao {
void deleteAll();
void add(String item);
void delete(String item);
List<String> getAll();
}

View File

@ -11,7 +11,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SearchHistoryDao {
public class SearchHistoryDao implements ISearchHistoryDao {
private DatabaseHelper helper;
private Dao<SearchHistoryInfo, String> dao;
@ -25,6 +25,7 @@ public class SearchHistoryDao {
}
}
@Override
public void add(String item) {
AppExecutor.getIoExecutor().execute(() -> {
try {
@ -35,6 +36,7 @@ public class SearchHistoryDao {
});
}
@Override
public void delete(String item) {
AppExecutor.getIoExecutor().execute(() -> {
try {
@ -45,6 +47,7 @@ public class SearchHistoryDao {
});
}
@Override
public void deleteAll() {
AppExecutor.getIoExecutor().execute(() -> {
CloseableIterator<SearchHistoryInfo> iterator = dao.iterator();
@ -59,6 +62,7 @@ public class SearchHistoryDao {
return;
}
@Override
public List<String> getAll() {
List<String> history = new ArrayList<String>();

View File

@ -6,12 +6,10 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.DirectUtils
import com.gh.common.util.DownloadItemUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.safelyGetInRelease
@ -21,6 +19,7 @@ import com.gh.gamecenter.entity.AdConfig
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.lightgame.adapter.BaseRecyclerAdapter
import com.lightgame.download.DownloadEntity
@ -93,11 +92,8 @@ class AdGameBannerAdapter(
it.id,
it.name ?: ""
)
if (it.isQQMiniGame()) {
GlobalActivityManager.currentActivity?.let { activity ->
NewFlatLogUtils.logQGameClick(it.qqMiniGameAppId, it.name)
DirectUtils.directToQGameById(activity, it.qqMiniGameAppId)
}
if (it.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(it.miniGameAppId, it.miniGameType)
} else {
GameDetailActivity.startGameDetailActivity(
mContext,

View File

@ -26,19 +26,19 @@ data class BottomTab(
@SerializedName("is_default_page")
var default: Boolean = false, // 是否为默认显示页
var isTransparentStyle: Boolean = false // 本地字段透明底部Tab
): Parcelable {
) : Parcelable {
@Parcelize
data class SearchStyle(
@SerializedName("style_type")
var styleType: String = STYLE_TWO_LINES, // 样式类型two_lines搜索栏与顶部tab分为两行、apposition搜索栏与顶部tab同一行
@SerializedName("search_type")
var searchType: String = TYPE_HALO_GAME, // 搜索类型halo_game光环游戏、qq_mini_gameQQ小游戏、bbs论坛
): Parcelable {
var searchType: String = TYPE_HALO_GAME, // 搜索类型halo_game光环游戏、bbs论坛、mini_game小游戏搜索低于v5.36版本返回qq_mini_game
) : Parcelable {
companion object {
const val STYLE_TWO_LINES = "two_lines"
const val STYLE_APPOSITION = "apposition"
const val TYPE_HALO_GAME = "halo_game"
const val TYPE_QQ_MINI_GAME = "qq_mini_game"
const val TYPE_MINI_GAME = "mini_game"
const val TYPE_BBS = "bbs"
}
}

View File

@ -1,6 +1,7 @@
package com.gh.gamecenter.entity
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.feature.entity.SettingsEntity
import com.gh.gamecenter.feature.entity.SimulatorEntity
import com.google.gson.annotations.SerializedName
@ -20,6 +21,7 @@ class NewApiSettingsEntity(
var install: Install, // 安装相关的
@SerializedName("game_shield_contents")
var gameShieldContents: List<String>? = listOf(),//游戏屏蔽内容
var search: SettingsEntity.Search? = null// 游戏搜索配置
) {
/**
*

View File

@ -17,7 +17,7 @@ class SubjectData(
var filter: String = "", // Filter: 类型(分类)
var tagType: String? = "", // 游戏Item 标签类型
var briefStyle: String = "",
var isQQMiniGame: Boolean = false,
var subjectType: SubjectType = SubjectType.NORMAL,
var subjectStyle: String = "",
var requireUpdateSetting: Boolean = false, // 多专题页面需要专题页面自行获取专题配置
@ -43,4 +43,24 @@ class SubjectData(
tag = tagType
)
}
/**
* 专题类型
*/
enum class SubjectType {
/**
* 普通专题
*/
NORMAL,
/**
* QQ小游戏专题
*/
QQ_GAME,
/**
* 微信小游戏专题
*/
WECHAT_GAME
}
}

View File

@ -102,6 +102,9 @@ data class SubjectEntity(
@SerializedName("is_qq_column")
var isQQColumn: Boolean = false,
@SerializedName("is_wechat_column")
var isWechatColumn: Boolean = false,
var explain: String = "", // 游戏单合集说明
@SerializedName("show_star")
@ -115,6 +118,14 @@ data class SubjectEntity(
mData = value
}
val subjectType: SubjectData.SubjectType get() = when {
isQQColumn -> SubjectData.SubjectType.QQ_GAME
isWechatColumn -> SubjectData.SubjectType.WECHAT_GAME
else -> SubjectData.SubjectType.NORMAL
}
val isMiniGame: Boolean get() = isQQColumn || isWechatColumn
val showStar: Boolean
get() = _showStar ?: false

View File

@ -16,6 +16,7 @@ import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.showKeyBoard
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.forum.detail.ForumDetailFragment
import com.gh.gamecenter.search.SearchDefaultFragment
import com.lightgame.utils.Util_System_Keyboard
@ -28,7 +29,6 @@ class ForumOrUserSearchActivity : SearchActivity() {
private var mBbsId = ""
private var mLocation = ""
private var mSourceEntrance = ""
private val mSearchHistoryDao by lazy { ForumSearchDao() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -63,66 +63,66 @@ class ForumOrUserSearchActivity : SearchActivity() {
}
}
override fun provideDao(): ISearchHistoryDao = ForumSearchDao()
override fun handleAutoSearch(key: String?) {
mSearchKey = key
updateDisplayType(DisplayType.FORUM_OR_USER)
SensorsBridge.trackSearchButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
key ?: "",
TRACK_SEARCH_TYPE_INPUT,
mSourceEntrance
)
}
override fun handleHistorySearch(key: String?) {
mSearchKey = key
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
updateDisplayType(DisplayType.FORUM_OR_USER)
SensorsBridge.trackSearchButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
key ?: "",
TRACK_SEARCH_TYPE_HISTORY,
mSourceEntrance
)
}
private fun handleOtherSearch(type: SearchType) {
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
if (newSearchKey != mSearchKey || mDisplayType != DisplayType.GAME_DETAIL) {
mSearchKey = newSearchKey
if (!TextUtils.isEmpty(mSearchKey)) {
mDao.add(mSearchKey!!)
updateDisplayType(DisplayType.FORUM_OR_USER)
val searchType = if (type == SearchType.MANUAL) {
TRACK_SEARCH_TYPE_INPUT
} else {
TRACK_SEARCH_TYPE_DEFAULT
}
SensorsBridge.trackSearchButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
newSearchKey,
searchType,
mSourceEntrance
)
} else {
toast("请先输入搜索内容再搜索~")
}
}
}
override fun search(type: SearchType, key: String?) {
mSearchType = type
mIsAutoSearchDisabled = true
when (type) {
SearchType.AUTO -> {
mSearchKey = key
updateDisplayType(DisplayType.FORUM_OR_USER)
SensorsBridge.trackSearchButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
key ?: "",
TRACK_SEARCH_TYPE_INPUT,
mSourceEntrance
)
}
SearchType.HISTORY -> {
mSearchKey = key
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
updateDisplayType(DisplayType.FORUM_OR_USER)
SensorsBridge.trackSearchButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
key ?: "",
TRACK_SEARCH_TYPE_HISTORY,
mSourceEntrance
)
}
else -> {
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
if (newSearchKey != mSearchKey || mDisplayType != DisplayType.GAME_DETAIL) {
mSearchKey = newSearchKey
if (!TextUtils.isEmpty(mSearchKey)) {
mSearchHistoryDao.add(mSearchKey!!)
updateDisplayType(DisplayType.FORUM_OR_USER)
if (type == SearchType.MANUAL) {
SensorsBridge.trackSearchButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
newSearchKey,
TRACK_SEARCH_TYPE_INPUT,
mSourceEntrance
)
} else {
SensorsBridge.trackSearchButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
newSearchKey,
TRACK_SEARCH_TYPE_DEFAULT,
mSourceEntrance
)
}
} else {
toast("请先输入搜索内容再搜索~")
}
}
}
SearchType.AUTO -> handleAutoSearch(key)
SearchType.HISTORY -> handleHistorySearch(key)
else -> handleOtherSearch(type)
}
mIsAutoSearchDisabled = false

View File

@ -7,6 +7,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.databinding.FragmentSearchDefaultBinding
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.eventbus.EBSearch
import com.gh.gamecenter.search.SearchDefaultFragment
import com.lightgame.utils.Util_System_Keyboard
@ -14,7 +15,6 @@ import org.greenrobot.eventbus.EventBus
class ForumOrUserSearchDefaultFragment : SearchDefaultFragment() {
private lateinit var mSearchDao: ForumSearchDao
private lateinit var mViewModel: ForumOrUserSearchDefaultViewModel
override fun onCreate(savedInstanceState: Bundle?) {
@ -38,10 +38,7 @@ class ForumOrUserSearchDefaultFragment : SearchDefaultFragment() {
updateView()
}
override fun initDao() {
mSearchDao = ForumSearchDao()
mHistoryList = mSearchDao.getAll()
}
override fun provideDao(): ISearchHistoryDao = ForumSearchDao()
override fun initView() {
mBinding = FragmentSearchDefaultBinding.bind(mCachedView)
@ -57,18 +54,12 @@ class ForumOrUserSearchDefaultFragment : SearchDefaultFragment() {
val params = mBinding.historyHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams
params.topMargin = 0.5f.dip2px()
mBinding.historyHeadContainer.root.layoutParams = params
defaultViewModel?.isExistHistory = mHistoryList?.isNotEmpty() == true
updateView()
mBinding.historyFlexContainer.setLimitHeight(mFlexMaxHeight)
createFlexContent(mBinding.historyFlex, mHistoryList, clickListener = {
val key = mHistoryList!![it]
mSearchDao.add(key)
EventBus.getDefault().post(EBSearch("history", key))
Util_System_Keyboard.hideSoftKeyboardByIBinder(
context,
mBinding.historyFlex.windowToken
)
})
updateHistorySearchView(null)
defaultViewModel?.historySearchLiveData?.observe(this) {
updateHistorySearchView(it)
}
mBinding.historyHeadContainer.run {
headTitle.text = getString(R.string.search_history)
@ -83,11 +74,27 @@ class ForumOrUserSearchDefaultFragment : SearchDefaultFragment() {
)
headActionTv.setOnClickListener {
DialogHelper.showCenterWarningDialog(requireContext(), "清空记录", "确定清空历史搜索记录?", confirmClickCallback = {
mSearchDao.deleteAll()
defaultViewModel?.deleteAll()
defaultViewModel?.isExistHistory = false
updateView()
})
}
}
}
override fun updateHistorySearchView(historyList: List<String>?) {
defaultViewModel?.isExistHistory = historyList?.isNotEmpty() == true
updateView()
historyList?.let {
createFlexContent(mBinding.historyFlex, historyList, clickListener = { id ->
val key = it[id]
defaultViewModel?.add(key)
EventBus.getDefault().post(EBSearch("history", key))
Util_System_Keyboard.hideSoftKeyboardByIBinder(
context,
mBinding.historyFlex.windowToken
)
})
}
}
}

View File

@ -1,9 +1,10 @@
package com.gh.gamecenter.forum.search
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.db.ISearchHistoryDao
class ForumSearchDao {
fun add(keyword: String) {
class ForumSearchDao : ISearchHistoryDao {
override fun add(keyword: String) {
val originString = SPUtils.getString(SP_KEY)
if (originString.isEmpty()) {
@ -28,13 +29,15 @@ class ForumSearchDao {
}
}
fun getAll(): ArrayList<String>? {
override fun delete(item: String) {}
override fun getAll(): ArrayList<String>? {
val list = SPUtils.getString(SP_KEY).split(SEARCH_KEY_DIVIDER)
return if (list.size == 1 && list[0].isEmpty()) null else ArrayList(list)
}
fun deleteAll() {
override fun deleteAll() {
SPUtils.setString(SP_KEY, "")
}

View File

@ -22,9 +22,11 @@ import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.MainActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.ImagePagerAdapter
import com.gh.gamecenter.adapter.viewholder.*
import com.gh.gamecenter.adapter.viewholder.GameHeadViewHolder
import com.gh.gamecenter.adapter.viewholder.GameImageViewHolder
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.adapter.viewholder.GameViewPagerViewHolder
import com.gh.gamecenter.category.CategoryDirectoryActivity
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.callback.OnViewClickListener
import com.gh.gamecenter.common.constant.EntranceConsts
@ -71,7 +73,10 @@ import com.gh.gamecenter.game.rank.RankCollectionViewHolder
import com.gh.gamecenter.game.vertical.GameVerticalAdapter
import com.gh.gamecenter.game.vertical.GameVerticalSlideViewHolder
import com.gh.gamecenter.game.vertical.OnPagerSnapScrollListener
import com.gh.gamecenter.home.*
import com.gh.gamecenter.home.BlankDividerViewHolder
import com.gh.gamecenter.home.HomeDividerViewHolder
import com.gh.gamecenter.home.HomeGameItemViewHolder
import com.gh.gamecenter.home.LegacyHomeFragmentAdapterAssistant
import com.gh.gamecenter.home.discovercard.DiscoverCardGameAdapter
import com.gh.gamecenter.home.discovercard.HomeDiscoverCardViewHolder
import com.gh.gamecenter.home.gamecollection.carousel.HomeGameCollectionCarouselViewHolder
@ -85,7 +90,8 @@ import com.gh.gamecenter.home.test_v2.HomeGameTestV2GameListRvAdapter
import com.gh.gamecenter.home.test_v2.HomeGameTestV2ViewModel
import com.gh.gamecenter.home.test_v2.HomeItemGameTestV2ViewHolder
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
import com.gh.gamecenter.qgame.QGameHorizontalSlideListViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.minigame.qq.QGameRecentlyPlayViewHolder
import com.gh.gamecenter.servers.gametest2.GameServerTestV2Activity
import com.gh.gamecenter.subject.SubjectActivity
import com.gh.vspace.HomeRecentVGameAdapter
@ -189,7 +195,7 @@ class GameFragmentAdapter(
ItemViewType.GAME_SUBJECT -> GameHorizontalListViewHolder(parent.toBinding())
// 游戏专题-横屏滑动
ItemViewType.GAME_SUBJECT_SLIDE -> GameHorizontalSlideListViewHolder(parent.toBinding())
ItemViewType.QQ_GAME_SUBJECT_SLIDE -> QGameHorizontalSlideListViewHolder(parent.toBinding())
ItemViewType.QQ_GAME_SUBJECT_SLIDE -> QGameRecentlyPlayViewHolder(parent.toBinding())
// 正常游戏
ItemViewType.GAME_NORMAL -> GameItemViewHolder(parent.toBinding())
// 游戏专题-大图-显示/只显示
@ -257,7 +263,7 @@ class GameFragmentAdapter(
is FooterViewHolder -> bindFooterView(holder)
is GameImageViewHolder -> bindGameImageView(holder, position)
is GameHorizontalListViewHolder -> bindGameHorizontalListView(holder, position)
is QGameHorizontalSlideListViewHolder -> bindQGameHorizontalSlideListView(holder, position)
is QGameRecentlyPlayViewHolder -> bindQGameHorizontalSlideListView(holder, position)
is GameHorizontalSlideListViewHolder -> bindGameHorizontalSlideListView(holder, position)
is GameImageSlideViewHolder -> bindGameImageSlide(holder, position)
is GameVerticalSlideViewHolder -> bindVerticalSlide(holder, position)
@ -306,7 +312,7 @@ class GameFragmentAdapter(
holder.cell.binding?.root?.setOnClickListener {
setPageSwitchData()
DirectUtils.directToSubject(
it.context, gallery.id ?: "", gallery.name, "(游戏-专题)", null, gallery.isQQColumn
it.context, gallery.id ?: "", gallery.name, "(游戏-专题)", null, gallery.subjectType
)
NewLogUtils.logColumnPictureClick(
"显示图集", gallery.name ?: "", gallery.id ?: "", gallery.id ?: "", "column",
@ -591,11 +597,8 @@ class GameFragmentAdapter(
val clickClosure: (Int, GameEntity) -> Unit = { _, gameEntity ->
val subjectData = gameEntity.subjectData
DataCollectionUtils.uploadClick(mContext, subjectData?.name + "-列表", "游戏-专题", gameEntity.name)
if (gameEntity.isQQMiniGame()) {
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
GlobalActivityManager.currentActivity?.let {
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
}
if (gameEntity.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
} else {
GameDetailActivity.startGameDetailActivity(
mContext, gameEntity,
@ -783,9 +786,9 @@ class GameFragmentAdapter(
}
}
private fun bindQGameHorizontalSlideListView(holder: QGameHorizontalSlideListViewHolder, position: Int) {
private fun bindQGameHorizontalSlideListView(holder: QGameRecentlyPlayViewHolder, position: Int) {
val subject = mItemDataList[position].qqHorizontalSlide
holder.bindHorizontalSlideList(subject!!)
holder.bindView(subject!!)
holder.binding.moreTv.setOnClickListener {
val buttonType = when (subject.home) {
@ -837,7 +840,7 @@ class GameFragmentAdapter(
subject.isOrder,
mBasicExposureSource,
"(游戏-专题:" + subject.name + "-全部)",
subject.isQQColumn
subject.subjectType
)
}
MtaHelper.onEvent("游戏专题", "全部", subject.name)
@ -1313,11 +1316,8 @@ class GameFragmentAdapter(
DataCollectionUtils.uploadClick(mContext, subjectData.name + "-列表", "游戏-专题", gameEntity.name)
if (gameEntity.isQQMiniGame()) {
GlobalActivityManager.currentActivity?.let {
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
}
if (gameEntity.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
} else if (gameEntity.isPluggable) {
GameDetailActivity.startGameDetailActivity(
mContext,
@ -1546,26 +1546,15 @@ class GameFragmentAdapter(
}
DirectUtils.directToLinkPage(mContext, link, "(游戏-专题:" + column.name + "-全部)", "")
} else {
if (column.isQQColumn) {
SubjectActivity.startSubjectActivity(
mContext,
column.id,
column.getFilterName(),
column.isOrder,
mBasicExposureSource,
"(游戏-专题:" + column.name + "-全部)",
column.isQQColumn
)
} else {
SubjectActivity.startSubjectActivity(
mContext,
column.id,
column.getFilterName(),
column.isOrder,
mBasicExposureSource,
"(游戏-专题:" + column.name + "-全部)"
)
}
SubjectActivity.startSubjectActivity(
mContext,
column.id,
column.getFilterName(),
column.isOrder,
mBasicExposureSource,
"(游戏-专题:" + column.name + "-全部)",
column.subjectType
)
}
MtaHelper.onEvent("游戏专题", "全部", column.name)
}

View File

@ -70,6 +70,11 @@ class ColumnCollectionDetailFragment : LazyListFragment<LinkEntity, ColumnCollec
val subjectDataList = arrayListOf<SubjectData>()
for (link in linkEntityList) {
val subjectType = when(link.type) {
TYPE_QQ_MINI_GAME_COLUMN -> SubjectData.SubjectType.QQ_GAME
TYPE_WECHAT_MINI_GAME_COLUMN -> SubjectData.SubjectType.WECHAT_GAME
else -> SubjectData.SubjectType.NORMAL
}
subjectDataList.add(
SubjectData(
subjectId = link.link,
@ -78,7 +83,7 @@ class ColumnCollectionDetailFragment : LazyListFragment<LinkEntity, ColumnCollec
isOrder = false,
requireUpdateSetting = true,
filter = "type:全部", // 默认显示大图
isQQMiniGame = link.type == "qq_mini_game_column"
subjectType = subjectType
)
)
}
@ -133,4 +138,9 @@ class ColumnCollectionDetailFragment : LazyListFragment<LinkEntity, ColumnCollec
return ViewModelProviders.of(this, factory).get(ColumnCollectionDetailViewModel::class.java)
}
companion object {
const val TYPE_QQ_MINI_GAME_COLUMN = "qq_mini_game_column"
const val TYPE_WECHAT_MINI_GAME_COLUMN = "wechat_mini_game_column"
}
}

View File

@ -5,12 +5,9 @@ import android.view.ViewGroup
import androidx.activity.ComponentActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.common.utils.toColor
@ -20,6 +17,7 @@ import com.gh.gamecenter.databinding.ItemWithinGameGallerySlideBinding
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.lightgame.adapter.BaseRecyclerAdapter
/**
@ -137,11 +135,8 @@ class GameGallerySlideViewHolder(val binding: GameGallerySlideItemBinding) : Bas
fun bindView(gameEntity: GameEntity) {
binding.iconIv.displayGameIcon(gameEntity)
binding.iconIv.setOnClickListener {
if (gameEntity.isQQMiniGame()) {
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
GlobalActivityManager.currentActivity?.let {
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
}
if (gameEntity.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
} else {
GameDetailActivity.startGameDetailActivity(
binding.root.context,

View File

@ -2,10 +2,8 @@ package com.gh.gamecenter.game.gallery
import android.content.Context
import android.view.View
import com.gh.common.util.DirectUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.common.utils.toColor
@ -14,6 +12,7 @@ import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.databinding.GameGalleryItemBinding
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
/**
* 游戏专题-显示图集
@ -54,11 +53,9 @@ class GameGalleryViewHolder(val cell: GameGalleryItemCell) :
gameIcon.rotation = 35F
gameIcon.displayGameIcon(gameEntity)
if (subjectEntity.isQQColumn) {
if (subjectEntity.isMiniGame) {
gameIcon.setOnClickListener {
GlobalActivityManager.currentActivity?.let {
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
}
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
}
} else {
gameIcon.setOnClickListener(null)

View File

@ -4,7 +4,6 @@ import android.content.Context
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.*
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
@ -16,6 +15,7 @@ import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.subjectTypeToComponentStyle
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.lightgame.adapter.BaseRecyclerAdapter
import com.lightgame.download.DownloadEntity
@ -55,12 +55,14 @@ class GameHorizontalAdapter(
override fun getItemCount(): Int {
val size = mSubjectEntity.data!!.size - getIndex()
return if (type == GameHorizontalListType.GameDetailHorizontalType) {
size
} else if (type == GameHorizontalListType.QGameSubjectHorizontalType) {
mSubjectEntity.data!!.size
} else {
when {
return when (type) {
GameHorizontalListType.GameDetailHorizontalType -> {
size
}
GameHorizontalListType.MiniGameSubjectHorizontalType -> {
mSubjectEntity.data!!.size
}
else -> when {
size < 4 -> size
size < 8 -> 4
else -> 8
@ -125,7 +127,7 @@ class GameHorizontalAdapter(
clickGameName = gameEntity.name ?: "",
clickGameId = gameEntity.id
)
if (!gameEntity.isQQMiniGame() && trackColumnClick) {
if (!gameEntity.isMiniGame() && trackColumnClick) {
SensorsBridge.trackColumnClick(
location = "游戏详情",
gameName = gameName,
@ -138,11 +140,8 @@ class GameHorizontalAdapter(
}
}
if (gameEntity.isQQMiniGame()) {
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
GlobalActivityManager.currentActivity?.let {
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
}
if (gameEntity.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
} else {
GameDetailActivity.startGameDetailActivity(
mContext,
@ -224,5 +223,5 @@ sealed class GameHorizontalListType {
object GameDetailHorizontalType : GameHorizontalListType()
object SubjectHorizontalType : GameHorizontalListType()
object QGameSubjectHorizontalType : GameHorizontalListType()
object MiniGameSubjectHorizontalType : GameHorizontalListType()
}

View File

@ -23,8 +23,8 @@ class GameHorizontalListViewHolder(val binding: GameHorizontalListBinding) :
subjectAdapter = GameHorizontalAdapter(
context,
subjectEntity,
if (subjectEntity.isQQColumn) {
GameHorizontalListType.QGameSubjectHorizontalType
if (subjectEntity.isMiniGame) {
GameHorizontalListType.MiniGameSubjectHorizontalType
}
else {
GameHorizontalListType.SubjectHorizontalType

View File

@ -2,18 +2,16 @@ package com.gh.gamecenter.game.horizontal
import android.content.Context
import android.view.ViewGroup
import com.gh.common.util.DirectUtils
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.common.util.DownloadItemUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.databinding.GameHorizontalItemBinding
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.lightgame.adapter.BaseRecyclerAdapter
import com.lightgame.download.DownloadEntity
@ -70,11 +68,8 @@ class GameHorizontalSlideAdapter(
}
holder.bindGameHorizontalItem(gameEntity, mSubjectEntity)
holder.itemView.setOnClickListener {
if (gameEntity.isQQMiniGame()) {
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
GlobalActivityManager.currentActivity?.let {
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
}
if (gameEntity.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
} else {
val exposureEvent = exposureEventList?.safelyGetInRelease(position)
if (exposureEvent != null) {

View File

@ -3,6 +3,7 @@ package com.gh.gamecenter.game.vertical
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.os.Build
import android.text.TextUtils
import android.util.AttributeSet
import android.view.Gravity
@ -59,6 +60,7 @@ class GameItemUi(override val ctx: Context) : Ui {
var recommendTv: TextView
var gameTagContainer: GameTagContainerView
var recommendConstraintLayout: ConstraintLayout
var gamePlayCountTv: TextView
var mGameDesSpace: Space
@ -78,6 +80,7 @@ class GameItemUi(override val ctx: Context) : Ui {
gameRatingTv = initGameRatingTv()
recommendIv = SimpleDraweeView(ctx).apply { id = R.id.recommendIv }
recommendTv = initRecommendTv()
gamePlayCountTv = initGamePlayCountTv()
gameTagContainer = GameTagContainerView(ctx).apply { id = R.id.label_list }
mGameDesSpace = space { }.apply { id = R.id.gameDesSpace }
recommendConstraintLayout = initRecommendConstraintLayout()
@ -120,8 +123,7 @@ class GameItemUi(override val ctx: Context) : Ui {
startToEndOf(gameRatingTv)
endToEndOf(mGameDesSpace)
topToTopOf(mGameDesSpace)
topMargin = dip(5)
bottomToBottomOf(mGameDesSpace)
})
add(recommendConstraintLayout, lParams(wrapContent, dip(18)) {
startToStartOf(mGameDesSpace)
@ -135,10 +137,17 @@ class GameItemUi(override val ctx: Context) : Ui {
add(gameTagContainer, lParams(0, wrapContent) {
topToBottomOf(mGameDesSpace)
bottomToBottomOf(iconIv)
startToStartOf(mGameDesSpace)
startToEndOf(gamePlayCountTv)
endToEndOf(mGameDesSpace)
orientation = LinearLayout.HORIZONTAL
})
add(gamePlayCountTv, lParams(wrapContent, wrapContent) {
topToBottomOf(mGameDesSpace)
bottomToBottomOf(iconIv)
startToStartOf(mGameDesSpace)
endToStartOf(gameTagContainer)
endMargin = dip(8)
})
add(gameNameContainer, lParams(0, wrapContent) {
startToStartOf(mGameDesSpace)
topToTopOf(iconIv)
@ -226,6 +235,15 @@ class GameItemUi(override val ctx: Context) : Ui {
setTextColor(ContextCompat.getColor(context, R.color.text_tertiary))
}
private fun initGamePlayCountTv() = textView {
id = R.id.game_play_count
textSize = 11F
includeFontPadding = false
gravity = Gravity.CENTER
setTextColor(ContextCompat.getColor(context, R.color.text_tertiary))
visibility = View.GONE
}
private fun initDownloadTv() = DownloadButton(ctx).apply {
id = R.id.download_btn
text = "下载"

View File

@ -14,6 +14,7 @@ import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.GameSubjectData
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.lightgame.adapter.BaseRecyclerAdapter
import com.lightgame.download.DownloadEntity
@ -178,6 +179,8 @@ class GameVerticalAdapter(
adLabelTv
)
MiniGameItemHelper.setMiniGameUsage(gamePlayCountTv, gameEntity)
var gameRatingPaddingEnd = 0
var gameRatingDrawableStart: Drawable? = null
var gameRatingTextColor = R.color.primary_theme.toColor(context)

View File

@ -7,12 +7,10 @@ import androidx.constraintlayout.widget.ConstraintSet
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.DirectUtils
import com.gh.common.util.DownloadItemUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.RandomUtils
@ -20,6 +18,7 @@ import com.gh.gamecenter.databinding.HomeGameItemBinding
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
@ -97,11 +96,8 @@ class HomeGameItemViewHolder(val binding: HomeGameItemBinding) : BaseRecyclerVie
}
}
holder.itemView.setOnClickListener {
if (game.isQQMiniGame()) {
NewFlatLogUtils.logQGameClick(game.qqMiniGameAppId, game.name)
GlobalActivityManager.currentActivity?.let {
DirectUtils.directToQGameById(it, game.qqMiniGameAppId)
}
if (game.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(game.miniGameAppId, game.miniGameType)
} else {
GameDetailActivity.startGameDetailActivity(
binding.root.context,
@ -156,6 +152,7 @@ class HomeGameItemViewHolder(val binding: HomeGameItemBinding) : BaseRecyclerVie
subjectEntity.adIconActive,
binding.adLabelTv
)
MiniGameItemHelper.setMiniGameUsage(binding.gamePlayCount, game)
val hierarchy = binding.gameImage.hierarchy
try {
hierarchy.setPlaceholderImage(ColorDrawable(game.homeSetting.placeholderColor.hexStringToIntColor()))

View File

@ -19,13 +19,11 @@ import com.gh.common.prioritychain.PullDownPushHandler
import com.gh.common.util.DefaultSearchHintHelper
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.xapk.XapkInstaller
import com.gh.common.xapk.XapkUnzipStatus
import com.gh.download.DownloadManager
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.base.fragment.LazyFragment
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.constant.Constants
@ -57,6 +55,7 @@ import com.gh.gamecenter.home.custom.adapter.CustomPageAdapter
import com.gh.gamecenter.home.custom.floatview.CustomFloatViewAnimationHelper
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
import com.gh.gamecenter.livedata.EventObserver
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.wrapper.MainWrapperViewModel
import com.gh.gamecenter.wrapper.SearchToolbarTabWrapperFragment
import com.gh.gamecenter.wrapper.SearchToolbarTabWrapperViewModel
@ -264,11 +263,8 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
}
gameDetailDestination.observe(viewLifecycleOwner, EventObserver { (trackData, entrance, game) ->
if (game.isQQMiniGame()) {
GlobalActivityManager.currentActivity?.let {
NewFlatLogUtils.logQGameClick(game.qqMiniGameAppId, game.name)
DirectUtils.directToQGameById(it, game.qqMiniGameAppId)
}
if (game.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(game.miniGameAppId, game.miniGameType)
} else {
GameDetailActivity.startGameDetailActivity(
requireContext(),
@ -284,13 +280,13 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
subjectDestination.observe(viewLifecycleOwner, EventObserver { subject ->
DirectUtils.directToSubject(
requireContext(), subject.id ?: "", subject.name, "自定义页面", null, subject.isQQColumn
requireContext(), subject.id ?: "", subject.name, "自定义页面", null, subject.subjectType
)
})
subjectDestinationWithCustom.observe(viewLifecycleOwner, EventObserver { (subject, isQqMini) ->
subjectDestinationWithCustom.observe(viewLifecycleOwner, EventObserver { (subject, subjectType) ->
DirectUtils.directToSubject(
requireContext(), subject.id, subject.title, "自定义页面", null, isQqMini
requireContext(), subject.id, subject.title, "自定义页面", null, subjectType
)
})
@ -458,7 +454,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
private fun setSearchHint(searchType: String) {
when (searchType) {
BottomTab.SearchStyle.TYPE_HALO_GAME -> DefaultSearchHintHelper.setSearchHint(binding.reuseSearchBar.searchTv)
BottomTab.SearchStyle.TYPE_QQ_MINI_GAME -> binding.reuseSearchBar.searchTv.hint = "请输入小游戏关键词"
BottomTab.SearchStyle.TYPE_MINI_GAME -> binding.reuseSearchBar.searchTv.hint = "请输入小游戏关键词"
BottomTab.SearchStyle.TYPE_BBS -> binding.reuseSearchBar.searchTv.hint = "搜索论坛内容、用户"
}
}

View File

@ -4,6 +4,7 @@ import android.app.Application
import androidx.collection.ArrayMap
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import com.gh.common.util.GameUtils
@ -17,10 +18,7 @@ import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.observableToMain
import com.gh.gamecenter.core.utils.RandomUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.entity.HomeSubSlide
import com.gh.gamecenter.entity.PullDownPush
import com.gh.gamecenter.entity.RatingComment
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.feature.entity.CustomPageTrackData
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PageLocation
@ -33,6 +31,7 @@ import com.gh.gamecenter.home.custom.model.*
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_COLLECTION_STYLE_REFRESH_ICONS_4_2
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_COLLECTION_STYLE_REFRESH_SLIDE_LIST
import com.gh.gamecenter.livedata.Event
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayUseCase
import com.gh.gamecenter.wrapper.SearchToolbarTabWrapperViewModel
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
@ -69,7 +68,13 @@ class CustomPageViewModel(
private val _customPageData = MutableLiveData<CustomPageData>()
val customPageData: LiveData<CustomPageData> = _customPageData
private val _dataList = MutableLiveData<List<CustomPageItem>>()
private val _dataList = MediatorLiveData<List<CustomPageItem>>().apply {
addSource(repository.recentMiniGamesItemLiveData, ::notifyItemChanged)
addSource(repository.customDiscoverItemLiveData, ::notifyItemChanged)
addSource(repository.recentGamesItemLiveData, ::notifyItemChanged)
addSource(repository.customPluginItemLiveData, ::notifyItemChanged)
}
val dataList: LiveData<List<CustomPageItem>> = _dataList
private val _loadStatus = MutableLiveData<Pair<LoadStatus, Boolean>>()
@ -77,12 +82,6 @@ class CustomPageViewModel(
var refreshCount = 0
private val recentGamesObserver = Observer<CustomRecentGamesItem>(::notifyItemChanged)
private val pluginObserver = Observer<CustomPluginItem>(::notifyItemChanged)
private val discoverObserver = Observer<CustomDiscoverCardItem>(::notifyItemChanged)
val pullDownPushData = MutableLiveData<PullDownPush?>()
val pageSwitchData = MutableLiveData<CustomPageData.PageSwitch>()
@ -100,12 +99,6 @@ class CustomPageViewModel(
val pageLocation: PageLocation
get() = pageTracker.pageLocation
init {
repository.recentGamesItemLiveData.observeForever(recentGamesObserver)
repository.customPluginItemLiveData.observeForever(pluginObserver)
repository.customDiscoverItemLiveData.observeForever(discoverObserver)
}
fun init(
pageConfigure: PageConfigure,
searchToolbarTabWrapperViewModel: SearchToolbarTabWrapperViewModel?,
@ -546,15 +539,15 @@ class CustomPageViewModel(
}
private val _subjectDestinationWithCustom =
MutableLiveData<Event<Pair<CustomPageData.LinkColumnCollection.CustomSubjectEntity, Boolean>>>()
val subjectDestinationWithCustom: LiveData<Event<Pair<CustomPageData.LinkColumnCollection.CustomSubjectEntity, Boolean>>> =
MutableLiveData<Event<Pair<CustomPageData.LinkColumnCollection.CustomSubjectEntity, SubjectData.SubjectType>>>()
val subjectDestinationWithCustom: LiveData<Event<Pair<CustomPageData.LinkColumnCollection.CustomSubjectEntity, SubjectData.SubjectType>>> =
_subjectDestinationWithCustom
override fun navigateSubjectDetailPage(
item: CustomSubjectCollectionItem,
subject: CustomPageData.LinkColumnCollection.CustomSubjectEntity
) {
_subjectDestinationWithCustom.value = Event(subject to item.data.isQqMini)
_subjectDestinationWithCustom.value = Event(subject to item.data.subjectType)
}
private val _subjectCollectionDestination =
@ -699,9 +692,6 @@ class CustomPageViewModel(
super.onCleared()
compositeDisposable.clear()
repository.onClear()
repository.recentGamesItemLiveData.removeObserver(recentGamesObserver)
repository.customPluginItemLiveData.removeObserver(pluginObserver)
repository.customDiscoverItemLiveData.removeObserver(discoverObserver)
}

View File

@ -28,6 +28,7 @@ import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.CustomPageTrackData
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.home.custom.eventlistener.SubjectEventHelper
import com.gh.gamecenter.home.custom.model.CustomSubjectItem
import com.lightgame.download.DownloadEntity
@ -166,7 +167,12 @@ class CustomFoldSlideLargeImageItemAdapter(
) {
item = game
ImageUtils.display(binding.poster, game.homeSetting.image)
if (game.isWechatMiniGame()) {
ImageUtils.display(binding.poster, game.banner)
} else {
ImageUtils.display(binding.poster, game.homeSetting.image)
}
binding.ivIcon.displayGameIcon(game)
binding.tvTitle.text = game.name
GameItemViewHolder.initGameSubtitleAndAdLabel(
@ -177,6 +183,8 @@ class CustomFoldSlideLargeImageItemAdapter(
data.data.adIconActive
)
MiniGameItemHelper.setMiniGameUsage(binding.gamePlayCount, game)
binding.tvBubble.text = game.bubbleText
binding.gStar.goneIf(!(data.data.showStar && game.commentCount > 3)) {
binding.tvStar.text = if (game.star == 10.0F) "10" else game.star.toString()

View File

@ -4,7 +4,6 @@ import android.content.Context
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.*
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
@ -19,6 +18,7 @@ import com.gh.gamecenter.game.horizontal.GameHorizontalSimpleItemViewHolder
import com.gh.gamecenter.home.PageConfigure
import com.gh.gamecenter.home.custom.model.CustomSubjectItem
import com.gh.gamecenter.home.custom.viewholder.CustomGameHorizontalItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.lightgame.download.DownloadEntity
class CustomGameHorizontalAdapter(
@ -40,8 +40,8 @@ class CustomGameHorizontalAdapter(
get() = _data.data
private val type: GameHorizontalListType
get() = if (subjectEntity.isQQColumn) {
GameHorizontalListType.QGameSubjectHorizontalType
get() = if (subjectEntity.isMiniGame) {
GameHorizontalListType.MiniGameSubjectHorizontalType
} else {
GameHorizontalListType.SubjectHorizontalType
}
@ -60,12 +60,14 @@ class CustomGameHorizontalAdapter(
override fun getItemCount(): Int {
val size = dataList.size
return if (type == GameHorizontalListType.GameDetailHorizontalType) {
size
} else if (type == GameHorizontalListType.QGameSubjectHorizontalType) {
dataList.size
} else {
when {
return when (type) {
GameHorizontalListType.GameDetailHorizontalType -> {
size
}
GameHorizontalListType.MiniGameSubjectHorizontalType -> {
dataList.size
}
else -> when {
size < 4 -> size
size < 8 -> 4
else -> 8
@ -132,11 +134,8 @@ class CustomGameHorizontalAdapter(
)
}
if (gameEntity.isQQMiniGame()) {
NewFlatLogUtils.logQGameClick(gameEntity.qqMiniGameAppId, gameEntity.name)
GlobalActivityManager.currentActivity?.let {
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
}
if (gameEntity.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
} else {
GameDetailActivity.startGameDetailActivity(
context,
@ -201,5 +200,5 @@ sealed class GameHorizontalListType {
object GameDetailHorizontalType : GameHorizontalListType()
object SubjectHorizontalType : GameHorizontalListType()
object QGameSubjectHorizontalType : GameHorizontalListType()
object MiniGameSubjectHorizontalType : GameHorizontalListType()
}

View File

@ -15,6 +15,7 @@ import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.CustomPageTrackData
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.game.vertical.GameItemUi
import com.gh.gamecenter.home.custom.eventlistener.GameSubjectCollectionEventHelper
import com.gh.gamecenter.home.custom.model.CustomPageData

View File

@ -1,12 +1,8 @@
package com.gh.gamecenter.home.custom.adapter
import android.content.Context
import android.graphics.drawable.Drawable
import android.os.Build
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import androidx.core.content.ContextCompat
import androidx.core.view.marginBottom
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.gh.common.databind.BindingAdapters
@ -20,6 +16,7 @@ import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.CustomPageTrackData
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.game.vertical.GameItemUi
import com.gh.gamecenter.home.custom.eventlistener.SubjectEventHelper
import com.lightgame.download.DownloadEntity
@ -45,7 +42,7 @@ class CustomGameVerticalAdapter(
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return SimpleGameItemViewHolder(GameItemUi(context))
return SimpleGameItemViewHolder(GameItemUi(context), eventHelper)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
@ -102,7 +99,10 @@ class CustomGameVerticalAdapter(
}
class SimpleGameItemViewHolder(private val ui: GameItemUi) : ViewHolder(ui.root) {
class SimpleGameItemViewHolder(
private val ui: GameItemUi,
private val eventHelper: SubjectEventHelper
) : ViewHolder(ui.root) {
var placeholderGameViewHolder: GameViewHolder? = null
fun bindSimpleGameItem(
@ -171,6 +171,8 @@ class CustomGameVerticalAdapter(
adLabelTv
)
MiniGameItemHelper.setMiniGameUsage(gamePlayCountTv, gameEntity)
// 没错,产品就把这个通用样式叫推荐榜单专题
downloadTv.putWidgetBusinessName("推荐榜单专题")
@ -201,7 +203,9 @@ class CustomGameVerticalAdapter(
adapter, entrance,
location = location,
traceEvent = gameEntity.exposureEvent
)
) {
eventHelper.onDownloadButtonClick(position, gameEntity)
}
root.setPadding(paddingStart, root.paddingTop, paddingEnd, root.paddingBottom)
}

View File

@ -42,6 +42,7 @@ import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_GAME_LONG_LIST
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_GAME_VERTICAL_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_HORIZONTAL_SLIDE_VIDEO_LIST
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_MINI_GAME_RECENT_PLAY
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_NAVIGATION
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_NEW_GAME_TEST
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_PLUGIN
@ -192,6 +193,8 @@ class CustomPageAdapter(
CUSTOM_PAGE_ITEM_TYPE_FOOTER -> CustomFooterViewHolder(viewModel, parent.toBinding())
CUSTOM_PAGE_ITEM_TYPE_MINI_GAME_RECENT_PLAY -> CustomHomeRecentMiniGameViewHolder(viewModel, parent.toBinding())
else -> CustomDoubleCardViewHolder(viewModel, parent.toBinding())
}
@ -256,6 +259,8 @@ class CustomPageAdapter(
is CustomRefreshIconViewHolder -> holder.bindView(item)
is CustomHomeRecentMiniGameViewHolder -> holder.bindView(item)
is CustomGameCollectionRefreshVerticalSlideViewHolder -> holder.bindView(item)
is CustomFooterViewHolder -> holder.initFooterViewHolder(

View File

@ -42,7 +42,9 @@ class GameSubjectCollectionEventHelper(
fun navigateToGameDetailPage(childPosition: Int, game: GameEntity, subject: CustomPageData.LinkColumnCollection.CustomSubjectEntity? = null) {
isMatch {
if (it.isSubjectCollection) {
if (game.isMiniGame()) {
tracker.trackMiniGameClick(it, subject, game)
} else if (it.isSubjectCollection) {
tracker.trackColumnCollectionClick(it, subject, game, "游戏")
} else {
tracker.trackGameListCollectionClickWithGame(it, game.id, game.name ?: "")
@ -53,7 +55,9 @@ class GameSubjectCollectionEventHelper(
fun onDownloadButtonClick(childPosition: Int, gameEntity: GameEntity, subject: CustomPageData.LinkColumnCollection.CustomSubjectEntity? = null) {
isMatch {
if (it.isSubjectCollection) {
if (gameEntity.isMiniGame()) {
tracker.trackMiniGameClick(it, subject, gameEntity)
} else if (it.isSubjectCollection) {
tracker.trackColumnCollectionClick(it, subject, gameEntity, "按钮")
} else {
tracker.trackGameListCollectionClick(it, "按钮")

View File

@ -0,0 +1,16 @@
package com.gh.gamecenter.home.custom.eventlistener
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.home.custom.CustomPageViewModel
import com.gh.gamecenter.home.custom.tracker.SubjectTracker
class RecentMiniGameItemEventHelper (viewModel: CustomPageViewModel
) : CustomPageItemChildEventHelper(viewModel) {
private val tracker = SubjectTracker(viewModel.pageLocation)
fun navigateToGameDetailPage(position: Int, gameEntity: GameEntity) {
viewModel.navigateToGameDetailPageByGame(_item, position, gameEntity)
tracker.trackMiniGameClick(_item, gameEntity)
}
}

View File

@ -12,8 +12,8 @@ class SubjectEventHelper(viewModel: CustomPageViewModel) : CustomPageItemChildEv
private val tracker = SubjectTracker(viewModel.pageLocation)
fun navigateToGameDetailPage(position: Int, gameEntity: GameEntity) {
if (gameEntity.isQQMiniGame()) {
tracker.trackQQGameClick(_item, gameEntity)
if (gameEntity.isMiniGame()) {
tracker.trackMiniGameClick(_item, gameEntity)
} else {
tracker.trackColumnClick(_item, gameEntity, "游戏")
}
@ -22,7 +22,11 @@ class SubjectEventHelper(viewModel: CustomPageViewModel) : CustomPageItemChildEv
}
fun onDownloadButtonClick(childPosition: Int, gameEntity: GameEntity) {
tracker.trackColumnClick(_item, gameEntity, "按钮")
if (gameEntity.isMiniGame()) {
tracker.trackMiniGameClick(_item, gameEntity)
} else {
tracker.trackColumnClick(_item, gameEntity, "按钮")
}
}
fun navigateSubjectPage() {

View File

@ -33,7 +33,7 @@ class CustomPageData(
data class PageSwitch(
@SerializedName("top_search")
private val _topSearch: String? = null,
private val _topSearch: String? = null,// 顶部搜索类型halo_game光环游戏、mini_game小游戏低于v5.36版本返回qq_mini_game、bbs论坛、空字符串不显示
@SerializedName("pull_down_push")
private val _pullDownPush: Boolean? = null,
@SerializedName("suspended_window")
@ -69,12 +69,18 @@ class CustomPageData(
val linkTopGameComments: List<AmwayCommentEntity>? = null,
@SerializedName("link_qq_mini_game_column_detail")
val qqMiniGameColumn: SubjectEntity? = null,
@SerializedName("link_wechat_game_column_detail")
val wechatMiniGameColumn: SubjectEntity? = null,
@SerializedName("link_common_collection")
val linkCommonCollection: CommonContentCollection? = null
) {
// 游戏专题
val gameSubjectEntity: SubjectEntity?
get() = linkColumn ?: qqMiniGameColumn
get() = when(link.type) {
CustomPageItem.CUSTOM_LINK_TYPE_QQ_MINI_GAME_COLUMN_DETAIL -> qqMiniGameColumn
CustomPageItem.CUSTOM_LINK_TYPE_WECHAT_MINI_GAME_COLUMN_DETAIL -> wechatMiniGameColumn
else -> linkColumn
}
val link: LinkEntity
get() = _link ?: LinkEntity()
@ -141,6 +147,15 @@ class CustomPageData(
val isQqMini: Boolean
get() = gamePlatform == "qq_mini"
val isWechatMini: Boolean
get() = gamePlatform == "wechat_mini"
val subjectType: SubjectData.SubjectType get() = when {
isQqMini -> SubjectData.SubjectType.QQ_GAME
isWechatMini -> SubjectData.SubjectType.WECHAT_GAME
else -> SubjectData.SubjectType.NORMAL
}
val explain: String
get() = _explain ?: ""

View File

@ -1,5 +1,6 @@
package com.gh.gamecenter.home.custom.model
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
@ -79,7 +80,10 @@ abstract class CustomPageItem(
const val CUSTOM_LINK_TYPE_QUESTION = "question"
const val CUSTOM_LINK_TYPE_PLUGIN_AREA = "plugin_area"
const val CUSTOM_LINK_TYPE_CWZS_RECENTLY_PLAYED = "cwzs_recently_played"
const val CUSTOM_LINK_TYPE_QQ_MINI_GAME_COLUMN_DETAIL = "qq_mini_game_column_detail"
const val CUSTOM_LINK_TYPE_QQ_GAME_RECENTLY_PLAYED = "qq_game_recently_played"
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_HALO_RECOMMEND = "halo_recommend"
const val CUSTOM_LINK_TYPE_COLUMN_COLLECTION = "column_collection" // 专题合集
const val CUSTOM_LINK_TYPE_GAME_LIST_COLLECTION = "game_list_collection"
@ -155,6 +159,7 @@ abstract class CustomPageItem(
const val CUSTOM_PAGE_ITEM_TYPE_COLLECTION_REFRESH_ICON_MATRIX = 28
const val CUSTOM_PAGE_ITEM_TYPE_COLLECTION_REFRESH_ICON_LANE = 29
const val CUSTOM_PAGE_ITEM_TYPE_COLLECTION_REFRESH_SLIDE_LIST = 30
const val CUSTOM_PAGE_ITEM_TYPE_MINI_GAME_RECENT_PLAY = 31
// 专题样式 to itemType
val subjectTypeMap: HashMap<String, Int> = hashMapOf(
@ -266,7 +271,10 @@ abstract class CustomPageItem(
CUSTOM_LINK_TYPE_QUESTION to "内容卡片",
CUSTOM_LINK_TYPE_PLUGIN_AREA to "插件化区域",
CUSTOM_LINK_TYPE_CWZS_RECENTLY_PLAYED to "最近在玩",
CUSTOM_LINK_TYPE_QQ_GAME_RECENTLY_PLAYED to "QQ小游戏-最近在玩",
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_HALO_RECOMMEND to "光环推荐",
CUSTOM_LINK_TYPE_COLUMN_COLLECTION to "专题合集",
CUSTOM_LINK_TYPE_GAME_LIST_COLLECTION to "游戏单合集",
@ -303,7 +311,7 @@ abstract class CustomPageItem(
CUSTOM_PAGE_ITEM_TYPE_GAME_LONG_LIST,
CUSTOM_PAGE_ITEM_TYPE_GAME_VERTICAL_SLIDE,
CUSTOM_PAGE_ITEM_TYPE_PLUGIN,
CUSTOM_PAGE_ITEM_TYPE_RECENT_PLAY
CUSTOM_PAGE_ITEM_TYPE_RECENT_PLAY,
)
@ -569,6 +577,26 @@ data class CustomRecentGamesItem(
}
}
// 最近在玩
data class CustomRecentMiniGamesItem(
private val _link: LinkEntity,
val data: List<GameEntity>,
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 CustomRecentMiniGamesItem
&& data == other.data
&& position == other.position
&& componentPosition == other.componentPosition
}
}
// 插件化区域
data class CustomPluginItem(
private val _link: LinkEntity,

View File

@ -45,6 +45,8 @@ class CustomPageRemoteDataSource(
fun loadChangeSubjectGame(subjectEntity: SubjectEntity): Observable<List<GameEntity>> =
if (subjectEntity.isQQColumn) {
newApi.getSubjectQGame(subjectEntity.id)
} else if (subjectEntity.isWechatColumn) {
newApi.getSubjectWGame(subjectEntity.id)
} else {
api.getSubjectGame(subjectEntity.id)
}

View File

@ -2,6 +2,7 @@ package com.gh.gamecenter.home.custom.model
import android.graphics.Paint
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import com.gh.common.filter.RegionSettingHelper
@ -9,6 +10,7 @@ import com.gh.common.util.GameSubstituteRepositoryHelper
import com.gh.common.util.HomePluggableHelper
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.TextHelper
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.sp2px
@ -46,7 +48,12 @@ import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_S
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
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_QQ_GAME_RECENTLY_PLAYED
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.minigame.MiniGameRecentlyPlayRepository
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayUseCase
import com.gh.gamecenter.packagehelper.PackageRepository
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.wrapper.MainWrapperRepository
@ -71,6 +78,10 @@ class CustomPageRepository private constructor(
private var recentItem: CustomRecentGamesItem? = null
private var recentQQItem: CustomRecentMiniGamesItem? = null
private var recentWechatItem: CustomRecentMiniGamesItem? = null
private var pluginItem: CustomPluginItem? = null
private var discoverCardItem: CustomDiscoverCardItem? = null
@ -79,43 +90,45 @@ class CustomPageRepository private constructor(
private var displayingGameIdSet = hashSetOf<String>() // 当前正在显示的游戏 id 列表
private val _customPluginItemLiveData = MutableLiveData<CustomPluginItem>()
private val _customPluginItemLiveData = MediatorLiveData<CustomPluginItem>().apply {
addSource(PackageRepository.gameUpdateLiveData) {
refreshPluginIfNeed(it)?.let(this::setValue)
}
}
val customPluginItemLiveData: LiveData<CustomPluginItem> = _customPluginItemLiveData
private val _recentGamesItemLiveData = MutableLiveData<CustomRecentGamesItem>()
private val _recentGamesItemLiveData = MediatorLiveData<CustomRecentGamesItem>().apply {
addSource(DownloadManager.getInstance().downloadEntityLiveData) {
refreshRecentVGameIfNeed()?.let(this::setValue)
}
addSource(PackageRepository.recentVaPlayedChanged) {
refreshRecentVGameIfNeed()?.let(this::setValue)
}
}
val recentGamesItemLiveData: LiveData<CustomRecentGamesItem> = _recentGamesItemLiveData
private val _customDiscoverItemLiveData = MutableLiveData<CustomDiscoverCardItem>()
private val _recentMiniGamesItemLiveData = MediatorLiveData<CustomRecentMiniGamesItem>().apply {
addSource(MiniGameRecentlyPlayUseCase.qqRecentGamesItemLiveData) {
refreshRecentQQMiniGameIfNeed(it)?.let(this::setValue)
}
addSource(MiniGameRecentlyPlayUseCase.wechatRecentGamesItemLiveData) {
refreshRecentWechatMiniGameIfNeed(it)?.let(this::setValue)
}
}
val recentMiniGamesItemLiveData: LiveData<CustomRecentMiniGamesItem> = _recentMiniGamesItemLiveData
private val _customDiscoverItemLiveData = MediatorLiveData<CustomDiscoverCardItem>().apply {
addSource(shareRepository.discoverData) {
refreshDiscoverDataIfNeed(it)?.let(this::setValue)
}
}
val customDiscoverItemLiveData: LiveData<CustomDiscoverCardItem> = _customDiscoverItemLiveData
private val gameUpdateObserver = Observer<List<GameUpdateEntity>> {
refreshPluginIfNeed(it)?.let(_customPluginItemLiveData::setValue)
}
private val recentVaPlayedObserver = Observer<Unit> {
refreshRecentVGameIfNeed()?.let(_recentGamesItemLiveData::setValue)
}
private val downloadEntityObserver = Observer<List<DownloadEntity>> {
refreshRecentVGameIfNeed()?.let(_recentGamesItemLiveData::setValue)
}
private val discoveryCardObserver = Observer<DiscoveryCardEntity> {
refreshDiscoverDataIfNeed(it)?.let(_customDiscoverItemLiveData::setValue)
}
private var lastComponentType = ""
private var lastSubjectId = ""
private var gameChildPosition = 0
init {
PackageRepository.gameUpdateLiveData.observeForever(gameUpdateObserver)
PackageRepository.recentVaPlayedChanged.observeForever(recentVaPlayedObserver)
DownloadManager.getInstance().downloadEntityLiveData.observeForever(downloadEntityObserver)
shareRepository.discoverData.observeForever(discoveryCardObserver)
}
private fun refreshPluginIfNeed(updateList: List<GameUpdateEntity>): CustomPluginItem? {
val gameList = arrayListOf<GameEntity>()
updateList.forEach {
@ -144,6 +157,20 @@ class CustomPageRepository private constructor(
}
}
private fun refreshRecentQQMiniGameIfNeed(list: List<GameEntity>): CustomRecentMiniGamesItem? {
return recentQQItem?.let {
recentQQItem = CustomRecentMiniGamesItem(it.link, list, it.position, it.componentPosition)
recentQQItem
}
}
private fun refreshRecentWechatMiniGameIfNeed(list: List<GameEntity>): CustomRecentMiniGamesItem? {
return recentWechatItem?.let {
recentQQItem = CustomRecentMiniGamesItem(it.link, list, it.position, it.componentPosition)
recentQQItem
}
}
private fun refreshDiscoverDataIfNeed(discoveryCardEntity: DiscoveryCardEntity): CustomDiscoverCardItem? {
return discoverCardItem?.let {
discoverCardItem = CustomDiscoverCardItem(it.link, discoveryCardEntity, it.position, it.componentPosition)
@ -220,15 +247,14 @@ 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_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 = if (item.link.type == CUSTOM_LINK_TYPE_COLUMN) {
item.linkColumn?.data?.forEach {
it.gameLocation = GameEntity.GameLocation.INDEX
val gameSubject = item.gameSubjectEntity?.also {
if (item.link.type == CUSTOM_LINK_TYPE_COLUMN) {
it.data?.forEach { game ->
game.gameLocation = GameEntity.GameLocation.INDEX
}
}
item.linkColumn
} else {
item.qqMiniGameColumn
}
var isAdded = false
@ -321,6 +347,30 @@ class CustomPageRepository private constructor(
}
}
item.link.type == CUSTOM_LINK_TYPE_WECHAT_GAME_RECENTLY_PLAYED ||
item.link.type == CUSTOM_LINK_TYPE_QQ_GAME_RECENTLY_PLAYED -> {
// 微信小游戏-最近在玩/QQ小游戏-最近在玩(需要用户登录才显示)
val gameType = if (item.link.type == CUSTOM_LINK_TYPE_WECHAT_GAME_RECENTLY_PLAYED) {
Constants.WECHAT_MINI_GAME
} else {
Constants.QQ_MINI_GAME
}
val recentItem = CustomRecentMiniGamesItem(
item.link,
MiniGameRecentlyPlayUseCase.getRecentlyPlayedMiniGameList(gameType),
pageInfo.position,
pageInfo.componentPosition
)
if (item.link.type == CUSTOM_LINK_TYPE_WECHAT_GAME_RECENTLY_PLAYED) {
recentWechatItem = recentItem
} else {
recentQQItem = recentItem
}
list.add(recentItem)
pageInfo.positionIncrement()
pageInfo.componentPositionIncrement()
}
item.linkColumnCollection != null -> {
// 专题合集
val linkColumnCollection = item.linkColumnCollection
@ -661,7 +711,7 @@ class CustomPageRepository private constructor(
*/
private fun substituteGameIfNeeded(gameSubject: SubjectEntity) {
if (!gameSubject.relatedColumnId.isNullOrEmpty() && gameSubject.data != null) {
when(gameSubject.type) {
when (gameSubject.type) {
COMPONENTS_GAME_SUBJECT_TYPE_GAME_VERTICAL,
COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_SLIDE,
COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL,
@ -726,10 +776,6 @@ class CustomPageRepository private constructor(
fun onClear() {
compositeDisposable.clear()
PackageRepository.gameUpdateLiveData.removeObserver(gameUpdateObserver)
PackageRepository.recentVaPlayedChanged.removeObserver(recentVaPlayedObserver)
shareRepository.discoverData.removeObserver(discoveryCardObserver)
DownloadManager.getInstance().downloadEntityLiveData.removeObserver(downloadEntityObserver)
}
companion object {

View File

@ -4,9 +4,9 @@ import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PageLocation
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.home.custom.CustomPageTracker
import com.gh.gamecenter.home.custom.model.CustomPageData
import com.gh.gamecenter.home.custom.model.CustomSubjectCollectionItem
import com.gh.gamecenter.home.custom.model.*
class GameSubjectCollectionTracker(private val pageLocation: PageLocation) {
@ -102,4 +102,26 @@ class GameSubjectCollectionTracker(private val pageLocation: PageLocation) {
}
trackGameListCollectionClick(item, "更多", otherParams)
}
fun trackMiniGameClick(
item: CustomSubjectCollectionItem,
subject: CustomPageData.LinkColumnCollection.CustomSubjectEntity?,
game: GameEntity
) {
MiniGameItemHelper.trackMiniGameClick(
gameEntity = game,
pageLocation.bottomTab,
pageLocation.severalTabPageId,
pageLocation.severalTabPageName,
pageLocation.tabPosition,
pageLocation.tabContent,
pageLocation.pageId,
pageLocation.pageName,
subject?.id ?: "",
subject?.title ?: "",
"自定义页面",
item.componentStyle,
"",
)
}
}

View File

@ -8,6 +8,7 @@ import com.gh.gamecenter.home.custom.model.CustomGameItem
import com.gh.gamecenter.home.custom.model.CustomPageItem
import com.gh.gamecenter.home.custom.model.CustomSplitSubjectItem
import com.gh.gamecenter.home.custom.model.CustomSubjectItem
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
class SubjectTracker(private val pageLocation: PageLocation) {
@ -46,14 +47,15 @@ class SubjectTracker(private val pageLocation: PageLocation) {
)
}
fun trackQQGameClick(item: CustomPageItem, game: GameEntity) {
fun trackMiniGameClick(item: CustomPageItem, game: GameEntity) {
val subject = when {
item is CustomGameItem -> item.linkColumn
item is CustomSubjectItem -> item.data
item is CustomSplitSubjectItem -> item.data
else -> null
}
SensorsBridge.trackQQGameClick(
MiniGameItemHelper.trackMiniGameClick(
gameEntity = game,
pageLocation.bottomTab,
pageLocation.severalTabPageId,
pageLocation.severalTabPageName,
@ -66,8 +68,6 @@ class SubjectTracker(private val pageLocation: PageLocation) {
"自定义页面",
item.componentStyle,
"",
game.id,
game.name ?: ""
)
}
}

View File

@ -100,7 +100,13 @@ class CustomDoubleCardViewHolder(
) {
subBinding.run {
poster.setTag(ImageUtils.TAG_TARGET_WIDTH, mPosterWidth)
poster.post { poster.display(gameEntity.columnImage) }
poster.post {
if (gameEntity.isWechatMiniGame()) {
poster.display(gameEntity.banner)
} else {
poster.display(gameEntity.columnImage)
}
}
gameName.text = gameEntity.name
brief.text =
if (gameEntity.columnRecommend?.text.isNullOrBlank()) gameEntity.brief

View File

@ -19,7 +19,7 @@ import com.gh.gamecenter.core.utils.StringUtils
import com.gh.gamecenter.databinding.GameItemCustomBinding
import com.gh.gamecenter.feature.R
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PluginLocation
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.feature.provider.IBindingAdaptersProvider
import com.gh.gamecenter.home.custom.CustomPageViewModel
import com.gh.gamecenter.home.custom.adapter.CustomViewExt
@ -27,7 +27,6 @@ import com.gh.gamecenter.home.custom.createExposureEvent
import com.gh.gamecenter.home.custom.eventlistener.SubjectEventHelper
import com.gh.gamecenter.home.custom.model.CustomPageItem
import com.gh.gamecenter.home.custom.model.CustomSplitSubjectItem
import splitties.views.bottomPadding
/**
* 长列表式
@ -93,6 +92,7 @@ class CustomGameItemViewHolder(
adLabelTv,
forceShowSubtitle
)
MiniGameItemHelper.setMiniGameUsage(gamePlayCount, entity)
}
entity.customPageTrackData = createTrackData(item)
@ -118,7 +118,7 @@ class CustomGameItemViewHolder(
briefStyle = subject.briefStyle
)
itemView.setOnClickListener {
binding.clContainer.setOnClickListener {
val entrance = if (entity.isPluggable) {
StringUtils.buildString("(游戏-专题:插件化-列表[", "${item.startChildPosition}", "])")
} else {

View File

@ -1,7 +1,6 @@
package com.gh.gamecenter.home.custom.viewholder
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.utils.DarkModeUtils
import com.gh.gamecenter.common.view.FixLinearLayoutManager
import com.gh.gamecenter.databinding.HomeGameCollectionSlideItemCustomBinding
import com.gh.gamecenter.home.custom.CustomPageViewModel

View File

@ -17,6 +17,7 @@ import com.gh.gamecenter.feature.entity.CustomPageTrackData
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.home.custom.CustomPageViewModel
import com.gh.gamecenter.home.custom.createExposureEvent
import com.gh.gamecenter.home.custom.eventlistener.SubjectEventHelper
@ -190,6 +191,8 @@ class CustomHomeGameItemViewHolder(
binding.adLabelTv
)
MiniGameItemHelper.setMiniGameUsage(binding.gamePlayCount, game)
game.customPageTrackData = createTrackData()
DownloadItemUtils.setOnClickListener(

View File

@ -17,6 +17,7 @@ import com.gh.gamecenter.feature.entity.CustomPageTrackData
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.home.custom.eventlistener.SubjectEventHelper
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
import splitties.views.backgroundColor
@ -86,6 +87,8 @@ class CustomHomeHorizontalSlideVideoItemViewHolder(
BindingAdapters.setGameTags(binding.gameTags, gameEntity)
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, binding.gameSubtitleTv)
MiniGameItemHelper.setMiniGameUsage(binding.gamePlayCount, gameEntity)
gameEntity.customPageTrackData = createTrackData()
DownloadItemUtils.setOnClickListener(
binding.root.context,

View File

@ -0,0 +1,132 @@
package com.gh.gamecenter.home.custom.viewholder
import android.view.View
import android.view.ViewGroup
import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.R
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.view.GridSpacingItemColorDecoration
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.databinding.ItemHomeRecentVgameBinding
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.home.custom.CustomPageViewModel
import com.gh.gamecenter.home.custom.IGameChangedNotifier
import com.gh.gamecenter.home.custom.adapter.CustomHomeRecentVGameAdapter
import com.gh.gamecenter.home.custom.createExposureEvent
import com.gh.gamecenter.home.custom.eventlistener.CustomPageItemChildEventHelper
import com.gh.gamecenter.home.custom.eventlistener.RecentMiniGameItemEventHelper
import com.gh.gamecenter.home.custom.model.CustomPageItem
import com.gh.gamecenter.home.custom.model.CustomRecentMiniGamesItem
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayListAdapter
/**
* 小游戏-最近在玩
*/
class CustomHomeRecentMiniGameViewHolder(
viewModel: CustomPageViewModel,
var binding: ItemHomeRecentVgameBinding
) : BaseCustomViewHolder(viewModel, binding.root) {
override val childEventHelper: RecentMiniGameItemEventHelper by lazy { RecentMiniGameItemEventHelper(viewModel) }
override fun bindView(item: CustomPageItem) {
super.bindView(item)
if (item is CustomRecentMiniGamesItem) {
fillExposureEventList(item)
binding.vspaceIv.visibility = View.GONE
binding.divider.visibility = View.GONE
binding.moreTv.visibility = View.GONE
val entities = item.data
if (entities.isEmpty()) {
binding.root.goneIf(true)
binding.root.updateLayoutParams {
height = 0
width = RecyclerView.LayoutParams.MATCH_PARENT
}
} else {
binding.root.goneIf(false)
binding.root.updateLayoutParams {
height = 106F.dip2px()
width = RecyclerView.LayoutParams.MATCH_PARENT
}
binding.titleTv.text = item.componentName
val gameListAdapter = if (binding.recyclerView.adapter == null) {
val layoutManager =
LinearLayoutManager(binding.root.context, RecyclerView.HORIZONTAL, false)
binding.recyclerView.layoutManager = layoutManager
binding.recyclerView.itemAnimator = null
val adapter = MiniGameRecentlyPlayListAdapter(binding.root.context) { game, position ->
childEventHelper.navigateToGameDetailPage(position, game)
}
binding.recyclerView.adapter = adapter
binding.recyclerView.addItemDecoration(
GridSpacingItemColorDecoration(binding.root.context, 4, 0, R.color.transparent)
)
binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
if (dx == 0) {
val scrollToEnd =
layoutManager.findLastCompletelyVisibleItemPosition() == (binding.recyclerView.adapter!!.itemCount - 1)
// 当游戏数量超过一屏时需去除列表右侧的分隔线去除后列表最后一个游戏图标与卡片右侧的边距应为16dp
if (scrollToEnd) {
binding.recyclerViewContainer.post {
binding.recyclerViewContainer.layoutParams =
(binding.recyclerViewContainer.layoutParams as ViewGroup.MarginLayoutParams).apply {
rightMargin = 10F.dip2px()
}
}
binding.divider.visibility = View.VISIBLE
} else {
binding.recyclerViewContainer.post {
binding.recyclerViewContainer.layoutParams =
(binding.recyclerViewContainer.layoutParams as ViewGroup.MarginLayoutParams).apply {
rightMargin = 0
}
}
binding.divider.visibility = View.GONE
}
}
}
})
adapter
} else {
binding.recyclerView.adapter as MiniGameRecentlyPlayListAdapter
}
gameListAdapter.submitList(item.data)
}
}
}
private fun fillExposureEventList(item: CustomRecentMiniGamesItem) {
val exposureEventList = arrayListOf<ExposureEvent>()
runOnIoThread(true) {
item.data.forEachIndexed { index, game ->
val event = createExposureEvent(
game,
listOf(
ExposureSource(item.componentName, "")
),
pageConfigure.exposureSourceList,
index,
item.componentPosition
)
exposureEventList.add(event)
}
}
item.exposureEventList = exposureEventList
}
}

View File

@ -7,7 +7,6 @@ import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.DarkModeUtils
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.databinding.HomeGameCollectionRefreshItemCustomBinding
import com.gh.gamecenter.home.custom.CustomPageViewModel

View File

@ -17,6 +17,7 @@ import com.gh.gamecenter.databinding.ItemHomeHorizontalSlideVideoBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
class HomeHorizontalSlideVideoItemViewHolder(val binding: ItemHomeHorizontalSlideVideoBinding) :
@ -78,6 +79,8 @@ class HomeHorizontalSlideVideoItemViewHolder(val binding: ItemHomeHorizontalSlid
BindingAdapters.setGameTags(binding.gameTags, gameEntity)
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, binding.gameSubtitleTv)
MiniGameItemHelper.setMiniGameUsage(binding.gamePlayCount, gameEntity)
DownloadItemUtils.setOnClickListener(
binding.root.context,
binding.downloadBtn,

View File

@ -0,0 +1,67 @@
package com.gh.gamecenter.minigame
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.baselist.DiffUtilAdapter
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.databinding.ItemHomeVgameBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
/**
* 微信小游戏-最近在玩列表
*/
class MiniGameRecentlyPlayListAdapter(
context: Context,
private val onItemClick:((GameEntity, Int) -> Unit)? = null
) : DiffUtilAdapter<GameEntity>(context) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): MiniGameRecentlyPlayItemViewHolder {
return MiniGameRecentlyPlayItemViewHolder(parent.toBinding())
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as MiniGameRecentlyPlayItemViewHolder).bindView(mDataList[position], position, onItemClick)
}
override fun getItemCount(): Int {
return mDataList.size
}
override fun areItemsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
return oldItem == newItem
}
class MiniGameRecentlyPlayItemViewHolder(private var mBinding: ItemHomeVgameBinding) :
RecyclerView.ViewHolder(mBinding.root) {
fun bindView(entity: GameEntity, position: Int, onItemClick: ((GameEntity, Int) -> Unit)? = null) {
mBinding.gameIconIv.displayGameIcon(entity)
mBinding.maskView.visibility = View.GONE
mBinding.controlTv.visibility = View.GONE
mBinding.progressBar.visibility = View.GONE
mBinding.dotView.visibility = View.GONE
mBinding.updateHintIv.visibility = View.GONE
mBinding.controlTv.visibility = View.GONE
mBinding.progressBar.visibility = View.GONE
mBinding.root.setOnClickListener {
if (onItemClick != null) {
onItemClick.invoke(entity, position)
} else {
MiniGameItemHelper.launchMiniGame(entity.miniGameAppId, entity.miniGameType)
}
}
}
}
}

View File

@ -0,0 +1,41 @@
package com.gh.gamecenter.minigame
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
import io.reactivex.Single
import okhttp3.ResponseBody
/**
* 小游戏-最近在玩-数据层
*/
class MiniGameRecentlyPlayRepository(
private val apiService: ApiService = RetrofitManager.getInstance().newApi
) {
/**
* 获取小游戏-最近在玩游戏列表
* @param gameType 游戏类型qq/wechat
*/
fun getRecentPlayedMiniGameList(gameType: String): Single<List<GameEntity>> {
return apiService.getRecentPlayedMiniGameList(gameType)
}
/**
* 提交微信小游戏秒玩记录
* @param wechatAppId 微信游戏ID
* @param gid 设备ID
*/
fun postRecentPlayedWGame(wechatAppId: String, gid: String): Single<ResponseBody> {
return apiService.postWGamePlay(wechatAppId, gid)
}
/**
* 提交QQ小游戏秒玩记录
* @param qqAppId QQ游戏ID
* @param userId 用户ID
*/
fun postRecentPlayedQGame(qqAppId: String, userId: String): Single<ResponseBody> {
return apiService.postQGamePlay(qqAppId, userId)
}
}

View File

@ -0,0 +1,86 @@
package com.gh.gamecenter.minigame
import android.annotation.SuppressLint
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
/**
* 小游戏-最近在玩-网域层
*/
object MiniGameRecentlyPlayUseCase {
private val repository = MiniGameRecentlyPlayRepository(RetrofitManager.getInstance().newApi)
/**
* 微信小游戏-最近在玩
*/
private val _wechatRecentGamesItemLiveData = MutableLiveData<List<GameEntity>>()
val wechatRecentGamesItemLiveData: LiveData<List<GameEntity>> = _wechatRecentGamesItemLiveData
/**
* QQ小游戏-最近在玩
*/
private val _qqRecentGamesItemLiveData = MutableLiveData<List<GameEntity>>()
val qqRecentGamesItemLiveData: LiveData<List<GameEntity>> = _qqRecentGamesItemLiveData
@SuppressLint("CheckResult")
fun loadRecentlyPlayedMiniGameList(gameType: String) {
repository.getRecentPlayedMiniGameList(gameType)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<List<GameEntity>>() {
override fun onSuccess(data: List<GameEntity>) {
if (gameType == Constants.QQ_MINI_GAME) {
_qqRecentGamesItemLiveData.value = data
} else {
_wechatRecentGamesItemLiveData.value = data
}
}
})
}
@SuppressLint("CheckResult")
fun submitRecentPlayedWGame(wechatAppId: String, gid: String) {
repository.postRecentPlayedWGame(wechatAppId, gid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
loadRecentlyPlayedMiniGameList(Constants.WECHAT_MINI_GAME)
}
})
}
@SuppressLint("CheckResult")
fun submitRecentPlayedQGame(qqAppId: String,userId: String) {
repository.postRecentPlayedQGame(qqAppId, userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
loadRecentlyPlayedMiniGameList(Constants.QQ_MINI_GAME)
}
})
}
/**
* 获取小游戏-最近在玩游戏列表缓存
* @param gameType 游戏类型qq/wechat
*/
fun getRecentlyPlayedMiniGameList(gameType: String): List<GameEntity> =
if (gameType == Constants.QQ_MINI_GAME) {
_qqRecentGamesItemLiveData.value
} else {
_wechatRecentGamesItemLiveData.value
} ?: let {
loadRecentlyPlayedMiniGameList(gameType)// 最近在玩数据为空时,则调用接口获取数据
emptyList()
}
}

View File

@ -1,45 +1,53 @@
package com.gh.gamecenter.qgame
package com.gh.gamecenter.minigame
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import com.gh.gamecenter.DisplayType
import com.gh.gamecenter.R
import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.SearchType
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.search.SearchGameIndexFragment
import com.lightgame.utils.Util_System_Keyboard
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.forum.search.ForumSearchDao
import com.gh.gamecenter.search.SearchDefaultFragment
import com.gh.gamecenter.search.SearchGameResultFragment
import com.lightgame.config.CommonDebug
import com.lightgame.listeners.OnBackPressedListener
/**
* QQ小游戏-搜索页面
* 小游戏-搜索页面
*/
class QGameSearchActivity : SearchActivity() {
class MiniGameSearchActivity : SearchActivity() {
override fun provideDao(): ISearchHistoryDao = MiniGameSearchDao()
override fun updateDisplayType(type: DisplayType) {
val transaction = supportFragmentManager.beginTransaction()
when(type) {
DisplayType.GAME_DETAIL -> {
val digestListFragment =
supportFragmentManager.findFragmentByTag(QGameSearchResultFragment::class.java.name) as? QGameSearchResultFragment
?: QGameSearchResultFragment()
digestListFragment.setParams(mSearchKey ?: "", mSearchType.value)
transaction.replace(com.gh.gamecenter.R.id.search_result, digestListFragment, SearchGameIndexFragment::class.java.name)
DisplayType.DEFAULT -> {
val fragment = supportFragmentManager.findFragmentByTag(SearchDefaultFragment::class.java.name)
?: MiniGameSearchDefaultFragment().apply {
arguments = Bundle().also { it.putBoolean(SearchDefaultFragment.KEY_IS_GAME_SEARCH, true) }
}
transaction.replace(R.id.search_result, fragment, SearchDefaultFragment::class.java.name)
}
else -> {
AppExecutor.uiExecutor.executeWithDelay({
Util_System_Keyboard.showSoftKeyboard(this)
}, 100)
val digestListFragment =
supportFragmentManager.findFragmentByTag(SearchGameResultFragment::class.java.name) as? MiniGameSearchResultFragment
?: MiniGameSearchResultFragment()
digestListFragment.setParams(mSearchKey ?: "", mSearchType.value)
transaction.replace(R.id.search_result, digestListFragment, SearchGameResultFragment::class.java.name)
}
}
mDisplayType = type
transaction.commitAllowingStateLoss()
}
override fun handleBackPressed(): Boolean {
Util_System_Keyboard.hideSoftKeyboard(this)
finish()
return true
}
companion object {
@JvmStatic
@ -54,7 +62,7 @@ class QGameSearchActivity : SearchActivity() {
customPageName: String = "",
searchBoxPattern: String = ""
): Intent {
val intent = Intent(context, QGameSearchActivity::class.java)
val intent = Intent(context, MiniGameSearchActivity::class.java)
intent.putExtra(EntranceConsts.KEY_HINT, hint)
intent.putExtra(EntranceConsts.KEY_SOURCE_ENTRANCE, sourceEntrance)
intent.putExtra(EntranceConsts.KEY_BOTTOM_TAB_NAME, bottomTab)

View File

@ -0,0 +1,53 @@
package com.gh.gamecenter.minigame
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.db.ISearchHistoryDao
/**
* 微信小游戏-历史搜索记录
*/
class MiniGameSearchDao : ISearchHistoryDao {
override fun add(keyword: String) {
val originString = SPUtils.getString(SP_KEY)
if (originString.isEmpty()) {
// Insert keyword only for the very first time.
SPUtils.setString(SP_KEY, keyword)
} else {
all?.let {
// Move keyword to the very front if it exists.
if (it.contains(keyword)) {
it.remove(keyword)
}
it.add(0, keyword)
val builder = StringBuilder()
for ((index, key) in it.withIndex()) {
builder.append(key)
if (index != it.size - 1) {
builder.append(SEARCH_KEY_DIVIDER)
}
}
SPUtils.setString(SP_KEY, builder.toString())
}
}
}
override fun getAll(): ArrayList<String>? {
val list = SPUtils.getString(SP_KEY).split(SEARCH_KEY_DIVIDER)
return if (list.size == 1 && list[0].isEmpty()) null else ArrayList(list)
}
override fun delete(item: String) {}
override fun deleteAll() {
SPUtils.setString(SP_KEY, "")
}
companion object {
const val SP_KEY = "mini_game_key"
const val SEARCH_KEY_DIVIDER = "<-||->"
}
}

View File

@ -0,0 +1,61 @@
package com.gh.gamecenter.minigame
import androidx.viewpager.widget.PagerAdapter
import com.gh.common.constant.Config
import com.gh.common.filter.RegionSettingHelper
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.databinding.FragmentSearchDefaultBinding
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.search.SearchDefaultFragment
/**
* 微信小游戏-搜索主页
*/
class MiniGameSearchDefaultFragment : SearchDefaultFragment() {
override fun provideDao(): ISearchHistoryDao = MiniGameSearchDao()
override fun initView() {
mBinding = FragmentSearchDefaultBinding.bind(mCachedView)
mRankList = Config.getNewApiSettingsEntity()?.search?.wechatGameSearchList?.apply {
forEachIndexed { outIndex, rankList ->
rankList.isShowIcon = !rankList.content.any { it.icon.isBlank() }
var i = 0
while (i < rankList.content.size) {
if (RegionSettingHelper.shouldThisGameBeFiltered(rankList.content[i].linkGame?.id)) {
rankList.content.removeAt(i)
i--
}
i++
}
rankList.content.forEachIndexed { index, rank ->
val source = listOf(ExposureSource("小游戏搜索 -> 搜索榜单", "${rankList.title}-${rank.name}"))
if (rank.link.type == "game") {
rank.exposureEvent = ExposureEvent.createEvent(
rank.linkGame?.toGameEntity()?.apply {
outerSequence = outIndex
sequence = index
},
source
)
} else {
rank.exposureEvent = ExposureEvent.createEvent(null, source)
}
}
}
}
defaultViewModel?.isExistRankList = mRankList?.isNotEmpty() == true
updateHistorySearchView(null)
defaultViewModel?.historySearchLiveData?.observe(this) {
updateHistorySearchView(it)
}
initHeadView()
initRankViewPager()
}
override fun provideAdapter(pageRatio: Float): PagerAdapter =
MiniGameSearchDefaultRankListAdapter(requireContext(), mRankList!!, pageRatio)
}

View File

@ -0,0 +1,89 @@
package com.gh.gamecenter.minigame
import android.content.Context
import android.graphics.Typeface
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import com.gh.common.util.DirectUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.databinding.SearchDefaultRankItemBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.SettingsEntity
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.lightgame.adapter.BaseRecyclerAdapter
import com.lightgame.utils.Util_System_Keyboard
/**
* 微信小游戏-搜索榜单列表
*/
class MiniGameSearchDefaultRankAdapter(
context: Context,
private val mRankList: SettingsEntity.Search.RankList,
) : BaseRecyclerAdapter<MiniGameSearchDefaultRankAdapter.MiniGameSearchDefaultRankItemViewHolder>(context) {
override fun getItemCount() = minOf(mRankList.content.size, 10)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
MiniGameSearchDefaultRankItemViewHolder(parent.toBinding())
override fun onBindViewHolder(holder: MiniGameSearchDefaultRankItemViewHolder, position: Int) {
val rank = mRankList.content[position]
holder.binding.run {
val gameEntity = rank.linkGame?.toGameEntity()
icon.goneIf(!mRankList.isShowIcon) {
icon.display(if (rank.link.type == "game") gameEntity?.icon else rank.icon)
}
name.text = if (rank.link.type == "game") gameEntity?.name else rank.name.ifBlank { rank.link.text }
index.run {
typeface = Typeface.createFromAsset(mContext.assets, Constants.DIN_FONT_PATH)
text = (position + 1).toString()
setTextColor(
when (position + 1) {
1 -> R.color.text_ff5151
2 -> R.color.text_f67722
3 -> R.color.text_ffbf00
else -> R.color.text_tertiary
}.toColor()
)
}
labelIv.visibility = View.GONE
// 转成Game实体比较好处理数据
val trackGame = GameEntity(
id = rank.id,
mName = rank.name,
miniGameAppId = rank.link.link ?: "",
miniGameType = Constants.WECHAT_MINI_GAME,
usage = rank.usage ?: 0
)
holder.binding.playCount.visibility = View.VISIBLE
MiniGameItemHelper.setMiniGameUsage(holder.binding.playCount, trackGame)
holder.binding.playContainer.visibility = View.VISIBLE
val onWechatMiniGameClick = OnClickListener {
MiniGameItemHelper.trackMiniGameClick(gameEntity = trackGame, location = "搜索榜单")
// 通过link启动微信小游戏
DirectUtils.directToLinkPage(
mContext,
rank.link,
"小游戏搜索-搜索榜单",
"${mRankList.title}-${rank.name}",
rank.exposureEvent
)
Util_System_Keyboard.hideSoftKeyboardByIBinder(mContext, it.windowToken)
}
holder.binding.playContainer.setOnClickListener(onWechatMiniGameClick)
holder.binding.root.setOnClickListener(onWechatMiniGameClick)
}
}
inner class MiniGameSearchDefaultRankItemViewHolder(val binding: SearchDefaultRankItemBinding) :
BaseRecyclerViewHolder<Any>(binding.root)
}

View File

@ -0,0 +1,46 @@
package com.gh.gamecenter.minigame
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.RecyclingPagerAdapter
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.feature.entity.SettingsEntity
/**
* 微信小游戏-搜索榜单
*/
class MiniGameSearchDefaultRankListAdapter(
private val mContext: Context,
private val mRankList: List<SettingsEntity.Search.RankList>,
private val mPageWidth: Float
) : RecyclingPagerAdapter() {
override fun getCount() = mRankList.size
override fun getPageWidth(position: Int) = mPageWidth
override fun getPageTitle(position: Int) = mRankList[position].title
override fun getView(position: Int, convertView: View?, container: ViewGroup?): View {
var view: View? = convertView
if (convertView == null) {
view = View.inflate(mContext, R.layout.search_default_rank_list_item, null).apply {
findViewById<RecyclerView>(R.id.rankContainer).apply {
setPadding(16F.dip2px(), 16F.dip2px(), 16F.dip2px(), 16F.dip2px())
}
}
container?.layoutParams?.height = 432F.dip2px()
}
view!!.findViewById<RecyclerView>(R.id.rankContainer).run {
layoutManager = LinearLayoutManager(mContext)
adapter = MiniGameSearchDefaultRankAdapter(mContext, mRankList[position])
}
return view
}
}

View File

@ -1,4 +1,4 @@
package com.gh.gamecenter.qgame
package com.gh.gamecenter.minigame
import com.gh.gamecenter.SearchActivity.Companion.TRACK_SEARCH_TYPE_INPUT
import com.gh.gamecenter.common.constant.EntranceConsts
@ -8,9 +8,9 @@ import com.gh.gamecenter.search.SearchGameResultViewModel
import com.halo.assistant.HaloApp
/**
* QQ小游戏-搜索结果页面
* 小游戏-搜索结果页面
*/
class QGameSearchResultFragment : SearchGameResultFragment() {
class MiniGameSearchResultFragment : SearchGameResultFragment() {
/**
* 仅替换搜索游戏的API搜索结果页面样式与首页的完全一致
@ -20,7 +20,7 @@ class QGameSearchResultFragment : SearchGameResultFragment() {
HaloApp.getInstance().application,
mKey,
true,
QGameSearchResultRepository(),
MiniGameSearchResultRepository(),
TRACK_SEARCH_TYPE_INPUT,
activity?.intent?.getStringExtra(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: ""
)

View File

@ -1,6 +1,5 @@
package com.gh.gamecenter.qgame
package com.gh.gamecenter.minigame
import com.gh.gamecenter.common.utils.EnvHelper
import com.gh.gamecenter.entity.SearchSubjectEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.retrofit.RetrofitManager
@ -9,7 +8,7 @@ import com.gh.gamecenter.search.ISearchGameResultRepository
import io.reactivex.Observable
import java.net.URLEncoder
class QGameSearchResultRepository(
class MiniGameSearchResultRepository(
private val api: ApiService = RetrofitManager.getInstance().newApi
) : ISearchGameResultRepository {
@ -17,12 +16,7 @@ class QGameSearchResultRepository(
key: String?,
page: Int
): Observable<List<GameEntity>> {
// 可能会有特殊字符,需要 encode 处理
val encodedKey = URLEncoder.encode(key, "utf-8")
return api.getSearchQGame(
EnvHelper.getNewHost() + "games/qq_mini/columns/game_search?keyword=" +
encodedKey + "&page=" + page + "&page_size=20"
)
return api.getSearchMiniGameList(key, page, 20)
}
override fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>> {

View File

@ -1,4 +1,4 @@
package com.gh.gamecenter.qgame
package com.gh.gamecenter.minigame.qq
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.entity.SubjectRecommendEntity
@ -6,7 +6,7 @@ import com.gh.gamecenter.game.GameFragment
import com.halo.assistant.HaloApp
/**
* QQ小游戏-专题页面
* QQ小游戏-主页
*/
class QGameFragment : GameFragment() {
@ -16,7 +16,7 @@ class QGameFragment : GameFragment() {
override fun provideViewModel(): QGameViewModel {
val factory = QGameViewModel.Factory(
HaloApp.getInstance().application,
SubjectRecommendEntity(text = "QQ小游戏")
SubjectRecommendEntity(text = "小游戏")
)
return viewModelProvider(factory)
}

View File

@ -1,4 +1,4 @@
package com.gh.gamecenter.qgame
package com.gh.gamecenter.minigame.qq
import android.content.Context
import android.content.Intent
@ -8,7 +8,7 @@ import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.utils.updateStatusBarColor
/**
* QQ小游戏-
* 小游戏-
*/
class QGameHomeWrapperActivity : ToolBarActivity() {

View File

@ -1,11 +1,9 @@
package com.gh.gamecenter.qgame
package com.gh.gamecenter.minigame.qq
import android.os.Bundle
import android.view.View
import com.gh.common.util.DirectUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.SearchType
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.databinding.FragmentQgameHomeBinding
@ -15,7 +13,7 @@ class QGameHomeWrapperFragment : ToolbarFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setNavigationTitle(getString(R.string.qgame_title))
setNavigationTitle(getString(R.string.mini_game_title))
val contentFragment = childFragmentManager.findFragmentById(R.id.wrapper_content) ?: QGameFragment()
childFragmentManager.beginTransaction().replace(R.id.wrapper_content, contentFragment).commitAllowingStateLoss()
}
@ -26,7 +24,7 @@ class QGameHomeWrapperFragment : ToolbarFragment() {
override fun initView(view: View?) {
super.initView(view)
viewBinding.searchBar.root.setOnClickListener {
DirectUtils.directToQGameSearch(it.context, "请输入小游戏关键词", "QQ小游戏")
DirectUtils.directToMiniGameSearch(it.context, "请输入小游戏关键词", "小游戏")
}
}

View File

@ -1,32 +1,20 @@
package com.gh.gamecenter.qgame
package com.gh.gamecenter.minigame.qq
import android.content.Context
import android.os.Build
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import com.gh.common.util.DirectUtils
import com.gh.common.util.DownloadItemUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.baselist.DiffUtilAdapter
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.common.utils.visibleIf
import com.gh.gamecenter.common.view.GridSpacingItemColorDecoration
import com.gh.gamecenter.databinding.ItemHomeRecentVgameBinding
import com.gh.gamecenter.databinding.ItemHomeVgameBinding
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayListAdapter
class QGameHorizontalSlideListViewHolder(var binding: ItemHomeRecentVgameBinding) :
RecyclerView.ViewHolder(binding.root) {
class QGameRecentlyPlayViewHolder(var binding: ItemHomeRecentVgameBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindHorizontalSlideList(subject: SubjectEntity) {
fun bindView(subject: SubjectEntity) {
binding.vspaceIv.visibility = View.GONE
binding.divider.visibility = View.GONE
@ -76,7 +64,7 @@ class QGameHorizontalSlideListViewHolder(var binding: ItemHomeRecentVgameBinding
binding.recyclerView.layoutManager = layoutManager
binding.recyclerView.itemAnimator = null
val adapter = QGameHorizontalSlideAdapter(binding.root.context)
val adapter = MiniGameRecentlyPlayListAdapter(binding.root.context)
binding.recyclerView.adapter = adapter
binding.recyclerView.addItemDecoration(
GridSpacingItemColorDecoration(binding.root.context, 4, 0, R.color.transparent)
@ -111,58 +99,11 @@ class QGameHorizontalSlideListViewHolder(var binding: ItemHomeRecentVgameBinding
})
adapter
} else {
binding.recyclerView.adapter as QGameHorizontalSlideAdapter
binding.recyclerView.adapter as MiniGameRecentlyPlayListAdapter
}
subjectAdapter.submitList(subject.data)
}
}
class QGameHorizontalSlideAdapter(context: Context) : DiffUtilAdapter<GameEntity>(context) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): QGameHorizontalSlideViewHolder {
return QGameHorizontalSlideViewHolder(parent.toBinding())
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as QGameHorizontalSlideViewHolder).bindView(mDataList[position])
}
override fun getItemCount(): Int {
return mDataList.size
}
override fun areItemsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: GameEntity?, newItem: GameEntity?): Boolean {
return oldItem == newItem
}
class QGameHorizontalSlideViewHolder(private var mBinding: ItemHomeVgameBinding) :
RecyclerView.ViewHolder(mBinding.root) {
fun bindView(entity: GameEntity) {
mBinding.gameIconIv.displayGameIcon(entity)
mBinding.maskView.visibility = View.GONE
mBinding.controlTv.visibility = View.GONE
mBinding.progressBar.visibility = View.GONE
mBinding.dotView.visibility = View.GONE
mBinding.updateHintIv.visibility = View.GONE
mBinding.controlTv.visibility = View.GONE
mBinding.progressBar.visibility = View.GONE
mBinding.root.setOnClickListener {
NewFlatLogUtils.logQGameClick(entity.qqMiniGameAppId, entity.name)
GlobalActivityManager.currentActivity?.let {
DirectUtils.directToQGameById(it, entity.qqMiniGameAppId)
}
}
}
}
}

View File

@ -1,9 +1,11 @@
package com.gh.gamecenter.qgame
package com.gh.gamecenter.minigame.qq
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
import com.gh.gamecenter.subject.ISubjectListRepository
import io.reactivex.Observable
import io.reactivex.Single
class QGameSubjectListRepository(
@ -14,4 +16,8 @@ class QGameSubjectListRepository(
return api.getQGameColumn(column_id, order, page, 20)
}
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {
return api.getQGameColumnSettings(column_id)
}
}

View File

@ -1,6 +1,5 @@
package com.gh.gamecenter.qgame
package com.gh.gamecenter.minigame.qq
import androidx.lifecycle.viewmodel.viewModelFactory
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
@ -15,7 +14,6 @@ class QGameSubjectRepository(
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {
return api.getQGameColumnSettings(column_id)
}
override fun getSubjectName(column_id: String?): Observable<ResponseBody> {

View File

@ -0,0 +1,4 @@
package com.gh.gamecenter.minigame.qq
class QGameSubjectUpdateEvent {
}

View File

@ -1,8 +1,9 @@
package com.gh.gamecenter.qgame
package com.gh.gamecenter.minigame.qq
import android.app.Application
import android.text.TextUtils
import androidx.collection.ArrayMap
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.filter.RegionSettingHelper
@ -23,13 +24,11 @@ import com.gh.gamecenter.game.data.GameItemData
import com.gh.gamecenter.game.rank.RankCollectionAdapter
import com.gh.gamecenter.home.BlankDividerViewHolder
import com.gh.gamecenter.home.LegacyHomeFragmentAdapterAssistant
import com.gh.gamecenter.minigame.MiniGameRecentlyPlayUseCase
import com.gh.gamecenter.retrofit.RetrofitManager
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import retrofit2.HttpException
import kotlin.math.roundToInt
@ -47,9 +46,15 @@ class QGameViewModel(application: Application, blockData: SubjectRecommendEntity
private var mIsLoading = false
private val mQGameRecentlyPlayObserver = Observer<List<GameEntity>> {
onInitData()
}
init {
initData()
EventBus.getDefault().register(this)// 为了减少对原有逻辑的影响把EventBus注册在这里
MiniGameRecentlyPlayUseCase
.qqRecentGamesItemLiveData
.observeForever(mQGameRecentlyPlayObserver)
}
override fun onInitData() {
@ -528,12 +533,9 @@ class QGameViewModel(application: Application, blockData: SubjectRecommendEntity
override fun onCleared() {
super.onCleared()
EventBus.getDefault().unregister(this)
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onQGameSubjectUpdate(event: QGameSubjectUpdateEvent) {
onInitData()
MiniGameRecentlyPlayUseCase
.qqRecentGamesItemLiveData
.removeObserver(mQGameRecentlyPlayObserver)
}
override fun replaceRefreshData(itemData: GameItemData): Boolean = false
@ -548,11 +550,4 @@ class QGameViewModel(application: Application, blockData: SubjectRecommendEntity
return QGameViewModel(mApplication, blockData) as T
}
}
companion object {
fun notifyQGameSubjectUpdate() {
EventBus.getDefault().post(QGameSubjectUpdateEvent())
}
}
}

View File

@ -0,0 +1,23 @@
package com.gh.gamecenter.minigame.wechat
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
import com.gh.gamecenter.subject.ISubjectListRepository
import io.reactivex.Observable
import io.reactivex.Single
class WGameSubjectListRepository(
private val api: ApiService = RetrofitManager.getInstance().newApi
) : ISubjectListRepository {
override fun getColumn(column_id: String?, page: Int, sort: String?, order: String?): Single<MutableList<GameEntity>> {
return api.getWGameColumn(column_id, order, page, 20)
}
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {
return api.getWGameColumnSettings(column_id)
}
}

View File

@ -0,0 +1,21 @@
package com.gh.gamecenter.minigame.wechat
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
import com.gh.gamecenter.subject.ISubjectRepository
import io.reactivex.Observable
import okhttp3.MediaType
import okhttp3.ResponseBody
class WGameSubjectRepository(
private val api: ApiService = RetrofitManager.getInstance().newApi
) : ISubjectRepository {
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {
return api.getWGameColumnSettings(column_id)
}
override fun getSubjectName(column_id: String?): Observable<ResponseBody> {
return Observable.just(ResponseBody.create(MediaType.parse("application/json"), "{\"name\": \"专题\"}"))
}
}

View File

@ -1,4 +0,0 @@
package com.gh.gamecenter.qgame
class QGameSubjectUpdateEvent {
}

View File

@ -3144,6 +3144,20 @@ public interface ApiService {
@GET("blocks/{block_id}/tabs")
Single<List<SubjectRecommendEntity>> getBlockTab(@Path("block_id") String blockId);
/**
* QQ/微信小游戏-搜索
*/
@GET("mini_game/search")
Observable<List<GameEntity>> getSearchMiniGameList(@Query("keyword") String keyword,
@Query("page") int page,
@Query("page_size") int pageSize);
/**
* QQ/微信小游戏-最近在玩
*/
@GET("mini_game/recently_played/{game_type}")
Single<List<GameEntity>> getRecentPlayedMiniGameList(@Path("game_type") String gameType);
/**
* QQ小游戏-专题列表
*/
@ -3165,12 +3179,6 @@ public interface ApiService {
@Query("page") int page,
@Query("page_size") int pageSize);
/**
* QQ小游戏-搜索
*/
@GET
Observable<List<GameEntity>> getSearchQGame(@Url String url);
/**
* QQ小游戏-游玩记录
*/
@ -3183,6 +3191,33 @@ public interface ApiService {
@GET("/games/qq_mini/columns/{column_id}/setting")
Observable<SubjectSettingEntity> getQGameColumnSettings(@Path("column_id") String column_id);
/**
* 微信小游戏-专题数据详情
*/
@GET("/wechat_game/columns/{column_id}/setting")
Observable<SubjectSettingEntity> getWGameColumnSettings(@Path("column_id") String column_id);
/**
* 微信小游戏-专题-换一换
*/
@GET("wechat_game/columns/{column_id}/games?page=1&page_size=30")
Observable<List<GameEntity>> getSubjectWGame(@Path("column_id") String columnId);
/**
* 微信小游戏-专题游戏列表
*/
@GET("wechat_game/columns/{column_id}/games")
Single<List<GameEntity>> getWGameColumn(@Path("column_id") String columnId,
@Query("filter") String order,
@Query("page") int page,
@Query("page_size") int pageSize);
/**
* 微信小游戏-游玩记录
*/
@POST("/wechat_game/{appid}/user/{gid}")
Single<ResponseBody> postWGamePlay(@Path("appid") String wechatGameId, @Path("gid") String gid);
/**
* 获取广告配置
*/

View File

@ -14,6 +14,7 @@ import android.widget.CheckedTextView
import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.viewpager.widget.PagerAdapter
import com.gh.common.constant.Config
import com.gh.common.exposure.ExposureManager
import com.gh.common.filter.RegionSettingHelper
@ -30,6 +31,7 @@ import com.gh.gamecenter.core.utils.PageSwitchDataHelper
import com.gh.gamecenter.core.utils.StringUtils
import com.gh.gamecenter.databinding.FragmentSearchDefaultBinding
import com.gh.gamecenter.databinding.TabItemSearchDefaultRankBinding
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.db.SearchHistoryDao
import com.gh.gamecenter.eventbus.EBSearch
import com.gh.gamecenter.feature.entity.HotTagEntity
@ -45,13 +47,10 @@ import org.json.JSONObject
open class SearchDefaultFragment : BaseFragment<Any>() {
private var mHotTagList: List<HotTagEntity>? = null
protected var mHistoryList: List<String>? = null
protected var mRankList: List<SettingsEntity.Search.RankList>? = null
protected lateinit var mBinding: FragmentSearchDefaultBinding
private var mSearchHistoryDao: SearchHistoryDao? = null
private var mViewModel: SearchDefaultViewModel? = null
private var mIsGameSearch = false // 是否为游戏搜索
@ -95,20 +94,19 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mViewModel = viewModelProvider()
mViewModel = provideViewModel()
mIsGameSearch = arguments?.getBoolean(KEY_IS_GAME_SEARCH) ?: false
mSourceEntrance = arguments?.getString(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: ""
initDao()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
}
open fun initDao() {
mSearchHistoryDao = SearchHistoryDao(context)
}
open fun initView() {
protected open fun initView() {
mBinding = FragmentSearchDefaultBinding.bind(mCachedView)
mRankList = Config.getSettings()?.search?.rankList?.apply {
forEachIndexed { outIndex, rankList ->
@ -143,7 +141,7 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
mViewModel?.isExistHotTag = mHotTagList?.isNotEmpty() == true
updateHistorySearchView(null)
mViewModel?.historySearchLiveData?.observe(this) {
mViewModel?.historySearchLiveData?.observe(viewLifecycleOwner) {
updateHistorySearchView(it)
}
@ -153,7 +151,7 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
initRankViewPager()
}
private fun initHeadView() {
protected open fun initHeadView() {
mBinding.historyHeadContainer.run {
headTitle.text = getString(R.string.search_history)
headTitle.textSize = 16F
@ -166,11 +164,15 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
)
)
headActionTv.setOnClickListener {
DialogHelper.showCenterWarningDialog(requireContext(), "清空记录", "确定清空历史搜索记录?", confirmClickCallback = {
mSearchHistoryDao?.deleteAll()
mViewModel?.isExistHistory = false
updateView()
})
DialogHelper.showCenterWarningDialog(
requireContext(),
"清空记录",
"确定清空历史搜索记录?",
confirmClickCallback = {
mViewModel?.deleteAll()
mViewModel?.isExistHistory = false
updateView()
})
}
}
mBinding.hotHeadContainer.headTitle.text = getString(R.string.search_hot)
@ -181,7 +183,7 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
mBinding.hotTagHeadContainer.headActionTv.visibility = View.GONE
}
fun initRankViewPager() {
protected open fun initRankViewPager() {
mRankList = mRankList?.filter { it.content.isNotEmpty() }?.take(6)
if (mRankList.isNullOrEmpty()) return
@ -204,7 +206,7 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
visibility = View.VISIBLE
offscreenPageLimit = mRankList!!.size
pageMargin = 12F.dip2px()
adapter = SearchDefaultRankListAdapter(requireContext(), mRankList!!, pageRatio, mIsGameSearch, mSourceEntrance)
adapter = provideAdapter(pageRatio)
postExposureEvent(0)
doOnPageSelected {
postExposureEvent(it)
@ -342,14 +344,14 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
mBinding.rankViewPager.visibility = if (mViewModel?.isExistRankList == true) View.VISIBLE else View.GONE
}
private fun updateHistorySearchView(historyList: List<String>?) {
protected open fun updateHistorySearchView(historyList: List<String>?) {
mViewModel?.isExistHistory = historyList?.isNotEmpty() == true
updateView()
if (historyList != null) {
mBinding.historyFlexContainer.setLimitHeight(DisplayUtils.dip2px(88F))
createFlexContent(mBinding.historyFlex, historyList, clickListener = {
val key = historyList[it]
mSearchHistoryDao?.add(key)
mViewModel?.add(key)
EventBus.getDefault().post(EBSearch("history", key))
Util_System_Keyboard.hideSoftKeyboardByIBinder(context, mBinding.historyFlex.windowToken)
})
@ -449,6 +451,16 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
createFlexContent(mBinding.hotTagFlex, getTagListString(), true, clickListener = mHotTagClickListener)
}
protected open fun provideDao(): ISearchHistoryDao = SearchHistoryDao(requireContext().applicationContext)
protected open fun provideAdapter(pageRatio: Float): PagerAdapter =
SearchDefaultRankListAdapter(requireContext(), mRankList!!, pageRatio, mIsGameSearch, mSourceEntrance)
private fun provideViewModel(): SearchDefaultViewModel {
val factory = SearchDefaultViewModel.Factory(provideDao())
return viewModelProvider(factory)
}
companion object {
const val KEY_IS_GAME_SEARCH = "key_is_game_search"
}

View File

@ -1,12 +1,12 @@
package com.gh.gamecenter.search
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.db.SearchHistoryDao
import com.gh.gamecenter.db.ISearchHistoryDao
class SearchDefaultViewModel(application: Application) : AndroidViewModel(application) {
class SearchDefaultViewModel(private val dao: ISearchHistoryDao) : ViewModel() {
val historySearchLiveData = MutableLiveData<List<String>>()
var isExistHotSearch: Boolean = false
@ -16,7 +16,32 @@ class SearchDefaultViewModel(application: Application) : AndroidViewModel(applic
init {
runOnIoThread {
historySearchLiveData.postValue(SearchHistoryDao(application).all)
historySearchLiveData.postValue(dao.all)
}
}
fun deleteAll() {
dao.deleteAll()
historySearchLiveData.postValue(emptyList())
}
fun add(item: String) {
val oldList = historySearchLiveData.value
if (oldList.isNullOrEmpty()) {
dao.add(item)
historySearchLiveData.postValue(listOf(item))
return
}
if (!oldList.contains(item)) {
dao.add(item)
historySearchLiveData.postValue(oldList + item)
}
}
class Factory(private val dao: ISearchHistoryDao) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return SearchDefaultViewModel(dao) as T
}
}

View File

@ -40,6 +40,7 @@ import com.gh.gamecenter.eventbus.EBSearch
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.ExposureType
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.gamedetail.GameDetailFragment
import com.lightgame.download.DownloadEntity
import com.lightgame.utils.Util_System_Keyboard
@ -158,6 +159,7 @@ class SearchGameIndexAdapter(
gameEntity.adIconActive,
adLabelTv
)
MiniGameItemHelper.setMiniGameUsage(gamePlayCount, gameEntity)
}
binding.topDivider.goneIf(position == 0)
binding.gameItemIncluded.root.setPadding(

View File

@ -110,7 +110,7 @@ class SearchSubjectItemViewHolder(var binding: SearchSubjectItemBinding) : Recyc
)
}
if (!it.isQQMiniGame()) {
if (!it.isMiniGame()) {
SensorsBridge.trackColumnClick(
location = "游戏搜索",
gameColumnId = entity.columnId,

View File

@ -43,6 +43,7 @@ import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.ExposureType
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.gamedetail.GameDetailFragment
import com.gh.gamecenter.help.HelpAndFeedbackBridge
import com.lightgame.download.DownloadEntity
@ -310,6 +311,7 @@ class SearchGameResultAdapter(
gameEntity.adIconActive,
adLabelTv
)
MiniGameItemHelper.setMiniGameUsage(gamePlayCount, gameEntity)
}
binding.gameItemIncluded.root.setPadding(16F.dip2px(), 16F.dip2px(), 16F.dip2px(), 16F.dip2px())
SearchGameIndexItemViewHolder.initServerType(gameEntity, binding.gameItemIncluded)
@ -685,15 +687,12 @@ class SearchGameResultAdapter(
EventBus.getDefault().post(EBSearch("click", gameEntity.id, gameEntity.name))
}
if (gameEntity.isQQMiniGame()) {
GlobalActivityManager.currentActivity?.let {
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
}
SensorsBridge.trackQQGameClick(
location = "QQ小游戏搜索结果列表",
if (gameEntity.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
MiniGameItemHelper.trackMiniGameClick(
gameEntity = gameEntity,
location = "小游戏搜索结果列表",
searchContent = key,
gameId = gameEntity.id,
gameName = gameEntity.name ?: ""
)
} else {
GameDetailActivity.startGameDetailActivity(
@ -791,6 +790,13 @@ class SearchGameResultAdapter(
gameEntity.name ?: ""
)
}
if (gameEntity.isMiniGame()) {
MiniGameItemHelper.trackMiniGameClick(
gameEntity = gameEntity,
location = "小游戏搜索结果列表",
searchContent = key,
)
}
},
refreshCallback = null
) {

View File

@ -5,15 +5,30 @@ import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.entity.SubjectData
import com.gh.gamecenter.feature.entity.PageLocation
class AdSubjectListFragment : SubjectListFragment() {
private var mSubjectData: SubjectData? = null
override fun provideListViewModel(): SubjectListViewModel = viewModelProvider(
AdSubjectListViewModel.Factory(
mSubjectData!!,
arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
override fun provideListViewModel(): SubjectListViewModel {
val bottomTabName = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, "") ?: ""
val tabIndex = arguments?.getInt(EntranceConsts.KEY_TAB_INDEX, -1) ?: -1
val tabName = arguments?.getString(EntranceConsts.KEY_TAB_NAME, "") ?: ""
val multiTabNavId = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: ""
val multiTabNavName = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""
return viewModelProvider(
AdSubjectListViewModel.Factory(
mSubjectData!!,
PageLocation(
bottomTab = bottomTabName,
severalTabPageId = multiTabNavId,
severalTabPageName = multiTabNavName,
tabPosition = tabIndex,
tabContent = tabName
),
arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
)
)
)
}
override fun onCreate(savedInstanceState: Bundle?) {
mSubjectData = arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_DATA)

View File

@ -7,6 +7,7 @@ import com.gh.gamecenter.common.baselist.LoadParams
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.entity.SubjectData
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PageLocation
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.Single
@ -14,9 +15,10 @@ import io.reactivex.Single
class AdSubjectListViewModel(
application: Application,
private val mSubjectData: SubjectData,
pageLocation: PageLocation,
exposureSourceList: List<ExposureSource>? = null
) :
SubjectListViewModel(application, mSubjectData, exposureSourceList) {
SubjectListViewModel(application, mSubjectData, pageLocation, exposureSourceList) {
override fun provideDataSingle(page: Int): Single<MutableList<GameEntity>> =
RetrofitManager.getInstance().newApi.getAdGames(
mSubjectData.adId,
@ -34,10 +36,11 @@ class AdSubjectListViewModel(
class Factory(
private val mSubjectData: SubjectData,
private val mPageLocation: PageLocation,
private val mExposureSourceList: List<ExposureSource>? = null
) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return AdSubjectListViewModel(HaloApp.getInstance(), mSubjectData, mExposureSourceList) as T
return AdSubjectListViewModel(HaloApp.getInstance(), mSubjectData, mPageLocation, mExposureSourceList) as T
}
}
}

View File

@ -1,6 +1,8 @@
package com.gh.gamecenter.subject
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.feature.entity.GameEntity
import io.reactivex.Observable
import io.reactivex.Single
interface ISubjectListRepository {
@ -11,4 +13,6 @@ interface ISubjectListRepository {
sort: String?,
order: String?,
): Single<MutableList<GameEntity>>
fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity>
}

View File

@ -70,13 +70,13 @@ open class SubjectActivity : DownloadToolbarActivity() {
isOrder: Boolean,
exposureSourceList: ArrayList<ExposureSource>? = null,
entrance: String?,
isQQMiniGame: Boolean = false
subjectType: SubjectData.SubjectType = SubjectData.SubjectType.NORMAL
) {
MtaHelper.onEvent("详情页面", "专题详情", name)
val bundle = Bundle()
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance)
val subjectData = SubjectData(subjectId = id, subjectName = name, isOrder = isOrder, isQQMiniGame = isQQMiniGame)
val subjectData = SubjectData(subjectId = id, subjectName = name, isOrder = isOrder, subjectType = subjectType)
bundle.putParcelable(EntranceConsts.KEY_SUBJECT_DATA, subjectData)
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance)
if (exposureSourceList != null) {

View File

@ -17,7 +17,6 @@ import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.viewholder.GameImageViewHolder
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.constant.ItemViewType
import com.gh.gamecenter.common.entity.LinkEntity
@ -33,6 +32,7 @@ import com.gh.gamecenter.feature.databinding.GameItemBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.home.custom.model.CustomPageItem
import com.lightgame.download.DownloadEntity
@ -218,19 +218,22 @@ class SubjectAdapter(
holder.itemView.setOnClickListener {
DataCollectionUtils.uploadClick(mContext, "列表", subjectData.subjectName, gameEntity.name)
if (gameEntity.isQQMiniGame()) {
GlobalActivityManager.currentActivity?.let {
DirectUtils.directToQGameById(it, gameEntity.qqMiniGameAppId)
}
if (!mIsColumnCollection) {
SensorsBridge.trackQQGameClick(
location = "专题详情",
gameColumnId = subjectData.subjectId ?: "",
gameColumnName = subjectData.subjectName ?: "",
gameId = gameEntity.id,
gameName = gameEntity.name ?: ""
)
}
if (gameEntity.isMiniGame()) {
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
val pageLocation = mViewModel.pageLocation
MiniGameItemHelper.trackMiniGameClick(
gameEntity = gameEntity,
location = "专题详情",
bottomTab = pageLocation.bottomTab,
multiTabId = pageLocation.severalTabPageId,
multiTabName = pageLocation.severalTabPageName,
position = pageLocation.tabPosition,
tabContent = pageLocation.tabContent,
gameColumnId = subjectData.subjectId ?: "",
gameColumnName = subjectData.subjectName ?: "",
columnPattern = CustomPageItem.collectionTypeToComponentName[mCollectionStyle]
?: mCollectionStyle
)
} else {
GameDetailActivity.startGameDetailActivity(
mContext,
@ -317,6 +320,23 @@ class SubjectAdapter(
text = "按钮"
)
}
if (gameEntity.isMiniGame() && !mIsColumnCollection) {
val pageLocation = mViewModel.pageLocation
MiniGameItemHelper.trackMiniGameClick(
gameEntity = gameEntity,
location = "专题详情",
bottomTab = pageLocation.bottomTab,
multiTabId = pageLocation.severalTabPageId,
multiTabName = pageLocation.severalTabPageName,
position = pageLocation.tabPosition,
tabContent = pageLocation.tabContent,
gameColumnId = subjectData.subjectId ?: "",
gameColumnName = subjectData.subjectName ?: "",
columnPattern = CustomPageItem.collectionTypeToComponentName[mCollectionStyle]
?: mCollectionStyle
)
}
}
)

View File

@ -14,6 +14,7 @@ import com.gh.gamecenter.common.baselist.LazyListFragment
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
import com.gh.gamecenter.common.view.SpacingItemDecoration
@ -23,6 +24,7 @@ import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PageLocation
import com.halo.assistant.HaloApp
import com.lightgame.OnTitleClickListener
import com.lightgame.download.DataWatcher
@ -86,9 +88,21 @@ open class SubjectListFragment : LazyListFragment<GameEntity, SubjectListViewMod
}
override fun provideListViewModel(): SubjectListViewModel {
val bottomTabName = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, "") ?: ""
val tabIndex = arguments?.getInt(EntranceConsts.KEY_TAB_INDEX, -1) ?: -1
val tabName = arguments?.getString(EntranceConsts.KEY_TAB_NAME, "") ?: ""
val multiTabNavId = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: ""
val multiTabNavName = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""
val factory = SubjectListViewModel.Factory(
HaloApp.getInstance().application,
arguments?.getParcelable(EntranceConsts.KEY_SUBJECT_DATA)!!,
PageLocation(
bottomTab = bottomTabName,
severalTabPageId = multiTabNavId,
severalTabPageName = multiTabNavName,
tabPosition = tabIndex,
tabContent = tabName
),
arguments?.getParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
)
if (requireContext() is SubjectActivity) {

View File

@ -1,8 +1,10 @@
package com.gh.gamecenter.subject
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
import io.reactivex.Observable
import io.reactivex.Single
class SubjectListRepository(
@ -12,4 +14,10 @@ class SubjectListRepository(
override fun getColumn(column_id: String?, page: Int, sort: String?, order: String?): Single<MutableList<GameEntity>> {
return api.getColumn(column_id, sort, order, page)
}
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {
return api.getColumnSettings(column_id)
}
}

View File

@ -13,8 +13,8 @@ import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.entity.SubjectData
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PageLocation
import com.gh.gamecenter.feature.entity.TagStyleEntity
import com.gh.gamecenter.qgame.QGameSubjectListRepository
import com.gh.gamecenter.retrofit.RetrofitManager
import io.reactivex.Observable
import io.reactivex.Single
@ -25,6 +25,7 @@ import retrofit2.HttpException
open class SubjectListViewModel(
application: Application,
var subjectData: SubjectData,
var pageLocation: PageLocation,
var exposureSourceList: List<ExposureSource>?
) : ListViewModel<GameEntity, GameEntity>(application) {
@ -34,7 +35,7 @@ open class SubjectListViewModel(
var lastPageDataMap: HashMap<String, String>? = null
private val repository = if (subjectData.isQQMiniGame) QGameSubjectListRepository() else SubjectListRepository()
private val repository = SubjectRepositoryFactory.createListRepo(subjectData.subjectType)
override fun provideDataObservable(page: Int): Observable<List<GameEntity>>? = null
@ -43,7 +44,7 @@ open class SubjectListViewModel(
subjectData.subjectId,
page,
subjectData.sort,
if (subjectData.filter.isEmpty()) "type:全部" else subjectData.filter,
subjectData.filter.ifEmpty { "type:全部" },
)
}
@ -76,7 +77,7 @@ open class SubjectListViewModel(
private fun updateSubjectSettingBeforeInitialLoad() {
// 无论是否加载成功都回落到普通的专题列表加载
RetrofitManager.getInstance().api
repository
.getColumnSettings(subjectData.subjectId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@ -115,10 +116,11 @@ open class SubjectListViewModel(
class Factory(
private val mApplication: Application,
private val subjectData: SubjectData,
private val pageLocation: PageLocation,
private val exposureSourceList: List<ExposureSource>? = null
) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return SubjectListViewModel(mApplication, subjectData, exposureSourceList) as T
return SubjectListViewModel(mApplication, subjectData, pageLocation, exposureSourceList) as T
}
}

View File

@ -0,0 +1,21 @@
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.WGameSubjectListRepository
import com.gh.gamecenter.minigame.wechat.WGameSubjectRepository
object SubjectRepositoryFactory {
fun createRepo(subjectType: SubjectData.SubjectType): ISubjectRepository = when(subjectType) {
SubjectData.SubjectType.QQ_GAME -> QGameSubjectRepository()
SubjectData.SubjectType.WECHAT_GAME -> WGameSubjectRepository()
else -> SubjectRepository()
}
fun createListRepo(subjectType: SubjectData.SubjectType): ISubjectListRepository = when(subjectType) {
SubjectData.SubjectType.QQ_GAME -> QGameSubjectListRepository()
SubjectData.SubjectType.WECHAT_GAME -> WGameSubjectListRepository()
else -> SubjectListRepository()
}
}

View File

@ -9,7 +9,6 @@ import com.gh.gamecenter.common.retrofit.JSONObjectResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.entity.SubjectData
import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.qgame.QGameSubjectRepository
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import org.json.JSONObject
@ -23,7 +22,8 @@ class SubjectViewModel(
val subjectNameLD = MutableLiveData<String>()
val subjectSettingLD = MutableLiveData<SubjectSettingEntity>()
private val repository = if (subjectData?.isQQMiniGame == true) QGameSubjectRepository() else SubjectRepository()
private val repository =
SubjectRepositoryFactory.createRepo(subjectData?.subjectType ?: SubjectData.SubjectType.NORMAL)
init {
initData()

View File

@ -195,6 +195,7 @@ abstract class BaseTabWrapperFragment : BaseLazyFragment(), IMultiTab {
bundle.putBoolean(EntranceConsts.KEY_IS_FROM_TAB_WRAPPER, true)
bundle.putInt(EntranceConsts.KEY_TAB_COUNT, tabEntityList.size)
bundle.putInt(EntranceConsts.KEY_TAB_INDEX, index)
bundle.putString(EntranceConsts.KEY_TAB_NAME, tabEntity.name)
bundle.putInt(EntranceConsts.KEY_POSITION, index)
val bottomTabExposureSource = arguments?.getParcelableArrayList<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
@ -214,7 +215,6 @@ abstract class BaseTabWrapperFragment : BaseLazyFragment(), IMultiTab {
val superiorChain = if (this is ISuperiorChain) this else null
bundle.putString(EntranceConsts.KEY_CUSTOM_PAGE_ID, tabEntity.link.link)
bundle.putString(EntranceConsts.KEY_CUSTOM_PAGE_NAME, tabEntity.link.text)
bundle.putString(EntranceConsts.KEY_TAB_NAME, tabEntity.name)
CustomPageFragment().setSuperiorChain(superiorChain).with(bundle)
}

View File

@ -299,7 +299,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
BottomTab.SearchStyle.TYPE_HALO_GAME -> {
mSearchHintTv?.let { DefaultSearchHintHelper.setSearchHint(it) }
}
BottomTab.SearchStyle.TYPE_QQ_MINI_GAME -> {
BottomTab.SearchStyle.TYPE_MINI_GAME -> {
mSearchHintTv?.hint = if (mSearchStyle?.styleType == BottomTab.SearchStyle.STYLE_APPOSITION) "搜索" else "请输入小游戏关键词"
}
BottomTab.SearchStyle.TYPE_BBS -> {

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

View File

@ -260,10 +260,27 @@
android:orientation="horizontal"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/gameIconView"
app:layout_constraintLeft_toLeftOf="@+id/gameDesSpace"
app:layout_constraintLeft_toRightOf="@+id/game_play_count"
app:layout_constraintRight_toRightOf="@+id/gameDesSpace"
app:layout_constraintTop_toBottomOf="@+id/gameDesSpace" />
<TextView
android:id="@+id/game_play_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:visibility="visible"
android:includeFontPadding="false"
app:layout_constraintBottom_toBottomOf="@+id/gameIconView"
app:layout_constraintLeft_toLeftOf="@+id/gameDesSpace"
app:layout_constraintRight_toLeftOf="@+id/label_list"
app:layout_constraintTop_toBottomOf="@+id/gameDesSpace"
android:textSize="11sp"
android:gravity="center"
android:layout_marginRight="8dp"
android:textColor="@color/text_tertiary"
tools:text="999.9万人玩过" />
<TextView
android:id="@+id/never_remind"
android:layout_width="wrap_content"

View File

@ -114,6 +114,18 @@
android:textStyle="bold"
tools:text="9.3" />
<TextView
android:id="@+id/game_play_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:includeFontPadding="false"
android:layout_marginEnd="4dp"
android:textSize="11sp"
android:gravity="center"
android:textColor="@color/text_tertiary"
tools:text="999.9万人玩过" />
<com.gh.common.view.GameTagFlexLinearLayout
android:id="@+id/game_tags"
android:layout_width="match_parent"

View File

@ -156,6 +156,18 @@
app:drawableStartCompat="@drawable/home_game_rating"
tools:text="9.3" />
<TextView
android:id="@+id/game_play_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:includeFontPadding="false"
android:layout_marginEnd="4dp"
android:textSize="11sp"
android:gravity="center"
android:textColor="@color/text_tertiary"
tools:text="999.9万人玩过" />
<com.gh.gamecenter.common.view.GameTagContainerView
android:id="@+id/game_tags"
android:layout_width="match_parent"

View File

@ -94,7 +94,23 @@
android:layout_marginStart="8dp"
android:layout_marginBottom="2dp"
app:layout_constraintBottom_toBottomOf="@+id/game_icon"
app:layout_constraintStart_toEndOf="@+id/game_icon" />
app:layout_constraintStart_toEndOf="@+id/game_play_count" />
<TextView
android:id="@+id/game_play_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="2dp"
android:visibility="gone"
android:includeFontPadding="false"
app:layout_constraintBottom_toBottomOf="@+id/game_icon"
app:layout_constraintStart_toEndOf="@+id/game_icon"
app:layout_constraintEnd_toStartOf="@id/game_tags"
android:textSize="11sp"
android:gravity="center"
android:textColor="@color/text_tertiary"
tools:text="999.9万人玩过" />
<com.gh.gamecenter.feature.view.DownloadButton
android:id="@+id/download_btn"

View File

@ -93,7 +93,23 @@
android:layout_marginStart="8dp"
android:layout_marginBottom="2dp"
app:layout_constraintBottom_toBottomOf="@+id/game_icon"
app:layout_constraintStart_toEndOf="@+id/game_icon" />
app:layout_constraintStart_toEndOf="@+id/game_play_count" />
<TextView
android:id="@+id/game_play_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="2dp"
android:visibility="gone"
android:includeFontPadding="false"
app:layout_constraintBottom_toBottomOf="@+id/game_icon"
app:layout_constraintStart_toEndOf="@+id/game_icon"
app:layout_constraintEnd_toStartOf="@id/game_tags"
android:textSize="11sp"
android:gravity="center"
android:textColor="@color/text_tertiary"
tools:text="999.9万人玩过" />
<com.gh.gamecenter.feature.view.DownloadButton
android:id="@+id/download_btn"

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