diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4bae8cb9b7..b6e2e2bd8b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -794,6 +794,12 @@
android:screenOrientation="portrait"
android:theme="@style/AppCompatTheme.APP" />
+
+
diff --git a/app/src/main/java/com/gh/common/provider/SearchTabUtilsProviderImpl.kt b/app/src/main/java/com/gh/common/provider/SearchTabUtilsProviderImpl.kt
new file mode 100644
index 0000000000..e8a0cdf2f6
--- /dev/null
+++ b/app/src/main/java/com/gh/common/provider/SearchTabUtilsProviderImpl.kt
@@ -0,0 +1,36 @@
+package com.gh.common.provider
+
+import android.content.Context
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.alibaba.android.arouter.facade.annotation.Route
+import com.gh.gamecenter.common.constant.RouteConsts
+import com.gh.gamecenter.core.provider.ISearchTabUtilsProvider
+import com.gh.gamecenter.search.viewmodel.SearchTabViewModel
+
+@Route(path = RouteConsts.provider.searchTabUtils, name = "SearchTabUtils暴露服务")
+class SearchTabUtilsProviderImpl : ISearchTabUtilsProvider {
+
+ override fun obtainParentViewModel(fragment: Fragment): ViewModel {
+ val store = (fragment.parentFragment ?: fragment).viewModelStore
+ val factory = fragment.defaultViewModelProviderFactory
+ return ViewModelProvider(
+ store,
+ factory
+ ).get(SearchTabViewModel::class.java)
+ }
+
+ override fun getKeyAndTypeLiveData(viewModel: ViewModel?): LiveData>? =
+ if (viewModel is SearchTabViewModel) {
+ viewModel.searchKeyAndType
+ } else {
+ null
+ }
+
+
+ override fun init(context: Context?) {
+ // no implement
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/common/util/DirectUtils.kt b/app/src/main/java/com/gh/common/util/DirectUtils.kt
index afb12201be..2b49d71c36 100644
--- a/app/src/main/java/com/gh/common/util/DirectUtils.kt
+++ b/app/src/main/java/com/gh/common/util/DirectUtils.kt
@@ -78,6 +78,7 @@ 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.retrofit.RetrofitManager
+import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.servers.GameServerTestActivity
import com.gh.gamecenter.servers.GameServersActivity
import com.gh.gamecenter.servers.gametest2.GameServerTestV2Activity
diff --git a/app/src/main/java/com/gh/common/util/NewFlatLogUtils.kt b/app/src/main/java/com/gh/common/util/NewFlatLogUtils.kt
index fa3e502ce6..89e047cc3b 100644
--- a/app/src/main/java/com/gh/common/util/NewFlatLogUtils.kt
+++ b/app/src/main/java/com/gh/common/util/NewFlatLogUtils.kt
@@ -661,12 +661,14 @@ object NewFlatLogUtils {
@JvmStatic
fun logSearchBbs(
searchType: String,
- searchKey: String
+ searchKey: String,
+ location: String
) {
json {
KEY_EVENT to "search_bbs"
"search_type" to searchType
"key" to searchKey
+ KEY_LOCATION to location
parseAndPutMeta()()
}.let(::log)
}
@@ -678,7 +680,8 @@ object NewFlatLogUtils {
bbsId: String,
sequence: Int,
name: String,
- button: String
+ button: String,
+ location: String
) {
json {
KEY_EVENT to "search_bbs_click"
@@ -688,6 +691,7 @@ object NewFlatLogUtils {
"sequence" to sequence
"name" to name
"button" to button
+ KEY_LOCATION to location
parseAndPutMeta()()
}.let(::log)
}
@@ -695,12 +699,14 @@ object NewFlatLogUtils {
@JvmStatic
fun logSearchUser(
searchType: String,
- searchKey: String
+ searchKey: String,
+ location: String
) {
json {
KEY_EVENT to "search_user"
"search_type" to searchType
"key" to searchKey
+ KEY_LOCATION to location
parseAndPutMeta()()
}.let(::log)
}
@@ -711,7 +717,8 @@ object NewFlatLogUtils {
searchKey: String,
userId: String,
name: String,
- sequence: Int
+ sequence: Int,
+ location: String
) {
json {
KEY_EVENT to "search_user_click"
@@ -720,6 +727,7 @@ object NewFlatLogUtils {
"user_id" to userId
"name" to name
"sequence" to sequence
+ KEY_LOCATION to location
parseAndPutMeta()()
}.let(::log)
}
@@ -1344,7 +1352,13 @@ object NewFlatLogUtils {
}
// 上传存档弹窗点击事件
- fun logCloudArchiveUploadDialogClick(gameId: String, gameName: String, cloudSaveId: String, cloudSaveName: String, isSuccess: Boolean) {
+ fun logCloudArchiveUploadDialogClick(
+ gameId: String,
+ gameName: String,
+ cloudSaveId: String,
+ cloudSaveName: String,
+ isSuccess: Boolean
+ ) {
val json = json {
KEY_EVENT to "cloud_save_upload_dialog_click"
KEY_GAME_ID to gameId
diff --git a/app/src/main/java/com/gh/gamecenter/SearchActivity.kt b/app/src/main/java/com/gh/gamecenter/SearchActivity.kt
index 97a4ba8ad2..5b17bebf64 100644
--- a/app/src/main/java/com/gh/gamecenter/SearchActivity.kt
+++ b/app/src/main/java/com/gh/gamecenter/SearchActivity.kt
@@ -22,6 +22,7 @@ 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.SearchTabActivity
import com.gh.gamecenter.search.SearchDefaultFragment
import com.gh.gamecenter.search.SearchGameIndexFragment
import com.gh.gamecenter.search.SearchGameResultFragment
@@ -52,7 +53,11 @@ open class SearchActivity : BaseActivity() {
private var mPublishSubject: PublishSubject? = null
- private var mSourceEntrance: String = ""
+ /**
+ * 神策的 SourceEntrance 字段相当于 火山云的 location
+ * 如果有火山云埋点需要上传 location 字段,那么直接使用此字段的值就行
+ */
+ protected var mSourceEntrance: String = ""
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
@@ -117,27 +122,10 @@ open class SearchActivity : BaseActivity() {
updateDisplayType(DEFAULT)
}
- trackSearchPageShow()
- }
-
- protected open fun trackSearchPageShow() {
- val bottomTab = intent.getStringExtra(EntranceConsts.KEY_BOTTOM_TAB_NAME) ?: ""
- val multiTabId = intent.getStringExtra(EntranceConsts.KEY_MULTI_TAB_NAV_ID) ?: ""
- val multiTabName = intent.getStringExtra(EntranceConsts.KEY_MULTI_TAB_NAV_NAME) ?: ""
- val customPageId = intent.getStringExtra(EntranceConsts.KEY_CUSTOM_PAGE_ID) ?: ""
- val customPageName = intent.getStringExtra(EntranceConsts.KEY_CUSTOM_PAGE_NAME) ?: ""
- val searchBoxPattern = intent.getStringExtra(EntranceConsts.KEY_SEARCH_BOX_PATTERN) ?: ""
-
- SensorsBridge.trackSearchPageShow(
+ SensorsBridge.trackGameSearchPageShow(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
- intent.getStringExtra(EntranceConsts.KEY_SOURCE_ENTRANCE) ?: "",
- bottomTab,
- multiTabId,
- multiTabName,
- customPageId,
- customPageName,
- searchBoxPattern
+ mSourceEntrance
)
}
@@ -206,12 +194,12 @@ open class SearchActivity : BaseActivity() {
updateDisplayType(GAME_DIGEST)
LogUtils.uploadSearchGame("searching", "搜索页", key, "自动搜索")
- SensorsBridge.trackSearchButtonClick(
+ SensorsBridge.trackGameSearchPageButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
+ mSourceEntrance,
key ?: "",
- TRACK_SEARCH_TYPE_INPUT,
- mSourceEntrance
+ TRACK_SEARCH_TYPE_AUTO
)
}
}
@@ -239,14 +227,13 @@ open class SearchActivity : BaseActivity() {
updateDisplayType(GAME_DETAIL)
LogUtils.uploadSearchGame("searching", "搜索页", key, "默认搜索")
- SensorsBridge.trackSearchButtonClick(
+ SensorsBridge.trackGameSearchPageButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
+ mSourceEntrance,
key ?: "",
- TRACK_SEARCH_TYPE_DEFAULT,
- mSourceEntrance
+ TRACK_SEARCH_TYPE_DEFAULT
)
-// MtaHelper.onEvent("游戏搜索", "默认搜索", key)
}
protected open fun handleHotSearch(key: String?) {
@@ -263,14 +250,13 @@ open class SearchActivity : BaseActivity() {
updateDisplayType(GAME_DETAIL)
LogUtils.uploadSearchGame("searching", "搜索页", key, "历史搜索")
- SensorsBridge.trackSearchButtonClick(
+ SensorsBridge.trackGameSearchPageButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
+ mSourceEntrance,
key ?: "",
- TRACK_SEARCH_TYPE_HISTORY,
- mSourceEntrance
+ TRACK_SEARCH_TYPE_HISTORY
)
-// MtaHelper.onEvent("游戏搜索", "历史搜索", key)
}
protected open fun handleManualSearch() {
@@ -284,16 +270,16 @@ open class SearchActivity : BaseActivity() {
} else if (newSearchKey != mSearchKey || mDisplayType != GAME_DETAIL) {
mSearchKey = newSearchKey
if (!TextUtils.isEmpty(mSearchKey)) {
- SensorsBridge.trackSearchButtonClick(
- GlobalActivityManager.getCurrentPageEntity().pageId,
- GlobalActivityManager.getCurrentPageEntity().pageName,
- newSearchKey,
- TRACK_SEARCH_TYPE_INPUT,
- mSourceEntrance
- )
-
mDao.add(mSearchKey)
updateDisplayType(GAME_DETAIL)
+
+ SensorsBridge.trackGameSearchPageButtonClick(
+ GlobalActivityManager.getCurrentPageEntity().pageId,
+ GlobalActivityManager.getCurrentPageEntity().pageName,
+ mSourceEntrance,
+ newSearchKey,
+ TRACK_SEARCH_TYPE_INPUT
+ )
} else {
toast("请输入搜索内容")
}
@@ -415,13 +401,15 @@ open class SearchActivity : BaseActivity() {
private const val KEY_SEARCH_IMMEDIATELY = "search_immediately"
private const val HINT_TEXT = "搜索游戏..."
+ const val TRACK_SEARCH_TYPE_AUTO = "自动搜索"
const val TRACK_SEARCH_TYPE_INPUT = "输入搜索"
const val TRACK_SEARCH_TYPE_DEFAULT = "默认搜索"
const val TRACK_SEARCH_TYPE_HISTORY = "历史搜索"
@JvmStatic
fun toTrackSearchType(type: String) = when (type) {
- SearchType.AUTO.value, SearchType.MANUAL.value -> TRACK_SEARCH_TYPE_INPUT
+ SearchType.AUTO.value -> TRACK_SEARCH_TYPE_AUTO
+ SearchType.MANUAL.value -> TRACK_SEARCH_TYPE_INPUT
SearchType.HISTORY.value -> TRACK_SEARCH_TYPE_HISTORY
else -> TRACK_SEARCH_TYPE_DEFAULT
}
@@ -433,7 +421,8 @@ open class SearchActivity : BaseActivity() {
hint: String,
entrance: String,
sourceEntrance: String
- ): Intent = getIntent(context, searchImmediately, hint, entrance, sourceEntrance, "", "", "", "", "", "")
+ ): Intent =
+ getIntent(context, searchImmediately, hint, entrance, sourceEntrance, "", "", "", "", "", "")
@JvmStatic
fun getIntent(
@@ -449,7 +438,7 @@ open class SearchActivity : BaseActivity() {
customPageName: String = "",
searchBoxPattern: String = ""
): Intent {
- val intent = Intent(context, SearchActivity::class.java)
+ val intent = Intent(context, SearchTabActivity::class.java)
intent.putExtra(KEY_SEARCH_IMMEDIATELY, searchImmediately)
intent.putExtra(EntranceConsts.KEY_HINT, hint)
intent.putExtra(EntranceConsts.KEY_ENTRANCE, entrance)
diff --git a/app/src/main/java/com/gh/gamecenter/amway/search/AmwaySearchActivity.kt b/app/src/main/java/com/gh/gamecenter/amway/search/AmwaySearchActivity.kt
index 742c978d3e..00f856885f 100644
--- a/app/src/main/java/com/gh/gamecenter/amway/search/AmwaySearchActivity.kt
+++ b/app/src/main/java/com/gh/gamecenter/amway/search/AmwaySearchActivity.kt
@@ -78,9 +78,6 @@ class AmwaySearchActivity : SearchActivity() {
transaction.commitAllowingStateLoss()
}
- // 安利墙搜索页不需要神策埋点
- override fun trackSearchPageShow() = Unit
-
companion object {
fun getIntent(context: Context): Intent {
val intent = Intent(context, AmwaySearchActivity::class.java)
diff --git a/app/src/main/java/com/gh/gamecenter/forum/search/ForumContentSearchListFragment.kt b/app/src/main/java/com/gh/gamecenter/forum/search/ForumContentSearchListFragment.kt
index e2671e0301..77fbce96ba 100644
--- a/app/src/main/java/com/gh/gamecenter/forum/search/ForumContentSearchListFragment.kt
+++ b/app/src/main/java/com/gh/gamecenter/forum/search/ForumContentSearchListFragment.kt
@@ -1,7 +1,9 @@
package com.gh.gamecenter.forum.search
+import android.os.Bundle
import android.view.View
import androidx.core.content.ContextCompat
+import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.NewLogUtils
@@ -24,12 +26,19 @@ import com.gh.gamecenter.feature.entity.AnswerEntity
import com.gh.gamecenter.forum.home.ForumScrollCalculatorHelper
import com.gh.gamecenter.forum.search.CommunitySearchEventListener.Companion.SEARCH_BUTTON_VIEW_CONTENT_DETAIL
import com.gh.gamecenter.forum.search.ForumOrUserSearchActivity.Companion.LOCATION_COMMUNITY
+import com.gh.gamecenter.search.viewmodel.SearchTabViewModel
import com.gh.gamecenter.video.detail.CustomManager
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
class ForumContentSearchListFragment : LazyListFragment(),
CommunitySearchEventListener {
+ private val parentTabViewModel by viewModels(
+ ownerProducer = {
+ parentFragment ?: this
+ }
+ )
+
private var mBbsId = ""
private var mSearchKey = ""
private var mSearchType = SearchType.DEFAULT.value
@@ -42,6 +51,8 @@ class ForumContentSearchListFragment : LazyListFragment {
return mAdapter
?: ForumContentSearchListAdapter(
@@ -79,6 +90,11 @@ class ForumContentSearchListFragment : LazyListFragment
+ setSearchKeyAndType(key, type)
+ }
}
override fun getItemDecoration(): RecyclerView.ItemDecoration? {
@@ -260,13 +281,16 @@ class ForumContentSearchListFragment : LazyListFragment() {
+ private val parentTabViewModel by viewModels(
+ ownerProducer = { parentFragment ?: this }
+ )
+
private var mSearchKey = ""
private var mAdapter: UserSearchListAdapter? = null
private var mSearchType = SearchType.DEFAULT.value
+ private var mIsAutoLoad = true
override fun provideListAdapter(): ListAdapter<*> {
return mAdapter
?: UserSearchListAdapter(requireContext(), mEntrance, mListViewModel) { userId, name, position ->
- SensorsBridge.trackSearchResultClick(
+ SensorsBridge.trackUserSearchResultClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
mSearchKey,
SearchActivity.toTrackSearchType(mSearchType),
- mListViewModel.sourceEntrance
+ mListViewModel.sourceEntrance,
+ userId
)
NewFlatLogUtils.logSearchUserClick(
SearchType.fromString(mSearchType).toChinese(),
mSearchKey,
userId,
name,
- position + 1
+ position + 1,
+ mListViewModel.sourceEntrance
)
}.apply { mAdapter = this }
}
@@ -54,6 +64,11 @@ class UserSearchListFragment : LazyListFragment
+ setSearchKeyAndType(key, type)
+ }
+
}
override fun getItemDecoration(): RecyclerView.ItemDecoration? = null
diff --git a/app/src/main/java/com/gh/gamecenter/forum/search/UserSearchListViewModel.kt b/app/src/main/java/com/gh/gamecenter/forum/search/UserSearchListViewModel.kt
index bf8064d7c6..c7ea50760c 100644
--- a/app/src/main/java/com/gh/gamecenter/forum/search/UserSearchListViewModel.kt
+++ b/app/src/main/java/com/gh/gamecenter/forum/search/UserSearchListViewModel.kt
@@ -34,7 +34,8 @@ class UserSearchListViewModel(application: Application) :
if (page == 1) {
NewFlatLogUtils.logSearchUser(
SearchType.fromString(searchType).toChinese(),
- searchKey
+ searchKey,
+ sourceEntrance
)
}
return RetrofitManager.getInstance().api.searchUsers(searchKey, page)
@@ -44,13 +45,13 @@ class UserSearchListViewModel(application: Application) :
mResultLiveData.addSource(mListLiveData) {
mResultLiveData.postValue(it)
if (page == 1) {
- SensorsBridge.trackSearchResultReturn(
+ SensorsBridge.trackUserSearchResultReturn(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
+ sourceEntrance,
searchKey,
SearchActivity.toTrackSearchType(searchType),
- it.isNotEmpty(),
- sourceEntrance
+ it.isNotEmpty()
)
}
}
diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt
index d5c267116e..2da9fba3cc 100644
--- a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt
+++ b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt
@@ -86,6 +86,7 @@ import com.gh.gamecenter.home.video.ScrollCalculatorHelper
import com.gh.gamecenter.login.user.UserViewModel
import com.gh.gamecenter.newsdetail.NewsDetailActivity
import com.gh.gamecenter.packagehelper.PackageViewModel
+import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.simulatorgame.SimulatorGameActivity
import com.gh.gamecenter.tag.TagsActivity
import com.gh.gamecenter.video.detail.CustomManager
diff --git a/app/src/main/java/com/gh/gamecenter/home/custom/model/CustomPageData.kt b/app/src/main/java/com/gh/gamecenter/home/custom/model/CustomPageData.kt
index 1eb0639c9f..9d13482d23 100644
--- a/app/src/main/java/com/gh/gamecenter/home/custom/model/CustomPageData.kt
+++ b/app/src/main/java/com/gh/gamecenter/home/custom/model/CustomPageData.kt
@@ -220,7 +220,9 @@ class CustomPageData(
@SerializedName("stamp")
private val _stamp: String? = null,
@SerializedName("style")
- private val _style: String? = null
+ private val _style: String? = null,
+ @SerializedName("tags")
+ private val _tags: List? = null
) {
val id: String
@@ -269,6 +271,9 @@ class CustomPageData(
@IgnoredOnParcel
private var filteredGames: List? = null
+ val tags: List
+ get() = _tags ?: emptyList()
+
data class User(
@SerializedName("_id")
private val _id: String? = null,
diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumActivity.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumActivity.kt
index c455ecaa9f..b53f8749fd 100644
--- a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumActivity.kt
+++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumActivity.kt
@@ -14,18 +14,13 @@ import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.base.adapter.FragmentAdapter
import com.gh.common.util.*
import com.gh.gamecenter.R
-import com.gh.gamecenter.SearchActivity
-import com.gh.gamecenter.SearchActivity.Companion.TRACK_SEARCH_TYPE_INPUT
import com.gh.gamecenter.SearchType
-import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.doOnPageSelected
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.doOnEnd
import com.gh.gamecenter.databinding.DialogChooseForumBinding
import com.gh.gamecenter.common.entity.CommunityEntity
-import com.gh.gamecenter.common.utils.SensorsBridge
-import com.gh.gamecenter.forum.detail.ForumDetailFragment.Companion.SOURCE_ENTRANCE
/**
* 选择论坛
@@ -57,13 +52,6 @@ class ChooseForumActivity : BaseActivity() {
} else {
switchUI(true)
mSearchResultFragment?.setSearchKeyAndType(searchKey, SearchType.MANUAL.value)
- SensorsBridge.trackSearchButtonClick(
- GlobalActivityManager.getCurrentPageEntity().pageId,
- GlobalActivityManager.getCurrentPageEntity().pageName,
- searchKey,
- TRACK_SEARCH_TYPE_INPUT,
- sourceEntrance
- )
}
}
binding.searchEt.setOnTouchListener { _, event ->
@@ -82,12 +70,6 @@ class ChooseForumActivity : BaseActivity() {
binding.maskView.setOnClickListener { binding.closeIv.performClick() }
binding.forumContainer.translationY = (DisplayUtils.getScreenHeight()).toFloat()
binding.forumContainer.animate().translationY(0f).setDuration(300).start()
-
- SensorsBridge.trackSearchPageShow(
- GlobalActivityManager.getCurrentPageEntity().pageId,
- GlobalActivityManager.getCurrentPageEntity().pageName,
- SOURCE_ENTRANCE
- )
}
private fun initViewPager() {
diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerFragment.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerFragment.kt
index b3a9008057..ec9195fd1f 100644
--- a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerFragment.kt
+++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerFragment.kt
@@ -1,8 +1,10 @@
package com.gh.gamecenter.qa.dialog
+import android.os.Bundle
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.NewLogUtils
@@ -18,9 +20,14 @@ import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.core.utils.HtmlUtils
import com.gh.gamecenter.entity.ForumEntity
import com.gh.gamecenter.forum.detail.ForumDetailActivity
+import com.gh.gamecenter.search.viewmodel.SearchTabViewModel
class ChooseForumContainerFragment : LazyListFragment() {
+ private val parentTabViewModel by viewModels(
+ ownerProducer = { parentFragment ?: this }
+ )
+
private var mAdapter: ChooseForumContainerAdapter? = null
private var type: String = ""
private var mSearchKey: String = ""
@@ -29,6 +36,13 @@ class ChooseForumContainerFragment : LazyListFragment
NewFlatLogUtils.logSearchBbsClick(
- mSearchType, mSearchKey, forumEntity.id, position + 1, HtmlUtils.stripHtml(forumEntity.name), button
+ mSearchType,
+ mSearchKey,
+ forumEntity.id,
+ position + 1,
+ HtmlUtils.stripHtml(forumEntity.name),
+ button,
+ mListViewModel.sourceEntrance
+ )
+
+ SensorsBridge.trackForumSearchResultClick(
+ GlobalActivityManager.getCurrentPageEntity().pageId,
+ GlobalActivityManager.getCurrentPageEntity().pageName,
+ mListViewModel.sourceEntrance,
+ mListViewModel.searchKey,
+ SearchActivity.toTrackSearchType(mSearchType),
+ forumEntity.id,
+ HtmlUtils.stripHtml(forumEntity.name),
+ forumEntity.typeChinese
)
}
) { enity, position ->
- SensorsBridge.trackSearchResultClick(
- GlobalActivityManager.getCurrentPageEntity().pageId,
- GlobalActivityManager.getCurrentPageEntity().pageName,
- mSearchKey,
- SearchActivity.toTrackSearchType(mSearchType),
- mListViewModel.sourceEntrance
- )
if (requireActivity() is ChooseForumActivity) {
(requireActivity() as ChooseForumActivity).chooseSuccess(enity)
val bbsType = if (enity.type == "game_bbs") "游戏论坛" else "综合论坛"
@@ -82,9 +106,13 @@ class ChooseForumContainerFragment : LazyListFragment
+ setSearchKeyAndType(key, type)
+ })
}
override fun onChanged(ts: MutableList?) {
diff --git a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerViewModel.kt b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerViewModel.kt
index 60962dff93..6a945834ec 100644
--- a/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerViewModel.kt
+++ b/app/src/main/java/com/gh/gamecenter/qa/dialog/ChooseForumContainerViewModel.kt
@@ -1,6 +1,5 @@
package com.gh.gamecenter.qa.dialog
-import android.annotation.SuppressLint
import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
@@ -13,7 +12,6 @@ import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.entity.ForumEntity
-import com.gh.gamecenter.forum.search.ForumOrUserSearchActivity.Companion.LOCATION_COMMUNITY
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
@@ -29,7 +27,7 @@ class ChooseForumContainerViewModel(
val type: String,
var searchKey: String,
var searchType: String,
- var sourceEntrance: String
+ var sourceEntrance: String // 神策sourceEntrance 相当火山云 location
) :
ListViewModel(application) {
@@ -47,7 +45,7 @@ class ChooseForumContainerViewModel(
override fun provideDataObservable(page: Int): Observable> {
mPage = page
if (mPage == 1 && type == ChooseForumContainerFragment.ChooseForumType.SEARCH.value) {
- NewFlatLogUtils.logSearchBbs(SearchType.fromString(searchType).toChinese(), searchKey)
+ NewFlatLogUtils.logSearchBbs(SearchType.fromString(searchType).toChinese(), searchKey, sourceEntrance)
}
return when (type) {
ChooseForumContainerFragment.ChooseForumType.ATTENTION.value -> {
@@ -74,13 +72,13 @@ class ChooseForumContainerViewModel(
mResultLiveData.addSource>(mListLiveData) {
mResultLiveData.postValue(it)
if (mPage == 1) {
- SensorsBridge.trackSearchResultReturn(
+ SensorsBridge.trackForumSearchResultReturn(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
+ sourceEntrance,
searchKey,
SearchActivity.toTrackSearchType(searchType),
- it.isNotEmpty(),
- sourceEntrance
+ it.isNotEmpty()
)
}
}
@@ -119,7 +117,13 @@ class ChooseForumContainerViewModel(
class Factory(val type: String, val searchKey: String, val searchType: String, private val sourceEntrance: String) :
ViewModelProvider.NewInstanceFactory() {
override fun create(modelClass: Class): T {
- return ChooseForumContainerViewModel(HaloApp.getInstance().application, type, searchKey, searchType, sourceEntrance) as T
+ return ChooseForumContainerViewModel(
+ HaloApp.getInstance().application,
+ type,
+ searchKey,
+ searchType,
+ sourceEntrance
+ ) as T
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
index 3890802e2e..95b5cd2408 100644
--- a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
+++ b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
@@ -3403,4 +3403,10 @@ public interface ApiService {
*/
@PATCH("app/{module}/diverter_visit_time")
Single patchDiverterVisitTime(@Path("module") String module, @Body RequestBody body);
+ /**
+ * 游戏单搜索(复用 游戏单合集-内容列表 (适用于刷新轮换) 接口实体)
+ */
+ @GET("game_lists/search")
+ Single> searchGameList(@Query("keyword") String keyword, @Query("page") int page);
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameFirstItemViewHolder.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameFirstItemViewHolder.kt
index 614cc89a4e..6771e99f0b 100644
--- a/app/src/main/java/com/gh/gamecenter/search/SearchGameFirstItemViewHolder.kt
+++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameFirstItemViewHolder.kt
@@ -11,8 +11,8 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.databind.BindingAdapters
import com.gh.common.util.DirectUtils
+import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.R
-import com.gh.gamecenter.SearchType
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.HtmlUtils
@@ -24,6 +24,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.SearchType
import com.gh.gamecenter.search.SearchGameResultAdapter.Companion.setItemCLick
import com.gh.gamecenter.search.SearchGameResultAdapter.Companion.showContentTag
import com.lzf.easyfloat.utils.DisplayUtils
@@ -51,7 +52,7 @@ class SearchGameFirstItemViewHolder(
game?.let {
val link = bannerItem.link ?: return@let
// 阿里云埋点
- com.gh.common.util.NewFlatLogUtils.logGameSearchFirstGameBannerClick(
+ NewFlatLogUtils.logGameSearchFirstGameBannerClick(
it.id,
HtmlUtils.stripHtml(it.name),
position + 1,
@@ -86,7 +87,7 @@ class SearchGameFirstItemViewHolder(
game?.let {
val link = cardItem.link ?: return@let
// 阿里云埋点
- com.gh.common.util.NewFlatLogUtils.logGameSearchFirstGameCardClick(
+ NewFlatLogUtils.logGameSearchFirstGameCardClick(
it.id,
HtmlUtils.stripHtml(it.name),
cardItem.cardName,
diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt
index eb3fd30689..e7aa2b1052 100644
--- a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt
+++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexAdapter.kt
@@ -17,11 +17,9 @@ import com.gh.common.util.LogUtils
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
-import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.SearchType
import com.gh.gamecenter.adapter.viewholder.GameViewHolder
import com.gh.gamecenter.adapter.viewholder.SearchHistoryViewHolder
-import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.ItemViewType
@@ -418,13 +416,6 @@ class SearchGameIndexAdapter(
gameEntity.adSpaceId,
gameEntity.gameAdSourceId
)
- SensorsBridge.trackSearchResultClick(
- GlobalActivityManager.getCurrentPageEntity().pageId,
- GlobalActivityManager.getCurrentPageEntity().pageName,
- key,
- SearchActivity.toTrackSearchType(type),
- sourceEntrance
- )
}
@@ -527,14 +518,6 @@ class SearchGameIndexAdapter(
gameEntity.adSpaceId,
gameEntity.gameAdSourceId
)
-
- SensorsBridge.trackSearchResultClick(
- GlobalActivityManager.getCurrentPageEntity().pageId,
- GlobalActivityManager.getCurrentPageEntity().pageName,
- key,
- SearchActivity.toTrackSearchType(type),
- sourceEntrance
- )
}
}
}
diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexItemViewHolder.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexItemViewHolder.kt
index 2c2f3c9a09..9b23e8c078 100644
--- a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexItemViewHolder.kt
+++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexItemViewHolder.kt
@@ -7,8 +7,6 @@ import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.R
-import com.gh.gamecenter.SearchActivity.Companion.toTrackSearchType
-import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.DrawableView
@@ -89,14 +87,6 @@ class SearchSubjectItemViewHolder(var binding: SearchSubjectItemBinding) : Recyc
subjectRv.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
subjectRv.adapter = SearchSubjectAdapter(context, entity.getFilterGame(), "($type-专题)") {
dao?.add(key)
- SensorsBridge.trackSearchButtonClick(
- GlobalActivityManager.getCurrentPageEntity().pageId,
- GlobalActivityManager.getCurrentPageEntity().pageName,
- key,
- toTrackSearchType(type),
- sourceEntrance
- )
-
if (itemData.adConfig != null) {
NewFlatLogUtils.logClickGameAd(
itemData.adConfig.id,
diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameListRepository.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameListRepository.kt
new file mode 100644
index 0000000000..528738737d
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameListRepository.kt
@@ -0,0 +1,20 @@
+package com.gh.gamecenter.search
+
+import com.gh.gamecenter.home.custom.model.CustomPageData
+import com.gh.gamecenter.retrofit.RetrofitManager
+import com.gh.gamecenter.retrofit.service.ApiService
+import io.reactivex.Single
+
+class SearchGameListRepository private constructor(private val newApi: ApiService) {
+
+ fun searchGameList(
+ key: String,
+ page: Int
+ ): Single> = newApi.searchGameList(key, page)
+
+ companion object {
+
+ fun newInstance() =
+ SearchGameListRepository(RetrofitManager.getInstance().newApi)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt
index 38424c001e..2462f2d509 100644
--- a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt
+++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultAdapter.kt
@@ -185,7 +185,13 @@ class SearchGameResultAdapter(
}
bottomDivider.visibility = View.VISIBLE
}
- holder.bindSubjectItem(mContext, mEntityList[position], SearchType.fromString(type).toChinese(), key, sourceEntrance = sourceEntrance)
+ holder.bindSubjectItem(
+ mContext,
+ mEntityList[position],
+ SearchType.fromString(type).toChinese(),
+ key,
+ sourceEntrance = sourceEntrance
+ )
}
is SearchGameFirstItemViewHolder -> {
@@ -688,6 +694,16 @@ class SearchGameResultAdapter(
}
if (gameEntity.isMiniGame()) {
+ SensorsBridge.trackMiniGameSearchResultClick(
+ GlobalActivityManager.getCurrentPageEntity().pageId,
+ GlobalActivityManager.getCurrentPageEntity().pageName,
+ sourceEntrance,
+ key,
+ SearchActivity.toTrackSearchType(type),
+ gameEntity.id,
+ gameEntity.name ?: "",
+ gameEntity.categoryChinese
+ )
MiniGameItemHelper.launchMiniGame(gameEntity.miniGameAppId, gameEntity.miniGameType)
MiniGameItemHelper.trackMiniGameClick(
gameEntity = gameEntity,
@@ -695,6 +711,16 @@ class SearchGameResultAdapter(
searchContent = key,
)
} else {
+ SensorsBridge.trackGameSearchResultClick(
+ GlobalActivityManager.getCurrentPageEntity().pageId,
+ GlobalActivityManager.getCurrentPageEntity().pageName,
+ sourceEntrance,
+ key,
+ SearchActivity.toTrackSearchType(type),
+ gameEntity.id,
+ gameEntity.name ?: "",
+ gameEntity.categoryChinese
+ )
GameDetailActivity.startGameDetailActivity(
context, gameEntity,
StringUtils.buildString(
@@ -730,14 +756,6 @@ class SearchGameResultAdapter(
gameEntity.name ?: ""
)
}
-
- SensorsBridge.trackSearchResultClick(
- GlobalActivityManager.getCurrentPageEntity().pageId,
- GlobalActivityManager.getCurrentPageEntity().pageName,
- key,
- SearchActivity.toTrackSearchType(type),
- sourceEntrance
- )
}
diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultFragment.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultFragment.kt
index 1f06f17227..f5f02dbdd8 100644
--- a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultFragment.kt
+++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultFragment.kt
@@ -11,6 +11,8 @@ import android.view.animation.Animation
import android.view.animation.TranslateAnimation
import android.widget.TextView
import androidx.core.content.ContextCompat
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.Observer
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.exposure.ExposureListener
import com.gh.common.util.*
@@ -18,8 +20,6 @@ import com.gh.common.xapk.XapkInstaller
import com.gh.common.xapk.XapkUnzipStatus
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
-import com.gh.gamecenter.SearchActivity
-import com.gh.gamecenter.SearchType
import com.gh.gamecenter.common.baselist.ListFragment
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.constant.EntranceConsts
@@ -33,6 +33,9 @@ import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.help.HelpAndFeedbackBridge
+import com.gh.gamecenter.SearchActivity
+import com.gh.gamecenter.SearchType
+import com.gh.gamecenter.search.viewmodel.SearchTabViewModel
import com.halo.assistant.HaloApp
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
@@ -42,6 +45,10 @@ import org.greenrobot.eventbus.ThreadMode
open class SearchGameResultFragment : ListFragment() {
+ private val parentTabViewModel by viewModels(
+ ownerProducer = { parentFragment ?: this }
+ )
+
private var mAdapter: SearchGameResultAdapter? = null
private var mExposureListener: ExposureListener? = null
private lateinit var mShowAction: Animation
@@ -53,6 +60,7 @@ open class SearchGameResultFragment : ListFragment
+ setParams(key, type)
+ }
}
private fun handleCloseMenuVisibility(recyclerView: RecyclerView) {
@@ -251,6 +267,7 @@ open class SearchGameResultFragment : ListFragment
mGameEntityList = ArrayList(list)
@@ -295,14 +300,27 @@ class SearchGameResultViewModel(
private fun postResultList(resultList: ArrayList, list: List) {
mResultLiveData.postValue(resultList)
if (mPage == 1) {
- SensorsBridge.trackSearchResultReturn(
- GlobalActivityManager.getCurrentPageEntity().pageId,
- GlobalActivityManager.getCurrentPageEntity().pageName,
- mSearchKey ?: "",
- SearchActivity.toTrackSearchType(mSearchType),
- list.isNotEmpty(),
- sourceEntrance
- )
+ if (repository is MiniGameSearchResultRepository) {
+ SensorsBridge.trackMiniGameSearchResultReturn(
+ GlobalActivityManager.getCurrentPageEntity().pageId,
+ GlobalActivityManager.getCurrentPageEntity().pageName,
+ sourceEntrance,
+ mSearchKey ?: "",
+ SearchActivity.toTrackSearchType(mSearchType),
+ list.isNotEmpty()
+ )
+ } else {
+ SensorsBridge.trackGameSearchResultReturn(
+ GlobalActivityManager.getCurrentPageEntity().pageId,
+ GlobalActivityManager.getCurrentPageEntity().pageName,
+ sourceEntrance,
+ mSearchKey ?: "",
+ SearchActivity.toTrackSearchType(mSearchType),
+ list.isNotEmpty()
+
+ )
+ }
+
}
}
@@ -355,7 +373,14 @@ class SearchGameResultViewModel(
private val mSourceEntrance: String
) : ViewModelProvider.NewInstanceFactory() {
override fun create(modelClass: Class): T {
- return SearchGameResultViewModel(mApplication, mSearchKey, mIsManuallySearch, repository, mSearchType, mSourceEntrance) as T
+ return SearchGameResultViewModel(
+ mApplication,
+ mSearchKey,
+ mIsManuallySearch,
+ repository,
+ mSearchType,
+ mSourceEntrance
+ ) as T
}
}
diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchTabActivity.kt b/app/src/main/java/com/gh/gamecenter/search/SearchTabActivity.kt
new file mode 100644
index 0000000000..8e2e31b3d8
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/SearchTabActivity.kt
@@ -0,0 +1,39 @@
+package com.gh.gamecenter.search
+
+import android.os.Bundle
+import androidx.activity.viewModels
+import com.gh.gamecenter.DisplayType
+import com.gh.gamecenter.R
+import com.gh.gamecenter.SearchActivity
+import com.gh.gamecenter.search.fragment.SearchTabFragment
+import com.gh.gamecenter.search.viewmodel.SearchTabActivityViewModel
+
+class SearchTabActivity : SearchActivity() {
+
+ private val viewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ viewModel.loadTabs()
+ }
+
+ override fun updateDisplayType(type: DisplayType) {
+ viewModel.updateSearchKeyAndType(mSearchKey, mSearchType.value)
+ val lastDisplayType = mDisplayType
+ mDisplayType = type
+ // 如果上一次展示的是SearchTabFragment,并且当前需要展示的也是SearchTabFragment,则无需重复显示
+ if (lastDisplayType != DisplayType.DEFAULT && type != DisplayType.DEFAULT) {
+ return
+ }
+
+ if (type == DisplayType.DEFAULT) {
+ super.updateDisplayType(type)
+ } else {
+ val transaction = supportFragmentManager.beginTransaction()
+ val fragment = supportFragmentManager.findFragmentByTag(SearchTabFragment::class.java.name)
+ ?: SearchTabFragment.newInstance(mSourceEntrance)
+ transaction.replace(R.id.search_result, fragment)
+ transaction.commitAllowingStateLoss()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchTabRepository.kt b/app/src/main/java/com/gh/gamecenter/search/SearchTabRepository.kt
new file mode 100644
index 0000000000..56f164cb58
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/SearchTabRepository.kt
@@ -0,0 +1,15 @@
+package com.gh.gamecenter.search
+
+import com.gh.common.constant.Config
+import com.gh.gamecenter.feature.entity.SettingsEntity
+
+class SearchTabRepository private constructor() {
+
+ fun getSearchTabs(): List =
+ Config.getNewApiSettingsEntity()?.search?.navigations ?: emptyList()
+
+ companion object {
+
+ fun newInstance() = SearchTabRepository()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/adapter/SearchGameListAdapter.kt b/app/src/main/java/com/gh/gamecenter/search/adapter/SearchGameListAdapter.kt
new file mode 100644
index 0000000000..5344271a75
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/adapter/SearchGameListAdapter.kt
@@ -0,0 +1,145 @@
+package com.gh.gamecenter.search.adapter
+
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import com.gh.gamecenter.common.baselist.LoadStatus
+import com.gh.gamecenter.common.utils.toBinding
+import com.gh.gamecenter.home.custom.model.CustomPageData
+import com.gh.gamecenter.search.viewholder.SearchGameListFooterViewHolder
+import com.gh.gamecenter.search.viewholder.SearchGameListViewHolder
+import com.gh.gamecenter.search.viewmodel.SearchGameListViewModel
+
+class SearchGameListAdapter(
+ private val viewModel: SearchGameListViewModel
+) : ListAdapter(
+ createDiffUtil()
+) {
+
+ private var _recyclerView: RecyclerView? = null
+
+ private var _loadStatus = LoadStatus.INIT
+
+ fun updateStatus(loadStatus: LoadStatus) {
+ _loadStatus = loadStatus
+ if (itemCount > 0) {
+ _recyclerView?.post {
+ notifyItemChanged(itemCount - 1)
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return if (viewType == ITEM_TYPE_CONTENT) {
+ SearchGameListViewHolder(parent.toBinding(), object : SearchGameListViewHolder.SearchGameListListener {
+
+ override fun navigateToGameDetailPage(
+ gameId: String,
+ collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity
+ ) {
+ viewModel.navigateToGameDetailPage(gameId, collection)
+ }
+
+ override fun navigateToHomePage(
+ userId: String,
+ collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity
+ ) {
+ viewModel.navigateToHomePage(userId, collection)
+ }
+
+ override fun navigateGameCollectionDetailPage(collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity) {
+ viewModel.navigateGameCollectionDetailPage(collection)
+ }
+
+ })
+ } else {
+ SearchGameListFooterViewHolder(parent.toBinding(), object : SearchGameListFooterViewHolder.FooterListener {
+ override fun loadMore() {
+ viewModel.onLoadMore()
+ }
+
+ override fun retry() {
+ viewModel.retry()
+ }
+
+ override fun toTop() {
+ _recyclerView?.scrollToPosition(0)
+ }
+
+ })
+ }
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ when (holder) {
+ is SearchGameListViewHolder -> {
+ holder.bind(getItem(position))
+ }
+
+ is SearchGameListFooterViewHolder -> {
+ holder.bind(_loadStatus)
+ }
+ }
+ }
+
+
+ override fun getItemCount(): Int {
+ val dataCount = super.getItemCount()
+
+ return if (dataCount > 0) {
+ dataCount + 1
+ } else {
+ 0
+ }
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return if (position < itemCount - 1) {
+ ITEM_TYPE_CONTENT
+ } else {
+ ITEM_TYPE_FOOTER
+ }
+ }
+
+ override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
+ _recyclerView = recyclerView
+ }
+
+ override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
+ _recyclerView = null
+ }
+
+ companion object {
+
+ private const val ITEM_TYPE_CONTENT = 0
+ private const val ITEM_TYPE_FOOTER = 1
+
+ fun createDiffUtil() =
+ object : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(
+ oldItem: CustomPageData.LinkColumnCollection.CustomSubjectEntity,
+ newItem: CustomPageData.LinkColumnCollection.CustomSubjectEntity
+ ): Boolean {
+ return oldItem.id == newItem.id
+ }
+
+ override fun areContentsTheSame(
+ oldItem: CustomPageData.LinkColumnCollection.CustomSubjectEntity,
+ newItem: CustomPageData.LinkColumnCollection.CustomSubjectEntity
+ ): Boolean {
+ return oldItem.id == newItem.id
+ && oldItem.user == newItem.user
+ && oldItem.count == newItem.count
+ && oldItem.games.size == newItem.games.size
+ && oldItem.adIconActive == newItem.adIconActive
+ && oldItem.intro == newItem.intro
+ && oldItem.title == newItem.title
+ && oldItem.image == newItem.image
+ && oldItem.tags.size == newItem.tags.size
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/adapter/SearchTabAdapter.kt b/app/src/main/java/com/gh/gamecenter/search/adapter/SearchTabAdapter.kt
new file mode 100644
index 0000000000..7198c3c6ea
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/adapter/SearchTabAdapter.kt
@@ -0,0 +1,72 @@
+package com.gh.gamecenter.search.adapter
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import androidx.viewpager2.adapter.FragmentStateAdapter
+import com.gh.gamecenter.SearchActivity
+import com.gh.gamecenter.common.constant.EntranceConsts
+import com.gh.gamecenter.feature.entity.SettingsEntity
+import com.gh.gamecenter.feedback.view.qa.HelpContentFragment
+import com.gh.gamecenter.forum.search.ForumContentSearchListFragment
+import com.gh.gamecenter.forum.search.UserSearchListFragment
+import com.gh.gamecenter.minigame.MiniGameSearchResultFragment
+import com.gh.gamecenter.qa.dialog.ChooseForumContainerFragment
+import com.gh.gamecenter.search.SearchGameResultFragment
+import com.gh.gamecenter.search.fragment.SearchGameListFragment
+
+class SearchTabAdapter(
+ private val location: String,
+ private val searchType: String?,
+ private val tabs: List,
+ private val fragment: Fragment
+) : FragmentStateAdapter(fragment) {
+
+ override fun getItemCount() = tabs.size
+
+ override fun createFragment(position: Int): Fragment {
+ val navigation = tabs[position]
+ val bundle = Bundle().apply {
+ putBoolean(EntranceConsts.KEY_IS_AUTO_LOAD, false)
+ putString(EntranceConsts.KEY_LOCATION, location)
+ }
+ val fragment = when (navigation.type) {
+ SEARCH_TYPE_GAME -> SearchGameResultFragment()
+
+ SEARCH_TYPE_BBS -> ChooseForumContainerFragment.getInstance(ChooseForumContainerFragment.ChooseForumType.SEARCH)
+
+ SEARCH_TYPE_BBS_CONTENT -> ForumContentSearchListFragment()
+
+ SEARCH_TYPE_USER -> UserSearchListFragment()
+
+ SEARCH_TYPE_MINI_GAME -> MiniGameSearchResultFragment()
+
+ SEARCH_TYPE_QA -> HelpContentFragment().apply {
+ arguments = Bundle().apply {
+ putString(EntranceConsts.KEY_SEARCH_TYPE, SearchActivity.toTrackSearchType(searchType ?: ""))
+ }
+ }
+
+ SEARCH_TYPE_GAME_LIST -> SearchGameListFragment()
+
+ else -> SearchGameResultFragment()
+ }.also {
+ if (it.arguments != null) {
+ it.arguments?.putAll(bundle)
+ } else {
+ it.arguments = bundle
+ }
+
+ }
+ return fragment
+ }
+
+ companion object {
+ private const val SEARCH_TYPE_GAME = "game"
+ private const val SEARCH_TYPE_BBS = "bbs"
+ private const val SEARCH_TYPE_BBS_CONTENT = "bbs_content"
+ private const val SEARCH_TYPE_USER = "user"
+ private const val SEARCH_TYPE_QA = "qa"
+ private const val SEARCH_TYPE_MINI_GAME = "mini_game"
+ private const val SEARCH_TYPE_GAME_LIST = "game_list"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/fragment/SearchGameListFragment.kt b/app/src/main/java/com/gh/gamecenter/search/fragment/SearchGameListFragment.kt
new file mode 100644
index 0000000000..a07c5fcb1c
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/fragment/SearchGameListFragment.kt
@@ -0,0 +1,118 @@
+package com.gh.gamecenter.search.fragment
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.view.View
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.Observer
+import com.gh.common.util.DirectUtils
+import com.gh.gamecenter.GameDetailActivity
+import com.gh.gamecenter.R
+import com.gh.gamecenter.common.base.activity.BaseActivity
+import com.gh.gamecenter.common.base.fragment.LazyFragment
+import com.gh.gamecenter.common.baselist.LoadStatus
+import com.gh.gamecenter.common.constant.EntranceConsts
+import com.gh.gamecenter.common.utils.goneIf
+import com.gh.gamecenter.common.view.FixLinearLayoutManager
+import com.gh.gamecenter.databinding.FragmentSearchGameListBinding
+import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
+import com.gh.gamecenter.livedata.EventObserver
+import com.gh.gamecenter.search.adapter.SearchGameListAdapter
+import com.gh.gamecenter.search.viewmodel.SearchGameListViewModel
+import com.gh.gamecenter.search.viewmodel.SearchTabViewModel
+
+class SearchGameListFragment : LazyFragment() {
+
+ private val viewModel by viewModels()
+
+ private val parentViewModel by viewModels(
+ ownerProducer = { parentFragment ?: this }
+ )
+
+ private var searchKey = ""
+ private var location: String = ""
+
+ private lateinit var binding: FragmentSearchGameListBinding
+
+ private val adapter by lazy(LazyThreadSafetyMode.NONE) {
+ SearchGameListAdapter(viewModel)
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ searchKey = arguments?.getString(EntranceConsts.KEY_SEARCHKEY, "") ?: ""
+ location = arguments?.getString(EntranceConsts.KEY_LOCATION, "") ?: ""
+ super.onCreate(savedInstanceState)
+ }
+
+
+ override fun getRealLayoutId(): Int = R.layout.fragment_search_game_list
+
+ override fun onRealLayoutInflated(inflatedView: View) {
+ binding = FragmentSearchGameListBinding.bind(inflatedView)
+ }
+
+ @SuppressLint("NotifyDataSetChanged")
+ override fun initRealView() {
+ super.initRealView()
+ parentViewModel.searchKeyAndType.observe(viewLifecycleOwner, Observer { (key, type) ->
+ // 清空上一次的搜索结果
+ adapter.submitList(null)
+ // 上面调用了 adapter.submitList(null) ,这里为什么还要调用 notifyDataSetChanged 呢?
+ // 因为adapter.submitList(null)最终调用的adapter.notifyItemRangeRemoved()方法更新RecyclerView
+ // 此方法不会立马清空RecyclerView 的内容,而是在postOnAnimation执行相关的移除工作,这里为了让RecyclerView的内容立马清空,需要再次调用adapter.notifyDataSetChanged()
+ adapter.notifyDataSetChanged()
+ viewModel.loadFirstData(key, type, location)
+ })
+ binding.rvGameList.layoutManager = FixLinearLayoutManager(context)
+ binding.rvGameList.adapter = adapter
+
+ binding.reuseNoData.reuseResetLoadTv.setOnClickListener {
+ viewModel.retry()
+ }
+ binding.reuseNoConnection.connectionReloadTv.setOnClickListener {
+ viewModel.retry()
+ }
+ with(viewModel) {
+ loadStatus.observe(viewLifecycleOwner) {
+ binding.rvGameList.goneIf(it == LoadStatus.INIT_LOADING || it == LoadStatus.INIT_FAILED || it == LoadStatus.INIT_EMPTY)
+ binding.reuseNoConnection.root.goneIf(it != LoadStatus.INIT_FAILED)
+ binding.reuseLoading.root.goneIf(it != LoadStatus.INIT_LOADING)
+ binding.reuseNoData.root.goneIf(it != LoadStatus.INIT_EMPTY)
+ adapter.updateStatus(it)
+ }
+
+ dataList.observe(viewLifecycleOwner, Observer {
+ adapter.submitList(it)
+ })
+
+ gameDetailDestination.observe(viewLifecycleOwner, EventObserver {
+ GameDetailActivity.startGameDetailActivity(
+ requireContext(),
+ it,
+ BaseActivity.mergeEntranceAndPath(location, "游戏单搜索"),
+ null
+ )
+ })
+
+ homeDestination.observe(viewLifecycleOwner, EventObserver {
+ DirectUtils.directToHomeActivity(
+ requireContext(),
+ it,
+ 0,
+ location,
+ "游戏单搜索"
+ )
+ })
+
+ gameCollectionDetailDestination.observe(viewLifecycleOwner, EventObserver {
+ startActivity(
+ GameCollectionDetailActivity.getIntent(
+ requireContext(),
+ it,
+ isFromSquare = false,
+ )
+ )
+ })
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/fragment/SearchTabFragment.kt b/app/src/main/java/com/gh/gamecenter/search/fragment/SearchTabFragment.kt
new file mode 100644
index 0000000000..73763e8a3a
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/fragment/SearchTabFragment.kt
@@ -0,0 +1,138 @@
+package com.gh.gamecenter.search.fragment
+
+import android.graphics.Color
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import androidx.fragment.app.activityViewModels
+import androidx.fragment.app.viewModels
+import com.gh.gamecenter.R
+import com.gh.gamecenter.common.base.fragment.BaseFragment
+import com.gh.gamecenter.common.constant.EntranceConsts
+import com.gh.gamecenter.common.utils.goneIf
+import com.gh.gamecenter.databinding.FragmentSearchTabBinding
+import com.gh.gamecenter.feature.entity.SettingsEntity
+import com.gh.gamecenter.search.SearchGameResultFragment
+import com.gh.gamecenter.search.adapter.SearchTabAdapter
+import com.gh.gamecenter.search.viewmodel.SearchTabActivityViewModel
+import com.gh.gamecenter.search.viewmodel.SearchTabViewModel
+import com.google.android.material.tabs.TabLayout
+import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
+import com.google.android.material.tabs.TabLayoutMediator
+
+class SearchTabFragment : BaseFragment() {
+
+ private lateinit var binding: FragmentSearchTabBinding
+
+ private val activityViewModel by activityViewModels()
+
+ private val viewModel by viewModels()
+
+ private lateinit var adapter: SearchTabAdapter
+
+ private var location = ""
+
+ private var _key: String? = null
+ private var _searchType: String? = null
+
+ override fun getLayoutId(): Int = 0
+
+ override fun getInflatedLayout() =
+ FragmentSearchTabBinding.inflate(LayoutInflater.from(context))
+ .also {
+ binding = it
+ }.root
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ location = arguments?.getString(EntranceConsts.KEY_LOCATION) ?: ""
+ with(activityViewModel) {
+ searchKeyAndType.observe(this@SearchTabFragment) { (key, type) ->
+ if (key != null) {
+ _key = key
+ _searchType = type
+ viewModel.updateSearchKeyAndType(key, type)
+ }
+ }
+
+
+ }
+ }
+
+ override fun initView(view: View?) {
+ super.initView(view)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ with(activityViewModel) {
+ tabs.observe(viewLifecycleOwner) {
+ if (it.size > 1) {
+ initTabs(it)
+ } else {
+ initSingleFragment()
+ }
+ }
+
+ }
+ }
+
+ private fun initTabs(tabs: List) {
+ binding.gTabs.goneIf(false)
+ binding.flContainer.goneIf(true)
+
+ binding.tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener {
+ override fun onTabSelected(tab: TabLayout.Tab) {
+ viewModel.trackGameSearchPageTabClick(location, tab.text?.toString(), tab.position)
+ }
+
+ override fun onTabUnselected(tab: TabLayout.Tab?) {
+
+ }
+
+ override fun onTabReselected(tab: TabLayout.Tab?) {
+
+ }
+
+ })
+
+ if (tabs.size > 5) {
+ binding.tabLayout.tabMode = TabLayout.MODE_SCROLLABLE
+ } else {
+ binding.tabLayout.tabMode = TabLayout.MODE_FIXED
+ }
+ adapter = SearchTabAdapter(location, _searchType, tabs, this)
+ binding.viewPager.adapter = adapter
+ TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
+ tab.text = tabs[position].title
+ tab.customView?.setBackgroundColor(Color.RED)
+ }.attach()
+ }
+
+ private fun initSingleFragment() {
+ binding.gTabs.goneIf(true)
+ binding.flContainer.goneIf(false)
+ val transaction = childFragmentManager.beginTransaction()
+ val fragment = childFragmentManager.findFragmentByTag(SearchGameResultFragment::class.java.name)
+ ?: SearchGameResultFragment().apply {
+ arguments = Bundle().apply {
+ putBoolean(EntranceConsts.KEY_IS_AUTO_LOAD, false)
+ }
+ }
+ transaction.replace(R.id.fl_container, fragment, SearchGameResultFragment::class.java.name)
+ transaction.commitAllowingStateLoss()
+
+ }
+
+ companion object {
+
+ fun newInstance(location: String) =
+ SearchTabFragment().apply {
+ arguments = Bundle().apply {
+ putString(EntranceConsts.KEY_LOCATION, location)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/viewholder/SearchGameListFooterViewHolder.kt b/app/src/main/java/com/gh/gamecenter/search/viewholder/SearchGameListFooterViewHolder.kt
new file mode 100644
index 0000000000..a593e69016
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/viewholder/SearchGameListFooterViewHolder.kt
@@ -0,0 +1,60 @@
+package com.gh.gamecenter.search.viewholder
+
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import com.gh.gamecenter.common.R
+import com.gh.gamecenter.common.baselist.LoadStatus
+import com.gh.gamecenter.common.databinding.RefreshFooterviewBinding
+import com.gh.gamecenter.common.utils.goneIf
+
+class SearchGameListFooterViewHolder(
+ val binding: RefreshFooterviewBinding,
+ private val listener: FooterListener
+) : ViewHolder(binding.root) {
+
+ private var _loadStatus = LoadStatus.INIT
+
+ fun bind(loadStatus: LoadStatus) {
+ if (_loadStatus == loadStatus) return
+ _loadStatus = loadStatus
+ when (loadStatus) {
+ LoadStatus.LIST_LOADING -> {
+ binding.footerviewLoading.goneIf(false)
+ binding.footerviewHint.goneIf(false)
+ binding.footerviewHint.setText(R.string.loading)
+ }
+
+ LoadStatus.LIST_FAILED -> {
+ binding.footerviewLoading.goneIf(true)
+ binding.footerviewHint.goneIf(false)
+ binding.footerviewHint.setText(R.string.loading_failed_retry)
+ }
+
+ LoadStatus.LIST_OVER -> {
+ binding.footerviewLoading.goneIf(true)
+ binding.footerviewHint.goneIf(false)
+ binding.footerviewHint.setText(R.string.load_over_hint)
+ }
+
+ LoadStatus.LIST_LOADED, LoadStatus.INIT_LOADED -> listener.loadMore()
+
+ else -> Unit
+ }
+ itemView.setOnClickListener {
+ when (loadStatus) {
+ LoadStatus.LIST_FAILED -> listener.retry()
+ LoadStatus.LIST_OVER -> listener.toTop()
+
+ else -> Unit
+ }
+ }
+ }
+
+ interface FooterListener {
+
+ fun loadMore()
+
+ fun retry()
+
+ fun toTop()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/viewholder/SearchGameListViewHolder.kt b/app/src/main/java/com/gh/gamecenter/search/viewholder/SearchGameListViewHolder.kt
new file mode 100644
index 0000000000..0ecb918814
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/viewholder/SearchGameListViewHolder.kt
@@ -0,0 +1,119 @@
+package com.gh.gamecenter.search.viewholder
+
+import android.content.Context
+import android.graphics.Color
+import android.view.View
+import android.view.ViewGroup
+import android.view.ViewGroup.MarginLayoutParams
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.core.view.updateLayoutParams
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import com.gh.common.util.CheckLoginUtils
+import com.gh.gamecenter.R
+import com.gh.gamecenter.common.utils.*
+import com.gh.gamecenter.databinding.GameCollectionSquareItemBinding
+import com.gh.gamecenter.home.custom.model.CustomPageData
+
+class SearchGameListViewHolder(
+ val binding: GameCollectionSquareItemBinding,
+ private val listener: SearchGameListListener
+) : ViewHolder(binding.root) {
+
+ private val context: Context
+ get() = binding.root.context
+
+ private val posterWidth by lazy(LazyThreadSafetyMode.NONE) {
+ context.resources.displayMetrics.widthPixels - 32F.dip2px()
+ }
+
+ fun bind(item: CustomPageData.LinkColumnCollection.CustomSubjectEntity) {
+ with(binding) {
+
+ root.updateLayoutParams {
+ if (this is MarginLayoutParams) {
+ topMargin = 16F.dip2px()
+ }
+ }
+ poster.setTag(ImageUtils.TAG_TARGET_WIDTH, posterWidth)
+ ImageUtils.display(poster, item.image)
+ ImageUtils.display(userIv, item.user.icon)
+ titleTv.text = item.title.fromHtml()
+ item.games.take(3).forEachIndexed { index, game ->
+ when (index) {
+ 0 -> iconIvOne.displayGameIcon(game)
+ 1 -> iconIvTwo.displayGameIcon(game)
+ 2 -> iconIvThree.displayGameIcon(game)
+ }
+ }
+ item.games.size.let {
+ iconIvOne.goneIf(it == 0)
+ iconIvTwo.goneIf(it < 2)
+ iconIvThree.goneIf(it < 3)
+ }
+
+ countTv.goneIf(item.count.game < 4 || item.games.isEmpty())
+ countTv.text = "+ ${item.count.game - 3}"
+ hotTv.text = if (item.count.hot > 10000) "10000+" else item.count.hot.toString()
+
+ userTv.text = item.user.name
+ playedGameProgress.max = item.count.game
+ playedGameProgress.progress = item.count.gamePlayed ?: 0
+ playedGameTv.text =
+ "玩过 ${item.count.gamePlayed} / ${item.count.game} 款"
+ stampIv.goneIf(item.stamp.isEmpty())
+ stampIv.setBackgroundResource(if (item.stamp == "official") R.drawable.ic_official else R.drawable.ic_chosen)
+
+ tagContainer.removeAllViews()
+ tagContainer.visibleIf(!CheckLoginUtils.isLogin() || item.count.game == 0) {
+ item.tags.forEachIndexed { index, tag ->
+ // 添加分隔线
+ if (index != 0) tagContainer.addView(View(context).apply {
+ layoutParams = ViewGroup.LayoutParams(1F.dip2px(), 14F.dip2px())
+ setBackgroundColor(Color.parseColor("#33FFFFFF"))
+ })
+ // 添加标签
+ tagContainer.addView(TextView(context).apply {
+ layoutParams = LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ )
+ setPadding(if (index == 0) 0 else 6F.dip2px(), 0, 6F.dip2px(), 0)
+ text = tag.name
+ setTextColor(R.color.white.toColor())
+ textSize = 10F
+ })
+ }
+ }
+ playedGamesContainer.visibleIf(CheckLoginUtils.isLogin() && item.count.game != 0)
+ adLabelTv.goneIf(!item.adIconActive)
+ arrayOf(iconIvOne, iconIvTwo, iconIvThree).forEachIndexed { index, ivIcon ->
+ ivIcon.setOnClickListener {
+ val game = item.games.getOrNull(index)
+ game?.id?.let { gameId ->
+ listener.navigateToGameDetailPage(gameId, item)
+ }
+ }
+ }
+
+ userContainer.setOnClickListener {
+ listener.navigateToHomePage(item.user.id, item)
+ }
+ root.setOnClickListener {
+ listener.navigateGameCollectionDetailPage(item)
+ }
+ }
+ }
+
+ interface SearchGameListListener {
+
+ fun navigateToGameDetailPage(
+ gameId: String,
+ collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity
+ )
+
+ fun navigateToHomePage(userId: String, collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity)
+
+ fun navigateGameCollectionDetailPage(collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/viewmodel/SearchGameListViewModel.kt b/app/src/main/java/com/gh/gamecenter/search/viewmodel/SearchGameListViewModel.kt
new file mode 100644
index 0000000000..b6f6d155ef
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/viewmodel/SearchGameListViewModel.kt
@@ -0,0 +1,141 @@
+package com.gh.gamecenter.search.viewmodel
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.gh.gamecenter.SearchActivity
+import com.gh.gamecenter.common.base.GlobalActivityManager
+import com.gh.gamecenter.common.baselist.LoadStatus
+import com.gh.gamecenter.common.retrofit.BiResponse
+import com.gh.gamecenter.common.utils.SensorsBridge
+import com.gh.gamecenter.common.utils.singleToMain
+import com.gh.gamecenter.home.custom.model.CustomPageData
+import com.gh.gamecenter.livedata.Event
+import com.gh.gamecenter.search.SearchGameListRepository
+import io.reactivex.disposables.CompositeDisposable
+
+class SearchGameListViewModel : ViewModel() {
+
+ private val repository = SearchGameListRepository.newInstance()
+
+ private val compositeDisposable = CompositeDisposable()
+
+ private var page = 1
+
+ private var key = ""
+ private var type = ""
+ private var location = ""
+
+ private val _loadStatus = MutableLiveData()
+ val loadStatus: LiveData = _loadStatus
+
+ private val _dataList = MutableLiveData?>()
+ val dataList: LiveData?> = _dataList
+
+ fun loadFirstData(key: String, type: String, location: String) {
+ this.key = key
+ this.type = type
+ this.location = location
+ page = 1
+ _loadStatus.value = LoadStatus.INIT_LOADING
+ searchGameList()
+ }
+
+ fun onLoadMore() {
+ page++
+ _loadStatus.value = LoadStatus.LIST_LOADING
+ searchGameList()
+ }
+
+ fun retry() {
+ _loadStatus.value = if (page == 1) {
+ LoadStatus.INIT_LOADING
+ } else {
+ LoadStatus.LIST_LOADED
+ }
+ searchGameList()
+ }
+
+ private fun searchGameList() {
+ repository.searchGameList(key, page)
+ .compose(singleToMain())
+ .subscribe(object : BiResponse>() {
+ override fun onSuccess(data: List) {
+ if (page == 1) {
+ _dataList.value = data
+ _loadStatus.value = if (data.isEmpty()) {
+ LoadStatus.INIT_EMPTY
+ } else {
+ LoadStatus.INIT_LOADED
+ }
+ SensorsBridge.trackGameCollectSearchResultReturn(
+ GlobalActivityManager.getCurrentPageEntity().pageId,
+ GlobalActivityManager.getCurrentPageEntity().pageName,
+ location,
+ key,
+ SearchActivity.toTrackSearchType(type),
+ data.isNotEmpty()
+ )
+ } else {
+ addData(data)
+ _loadStatus.value = if (data.isEmpty()) {
+ LoadStatus.LIST_OVER
+ } else {
+ LoadStatus.LIST_LOADED
+ }
+ }
+
+ }
+
+ override fun onFailure(exception: Exception) {
+ _loadStatus.value = if (page == 1) {
+ LoadStatus.INIT_FAILED
+ } else {
+ LoadStatus.LIST_FAILED
+ }
+ }
+ }).let(compositeDisposable::add)
+ }
+
+ private fun addData(newData: List) {
+ val oldData = dataList.value
+ _dataList.value = if (oldData == null) {
+ newData
+ } else {
+ oldData + newData
+ }
+ }
+
+ private val _gameDetailDestination = MutableLiveData>()
+ val gameDetailDestination: LiveData> = _gameDetailDestination
+ fun navigateToGameDetailPage(gameId: String, collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity) {
+ trackGameCollectSearchResultClick(collection)
+ _gameDetailDestination.value = Event(gameId)
+ }
+
+ private val _homeDestination = MutableLiveData>()
+ val homeDestination: LiveData> = _homeDestination
+ fun navigateToHomePage(userId: String, collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity) {
+ trackGameCollectSearchResultClick(collection)
+ _homeDestination.value = Event(userId)
+ }
+
+ private val _gameCollectionDetailDestination = MutableLiveData>()
+ val gameCollectionDetailDestination: LiveData> = _gameCollectionDetailDestination
+ fun navigateGameCollectionDetailPage(collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity) {
+ trackGameCollectSearchResultClick(collection)
+ _gameCollectionDetailDestination.value = Event(collection.id)
+ }
+
+ private fun trackGameCollectSearchResultClick(collection: CustomPageData.LinkColumnCollection.CustomSubjectEntity) {
+ SensorsBridge.trackGameCollectSearchResultClick(
+ GlobalActivityManager.getCurrentPageEntity().pageId,
+ GlobalActivityManager.getCurrentPageEntity().pageName,
+ key,
+ SearchActivity.toTrackSearchType(type),
+ location,
+ collection.id,
+ collection.title
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/viewmodel/SearchTabActivityViewModel.kt b/app/src/main/java/com/gh/gamecenter/search/viewmodel/SearchTabActivityViewModel.kt
new file mode 100644
index 0000000000..83ab4853ef
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/viewmodel/SearchTabActivityViewModel.kt
@@ -0,0 +1,26 @@
+package com.gh.gamecenter.search.viewmodel
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.gh.gamecenter.feature.entity.SettingsEntity
+import com.gh.gamecenter.search.SearchTabRepository
+
+class SearchTabActivityViewModel : ViewModel() {
+
+ private val repository = SearchTabRepository.newInstance()
+
+ private val _searchKeyAndType = MutableLiveData>()
+ val searchKeyAndType: LiveData> = _searchKeyAndType
+
+ fun updateSearchKeyAndType(key: String?, type: String) {
+ _searchKeyAndType.value = key to type
+ }
+
+ private val _tabs = MutableLiveData>()
+ val tabs: LiveData> = _tabs
+
+ fun loadTabs() {
+ _tabs.value = repository.getSearchTabs()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/search/viewmodel/SearchTabViewModel.kt b/app/src/main/java/com/gh/gamecenter/search/viewmodel/SearchTabViewModel.kt
new file mode 100644
index 0000000000..5d4965aa12
--- /dev/null
+++ b/app/src/main/java/com/gh/gamecenter/search/viewmodel/SearchTabViewModel.kt
@@ -0,0 +1,29 @@
+package com.gh.gamecenter.search.viewmodel
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.gh.gamecenter.common.base.GlobalActivityManager
+import com.gh.gamecenter.common.utils.SensorsBridge
+import io.reactivex.disposables.CompositeDisposable
+
+class SearchTabViewModel : ViewModel() {
+
+ private val _searchKeyAndType = MutableLiveData>()
+ val searchKeyAndType: LiveData> = _searchKeyAndType
+ fun updateSearchKeyAndType(key: String, type: String) {
+ _searchKeyAndType.value = key to type
+ }
+
+ fun trackGameSearchPageTabClick(location: String, text: String?, position: Int) {
+ SensorsBridge.trackGameSearchPageTabClick(
+ GlobalActivityManager.getCurrentPageEntity().pageId,
+ GlobalActivityManager.getCurrentPageEntity().pageName,
+ location,
+ searchKeyAndType.value?.first ?: "",
+ searchKeyAndType.value?.second ?: "",
+ text ?: "",
+ position
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/gamecenter/vote/VoteViewModel.kt b/app/src/main/java/com/gh/gamecenter/vote/VoteViewModel.kt
index 760c303f2d..8104817d9e 100644
--- a/app/src/main/java/com/gh/gamecenter/vote/VoteViewModel.kt
+++ b/app/src/main/java/com/gh/gamecenter/vote/VoteViewModel.kt
@@ -1,11 +1,9 @@
package com.gh.gamecenter.vote
-import android.annotation.SuppressLint
import android.app.Application
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
-import com.gh.gamecenter.SearchType
import com.gh.gamecenter.common.baselist.ListViewModel
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.retrofit.ApiResponse
diff --git a/app/src/main/res/drawable/search_tab_indicator.xml b/app/src/main/res/drawable/search_tab_indicator.xml
new file mode 100644
index 0000000000..23091ba4dc
--- /dev/null
+++ b/app/src/main/res/drawable/search_tab_indicator.xml
@@ -0,0 +1,14 @@
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_search_game_list.xml b/app/src/main/res/layout/fragment_search_game_list.xml
new file mode 100644
index 0000000000..1988bcedd0
--- /dev/null
+++ b/app/src/main/res/layout/fragment_search_game_list.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_search_tab.xml b/app/src/main/res/layout/fragment_search_tab.xml
new file mode 100644
index 0000000000..550a8ed612
--- /dev/null
+++ b/app/src/main/res/layout/fragment_search_tab.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/feature/new_feedback/src/main/java/com/gh/gamecenter/feedback/view/qa/HelpContentAdapter.kt b/feature/new_feedback/src/main/java/com/gh/gamecenter/feedback/view/qa/HelpContentAdapter.kt
index 6be93bf74a..c4c6309c66 100644
--- a/feature/new_feedback/src/main/java/com/gh/gamecenter/feedback/view/qa/HelpContentAdapter.kt
+++ b/feature/new_feedback/src/main/java/com/gh/gamecenter/feedback/view/qa/HelpContentAdapter.kt
@@ -5,9 +5,11 @@ import android.text.TextUtils
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
+import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.baselist.NormalListViewModel
import com.gh.gamecenter.common.constant.ItemViewType
+import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.toBinding
import com.gh.gamecenter.common.utils.toColor
@@ -23,7 +25,9 @@ class HelpContentAdapter(
private val mViewModel: NormalListViewModel,
private val mQaId: String?,
private val mQaCollectionId: String?,
- private val mNavigationTitle: String
+ private val mNavigationTitle: String,
+ private val searchType: String,
+ private val location: String
) : ListAdapter(context) {
var searchKey = ""
@@ -107,6 +111,15 @@ class HelpContentAdapter(
mContext.javaClass.simpleName
)
}
+ SensorsBridge.trackQASearchResultClick(
+ GlobalActivityManager.getCurrentPageEntity().pageId,
+ GlobalActivityManager.getCurrentPageEntity().pageName,
+ location,
+ searchKey,
+ searchType,
+ entity.id,
+ entity.title
+ )
}
}
diff --git a/feature/new_feedback/src/main/java/com/gh/gamecenter/feedback/view/qa/HelpContentFragment.kt b/feature/new_feedback/src/main/java/com/gh/gamecenter/feedback/view/qa/HelpContentFragment.kt
index f02deb083b..3608931612 100644
--- a/feature/new_feedback/src/main/java/com/gh/gamecenter/feedback/view/qa/HelpContentFragment.kt
+++ b/feature/new_feedback/src/main/java/com/gh/gamecenter/feedback/view/qa/HelpContentFragment.kt
@@ -7,12 +7,17 @@ import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.RecyclerView
+import com.alibaba.android.arouter.launcher.ARouter
+import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.baselist.ListFragment
import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.baselist.NormalListViewModel
import com.gh.gamecenter.common.constant.EntranceConsts
+import com.gh.gamecenter.common.constant.RouteConsts
+import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.toDrawable
+import com.gh.gamecenter.core.provider.ISearchTabUtilsProvider
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.feedback.HaloApp
import com.gh.gamecenter.feedback.R
@@ -40,12 +45,27 @@ class HelpContentFragment : ListFragment
+ updateSearchKey(key)
+ }
}
override fun provideDataObservable(page: Int): Observable> {
@@ -125,6 +152,17 @@ class HelpContentFragment : ListFragment>?
+}
\ No newline at end of file
diff --git a/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/SettingsEntity.kt b/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/SettingsEntity.kt
index 7be6421d30..41ea57819a 100644
--- a/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/SettingsEntity.kt
+++ b/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/SettingsEntity.kt
@@ -75,8 +75,14 @@ class SettingsEntity(
@SerializedName("hot_list")
var rankList: List? = listOf(),
@SerializedName("wechat_game_search_list")
- var wechatGameSearchList: List? = listOf()// 微信小游戏-搜索榜单
+ var wechatGameSearchList: List? = listOf(),// 微信小游戏-搜索榜单
+ @SerializedName("navigations")
+ private val _navigations: List? = null
) {
+
+ val navigations: List
+ get() = _navigations ?: emptyList()
+
class RankList(
var title: String = "",
var content: ArrayList = arrayListOf(),
@@ -103,6 +109,19 @@ class SettingsEntity(
var exposureEvent: ExposureEvent? = null
}
}
+
+ data class Navigation(
+ @SerializedName("type")
+ private val _type: String? = null,
+ @SerializedName("title")
+ private val _title: String? = null
+ ) {
+ val type: String
+ get() = _type ?: ""
+
+ val title: String
+ get() = _title ?: ""
+ }
}
class Suggestion(
@@ -239,10 +258,11 @@ class SettingsEntity(
var text: String = "",
var display: Display? = Display()
) {
- val typeChinese: String get() = when(type) {
- "revolving" -> "走马灯"
- else -> "图片"
- }
+ val typeChinese: String
+ get() = when (type) {
+ "revolving" -> "走马灯"
+ else -> "图片"
+ }
}
class PermissionPopupAppliedVersions(