Compare commits

..

6 Commits

245 changed files with 1977 additions and 6289 deletions

View File

@ -72,7 +72,6 @@ android_build:
only:
- dev
- release
- feat/GHZSCY-6578
# 代码检查
sonarqube_analysis:
@ -157,5 +156,4 @@ oss-upload&send-email:
- /usr/local/bin/python /ci-android-mail-jira-comment.py
only:
- dev
- release
- feat/GHZSCY-6578
- release

View File

@ -479,8 +479,6 @@ dependencies {
implementation(project(':feature:sentry'))
}
implementation(project(':feature:media_select'))
implementation(project(":module_va_api"))
implementation(project(":va-archive-common"))
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableVa) {

View File

@ -32,11 +32,43 @@ class ExternalGameUsage : ITestCase {
it.titleTv.text = context.getString(R.string.title_install_external_game)
it.iconIv.setImageResource(R.drawable.ic_personal_my_game)
it.root.setOnClickListener {
context.startActivity(
InstallExternalGameActivity.getIntent(context)
.apply { flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK })
VHelper.connectService {
context.startActivity(
InstallExternalGameActivity.getIntent(context)
.apply { flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK })
}
}
}
}
override fun addInstallPluginButton(viewParent: ViewGroup) {
buttonTemplate(viewParent, R.id.install_plugin) {
it.titleTv.text = "安装64位插件"
it.root.setOnClickListener {
val file = File("/data/local/tmp/gh-plugins/artifacts.zip")
if (file.exists()) {
Utils.log(VHelper.LOG_TAG, "有本地更新文件: 64位插件")
// TODO: 补充debug插件更新
ToastUtils.showToast("暂未实现debug功能")
} else {
ToastUtils.showToast("data/local/tmp没有push文件")
}
}
}
}
override fun addInstallPlugin32Button(viewParent: ViewGroup) {
buttonTemplate(viewParent, R.id.install_plugin_32) {
it.titleTv.text = "安装32位插件"
it.root.setOnClickListener {
val file = File("/data/local/tmp/gh-plugins/artifacts32.zip")
if (file.exists()) {
// TODO: 补充debug插件更新
ToastUtils.showToast("暂未实现debug功能")
} else {
ToastUtils.showToast("data/local/tmp没有push文件")
}
}
}
}
}

View File

@ -1,12 +1,7 @@
package com.gh.vspace.installexternalgames
import android.Manifest
import android.app.Dialog
import android.content.ComponentName
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.gh.common.util.DialogUtils
import com.gh.gamecenter.R
@ -45,19 +40,6 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
private lateinit var dialog: Dialog
private val requestPermissionLauncher = registerForActivityResult<String, Boolean>(
ActivityResultContracts.RequestPermission()
) { result ->
if (result == true) {
// grant
mViewModel.scanPaths()
} else {
// not grant
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setNavigationTitle(getString(com.gh.gamecenter.R.string.title_install_external_game))
@ -74,30 +56,11 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
)
adapter.notifyDataSetChanged()
}
mViewModel.scanPaths()
requestStoragePermission()
}
private fun requestStoragePermission() {
when {
ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED -> {
mViewModel.scanPaths()
}
shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE) -> {
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
}
else -> {
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
}
}
}
private fun initView() {
dialog = DialogUtils.showWaitDialog(requireContext(), "")
mBinding.externalGamesList.let {
@ -131,11 +94,9 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
OnItemClickListener.ClickType.CLICK_INSTALL -> {
install(externalGameUiState)
}
OnItemClickListener.ClickType.CLICK_UNINSTALL -> {
uninstall(externalGameUiState)
}
OnItemClickListener.ClickType.CLICK_START -> {
start(externalGameUiState)
}
@ -143,8 +104,9 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
}
private fun install(externalGameUiState: ExternalGameUiState) {
val bit =
externalGameUiState.externalGameEntity.cpuAbi.let { if (it.size == 1 && it.contains("armeabi-v7a")) "32" else "64" }
VHelper.disableLaunchGameAfterInstallation()
VHelper.install(requireContext(), DownloadEntity().apply {
externalGameUiState.externalGameEntity.apply {
packageName = apkPackageName
@ -152,12 +114,20 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
}
}, true)
VHelper.newCwValidateVspaceBeforeAction(
requireContext(),null,
) {
dialog.show()
}
if (VHelper.showDialogIfVSpaceIsNeeded(
requireContext(),
"",
externalGameUiState.externalGameEntity.appName,
"",
bit = bit
)
) return
dialog.show()
externalGameUiState.externalGameEntity.let {
val intent = VirtualAppManager.getInstallIntent(context, it.apkPath, it.apkPackageName)
requireActivity().startActivity(intent)
}
}
private fun uninstall(externalGameUiState: ExternalGameUiState) {
@ -188,12 +158,6 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
com.gh.gamecenter.BuildConfig.VA_VERSION_NAME,
HaloApp.getInstance().oaid
)
intent.setComponent(
ComponentName(
com.gh.gamecenter.BuildConfig.APPLICATION_ID,
VirtualAppManager.AIDL_SERVER_REMOTE_GUIDE_ACTIVITY
)
)
requireActivity().startActivity(intent)
}

View File

@ -2,7 +2,6 @@
<resources>
<string name="title_install_external_game">從SD卡安裝</string>
<string name="text_install">安裝</string>
<string name="text_update">更新</string>
<string name="text_uninstall">卸載</string>
<string name="text_start">啟動</string>
</resources>

View File

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="install_game_from_external" type="id" />
<item name="install_plugin" type="id" />
<item name="install_plugin_32" type="id" />
</resources>

View File

@ -456,6 +456,9 @@
android:name="com.gh.gamecenter.video.game.GameVideoActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.editor.LocalMediaActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.servers.GameServersActivity"
@ -573,6 +576,10 @@
android:name=".personal.DeliveryInfoActivity"
android:screenOrientation="portrait" />
<activity
android:name=".qa.editor.PreviewVideoActivity"
android:screenOrientation="portrait" />
<activity
android:name=".qa.video.publish.VideoPublishActivity"
android:screenOrientation="portrait" />

View File

@ -227,7 +227,18 @@ object AdDelegateHelper {
/**
* 是否大于开屏广告展示间隔时长
*/
private fun isMatchStartUpAdDisplayRule(): Boolean = isMatchAdDisplayRule(mSplashAd, Constants.SP_LAST_SPLASH_AD_SHOW_TIME)
private fun isMatchStartUpAdDisplayRule(): Boolean {
mSplashAd?.displayRule?.run {
if (adDisplayInterval > 0) {
val lastShowTime = SPUtils.getLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, 0L)
val durationInMinutes = (System.currentTimeMillis() - lastShowTime).toFloat() / 1000 / 60
return durationInMinutes > adDisplayInterval
} else {
return true
}
}
return true
}
/**
* 是否大于广告管理展示间隔时长
@ -281,7 +292,6 @@ object AdDelegateHelper {
adViewHeightInDp: Float,
startAdContainer: ViewGroup,
sdkStartAdContainer: ViewGroup,
sdkJumpBtn: TextView,
adsViewGroup: FrameLayout,
handler: BaseActivity.BaseHandler,
isHotLaunch: Boolean,
@ -303,7 +313,6 @@ object AdDelegateHelper {
adViewHeightInDp,
startAdContainer,
sdkStartAdContainer,
sdkJumpBtn,
adsViewGroup,
handler,
isHotLaunch,
@ -321,7 +330,6 @@ object AdDelegateHelper {
adViewHeightInDp,
startAdContainer,
sdkStartAdContainer,
sdkJumpBtn,
adsViewGroup,
handler,
isHotLaunch,
@ -345,7 +353,6 @@ object AdDelegateHelper {
adViewHeightInDp: Float,
startAdContainer: ViewGroup,
sdkStartAdContainer: ViewGroup,
sdkJumpBtn: TextView,
adsViewGroup: FrameLayout,
handler: BaseActivity.BaseHandler,
isHotLaunch: Boolean,
@ -367,7 +374,6 @@ object AdDelegateHelper {
adViewHeightInDp,
startAdContainer,
sdkStartAdContainer,
sdkJumpBtn,
adsViewGroup,
handler,
isHotLaunch,
@ -397,14 +403,13 @@ object AdDelegateHelper {
sdkStartAdContainer.visibility = View.VISIBLE
requestCsjSplashAd(
activity,
thirdPartyAd.slotId,
adViewWidthInPx,
adViewHeightInPx,
adViewWidthInDp,
adViewHeightInDp,
sdkStartAdContainer,
sdkJumpBtn,
timeout,
isHotLaunch,
sdkSplashCallback
)
}
@ -415,65 +420,27 @@ object AdDelegateHelper {
*/
private fun requestCsjSplashAd(
activity: Activity,
slotId: String,
adViewWidthInPx: Int,
adViewHeightInPx: Int,
adViewWidthInDp: Float,
adViewHeightInDp: Float,
startAdContainer: ViewGroup,
sdkJumpBtn: TextView,
timeout: Int,
isHotLaunch: Boolean,
callback: (isSuccess: Boolean) -> Unit,
) {
val thirdPartyAd = if (isHotLaunch) mSplashAd?.hotStartThirdPartyAd else mSplashAd?.thirdPartyAd
if (mCsjAdImpl == null || thirdPartyAd == null) {
if (mCsjAdImpl == null) {
callback.invoke(false)
} else {
sdkJumpBtn.setOnClickListener {
callback.invoke(true)
if (activity is BaseActivity) {
activity.baseHandler.removeMessages(MainActivity.COUNTDOWN_SDK_AD)
}
}
val onAdShowAction = {
sdkJumpBtn.visibility = View.VISIBLE
if (activity is BaseActivity) {
activity.baseHandler.sendEmptyMessageDelayed(MainActivity.COUNTDOWN_SDK_AD, 1000)
}
SensorsBridge.trackEvent("ThirdPartyAdShow",
"ad_source", thirdPartyAd.sourceName,
"ad_id", thirdPartyAd.slotId,
"ad_format", mSplashAd?.typeChinese ?: "",
"ad_placement", "光环启动",
"launch_type", if (isHotLaunch) "热启动" else "冷启动",
"ad_space_id", mSplashAd?.id ?: "",
"ad_space_name", mSplashAd?.name ?: ""
)
}
val onAdClickAction = {
callback.invoke(true)
SensorsBridge.trackEvent("ThirdPartyAdClick",
"ad_source", thirdPartyAd.sourceName,
"ad_id", thirdPartyAd.slotId,
"ad_format", mSplashAd?.typeChinese ?: "",
"ad_placement", "光环启动",
"launch_type", if (isHotLaunch) "热启动" else "冷启动",
"ad_space_id", mSplashAd?.id ?: "",
"ad_space_name", mSplashAd?.name ?: ""
)
}
mCsjAdImpl?.requestSplashAd(
activity,
thirdPartyAd.slotId,
slotId,
adViewWidthInPx,
adViewHeightInPx,
adViewWidthInDp,
adViewHeightInDp,
startAdContainer,
timeout,
onAdShowAction,
onAdClickAction,
callback,
)
}
@ -490,7 +457,6 @@ object AdDelegateHelper {
adViewHeightInDp: Float,
startAdContainer: ViewGroup,
sdkStartAdContainer: ViewGroup,
sdkJumpBtn: TextView,
adsViewGroup: FrameLayout,
handler: BaseActivity.BaseHandler,
isHotLaunch: Boolean,
@ -508,7 +474,6 @@ object AdDelegateHelper {
adViewHeightInDp,
startAdContainer,
sdkStartAdContainer,
sdkJumpBtn,
adsViewGroup,
handler,
isHotLaunch,
@ -656,11 +621,9 @@ object AdDelegateHelper {
slotId: String,
adContainerView: ViewGroup,
expressViewWidth: Float,
onAdShowAction: () -> Unit,
onAdClickAction: () -> Unit,
callback: (isSuccess: Boolean) -> Unit,
) {
mCsjAdImpl?.requestFlowAd(fragment, adContainerView, slotId, expressViewWidth, onAdShowAction, onAdClickAction, callback)
mCsjAdImpl?.requestFlowAd(fragment, adContainerView, slotId, expressViewWidth, callback)
}
/**
@ -671,8 +634,6 @@ object AdDelegateHelper {
containerView: ViewGroup,
ad: AdConfig.ThirdPartyAd,
expressViewWidthInDp: Float,
onAdShowAction: () -> Unit,
onAdClickAction: () -> Unit,
callback: (isSuccess: Boolean) -> Unit
) {
@ -695,28 +656,6 @@ object AdDelegateHelper {
slotId,
expressViewWidthInDp,
expressViewHeightInDp,
onAdShowAction,
onAdClickAction,
callback
)
}
/**
* 获取第三方 全屏/插屏 广告
*/
fun requestFullScreenAd(
fragment: Fragment,
ad: AdConfig.ThirdPartyAd,
onAdShowAction: () -> Unit,
onAdClickAction: () -> Unit,
callback: (isSuccess: Boolean) -> Unit
) {
val slotId = ad.slotId
mCsjAdImpl?.requestFullScreenAd(
fragment,
slotId,
onAdShowAction,
onAdClickAction,
callback
)
}

View File

@ -3,105 +3,42 @@ package com.gh.ad
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.view.ViewStub
import androidx.fragment.app.Fragment
import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.provider.ILaunchAd
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.entity.AdConfig
@Route(path = RouteConsts.provider.vaAd, name = "畅玩启动页广告")
class LaunchAdImpl : ILaunchAd {
override fun init(context: Context?) {
}
override fun requestAd(fragment: Fragment, container: ViewGroup, maskView: View, topViewStub: ViewStub, bottomViewStub: ViewStub, adClickAction: () -> Unit): View {
override fun requestAd(fragment: Fragment, container: ViewGroup, maskView: View) {
if (AdDelegateHelper.shouldShowHelperLaunchAd()) {
val launchAd = AdDelegateHelper.vGameLaunchAd
val showThirdPartyAd = launchAd?.displayRule?.adSource == AdDelegateHelper.AD_TYPE_SDK
val thirdPartyAd = launchAd?.thirdPartyAd
if (showThirdPartyAd && thirdPartyAd != null) {
val onAdShowAction = {
SensorsBridge.trackEvent("ThirdPartyAdShow",
"ad_source", thirdPartyAd.sourceName,
"ad_id", thirdPartyAd.slotId,
"ad_format", launchAd.typeChinese,
"ad_placement", AD_PLACEMENT,
"ad_space_id", launchAd.id,
"ad_space_name", launchAd.name
)
}
val onAdClickAction = {
SensorsBridge.trackEvent("ThirdPartyAdClick",
"ad_source", thirdPartyAd.sourceName,
"ad_id", thirdPartyAd.slotId,
"ad_format", launchAd.typeChinese,
"ad_placement", AD_PLACEMENT,
"ad_space_id", launchAd.id,
"ad_space_name", launchAd.name
)
adClickAction.invoke()
}
if (launchAd.type == AdConfig.TYPE_BANNER) {
requestBannerAd(fragment, container, maskView, thirdPartyAd, onAdShowAction, onAdClickAction)
return topViewStub.inflate()
} else if (launchAd.type == AdConfig.TYPE_INTERSTITIAL) {
requestFullScreenAd(fragment, thirdPartyAd, onAdShowAction, onAdClickAction)
return bottomViewStub.inflate()
AdDelegateHelper.requestThirdPartyBannerAd(
fragment,
container,
thirdPartyAd,
DisplayUtils.getScreenWidthInDp(fragment.requireActivity()),
) { isSuccess ->
maskView.goneIf(!isSuccess)
if (isSuccess) {
SPUtils.setLong(Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME, System.currentTimeMillis())
}
}
}
}
return bottomViewStub.inflate()
}
private fun requestBannerAd(
fragment: Fragment,
container: ViewGroup,
maskView: View,
thirdPartyAd: AdConfig.ThirdPartyAd,
onAdShowAction: () -> Unit,
onAdClickAction: () -> Unit,
) {
AdDelegateHelper.requestThirdPartyBannerAd(
fragment,
container,
thirdPartyAd,
DisplayUtils.getScreenWidthInDp(fragment.requireActivity()),
onAdShowAction,
onAdClickAction
) { isSuccess ->
maskView.goneIf(!isSuccess)
if (isSuccess) {
SPUtils.setLong(Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME, System.currentTimeMillis())
}
}
}
private fun requestFullScreenAd(
fragment: Fragment,
thirdPartyAd: AdConfig.ThirdPartyAd,
onAdShowAction: () -> Unit,
onAdClickAction: () -> Unit
) {
AdDelegateHelper.requestFullScreenAd(
fragment,
thirdPartyAd,
onAdShowAction,
onAdClickAction
) { isSuccess ->
if (isSuccess) {
SPUtils.setLong(Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME, System.currentTimeMillis())
}
}
}
companion object {
private const val AD_PLACEMENT = "畅玩启动"
}
}

View File

@ -21,8 +21,6 @@ import com.gh.common.view.RichEditor
import com.gh.gamecenter.CropImageActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.entity.LocalVideoEntity
import com.gh.gamecenter.feature.selector.LocalMediaActivity
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.runOnIoThread
@ -32,7 +30,6 @@ import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.qa.editor.*
import com.gh.gamecenter.feature.entity.AnswerEntity
import com.gh.gamecenter.feature.entity.ArticleEntity
import com.gh.gamecenter.feature.selector.ChooseType
import com.gh.gamecenter.qa.entity.EditorInsertEntity
import com.gh.gamecenter.video.poster.PosterEditActivity
import com.gh.gamecenter.video.upload.UploadManager
@ -505,7 +502,7 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
startActivityForResult(
LocalMediaActivity.getIntent(
this@BaseRichEditorActivity,
ChooseType.VIDEO,
LocalMediaActivity.ChooseType.VIDEO,
maxChooseCount,
if (mtaEventName() == "提问帖") "发提问帖" else "发帖子"
), INSERT_MEDIA_VIDEO_CODE
@ -534,7 +531,7 @@ abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor(
val maxChooseCount = if (imageCount + 10 <= MAX_IMAGE_COUNT) 10 else MAX_IMAGE_COUNT - imageCount
val intent = LocalMediaActivity.getIntent(
this@BaseRichEditorActivity,
ChooseType.IMAGE,
LocalMediaActivity.ChooseType.IMAGE,
maxChooseCount,
if (mtaEventName() == "提问帖") "发提问帖" else "发帖子"
)

View File

@ -20,7 +20,7 @@ import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.ForumDetailEntity
import com.gh.gamecenter.common.entity.LocalVideoEntity
import com.gh.gamecenter.entity.LocalVideoEntity
import com.gh.gamecenter.entity.QuoteCountEntity
import com.gh.gamecenter.qa.BbsType
import com.gh.gamecenter.retrofit.RetrofitManager
@ -39,6 +39,8 @@ import retrofit2.HttpException
import java.io.File
import java.io.FileOutputStream
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.collections.LinkedHashMap
import kotlin.collections.set

View File

@ -6,8 +6,8 @@ class DownloadChainBuilder {
private var processEndCallback: ((asVGame: Boolean, Any?) -> Unit)? = null
fun setProcessEndCallback(gameId: String, callback: (asVGame: Boolean, Any?) -> Unit): DownloadChainBuilder {
processEndCallback = VaPluginDownloadWrapper(gameId = gameId, callback = callback) // 其他需要添加行为的装饰者可以一直包装A(B(C(callback))), 执行顺序 A->B->C->callback
fun setProcessEndCallback(callback: (asVGame: Boolean, Any?) -> Unit): DownloadChainBuilder {
processEndCallback = VaPluginDownloadWrapper(callback) // 其他需要添加行为的装饰者可以一直包装A(B(C(callback))), 执行顺序 A->B->C->callback
return this
}

View File

@ -2,11 +2,11 @@ package com.gh.common.chain
import com.gh.vspace.VHelper
class VaPluginDownloadWrapper(val gameId: String, val callback: (Boolean, Any?) -> Unit) : (Boolean, Any?) -> Unit {
class VaPluginDownloadWrapper(val callback: (Boolean, Any?) -> Unit) : (Boolean, Any?) -> Unit {
override fun invoke(asVGame: Boolean, any: Any?) {
callback.invoke(asVGame, any)
if (asVGame) {
VHelper.initVaPlugin(gameId)
VHelper.initVaPlugin()
}
}
}

View File

@ -172,7 +172,7 @@ public class BindingAdapters {
builder.addHandler(new OverseaDownloadHandler());
builder.addHandler(new CheckDownloadHandler());
builder.setProcessEndCallback(gameEntity.getId(), (asVGame, isSubscribe) -> {
builder.setProcessEndCallback((asVGame, isSubscribe) -> {
download(v.getContext(),
progressBar,
gameEntity,
@ -197,7 +197,7 @@ public class BindingAdapters {
builder.addHandler(new GamePermissionHandler());
builder.addHandler(new VersionNumberHandler());
builder.setProcessEndCallback(gameEntity.getId(), (asVGame, isSubscribe) -> {
builder.setProcessEndCallback((asVGame, isSubscribe) -> {
DownloadDialog.showDownloadDialog(
v.getContext(),
gameEntity,

View File

@ -1,52 +0,0 @@
package com.gh.common.prioritychain
import android.content.Context
import android.view.LayoutInflater
import android.widget.FrameLayout
import com.airbnb.lottie.LottieAnimationView
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.databinding.LayoutCommunityHomeVideoGuideBinding
class CommunityHomeGuideHandler(
priority: Int,
private val context: Context,
private val decorView: FrameLayout?,
private val videoLottie: LottieAnimationView?
) : PriorityChainHandler(priority) {
init {
updateStatus(STATUS_VALID)
}
override fun onProcess(): Boolean {
return if (SPUtils.getBoolean(Constants.SP_SHOW_COMMUNITY_HOME_VIDEO_GUIDE, true)) {
showHomeVideoGuide(context, decorView, videoLottie)
processNext()
true
} else {
processNext()
false
}
}
companion object {
fun showHomeVideoGuide(context: Context, decorView: FrameLayout?, videoLottie: LottieAnimationView?) {
val guideLayoutBinding = LayoutCommunityHomeVideoGuideBinding.inflate(
LayoutInflater.from(context),
decorView,
true
)
guideLayoutBinding.root.setOnClickListener { view ->
decorView?.removeView(view)
SPUtils.setBoolean(Constants.SP_SHOW_COMMUNITY_HOME_VIDEO_GUIDE, false)
videoLottie?.playAnimation()
SPUtils.setLong(
Constants.SP_COMMUNITY_HOME_VIDEO_LOTTIE_LAST_PLAY_TIME,
System.currentTimeMillis()
)
}
}
}
}

View File

@ -1,16 +0,0 @@
package com.gh.common.prioritychain
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
class VideoHandler(priority: Int, val scrollCalculatorHelper: ScrollCalculatorHelper): PriorityChainHandler(priority) {
init {
updateStatus(STATUS_VALID)
}
override fun onProcess(): Boolean {
scrollCalculatorHelper.enableAndPlayIfValid()
return true
}
}

View File

@ -2,15 +2,12 @@ package com.gh.common.provider
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.fragment.app.FragmentActivity
import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.common.util.EntranceUtils
import com.gh.gamecenter.common.avoidcallback.Callback
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IEntranceUtilsProvider
import com.lightgame.utils.AppManager
@Route(path = RouteConsts.provider.entranceUtils, name = "EntranceUtils暴露服务")
class EntranceUtilsProviderImpl : IEntranceUtilsProvider {
@ -23,16 +20,11 @@ class EntranceUtilsProviderImpl : IEntranceUtilsProvider {
}
override fun jumpActivityWithCallback(context: Context, bundle: Bundle, callback: () -> Unit) {
if (context is FragmentActivity && !context.supportFragmentManager.isDestroyed) {
EntranceUtils.jumpActivityCompat(context, bundle, null, object : Callback {
override fun onActivityResult(resultCode: Int, data: Intent?) {
callback()
}
})
} else {
EntranceUtils.jumpActivityCompat(AppManager.getInstance().currentActivity(), bundle)
}
EntranceUtils.jumpActivity(context, null, bundle, object : Callback {
override fun onActivityResult(resultCode: Int, data: Intent?) {
callback()
}
})
}
override fun init(context: Context?) {

View File

@ -74,7 +74,7 @@ public class CheckLoginUtils {
Bundle bundle = new Bundle();
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance);
bundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
EntranceUtils.jumpActivityCompat(context, bundle, nextToBundle, (resultCode, data) -> {
EntranceUtils.jumpActivity(context, nextToBundle, bundle, (resultCode, data) -> {
if (isTriggerNextStep && listener != null && isLogin()) {
listener.onLogin();
}

View File

@ -37,10 +37,10 @@ import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PluginLocation
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
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
@ -697,7 +697,7 @@ object DownloadItemUtils {
// 为 downloadButton 添加游戏实体,供点击的时候上报用
downloadBtn.putObject(gameEntity)
val gamePermissionDialogFragment = (context as? AppCompatActivity)?.supportFragmentManager?.findFragmentByTag(
val gamePermissionDialogFragment = (context as AppCompatActivity).supportFragmentManager.findFragmentByTag(
GamePermissionDialogFragment::class.java.name
) as GamePermissionDialogFragment?
gamePermissionDialogFragment?.dismissAllowingStateLoss()
@ -910,7 +910,7 @@ object DownloadItemUtils {
addHandler(CheckStoragePermissionHandler())
addHandler(VersionNumberHandler())
}
.setProcessEndCallback(gameEntity.id) { _, _ ->
.setProcessEndCallback { _, _ ->
DownloadDialog.showDownloadDialog(view.context, gameEntity, traceEvent, entrance, location)
}
.buildHandlerChain()
@ -953,7 +953,7 @@ object DownloadItemUtils {
addHandler(LandPageAddressHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback(gameEntity.id) { asVGame, isSubscribe ->
.setProcessEndCallback { asVGame, isSubscribe ->
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
@ -972,7 +972,7 @@ object DownloadItemUtils {
addHandler(OverseaDownloadHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback(gameEntity.id) { asVGame, isSubscribe ->
.setProcessEndCallback { asVGame, isSubscribe ->
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
@ -991,7 +991,7 @@ object DownloadItemUtils {
addHandler(ValidateVSpaceHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback(gameEntity.id) { asVGame, isSubscribe ->
.setProcessEndCallback { asVGame, isSubscribe ->
download(context, gameEntity, downloadBtn, entrance, location, asVGame, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
@ -1004,7 +1004,7 @@ object DownloadItemUtils {
addHandler(DownloadDialogHelperHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback(gameEntity.id) { _, isSubscribe ->
.setProcessEndCallback { _, isSubscribe ->
plugin(context, gameEntity, downloadBtn, entrance, location, isSubscribe as Boolean, traceEvent)
}
.buildHandlerChain()
@ -1089,7 +1089,7 @@ object DownloadItemUtils {
DownloadChainBuilder()
.apply {
addHandler(LandPageAddressHandler())
}.setProcessEndCallback(gameEntity.id) { asVGame, _ ->
}.setProcessEndCallback { asVGame, _ ->
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk) {
DialogUtils.checkDownload(
context,

View File

@ -69,13 +69,11 @@ object DownloadObserver {
DownloadDataHelper.uploadDownloadEvent(downloadEntity)
}
val status = downloadEntity.status
if (DownloadStatus.hijack == status) {
if (DownloadStatus.hijack == downloadEntity.status) {
// 链接被劫持
processHijack(downloadEntity)
return
} else if (DownloadStatus.notfound == status) {
} else if (DownloadStatus.notfound == downloadEntity.status) {
// 404 Not Found
// 删除任务
downloadEntity.status = DownloadStatus.cancel
@ -129,9 +127,10 @@ object DownloadObserver {
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
)
return
} else if (DownloadStatus.neterror == status
|| DownloadStatus.diskioerror == status
|| DownloadStatus.timeout == status
} else if (DownloadStatus.neterror == downloadEntity.status
|| DownloadStatus.timeout == downloadEntity.status
|| DownloadStatus.diskioerror == downloadEntity.status
|| DownloadStatus.diskisfull == downloadEntity.status
) {
if (mRetryableHashMap[downloadEntity.url] == true
&& NetworkUtils.isWifiConnected(HaloApp.getInstance().application)
@ -140,7 +139,9 @@ object DownloadObserver {
mRetryableHashMap[downloadEntity.url] = false
Utils.log(TAG, "下载重试->" + downloadEntity.toJson())
} else {
if (DownloadStatus.diskioerror == status) {
if (DownloadStatus.diskisfull == downloadEntity.status) {
ToastUtils.toast("磁盘已满,请清理空间后重试下载")
} else if (DownloadStatus.diskioerror == downloadEntity.status) {
ToastUtils.toast("磁盘 IO 异常,请稍后重试")
} else {
ToastUtils.toast("网络不稳定,下载任务已暂停")
@ -149,21 +150,17 @@ object DownloadObserver {
DataLogUtils.uploadNeterrorLog(mApplication, downloadEntity)
Utils.log(TAG, "下载自动暂停->" + downloadEntity.toJson())
}
} else if (DownloadStatus.diskisfull == status) {
ToastUtils.toast("磁盘已满,请清理空间后重试下载")
downloadManager.pause(downloadEntity.url)
} else if (DownloadStatus.redirected == status) {
} else if (DownloadStatus.redirected == downloadEntity.status) {
Utils.log(TAG, "重定向完毕")
DownloadDataHelper.uploadRedirectEvent(downloadEntity)
} else if (DownloadStatus.unqualified == status) {
} else if (DownloadStatus.unqualified == downloadEntity.status) {
// 未成年
RealNameHelper.showRealNameUnqualifiedDialog(downloadEntity)
// 删除任务
downloadEntity.status = DownloadStatus.cancel
downloadManager.cancel(downloadEntity.url)
} else if (DownloadStatus.unavailable == status) {
} else if (DownloadStatus.unavailable == downloadEntity.status) {
// 未接入防沉迷系统
val currentActivity = AppManager.getInstance().currentActivity()
@ -182,7 +179,7 @@ object DownloadObserver {
// 删除任务
downloadEntity.status = DownloadStatus.cancel
downloadManager.cancel(downloadEntity.url)
} else if (DownloadStatus.isCertificating == status) {
} else if (DownloadStatus.isCertificating == downloadEntity.status) {
// 未接入防沉迷系统
val currentActivity = AppManager.getInstance().currentActivity()
@ -210,21 +207,21 @@ object DownloadObserver {
// 删除任务
downloadEntity.status = DownloadStatus.cancel
downloadManager.cancel(downloadEntity.url)
} else if (DownloadStatus.uncertificated == status) {
} else if (DownloadStatus.uncertificated == downloadEntity.status) {
// 未实名
RealNameHelper.showRealNameUncertificatedDialog(downloadEntity)
// 删除任务
downloadEntity.status = DownloadStatus.cancel
downloadManager.cancel(downloadEntity.url)
} else if (DownloadStatus.banned == status) {
} else if (DownloadStatus.banned == downloadEntity.status) {
ToastUtils.showToast("网络异常")
// 删除任务
downloadEntity.status = DownloadStatus.cancel
downloadManager.cancel(downloadEntity.url)
}
if (DownloadStatus.done == status) {
if (DownloadStatus.done == downloadEntity.status) {
if (mDoneDebouncePair?.first != downloadEntity.url) {
mDoneDebouncePair = Pair(downloadEntity.url, System.currentTimeMillis())
performDownloadCompleteAction(downloadEntity, downloadManager)
@ -244,7 +241,7 @@ object DownloadObserver {
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
// 如果已下载大小发生变化,表示成功恢复下载,则重置重试标记
if (status == DownloadStatus.downloading) {
if (downloadEntity.status == DownloadStatus.downloading) {
mRetryableHashMap[downloadEntity.url] = true
}
}

View File

@ -27,6 +27,7 @@ import com.gh.gamecenter.core.utils.ClassUtils;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.SPUtils;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.AppManager;
import com.lightgame.utils.Utils;
import org.json.JSONException;
@ -37,18 +38,7 @@ import java.util.Set;
public class EntranceUtils {
public static void jumpActivity(Context context, Bundle bundle) {
jumpActivityCompat(context, bundle, null, null);
}
public static void jumpActivityCompat(Context context, Bundle bundle) {
jumpActivityCompat(context, bundle, null,null);
}
public static void jumpActivityCompat(Context context,
Bundle bundle,
@Nullable Bundle nextToBundle,
@Nullable Callback callback) {
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
if (HaloApp.getInstance().isRunningForeground || HaloApp.getInstance().isAlreadyUpAndRunning) {
@ -58,18 +48,6 @@ public class EntranceUtils {
if (clazz == null) clazz = MainActivity.class;
if (ToolbarFragment.class.isAssignableFrom(clazz)) { // 兼容ToolbarFragment
ToolBarActivity.startFragmentNewTask(context, (Class<? extends ToolbarFragment>) clazz, bundle);
} else if (callback != null ) {
Intent intent1 = new Intent(context, clazz);
//TODO:添加FLAG_ACTIVITY_NEW_TASK会导致一跳转页面callback就被调用
//intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.putExtras(bundle);
if (context instanceof AppCompatActivity) {
AvoidOnResultManager.Companion.getInstance((AppCompatActivity) context)
.startForResult(intent1, callback);
} else {
// 不要回调,正常跳转
context.startActivity(intent1);
}
} else {
Intent intent1 = new Intent(context, clazz);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@ -80,6 +58,57 @@ public class EntranceUtils {
intent1.putExtras(bundle);
context.startActivity(intent1);
}
} else {
// 应用未在运行
context.startActivity(SplashScreenActivity.getSplashScreenIntent(context, bundle));
}
}
public static void jumpActivity(Context context, Bundle bundle) {
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
if (AppManager.getInstance().findActivity(MainActivity.class) != null) {
// 应用正在运行前台或后台且MainActivity在栈中
String to = bundle.getString(KEY_TO);
Class<?> clazz = ClassUtils.forName(to);
if (clazz == null) clazz = MainActivity.class;
if (ToolbarFragment.class.isAssignableFrom(clazz)) { // 兼容ToolbarFragment
ToolBarActivity.startFragmentNewTask(context, (Class<? extends ToolbarFragment>) clazz, bundle);
} else {
Intent intent1 = new Intent(context, clazz);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 如果 activity 名称有 singleton 的就添加 reorder_to_front 标签 (有点粗暴有点蠢,但暂时就先这样吧 :C )
if (clazz.getSimpleName().toLowerCase().contains("singleton")) {
intent1.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
}
intent1.putExtras(bundle);
context.startActivity(intent1);
}
} else {
// 应用未在运行
context.startActivity(SplashScreenActivity.getSplashScreenIntent(context, bundle));
}
}
public static void jumpActivity(Context context, Bundle nextToBundle, Bundle bundle, Callback callback) {
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
if (AppManager.getInstance().findActivity(MainActivity.class) != null) {
// 应用正在运行前台或后台且MainActivity在栈中
String to = bundle.getString(KEY_TO);
Class<?> clazz = ClassUtils.forName(to);
if (clazz == null) clazz = MainActivity.class;
if (ToolbarFragment.class.isAssignableFrom(clazz)) { // 兼容ToolbarFragment
ToolBarActivity.startFragmentNewTask(context, (Class<? extends ToolbarFragment>) clazz, bundle);
} else {
Intent intent1 = new Intent(context, clazz);
//TODO:添加FLAG_ACTIVITY_NEW_TASK会导致一跳转页面callback就被调用
//intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.putExtras(bundle);
AvoidOnResultManager.Companion.getInstance((AppCompatActivity) context)
.startForResult(intent1, callback);
}
} else {
// 应用未在运行
if (nextToBundle != null) {

View File

@ -7,7 +7,6 @@ import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
@ -112,14 +111,6 @@ object GameSubstituteRepositoryHelper {
}
}
// 检查是否已安装该游戏 id
if (PackagesManager.getInstalledDataByGameId(game.id) != null) {
// 将该位置的游戏标记为需要替换
positionOfGameToBeReplacedList.add(index)
thisPositionNeedToBeReplaced = true
break
}
// 若此游戏所包含的 apk 没有已安装,那么再检查是否已安装有预设相关包名
if (!thisPositionNeedToBeReplaced) {
var relatedPackageList = arrayListOf<String>()

View File

@ -308,7 +308,7 @@ object GameUtils {
}
/**
* 是否默认以畅玩游戏的形式来处理
* 是否以畅玩游戏的形式来处理
*/
@JvmStatic
fun shouldPerformAsVGame(gameEntity: GameEntity): Boolean {

View File

@ -30,9 +30,6 @@ object NewFlatLogUtils {
private const val EVENT_LOGIN_FROM_GHZS_SHOW = "halo_fun_login_from_ghzs_show"
private const val EVENT_LOGIN_FROM_GHZS_CLICK = "halo_fun_login_from_ghzs_click"
private const val EVENT_INSTALLED_LAUNCH_DIALOG_SHOW = "halo_fun_installed_launch_dialog_show"
private const val EVENT_INSTALLED_LAUNCH_DIALOG_CLICK = "halo_fun_installed_launch_dialog_click"
private fun log(jsonObject: JSONObject, logStore: String = "event", uploadImmediately: Boolean = false) {
Utils.log("NewFlatLogUtils", jsonObject.toString(4))
LoghubUtils.log(jsonObject, logStore, uploadImmediately, true)
@ -553,8 +550,6 @@ object NewFlatLogUtils {
// 搜索-点击搜索榜单内容
@JvmStatic
fun logSearchClickRankDetail(
key: String,
rankType: String,
rankName: String,
rankSequence: String,
linkId: String,
@ -563,8 +558,6 @@ object NewFlatLogUtils {
) {
val json = json {
KEY_EVENT to "search_click_rank_detail"
"key" to key
"rank_type" to rankType
"rank_name" to rankName
"rank_sequence" to rankSequence
"link_id" to linkId
@ -2695,73 +2688,4 @@ object NewFlatLogUtils {
parseAndPutMeta()(this)
}.let(::log)
}
fun logHaloFunInstalledLaunchDialogShow() {
json {
KEY_EVENT to EVENT_INSTALLED_LAUNCH_DIALOG_SHOW
parseAndPutMeta()(this)
}.let(::log)
}
fun logHaloFunInstalledLaunchDialogClick(
gameId: String,
gameName: String,
buttonType: String
) {
json {
KEY_EVENT to EVENT_INSTALLED_LAUNCH_DIALOG_CLICK
"game_id" to gameId
"game_name" to gameName
"button_type" to buttonType
parseAndPutMeta()(this)
}.let(::log)
}
// 用户访问分流器
fun logByPassBrowsing(
source: String,
bypassName: String,
bypassId: String,
branchId: String,
branchName: String,
inProcessTime: Int,
bypassVisitTime: Int,
linkType: String,
linkId: String,
linkText: String,
bypassStatus: Int
) {
json {
KEY_EVENT to "BypassBrowsing"
"source" to source
"bypass_name" to bypassName
"bypass_id" to bypassId
"branch_id" to branchId
"branch_name" to branchName
"inprocess_time" to inProcessTime
"bypass_visit_time" to bypassVisitTime
"link_type" to linkType
"link_id" to linkId
"link_text" to linkText
"bypass_status" to bypassStatus
parseAndPutMeta()(this)
}.let(::log)
}
// 分流失败
fun logFailByPass(
source: String,
bypassName: String,
bypassId: String,
defeatedReason: String
) {
json {
KEY_EVENT to "FailBypass"
"source" to source
"bypass_name" to bypassName
"bypass_id" to bypassId
"defeated_reason" to defeatedReason
parseAndPutMeta()(this)
}.let(::log)
}
}

View File

@ -90,7 +90,7 @@ object PackageChangeHelper : DefaultLifecycleObserver {
pendingPackageTriple = null
pendingGhId = null
PackageRepository.addInstalledGame(PackageRepository.packageFilterManager, packageName)
PackageRepository.addInstalledGame(packageName)
// 添加到额外的包名白名单,下次启动同时查询此包的安装情况
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = true)

View File

@ -81,28 +81,23 @@ object PackageHelper {
// 评论黑名单包名列表,避免用户安装了 Xposed Installer 这样的工具,也能在包含该安装包的游戏详情页评论
private var _commentPackageNameBlackList = arrayListOf<String>()
val commentPackageNameBlackList: ArrayList<String>
get() = _commentPackageNameBlackList
val commentPackageNameBlackList: ArrayList<String> = _commentPackageNameBlackList
// 关闭下载的包列表
private var _downloadPackageNameBlackList = arrayListOf<String>()
val downloadPackageNameBlackList: ArrayList<String>
get() = _downloadPackageNameBlackList
val downloadPackageNameBlackList: ArrayList<String> = _downloadPackageNameBlackList
// 本地已安装的包去掉关闭下载的包后的列表
private var _validLocalPackageNameSet = hashSetOf<String>()
val validLocalPackageNameSet: HashSet<String>
get() = _validLocalPackageNameSet
val validLocalPackageNameSet: HashSet<String> = _validLocalPackageNameSet
// 游戏包名匹配列表
private var _relatedPackageList = arrayListOf<SettingsEntity.GameWithPackages>()
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages>
get() = _relatedPackageList
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages> = _relatedPackageList
// 接口控制的已安装应用列表获取开关状态 (UI 显示)
private var _installedPackageApiSwitchStatusLiveData = MutableLiveData<Boolean>()
val installedPackageApiSwitchStatusLiveData: LiveData<Boolean>
get() = _installedPackageApiSwitchStatusLiveData
val installedPackageApiSwitchStatusLiveData: LiveData<Boolean> = _installedPackageApiSwitchStatusLiveData
// 本地已安装包的列表
var localPackageNameSet = hashSetOf<String>()
@ -546,7 +541,6 @@ object PackageHelper {
Utils.log(TAG, "addInstalledButMissingPackages 需要请求接口获取的包数量为 ${installedPackageNameSet.size}")
PackageRepository.addInstalledGames(
packageFilterManager = PackageRepository.packageFilterManager,
pkgNameList = ArrayList(installedPackageNameSet),
updateInstallStatus = true
)

View File

@ -14,7 +14,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.text.TextUtils;
import android.util.AndroidException;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -223,19 +222,8 @@ public class PackageUtils {
if (metaDate != null) {
return metaDate.get(name);
}
} catch (Exception e) {
e.printStackTrace();
if (e instanceof AndroidException) {
// 有些设备会出现 DeadSystemException
SentryHelper.INSTANCE.onEvent(
"GET_META_DATA_ERROR",
"packageName",
packageName,
"exception_digest",
e.getLocalizedMessage()
);
}
} catch (NameNotFoundException e) {
// e.printStackTrace();
}
return null;
}
@ -639,19 +627,8 @@ public class PackageUtils {
try {
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
} catch (Exception e) {
e.printStackTrace();
if (e instanceof AndroidException) {
// 有些设备会出现 DeadSystemException
SentryHelper.INSTANCE.onEvent(
"GET_VERSION_NAME_ERROR",
"packageName",
packageName,
"exception_digest",
e.getLocalizedMessage()
);
}
} catch (NameNotFoundException e) {
// do nothing
}
return null;
}
@ -663,18 +640,8 @@ public class PackageUtils {
try {
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionCode;
} catch (Exception e) {
e.printStackTrace();
if (e instanceof AndroidException) {
// 有些设备会出现 DeadSystemException
SentryHelper.INSTANCE.onEvent(
"GET_VERSION_CODE_ERROR",
"packageName",
packageName,
"exception_digest",
e.getLocalizedMessage()
);
}
} catch (NameNotFoundException e) {
// do nothing
}
return 0;
}
@ -687,18 +654,8 @@ public class PackageUtils {
try {
PackageManager packageManager = context.getApplicationContext().getPackageManager();
return packageManager.getApplicationIcon(packageName);
} catch (Exception e) {
e.printStackTrace();
if (e instanceof AndroidException) {
// 有些设备会出现 DeadSystemException
SentryHelper.INSTANCE.onEvent(
"GET_ICON_ERROR",
"packageName",
packageName,
"exception_digest",
e.getLocalizedMessage()
);
}
} catch (NameNotFoundException e) {
// do nothing
}
return null;
}
@ -749,19 +706,8 @@ public class PackageUtils {
jsonObject.put("version", packageInfo.versionName);
}
return jsonObject;
} catch (Exception e) {
} catch (JSONException | NameNotFoundException e) {
e.printStackTrace();
if (e instanceof AndroidException) {
// 有些设备会出现 DeadSystemException
SentryHelper.INSTANCE.onEvent(
"GET_APP_BASIC_INFO_BY_PACKAGE_NAME",
"packageName",
packageName,
"exception_digest",
e.getLocalizedMessage()
);
}
return jsonObject;
}
}

View File

@ -82,7 +82,6 @@ object ViewPagerFragmentHelper {
const val TYPE_TOOLKIT = "toolkit" // 工具箱
fun createFragment(parentFragment: Fragment?, bundle: Bundle, linkEntity: LinkEntity, isTabWrapper: Boolean): Fragment {
val superiorChain = if (parentFragment is ISuperiorChain) parentFragment else null
return when (linkEntity.type) {
// 游戏详情页
TYPE_GAME -> {
@ -91,12 +90,11 @@ object ViewPagerFragmentHelper {
}
// 我的光环
TYPE_MY_HALO -> {
val superiorChain = if (parentFragment is ISuperiorChain) parentFragment else null
HaloPersonalFragment().setSuperiorChain(superiorChain).with(bundle)
}
// 社区首页
TYPE_COMMUNITY_HOME -> {
CommunityHomeFragment().setSuperiorChain(superiorChain).with(bundle)
}
TYPE_COMMUNITY_HOME -> CommunityHomeFragment().with(bundle)
// 视频信息流
TYPE_VIDEO_STREAM -> {
bundle.putBoolean(EntranceConsts.KEY_IS_HOME_VIDEO, true)
@ -150,11 +148,11 @@ object ViewPagerFragmentHelper {
NewQuestionDetailFragment().with(bundle)
}
// 其他原来带Toolbar的Fragment
else -> createToolbarWrapperFragment(parentFragment, bundle, linkEntity, isTabWrapper)
else -> createToolbarWrapperFragment(bundle, linkEntity, isTabWrapper)
}
}
private fun createToolbarWrapperFragment(parentFragment: Fragment?, bundle: Bundle, entity: LinkEntity, isTabWrapper: Boolean): Fragment {
private fun createToolbarWrapperFragment(bundle: Bundle, entity: LinkEntity, isTabWrapper: Boolean): Fragment {
var className = ReloadFragment::class.java.name
when (entity.type) {

View File

@ -59,8 +59,8 @@ class GameDetailActivity : DownloadToolbarActivity() {
}
override fun getBusinessId(): Pair<String, String> {
val fragment = targetFragment as? GameDetailFragment?
return if (fragment?.arguments != null) {
val fragment = targetFragment as GameDetailFragment
return if (fragment.arguments != null) {
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_GAMEID) ?: "", "")
} else {
super.getBusinessId()

View File

@ -48,7 +48,6 @@ import com.gh.gamecenter.common.entity.SensorsEvent
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.ImageUtils.getIdealImageUrl
import com.gh.gamecenter.common.view.DragListener
import com.gh.gamecenter.common.view.DraggableBigImageView
import com.gh.gamecenter.common.view.Gh_RelativeLayout
import com.gh.gamecenter.core.runOnIoThread
@ -816,18 +815,18 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
if (mBigImageView == null) {
mBigImageView = imageView
}
imageView.setDragListener(object : DragListener {
override fun onRelease(scale: Float) {
imageView.setDragListener(object : DraggableBigImageView.DragListener {
override fun onRelease(draggableBigImageView: DraggableBigImageView, scale: Float) {
updateOriginPosition(mViewPager.currentItem)
performExitAnimation(imageView, scale, isFadeOnly())
performExitAnimation(draggableBigImageView, scale, isFadeOnly())
}
override fun onDrag(fraction: Float) {
override fun onDrag(draggableBigImageView: DraggableBigImageView, fraction: Float) {
mBackgroundView.alpha = 1 - fraction
mIndicatorMask.visibility = View.GONE
}
override fun onRestore(fraction: Float) {
override fun onRestore(draggableBigImageView: DraggableBigImageView, fraction: Float) {
mBackgroundView.alpha = 1F
// mIndicatorMask.goneIf(mUrlList?.size == 1)
if (mUrlList?.size != 1 || mAnswerEntity != null) {

View File

@ -138,6 +138,7 @@ import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.HttpException;
@ -148,8 +149,6 @@ public class MainActivity extends BaseActivity {
public static final String SHOW_AD = "show_ad";
public static final int COUNTDOWN_AD = 100;
private int mCountdownMaxCount = 3;
public static final int COUNTDOWN_SDK_AD = 101;
public static final int COUNTDOWN_SDK_MAX_COUNT = 5;
private int mCountdownCount = 0;
private static final String CURRENT_PAGE = "current_page";
@ -491,7 +490,6 @@ public class MainActivity extends BaseActivity {
if (AdDelegateHelper.INSTANCE.shouldShowStartUpAd(false)) {
ViewGroup startAdContainer = findViewById(R.id.startAdContainer);
ViewGroup sdkStartAdContainer = findViewById(R.id.sdkStartAdContainer);
TextView sdkJumpBtn = findViewById(R.id.sdkJumpBtn);
FrameLayout adsFl = findViewById(R.id.adsFl);
View icpContainer = findViewById(R.id.sdkStartAdIcpContainer);
if (icpContainer != null) {
@ -520,7 +518,6 @@ public class MainActivity extends BaseActivity {
screenHeightInDp,
startAdContainer,
sdkStartAdContainer,
sdkJumpBtn,
adsFl,
(BaseHandler) mBaseHandler,
false,
@ -540,19 +537,13 @@ public class MainActivity extends BaseActivity {
@Override
protected void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == COUNTDOWN_AD || msg.what == COUNTDOWN_SDK_AD) {
if (msg.what == COUNTDOWN_AD) {
mCountdownCount++;
int maxCount;
if (msg.what == COUNTDOWN_AD) {
maxCount = mCountdownMaxCount;
} else {
maxCount = COUNTDOWN_SDK_MAX_COUNT;
}
if (maxCount < mCountdownCount) {
if (mCountdownMaxCount < mCountdownCount) {
AdDelegateHelper.INSTANCE.setShowingSplashAd(false);
hideSplashAd();
if (msg.what == COUNTDOWN_AD && msg.obj instanceof StartupAdEntity) {
if (msg.obj instanceof StartupAdEntity) {
StartupAdEntity ad = (StartupAdEntity) msg.obj;
LinkEntity linkEntity = ad.getJump();
SensorsBridge.trackEvent(
@ -565,26 +556,14 @@ public class MainActivity extends BaseActivity {
linkEntity.getLink(),
"link_text",
linkEntity.getText());
} else if (msg.what == COUNTDOWN_SDK_AD) {
SPUtils.setLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, System.currentTimeMillis());
}
} else {
if (msg.what == COUNTDOWN_AD) {
TextView jumpBtn = findViewById(R.id.jumpBtn);
if (jumpBtn != null) {
jumpBtn.setText(getString(R.string.splash_jump, maxCount - mCountdownCount));
}
Message newMsg = Message.obtain();
newMsg.what = COUNTDOWN_AD;
newMsg.obj = msg.obj;
mBaseHandler.sendMessageDelayed(newMsg, 1000);
} else {
TextView jumpBtn = findViewById(R.id.sdkJumpBtn);
if (jumpBtn != null) {
jumpBtn.setText(getString(R.string.splash_jump, maxCount - mCountdownCount));
}
mBaseHandler.sendEmptyMessageDelayed(COUNTDOWN_SDK_AD, 1000);
}
TextView jumpBtn = findViewById(R.id.jumpBtn);
jumpBtn.setText(getString(R.string.splash_jump, mCountdownMaxCount - mCountdownCount));
Message newMsg = Message.obtain();
newMsg.what = COUNTDOWN_AD;
newMsg.obj = msg.obj;
mBaseHandler.sendMessageDelayed(newMsg, 1000);
}
}
}
@ -622,11 +601,7 @@ public class MainActivity extends BaseActivity {
ExtensionsKt.removeFromParent(startSdkAdContainer, true);
AdDelegateHelper.INSTANCE.cancelSplashAd(this);
}
TextView jumpBtn = findViewById(R.id.sdkJumpBtn);
if (jumpBtn != null) {
jumpBtn.setVisibility(View.GONE);
ExtensionsKt.removeFromParent(jumpBtn, true);
}
View startSdkAdIcpContainer = findViewById(R.id.sdkStartAdIcpContainer);
if (startSdkAdIcpContainer != null) {
startSdkAdIcpContainer.setVisibility(View.GONE);

View File

@ -10,8 +10,6 @@ import android.view.inputmethod.EditorInfo
import android.widget.*
import androidx.core.widget.doAfterTextChanged
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import com.gh.common.util.*
import com.gh.common.util.LogUtils
import com.gh.gamecenter.DisplayType.*
@ -120,7 +118,7 @@ open class SearchActivity : BaseActivity() {
trackSearchPageShow()
}
protected open fun 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) ?: ""
@ -181,11 +179,10 @@ open class SearchActivity : BaseActivity() {
open fun search(type: SearchType, key: String?) {
mSearchType = type
mIsAutoSearchDisabled = true
// 自动搜索,默认搜索,热门搜索,历史搜索,主动搜索,榜单搜索
// 自动搜索,默认搜索,热门搜索,历史搜索,主动搜索
when (type) {
SearchType.AUTO -> handleAutoSearch(key)
SearchType.DEFAULT -> handleDefaultSearch(key)
SearchType.RANK -> handleRankSearch(key)
SearchType.HOT -> handleHotSearch(key)
SearchType.HISTORY -> handleHistorySearch(key)
SearchType.MANUAL -> handleManualSearch()
@ -216,22 +213,6 @@ open class SearchActivity : BaseActivity() {
}
}
protected open fun handleRankSearch(key: String?) {
mSearchKey = key
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
updateDisplayType(GAME_DETAIL)
LogUtils.uploadSearchGame("searching", "搜索页", key, "榜单搜索")
SensorsBridge.trackSearchButtonClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
key ?: "",
TRACK_SEARCH_TYPE_DEFAULT,
mSourceEntrance
)
}
protected open fun handleDefaultSearch(key: String?) {
mSearchKey = key
searchEt.setText(key)
@ -305,72 +286,38 @@ open class SearchActivity : BaseActivity() {
protected open fun provideDao(): ISearchHistoryDao = SearchHistoryDao(this)
open fun updateDisplayType(type: DisplayType) {
val transaction = when (type) {
DEFAULT -> showFragment(
SearchDefaultFragment::class.java.name,
{ SearchDefaultFragment() }
) {
it.arguments = Bundle().also { bundle ->
bundle.putBoolean(SearchDefaultFragment.KEY_IS_GAME_SEARCH, true)
}
}
GAME_DIGEST -> showFragment(
SearchGameIndexFragment::class.java.name,
{ SearchGameIndexFragment() }
) {
removeFragment(SearchGameResultFragment::class.java.name)
it.setParams(mSearchKey ?: "", mSearchType.value)
}
GAME_DETAIL -> showFragment(
SearchGameResultFragment::class.java.name,
{ SearchGameResultFragment() }
) {
removeFragment(SearchGameIndexFragment::class.java.name)
it.setParams(mSearchKey ?: "", mSearchType.value)
}
else -> null
}
transaction?.let {
mDisplayType = type
it.commitAllowingStateLoss()
}
}
protected fun <T : Fragment> showFragment(
tag: String,
onFragmentCreate: () -> T,
onFragmentCreated: ((T) -> Unit)? = null,
): FragmentTransaction {
val transaction = supportFragmentManager.beginTransaction()
var createNewFragment = false
var fragment = supportFragmentManager
.findFragmentByTag(tag)
if (fragment == null) {
createNewFragment = true
fragment = onFragmentCreate.invoke()
}
onFragmentCreated?.invoke(fragment as T)
if (createNewFragment) {
transaction.add(R.id.search_result, fragment, tag)
transaction.addToBackStack(null)
} else if (!fragment.isAdded) {
transaction.show(fragment)
transaction.addToBackStack(null)
}
return transaction
}
when (type) {
DEFAULT -> {
val fragment = supportFragmentManager.findFragmentByTag(SearchDefaultFragment::class.java.name)
?: SearchDefaultFragment().apply {
arguments = Bundle().also { it.putBoolean(SearchDefaultFragment.KEY_IS_GAME_SEARCH, true) }
}
transaction.replace(R.id.search_result, fragment, SearchDefaultFragment::class.java.name)
}
protected fun removeFragment(tag: String) {
val fragment = supportFragmentManager
.findFragmentByTag(tag) ?: return
supportFragmentManager
.beginTransaction()
.remove(fragment)
.commit()
supportFragmentManager.popBackStack()
GAME_DIGEST -> {
val digestListFragment =
supportFragmentManager.findFragmentByTag(SearchGameIndexFragment::class.java.name) as? SearchGameIndexFragment
?: SearchGameIndexFragment()
digestListFragment.setParams(mSearchKey ?: "", mSearchType.value)
transaction.replace(R.id.search_result, digestListFragment, SearchGameIndexFragment::class.java.name)
}
GAME_DETAIL -> {
val detailListFragment =
supportFragmentManager.findFragmentByTag(SearchGameResultFragment::class.java.name) as? SearchGameResultFragment
?: SearchGameResultFragment()
detailListFragment.setParams(mSearchKey ?: "", mSearchType.value)
transaction.replace(R.id.search_result, detailListFragment, SearchGameResultFragment::class.java.name)
}
else -> {
//do nothing
}
}
mDisplayType = type
transaction.commitAllowingStateLoss()
}
@Subscribe(threadMode = ThreadMode.MAIN)
@ -378,7 +325,6 @@ open class SearchActivity : BaseActivity() {
when (search.type) {
SearchType.HISTORY.value -> search(SearchType.HISTORY, search.key)
SearchType.HOT.value -> search(SearchType.HOT, search.key)
SearchType.RANK.value -> search(SearchType.RANK, search.key)
"click" -> DataCollectionUtils.uploadSearchClick(
this, mSearchKey, mSearchType.value, "搜索页面",
@ -395,8 +341,9 @@ open class SearchActivity : BaseActivity() {
}
override fun handleBackPressed(): Boolean {
if (supportFragmentManager.fragments.size == 1) {
finish()
val fragment = supportFragmentManager.findFragmentByTag(SearchDefaultFragment::class.java.name)
if (fragment == null) {
updateDisplayType(DEFAULT)
return true
}
return super.handleBackPressed()
@ -470,8 +417,7 @@ enum class SearchType(var value: String) {
DEFAULT("default"),
HISTORY("history"),
MANUAL("initiative"),
HOT("remen"),
RANK("rank");
HOT("remen");
fun toChinese() = when (this) {
AUTO -> "自动搜索"
@ -479,7 +425,6 @@ enum class SearchType(var value: String) {
HISTORY -> "历史搜索"
MANUAL -> "主动搜索"
HOT -> "热门搜索"
RANK -> "榜单搜索"
}
companion object {

View File

@ -419,7 +419,7 @@ public class SkipActivity extends BaseActivity {
} else {
Bundle newBundle = new Bundle();
newBundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
EntranceUtils.jumpActivityCompat(this, newBundle, null, (resultCode, data) -> {
EntranceUtils.jumpActivity(this, null, newBundle, (resultCode, data) -> {
if(CheckLoginUtils.isLogin()) {
VHelper.INSTANCE.updateAuthorizeInfo(true);
}
@ -442,7 +442,7 @@ public class SkipActivity extends BaseActivity {
break;
default:
EntranceUtils.jumpActivity(this, new Bundle()); // 跳转至首页
break;
return;
}
}
} else if ("market".equals(uri.getScheme())) {

View File

@ -12,10 +12,8 @@ import com.gh.ad.AdDelegateHelper
import com.gh.ad.AdDelegateHelper.requestSplashAd
import com.gh.ad.AdDelegateHelper.shouldShowStartUpAd
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import java.util.*
/**
@ -39,7 +37,6 @@ class SplashAdActivity : BaseActivity() {
if (shouldShowStartUpAd(true)) {
val startAdContainer = findViewById<ViewGroup>(R.id.startAdContainer)
val sdkStartAdContainer = findViewById<ViewGroup>(R.id.sdkStartAdContainer)
val sdkJumpBtn = findViewById<TextView>(R.id.sdkJumpBtn)
val adsFl = findViewById<FrameLayout>(R.id.adsFl)
val icpContainer = findViewById<View>(R.id.sdkStartAdIcpContainer)
@ -61,7 +58,6 @@ class SplashAdActivity : BaseActivity() {
screenHeightInDp,
startAdContainer!!,
sdkStartAdContainer!!,
sdkJumpBtn!!,
adsFl!!,
(mBaseHandler as BaseHandler),
true
@ -85,23 +81,15 @@ class SplashAdActivity : BaseActivity() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
if (msg.what == MainActivity.COUNTDOWN_AD || msg.what == MainActivity.COUNTDOWN_SDK_AD) {
if (msg.what == MainActivity.COUNTDOWN_AD) {
mCountdownCount++
val maxCount = if (msg.what == MainActivity.COUNTDOWN_AD) {
COUNTDOWN_MAX_COUNT
} else {
MainActivity.COUNTDOWN_SDK_MAX_COUNT
}
if (maxCount < mCountdownCount) {
if (COUNTDOWN_MAX_COUNT < mCountdownCount) {
AdDelegateHelper.isShowingSplashAd = false
if (msg.what == MainActivity.COUNTDOWN_SDK_AD) {
SPUtils.setLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, System.currentTimeMillis())
}
finishActivity()
} else {
val jumpBtn = findViewById<TextView>(if (msg.what == MainActivity.COUNTDOWN_AD) R.id.jumpBtn else R.id.sdkJumpBtn)
jumpBtn?.text = getString(R.string.splash_jump, maxCount - mCountdownCount)
mBaseHandler.sendEmptyMessageDelayed(msg.what, 1000)
val jumpBtn = findViewById<TextView>(R.id.jumpBtn)
jumpBtn.text = getString(R.string.splash_jump, COUNTDOWN_MAX_COUNT - mCountdownCount)
mBaseHandler.sendEmptyMessageDelayed(MainActivity.COUNTDOWN_AD, 1000)
}
}
}

View File

@ -17,11 +17,8 @@ import androidx.core.text.color
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.common.dialog.NewPrivacyPolicyDialogFragment
import com.gh.common.util.DeviceTokenUtils
import com.gh.common.util.DialogUtils
import com.gh.common.util.*
import com.gh.common.util.GameSubstituteRepositoryHelper.updateGameSubstituteRepository
import com.gh.common.util.PackageHelper
import com.gh.common.util.PackageUtils
import com.gh.common.util.UsageStatsHelper.checkAndPostUsageStats
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.base.activity.BaseActivity
@ -31,7 +28,6 @@ import com.gh.gamecenter.common.tracker.TrackerLogger
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
import com.gh.gamecenter.core.provider.IPushProvider
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
@ -59,9 +55,6 @@ class SplashScreenActivity : BaseActivity() {
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
mIsNewForThisVersion = HaloApp.getInstance().isNewForThisVersion
HaloApp.getInstance().isBrandNewInstall = SPUtils.getBoolean(Constants.SP_BRAND_NEW_USER, true)
if (HaloApp.getInstance().isBrandNewInstall) {
SPUtils.setLong(Constants.SP_BRAND_NEW_FIRST_LAUNCH_TIME, System.currentTimeMillis())
}
// 用户不是新版本,但应用最后更新时间不是上次的时间代表用户重新安装了当前版本
if (!mIsNewForThisVersion) {
@ -281,12 +274,6 @@ class SplashScreenActivity : BaseActivity() {
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
SensorsBridge.setOAID(HaloApp.getInstance().oaid)
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
val registrationId = pushProvider?.getRegistrationId(this)
if (!registrationId.isNullOrEmpty()) {
SensorsBridge.profileAppend(KEY_REGISTRATION_ID, registrationId)
}
}
private fun prefetchData() {
@ -318,7 +305,6 @@ class SplashScreenActivity : BaseActivity() {
companion object {
private const val KEY_REGISTRATION_ID = "registration_id"
const val HONOR_CULPRIT_ID = 12324
const val HONOR_CULPRIT_CHANNEL = "荣耀通道"

View File

@ -24,7 +24,6 @@ import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.viewholder.KcSelectGameViewHolder;
import com.gh.gamecenter.common.retrofit.Response;
import com.gh.gamecenter.common.utils.BitmapUtils;
import com.gh.gamecenter.common.utils.FileUtils;
import com.gh.gamecenter.core.utils.MtaHelper;
import com.gh.gamecenter.core.utils.TimeUtils;
import com.gh.gamecenter.core.utils.ToastUtils;
@ -86,7 +85,7 @@ public class CleanApkAdapter extends BaseRecyclerAdapter<KcSelectGameViewHolder>
Observable.create(emitter -> {
// 扫描和获取apk数据 分步操作 尽量避免 StackoverflowError
FindAllAPKPath(Environment.getExternalStorageDirectory());
FindAllAPKPath(new File(FileUtils.getDownloadDir(mContext)));
FindAllAPKPath(mContext.getFilesDir());
LoadApkData();
emitter.onComplete();
})

View File

@ -652,12 +652,12 @@ class DetailViewHolder(
builder.addHandler(LandPageAddressHandler())
builder.addHandler(OverseaDownloadHandler())
builder.addHandler(CheckDownloadHandler())
builder.setProcessEndCallback(mGameEntity.id) { asVGame: Boolean, isSubscribe: Any? ->
builder.setProcessEndCallback { asVGame: Boolean, isSubscribe: Any? ->
download(asVGame, isSubscribe as Boolean)
}
} else {
builder.addHandler(VersionNumberHandler())
builder.setProcessEndCallback(mGameEntity.id) { _: Boolean?, _: Any? ->
builder.setProcessEndCallback { _: Boolean?, _: Any? ->
DownloadDialog.showDownloadDialog(
mViewHolder.context,
mGameEntity,

View File

@ -4,10 +4,11 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import com.gh.gamecenter.common.utils.viewModelProvider
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.utils.viewModelProvider
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.search.SearchDefaultFragment
@ -63,16 +64,19 @@ class AmwaySearchActivity : SearchActivity() {
}
override fun updateDisplayType(type: DisplayType) {
val transaction = when (type) {
DisplayType.DEFAULT -> showFragment(
SearchDefaultFragment::class.java.name,
{ AmwaySearchDefaultFragment() }
)
val transaction = supportFragmentManager.beginTransaction()
when (type) {
DisplayType.DEFAULT -> {
val fragment = supportFragmentManager.findFragmentByTag(SearchDefaultFragment::class.java.name)
?: AmwaySearchDefaultFragment()
transaction.replace(R.id.search_result, fragment, SearchDefaultFragment::class.java.name)
}
else -> showFragment(
AmwaySearchListFragment::class.java.name,
{ AmwaySearchListFragment() }
)
else -> {
val fragment = supportFragmentManager.findFragmentByTag(AmwaySearchListFragment::class.java.name)
?: AmwaySearchListFragment()
transaction.replace(R.id.search_result, fragment, AmwaySearchListFragment::class.java.name)
}
}
mDisplayType = type
transaction.commitAllowingStateLoss()

View File

@ -33,7 +33,7 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
mViewModel.playedGames.observeNonNull(viewLifecycleOwner) {
defaultViewModel?.isExistHotSearch = it.isNotEmpty()
updateView()
mBinding.searchDiscoveryList.run {
mBinding.hotList.run {
layoutManager = LinearLayoutManager(context)
adapter = AmwaySearchAdapter(context, mViewModel, "安利墙搜索-最近玩过").apply { setData(it) }
}
@ -45,7 +45,7 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
override fun provideDao(): ISearchHistoryDao = AmwaySearchDao()
override fun initView() {
mBinding = mAmwayBinding.searchContent
mBinding.searchDiscoveryHeadContainer.headTitle.text = "最近玩过"
mBinding.hotHeadContainer.headTitle.text = "最近玩过"
mBinding.historyFlexContainer.setLimitHeight(mFlexMaxHeight)
updateHistorySearchView(null)

View File

@ -57,7 +57,6 @@ class AmwaySearchListFragment : ToolbarFragment() {
when (it) {
LoadStatus.INIT_LOADING -> {
hideError()
hideRvList()
showLoading()
hideNoDataHint()
}
@ -65,19 +64,16 @@ class AmwaySearchListFragment : ToolbarFragment() {
hideError()
hideLoading()
hideNoDataHint()
showRvList()
}
LoadStatus.INIT_FAILED -> {
hideLoading()
hideNoDataHint()
showError()
hideRvList()
}
LoadStatus.INIT_EMPTY -> {
showNoDataHint()
hideError()
hideLoading()
hideRvList()
}
else -> {
// do nothing
@ -86,14 +82,6 @@ class AmwaySearchListFragment : ToolbarFragment() {
}
}
private fun hideRvList() {
mBinding.recyclerView.visibility = View.GONE
}
private fun showRvList() {
mBinding.recyclerView.visibility = View.VISIBLE
}
private fun showLoading() {
mBinding.loadingContainer.visibility = View.VISIBLE
}

View File

@ -44,7 +44,6 @@ class AmwaySearchViewModel(application: Application) : AndroidViewModel(applicat
mTempSearchKey = searchKey
currentSearchKey = searchKey
loadStatus.postValue(LoadStatus.INIT_LOADING)
searchGames.postValue(emptyList())
RetrofitManager
.getInstance().api
.getSearchGame(Config.API_HOST + "games:search?keyword=" + searchKey + "&view=anliwall" + "&channel=" + HaloApp.getInstance().channel + "&version=" + BuildConfig.VERSION_NAME)

View File

@ -160,7 +160,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
val ownerAd = downloadManagerAd?.ownerAd
val showOnFailed = downloadManagerAd?.displayRule?.onFailedAction == "show"
if ((showThirdPartyAd && thirdPartyAd != null) || (!showThirdPartyAd && thirdPartyAd != null && ownerAd == null)) {
initThirdPartyAd(downloadManagerAd, thirdPartyAd) { isSuccess ->
initThirdPartyAd(thirdPartyAd) { isSuccess ->
mBinding.maskView.goneIf(!isSuccess)
if (!isSuccess && ownerAd != null && showOnFailed) {
mSlideInterval = ownerAd.adSource?.sliderInterval ?: -1
@ -182,34 +182,12 @@ class DownloadFragment : BaseFragment_TabLayout() {
}
}
private fun initThirdPartyAd(adConfig: AdConfig?, thirdPartyAd: AdConfig.ThirdPartyAd, callback: (isSuccess: Boolean) -> Unit) {
val onAdShowAction = {
SensorsBridge.trackEvent("ThirdPartyAdShow",
"ad_source", thirdPartyAd.sourceName,
"ad_id", thirdPartyAd.slotId,
"ad_format", adConfig?.typeChinese ?: "",
"ad_placement", "下载管理",
"ad_space_id", adConfig?.id ?: "",
"ad_space_name", adConfig?.name ?: ""
)
}
val onAdClickAction = {
SensorsBridge.trackEvent("ThirdPartyAdClick",
"ad_source", thirdPartyAd.sourceName,
"ad_id", thirdPartyAd.slotId,
"ad_format", adConfig?.typeChinese ?: "",
"ad_placement", "下载管理",
"ad_space_id", adConfig?.id ?: "",
"ad_space_name", adConfig?.name ?: ""
)
}
private fun initThirdPartyAd(thirdPartyAd: AdConfig.ThirdPartyAd, callback: (isSuccess: Boolean) -> Unit) {
AdDelegateHelper.requestThirdPartyBannerAd(
this,
mBinding.adContainer,
thirdPartyAd,
DisplayUtils.getScreenWidthInDp(requireActivity()),
onAdShowAction,
onAdClickAction,
callback
)
}
@ -248,7 +226,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
if (it.isNullOrEmpty() && adConfig.displayRule.adSource == AdDelegateHelper.AD_TYPE_OWNER &&
adConfig.displayRule.onFailedAction == "show" && adConfig.thirdPartyAd != null) {
// 自有广告游戏为空时,显示第三方广告
initThirdPartyAd(adConfig, adConfig.thirdPartyAd) { isSuccess ->
initThirdPartyAd(adConfig.thirdPartyAd) { isSuccess ->
mBinding.maskView.goneIf(!isSuccess)
if (isSuccess) {
SPUtils.setLong(Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME, System.currentTimeMillis())

View File

@ -6,7 +6,7 @@ class AdConfig(
@SerializedName("_id")
val id: String = "",
val name: String,
val location: String, // 广告插入位置。光环启动halo_launch 下载管理download_manager 游戏搜索game_search 畅玩启动helper_launch
val location: String, // 广告插入位置。光环启动halo_launch 下载管理download_manager 游戏搜索game_search 助手启动helper_launch
val type: String, // 广告位类型。开屏广告launch 信息流广告native banner 广告banner 插屏广告interstitial
val position: Int, // 定位,不存在的时候返回:-1
@SerializedName("display_rules")
@ -18,19 +18,12 @@ class AdConfig(
@SerializedName("owner_ads")
val ownerAd: OwnerAdEntity? = null,
) {
companion object {
const val TYPE_LAUNCH = "launch"
const val TYPE_NATIVE = "native"
const val TYPE_BANNER = "banner"
const val TYPE_INTERSTITIAL = "interstitial"
}
val typeChinese
get() = when (type) {
TYPE_LAUNCH -> "开屏"
TYPE_NATIVE -> "信息流"
TYPE_BANNER -> "banner"
TYPE_INTERSTITIAL -> "插屏"
"launch" -> "开屏"
"native" -> "信息流"
"banner" -> "banner"
"interstitial" -> "插屏"
else -> ""
}

View File

@ -26,8 +26,7 @@ data class BottomTab(
@SerializedName("is_default_page")
var default: Boolean = false, // 是否为默认显示页
var guide: Guide? = null, // 引导文案
var diverter: DiverterEntity? = null, // 分流器
var isTransparentStyle: Boolean = false, // 本地字段透明底部Tab
var isTransparentStyle: Boolean = false // 本地字段透明底部Tab
) : Parcelable {
@Parcelize
data class SearchStyle(

View File

@ -1,31 +0,0 @@
package com.gh.gamecenter.entity
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.parcelize.Parcelize
@Parcelize
class DiverterData(
@SerializedName("diverter_id")
val diverterId: String = "",
@SerializedName("diverter_name")
val diverterName: String = "",
@SerializedName("branch_id")
val branchId: String = "",
@SerializedName("branch_name")
val branchName: String = "",
@SerializedName("branch_type")
val branchType: String = "",
@SerializedName("inprocess_time")
val inprocessTime: Int = 0,
@SerializedName("bypass_visit_time")
val bypassVisitTime: Int = 0,
@SerializedName("link_id")
val linkId: String = "",
@SerializedName("link_type")
val linkType: String = "",
@SerializedName("link_text")
val linkText: String = "",
@SerializedName("bypass_status")
val bypassStatus: Int = 0,
): Parcelable

View File

@ -1,15 +0,0 @@
package com.gh.gamecenter.entity
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.parcelize.Parcelize
@Parcelize
class DiverterEntity(
@SerializedName("module_id")
val moduleId: String = "",
@SerializedName("module_index")
val moduleIndex: Int = -1,
@SerializedName("diverter_data")
val diverterData: DiverterData = DiverterData()
): Parcelable

View File

@ -1,4 +1,4 @@
package com.gh.gamecenter.common.entity
package com.gh.gamecenter.entity
import android.net.Uri
import android.os.Parcelable

View File

@ -23,9 +23,6 @@ import com.airbnb.lottie.SimpleColorFilter
import com.airbnb.lottie.model.KeyPath
import com.airbnb.lottie.value.LottieValueCallback
import com.gh.common.browse.BrowseTimer
import com.gh.common.iinterface.ISuperiorChain
import com.gh.common.prioritychain.CommunityHomeGuideHandler
import com.gh.common.prioritychain.PriorityChain
import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.NewLogUtils
@ -45,6 +42,7 @@ import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.databinding.FragmentCommunityHomeBinding
import com.gh.gamecenter.databinding.LayoutCommunityHomeVideoGuideBinding
import com.gh.gamecenter.databinding.TabItemCommunityBinding
import com.gh.gamecenter.eventbus.EBSkip
import com.gh.gamecenter.eventbus.EBTypeChange
@ -83,8 +81,6 @@ class CommunityHomeFragment : LazyFragment() {
private var mNavigationBitmap: Bitmap? = null
private var mShowVideo = true
private var mBottomTabId = ""
private val mPriorityChain by lazy { PriorityChain() }
private var mSuperiorChain: ISuperiorChain? = null
private val browseTimer = BrowseTimer()
.withResult {
@ -160,12 +156,6 @@ class CommunityHomeFragment : LazyFragment() {
})
}
private fun addHomeVideoGuideHandler() {
val decorView = activity?.window?.decorView as? FrameLayout
val communityHomeGuideHandler = CommunityHomeGuideHandler(21, requireContext(), decorView, mBinding?.videoLottie)
mPriorityChain.addHandler(communityHomeGuideHandler)
}
override fun initRealView() {
super.initRealView()
@ -176,7 +166,24 @@ class CommunityHomeFragment : LazyFragment() {
mMainWrapperViewModel?.bottomTabListLiveData?.observe(this) { tabList ->
mBinding?.videoAndSearchContainer?.goneIf(!mShowVideo) {
val decorView = requireActivity().window.decorView as? FrameLayout
addHomeVideoGuideHandler()
if (SPUtils.getBoolean(Constants.SP_SHOW_COMMUNITY_HOME_VIDEO_GUIDE, true)) {
val guideLayoutBinding = LayoutCommunityHomeVideoGuideBinding.inflate(
LayoutInflater.from(requireContext()),
decorView,
true
)
guideLayoutBinding.root.setOnClickListener { view ->
decorView?.removeView(view)
SPUtils.setBoolean(Constants.SP_SHOW_COMMUNITY_HOME_VIDEO_GUIDE, false)
mBinding?.videoLottie?.playAnimation()
SPUtils.setLong(
Constants.SP_COMMUNITY_HOME_VIDEO_LOTTIE_LAST_PLAY_TIME,
System.currentTimeMillis()
)
}
}
// 每日首次进入社区tab视频lottie播放3次
val lastPlayTime = SPUtils.getLong(Constants.SP_COMMUNITY_HOME_VIDEO_LOTTIE_LAST_PLAY_TIME, 0L) / 1000
@ -278,14 +285,6 @@ class CommunityHomeFragment : LazyFragment() {
DisplayUtils.transparentStatusBar(requireActivity())
DisplayUtils.setLightStatusBar(requireActivity(), !mIsDarkModeOn)
NewLogUtils.logCommunityHomeEvent("view_community")
mSuperiorChain?.registerInferiorChain(mPriorityChain)
}
override fun onFragmentPause() {
super.onFragmentPause()
mSuperiorChain?.unregisterInferiorChain(mPriorityChain)
}
fun setCurrentItem(index: Int) {
@ -837,11 +836,6 @@ class CommunityHomeFragment : LazyFragment() {
fun getTopBgView() = mBinding?.topBg
fun setSuperiorChain(superiorChain: ISuperiorChain?): CommunityHomeFragment {
this.mSuperiorChain = superiorChain
return this
}
companion object {
var TAB_SELECTED_COLOR: Int = R.color.text_primary
var TAB_DEFAULT_COLOR: Int = R.color.community_forum_more

View File

@ -129,40 +129,39 @@ class ForumOrUserSearchActivity : SearchActivity() {
}
override fun updateDisplayType(type: DisplayType) {
val transaction = when (type) {
DisplayType.DEFAULT -> showFragment(
SearchDefaultFragment::class.java.name,
onFragmentCreate = { ForumOrUserSearchDefaultFragment() }
) { fragment ->
fragment.arguments = intent.extras
}.apply {
val key = searchEt.text.toString().trim { it <= ' ' }
if (key.isNotEmpty()) {
val stayTime = (System.currentTimeMillis() - startPageTime) / 1000
if (mEntrance != ForumDetailFragment.ENTRANCE) {
NewFlatLogUtils.logViewSearchList(stayTime, key)
} else {
NewFlatLogUtils.logViewBbsSearchList(stayTime, key, mBbsId)
}
val transaction = supportFragmentManager.beginTransaction()
when (type) {
DisplayType.DEFAULT -> {
val fragment = supportFragmentManager.findFragmentByTag(SearchDefaultFragment::class.java.name)
?: ForumOrUserSearchDefaultFragment()
fragment.arguments = intent.extras
transaction.replace(R.id.search_result, fragment, SearchDefaultFragment::class.java.name)
val key = searchEt.text.toString().trim { it <= ' ' }
if (key.isNotEmpty()) {
val stayTime = (System.currentTimeMillis() - startPageTime) / 1000
if (mEntrance != ForumDetailFragment.ENTRANCE) {
NewFlatLogUtils.logViewSearchList(stayTime, key)
} else {
NewFlatLogUtils.logViewBbsSearchList(stayTime, key, mBbsId)
}
}
}
else -> if (mEntrance != ForumDetailFragment.ENTRANCE) {
showFragment(
ForumOrUserSearchFragment::class.java.name,
{ ForumOrUserSearchFragment() }
) { fragment ->
fragment.setSearchKeyAndType(mSearchKey ?: "", mSearchType.value)
}
else -> {
if (mEntrance != ForumDetailFragment.ENTRANCE) {
val fragment =
supportFragmentManager.findFragmentByTag(ForumOrUserSearchFragment::class.java.name) as? ForumOrUserSearchFragment
?: ForumOrUserSearchFragment()
fragment.setSearchKeyAndType(mSearchKey ?: "", mSearchType.value)
transaction.replace(R.id.search_result, fragment, ForumOrUserSearchFragment::class.java.name)
} else {
showFragment(
ForumOrUserSearchFragment::class.java.name,
{ ForumContentSearchListFragment() }
) { fragment ->
fragment.setSearchKeyAndType(mSearchKey ?: "", mSearchType.value)
fragment.arguments = intent.extras
}
}.apply {
val fragment =
supportFragmentManager.findFragmentByTag(ForumContentSearchListFragment::class.java.name) as? ForumContentSearchListFragment
?: ForumContentSearchListFragment()
fragment.setSearchKeyAndType(mSearchKey ?: "", mSearchType.value)
fragment.arguments = intent.extras
transaction.replace(R.id.search_result, fragment, ForumContentSearchListFragment::class.java.name)
}
startPageTime = System.currentTimeMillis()
}
}

View File

@ -42,14 +42,14 @@ class ForumOrUserSearchDefaultFragment : SearchDefaultFragment() {
override fun initView() {
mBinding = FragmentSearchDefaultBinding.bind(mCachedView)
mBinding.searchDiscoveryTagHeadContainer.root.visibility = View.GONE
mBinding.searchDiscoveryTagFlexContainer.visibility = View.GONE
mBinding.hotTagHeadContainer.root.visibility = View.GONE
mBinding.hotTagFlexContainer.visibility = View.GONE
if (mEntrance == "论坛首页" || mEntrance == "搜索栏") {
mBinding.searchDiscoveryHeadContainer.headTitle.text = "热门论坛"
mBinding.hotHeadContainer.headTitle.text = "热门论坛"
mViewModel.getForumSearchHotContent()
} else {
mBinding.searchDiscoveryHeadContainer.root.visibility = View.GONE
mBinding.searchDiscoveryList.visibility = View.GONE
mBinding.hotHeadContainer.root.visibility = View.GONE
mBinding.hotList.visibility = View.GONE
}
val params = mBinding.historyHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams
params.topMargin = 0.5f.dip2px()

View File

@ -23,7 +23,7 @@ class ReloadFragment: BaseLazyFragment() {
super.onCreate(savedInstanceState)
mBinding.reuseLoading.root.visibility = View.VISIBLE
mBinding.reuseNoConnection.connectionReloadTv.setOnClickListener {
MainWrapperRepository.getInstance().init()
MainWrapperRepository.getInstance().getDataUnion()
mBinding.reuseNoConnection.root.visibility = View.GONE
mBinding.reuseLoading.root.visibility = View.VISIBLE
}

View File

@ -2,8 +2,8 @@ package com.gh.gamecenter.game.columncollection.detail
import android.content.Intent
import android.os.Bundle
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.updateStatusBarColor
@ -34,8 +34,8 @@ class ColumnCollectionDetailActivity : ToolBarActivity() {
}
override fun getBusinessId(): Pair<String, String> {
val fragment = targetFragment as? ColumnCollectionDetailFragment?
return if (fragment?.arguments != null) {
val fragment = targetFragment as ColumnCollectionDetailFragment
return if (fragment.arguments != null) {
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "", "")
} else {
super.getBusinessId()

View File

@ -36,8 +36,8 @@ class CommonCollectionDetailActivity : ToolBarActivity() {
}
override fun getBusinessId(): Pair<String, String> {
val fragment = targetFragment as? CommonCollectionDetailFragment?
return if (fragment?.arguments != null) {
val fragment = targetFragment as CommonCollectionDetailFragment
return if (fragment.arguments != null) {
Pair(
fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "",
fragment.requireArguments().getString(EntranceConsts.KEY_BLOCK_ID) ?: ""

View File

@ -36,8 +36,8 @@ class CustomCommonCollectionDetailActivity : ToolBarActivity() {
}
override fun getBusinessId(): Pair<String, String> {
val fragment = targetFragment as? CustomCommonCollectionDetailFragment?
return if (fragment?.arguments != null) {
val fragment = targetFragment as CustomCommonCollectionDetailFragment
return if (fragment.arguments != null) {
Pair(
fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "",
fragment.requireArguments().getString(EntranceConsts.KEY_BLOCK_ID) ?: ""

View File

@ -3,6 +3,7 @@ package com.gh.gamecenter.game.upload
import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import android.provider.MediaStore
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextPaint
@ -28,21 +29,18 @@ import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.callback.OnListClickListener
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.feature.selector.LocalMediaActivity
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.choosepic.ChoosePicAdapter
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.SpanBuilder
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.databinding.FragmentGameUploadBinding
import com.gh.gamecenter.feature.entity.InstallGameEntity
import com.gh.gamecenter.feature.game.SelectGameAdapter
import com.gh.gamecenter.feature.selector.ChooseType
import com.halo.assistant.HaloApp
import com.lightgame.utils.Util_System_Keyboard
import com.lightgame.utils.Utils
import com.zhihu.matisse.Matisse
import com.zhihu.matisse.internal.utils.PathUtils
import io.reactivex.disposables.Disposable
import okhttp3.MediaType
import okhttp3.RequestBody
@ -88,6 +86,7 @@ class GameUploadFragment : ToolbarFragment() {
mViewModel.upLoadSuccess.observe(viewLifecycleOwner, Observer {
if (it) {
ToastUtils.showToast("上传成功")
MtaHelper.onEvent("游戏上传", "游戏上传", "上传成功")
mUploadDialog.dismiss()
requireActivity().finish()
} else {
@ -120,11 +119,17 @@ class GameUploadFragment : ToolbarFragment() {
5,
object : OnListClickListener {
override fun <T : Any?> onListClick(view: View?, position: Int, data: T) {
val intent = LocalMediaActivity.getIntent(requireContext(), ChooseType.IMAGE, 1, "游戏上传")
MtaHelper.onEvent("游戏上传", "游戏图片", "添加图片")
val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startActivityForResult(intent, MEDIA_STORE_REQUEST)
}
}
) {
MtaHelper.onEvent(
"游戏上传",
"游戏图片",
"删除图片"
)
}
mAdapter?.setPicItem(R.layout.game_upload_pic_item)
mAdapter?.setSuggestAddPicIcon(R.drawable.icon_pic_add)
@ -142,13 +147,19 @@ class GameUploadFragment : ToolbarFragment() {
1,
object : OnListClickListener {
override fun <T : Any?> onListClick(view: View?, position: Int, data: T) {
MtaHelper.onEvent("游戏上传", "游戏图标", "添加图片")
PermissionHelper.checkStoragePermissionBeforeAction(requireActivity()) {
val intent = LocalMediaActivity.getIntent(requireContext(), ChooseType.IMAGE, 1, "游戏上传")
val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
startActivityForResult(intent, MEDIA_ICON_STORE_REQUEST)
}
}
}
) {
MtaHelper.onEvent(
"游戏上传",
"游戏图标",
"删除图片"
)
}
mIconAdapter?.setPicItem(R.layout.game_upload_pic_item)
mIconAdapter?.setSuggestAddPicIcon(R.drawable.icon_pic_add)
@ -183,15 +194,18 @@ class GameUploadFragment : ToolbarFragment() {
private fun initListener() {
mBinding.chooseGameLl.setOnClickListener {
MtaHelper.onEvent("游戏上传", "安装包", "点我选择")
showSelectDialog()
}
mBinding.gameIsNetworkingRg.setOnCheckedChangeListener { _, checkedId ->
when (checkedId) {
R.id.gameNetworkingRb -> {
mIsOnline = "yes"
MtaHelper.onEvent("游戏上传", "是否联网", "需要联网")
}
R.id.gameNoNetworkingRb -> {
mIsOnline = "no"
MtaHelper.onEvent("游戏上传", "是否联网", "无需联网")
}
}
}
@ -199,12 +213,15 @@ class GameUploadFragment : ToolbarFragment() {
when (checkedId) {
R.id.gameLanguageChineseRb -> {
mGameLanguage = "中文"
MtaHelper.onEvent("游戏上传", "游戏语言", "中文")
}
R.id.gameLanguageEnglishRb -> {
mGameLanguage = "英文"
MtaHelper.onEvent("游戏上传", "游戏语言", "英文")
}
R.id.gameLanguageOtherRb -> {
mGameLanguage = "其他"
MtaHelper.onEvent("游戏上传", "游戏语言", "其他")
}
}
}
@ -212,17 +229,21 @@ class GameUploadFragment : ToolbarFragment() {
when (checkedId) {
R.id.gameTypeLocalRb -> {
mGameType = "local"
MtaHelper.onEvent("游戏上传", "游戏类型", "单机")
}
R.id.gameTypeOnlineRb -> {
mGameType = "online"
MtaHelper.onEvent("游戏上传", "游戏类型", "网游")
}
R.id.gameTypeOtherRb -> {
mGameType = "other"
MtaHelper.onEvent("游戏上传", "游戏类型", "其他")
}
}
}
mBinding.addGameLabeTv.setOnClickListener {
MtaHelper.onEvent("游戏上传", "游戏标签", "添加标签")
if (mTags.size < mMaxTagSize) {
showAddTagDialog()
} else {
@ -235,6 +256,7 @@ class GameUploadFragment : ToolbarFragment() {
}
private fun commit() {
MtaHelper.onEvent("游戏上传", "提交", "提交")
if (TextUtils.isEmpty(mBinding.tvChoose.text.toString())) {
ToastUtils.showToast("请先选择游戏安装包")
return
@ -449,9 +471,11 @@ class GameUploadFragment : ToolbarFragment() {
}
back.setOnClickListener {
MtaHelper.onEvent("游戏上传", "安装包", "关闭")
mSelectGameDialog?.cancel()
}
manualBtn.setOnClickListener {
MtaHelper.onEvent("游戏上传", "安装包", "从设备上选择")
val intent = CleanApkActivity.getIntent(requireContext(), true)
PermissionHelper.checkManageAllFilesOrStoragePermissionBeforeAction(requireActivity()) {
startActivityForResult(intent, CHOOSE_LOCAL_APK)
@ -475,20 +499,32 @@ class GameUploadFragment : ToolbarFragment() {
super.onActivityResult(requestCode, resultCode, data)
if (data == null) return
if (requestCode == MEDIA_STORE_REQUEST || requestCode == MEDIA_ICON_STORE_REQUEST) {
val selectedPaths = Matisse.obtainResult(data) ?: return
val picturePath = PathUtils.getPath(requireContext(), selectedPaths[0])
val selectedImage = data.data ?: return
val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
Utils.log("picturePath = $picturePath")
val cursor = requireContext().contentResolver.query(selectedImage, filePathColumn, null, null, null)
?: return
cursor.moveToFirst()
val file = File(picturePath)
if (file.length() > 5 * 1024 * 1024) {
ToastUtils.showToast(getString(R.string.pic_max_hint, 5))
} else {
if (requestCode == MEDIA_STORE_REQUEST) {
mAdapter!!.addFileList(picturePath)
try {
val columnIndex = cursor.getColumnIndex(filePathColumn[0])
val picturePath = cursor.getString(columnIndex)
cursor.close()
Utils.log("picturePath = $picturePath")
val file = File(picturePath)
if (file.length() > 5 * 1024 * 1024) {
ToastUtils.showToast(getString(R.string.pic_max_hint, 5))
} else {
mIconAdapter!!.addFileList(picturePath)
if (requestCode == MEDIA_STORE_REQUEST) {
mAdapter!!.addFileList(picturePath)
} else {
mIconAdapter!!.addFileList(picturePath)
}
}
} catch (e: Exception) {
ToastUtils.showToast(e.message ?: "")
}
} else if (requestCode == CHOOSE_LOCAL_APK) {
val packageName = data.getStringExtra(EntranceConsts.KEY_PACKAGENAME) ?: ""
@ -574,6 +610,7 @@ class GameUploadFragment : ToolbarFragment() {
labelTv.text = tag
labelView.findViewById<View>(R.id.picDelIv).setOnClickListener {
if (mTags.contains(tag)) {
MtaHelper.onEvent("游戏上传", "游戏标签", "删除标签")
mBinding.gameLabelFl.removeView(labelView)
mTags.remove(tag)
mBinding.gameLabelFl.goneIf(mTags.isEmpty())

View File

@ -182,9 +182,7 @@ class AddGamesDialogFragment : BaseDialogFragment() {
return super.onBack()
}
private fun showGuidePopupWindow(): PopupWindow? {
if (!isAdded) return null
private fun showGuidePopupWindow(): PopupWindow {
val guideBinding = LayoutGameCollectionAddGamesGuideBinding.inflate(layoutInflater)
val popupWindow = BugFixedPopupWindow(
guideBinding.root,

View File

@ -7,8 +7,8 @@ import android.view.View
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.common.exposure.ExposureSource
/**
* 游戏单详情
@ -30,8 +30,8 @@ class GameCollectionDetailActivity : ToolBarActivity() {
}
override fun getBusinessId(): Pair<String, String> {
val fragment = targetFragment as? GameCollectionDetailFragment?
return if (fragment?.arguments != null) {
val fragment = targetFragment as GameCollectionDetailFragment
return if (fragment.arguments != null) {
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_GAME_COLLECTION_ID) ?: "", "")
} else {
super.getBusinessId()

View File

@ -16,13 +16,12 @@ import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.common.util.NewLogUtils
import com.gh.gamecenter.common.utils.PermissionHelper
import com.gh.gamecenter.R
import com.gh.gamecenter.feature.selector.LocalMediaActivity
import com.gh.gamecenter.common.utils.setRootBackgroundDrawable
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.toDrawable
import com.gh.gamecenter.databinding.DialogChooseGameCollectionCoverTypeBinding
import com.gh.gamecenter.feature.selector.ChooseType
import com.gh.gamecenter.gamecollection.publish.GameCollectionEditActivity.Companion.REQUEST_CODE_IMAGE
import com.gh.gamecenter.qa.editor.LocalMediaActivity
import com.halo.assistant.HaloApp
class ChooseGameCollectionCoverTypeDialog : BaseDialogFragment() {
@ -43,7 +42,7 @@ class ChooseGameCollectionCoverTypeDialog : BaseDialogFragment() {
startActivityForResult(
LocalMediaActivity.getIntent(
requireContext(),
ChooseType.IMAGE,
LocalMediaActivity.ChooseType.IMAGE,
1,
"创建游戏单"
), REQUEST_CODE_IMAGE

View File

@ -285,7 +285,7 @@ class GameCollectionSquareAdapter(
}
})
addOnScrollListener(ScrollEventListener(this).apply {
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
binding.bannerIndicator.onPageScrolled(

View File

@ -410,7 +410,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
}
})
addOnScrollListener(ScrollEventListener(this).apply {
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
mDefaultBinding.headerContainer.bannerIndicator.onPageScrolled(

View File

@ -63,10 +63,7 @@ import com.gh.gamecenter.databinding.*
import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.entity.RecommendPopupEntity
import com.gh.gamecenter.eventbus.*
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PluginLocation
import com.gh.gamecenter.feature.entity.SimpleGame
import com.gh.gamecenter.feature.entity.TagStyleEntity
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.feature.eventbus.EBConcernChanged
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.utils.ApkActiveUtils
@ -74,7 +71,11 @@ import com.gh.gamecenter.feature.utils.SentryHelper
import com.gh.gamecenter.forum.detail.ForumDetailActivity
import com.gh.gamecenter.gamedetail.cloudarchive.CloudArchiveFragment
import com.gh.gamecenter.gamedetail.desc.DescFragment
import com.gh.gamecenter.gamedetail.dialog.*
import com.gh.gamecenter.gamedetail.dialog.GameBigEventDialog
import com.gh.gamecenter.gamedetail.dialog.GameDetailMoreDialog
import com.gh.gamecenter.gamedetail.dialog.GameTagsDialog
import com.gh.gamecenter.gamedetail.dialog.SpecialDownloadDialogFragment
import com.gh.gamecenter.gamedetail.dialog.SpecialDownloadVisibilityViewModel
import com.gh.gamecenter.gamedetail.entity.ContentCardEntity
import com.gh.gamecenter.gamedetail.entity.NewGameDetailEntity
import com.gh.gamecenter.gamedetail.entity.Video
@ -148,6 +149,8 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
private var mShowConcernOnMenu = false
private var mSpecialDownloadDetailFragmentIsShowing = false
private val mFragmentsList = ArrayList<Fragment>()
private val mTabTitleList = ArrayList<String>()
private val mTabTypeList = ArrayList<String>() // tab 类型的列表,用于确定某个类型的 tab 在第几个位置
@ -164,7 +167,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|| downloadEntity.status == DownloadStatus.redirected
) {
// 特殊下载弹窗
if (isSpecialDownloadDialogAvailable(downloadEntity) && !isSpecialDownloadDetailFragmentIsShowing()) {
if (isSpecialDownloadDialogAvailable() && !mSpecialDownloadDetailFragmentIsShowing) {
updateSpecialDownloadDialogIcon(true)
if (downloadEntity.status == DownloadStatus.add) {
@ -865,10 +868,8 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
showConcernIconAtBottomBarIfAvailable()
val downloadEntitySnapshot = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
if (isSpecialDownloadDialogAvailable(downloadEntitySnapshot)
&& downloadEntitySnapshot != null) {
if (isSpecialDownloadDialogAvailable()
&& DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity) != null) {
updateSpecialDownloadDialogIcon(true)
}
@ -1179,11 +1180,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
}
private fun doShowAlertDialog(dialog: GameEntity.Dialog) {
SensorsBridge.trackEvent("GameDetailDialogShow",
"game_id", mGameEntity?.id ?: "",
"game_name", mGameEntity?.name ?: "",
"game_type", mGameEntity?.categoryChinese ?: ""
)
DialogHelper.showDialogWithHtmlContent(
requireContext(),
dialog.title,
@ -1191,33 +1187,8 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
dialog.confirmButton.text.toString(),
dialog.closeButtonText,
{
SensorsBridge.trackEvent("GameDetailDialogClick",
"game_id", mGameEntity?.id ?: "",
"game_name", mGameEntity?.name ?: "",
"game_type", mGameEntity?.categoryChinese ?: "",
"link_type", dialog.confirmButton.type ?: "",
"link_id", dialog.confirmButton.link ?: "",
"link_text", dialog.confirmButton.linkText ?: "",
"button_name", dialog.confirmButton.text.toString()
)
dialog.confirmButton.text = dialog.confirmButton.linkText
DirectUtils.directToLinkPage(requireContext(), dialog.confirmButton, mEntrance, "")
},
{
SensorsBridge.trackEvent("GameDetailDialogClick",
"game_id", mGameEntity?.id ?: "",
"game_name", mGameEntity?.name ?: "",
"game_type", mGameEntity?.categoryChinese ?: "",
"button_name", dialog.closeButtonText
)
},
{
SensorsBridge.trackEvent("GameDetailDialogClick",
"game_id", mGameEntity?.id ?: "",
"game_name", mGameEntity?.name ?: "",
"game_type", mGameEntity?.categoryChinese ?: "",
"button_name", "关闭弹窗"
)
}
)
}
@ -2591,15 +2562,12 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
* 2. 未获取到游戏详情数据
* 3. 当前游戏 APK 不为 1 个
* 4. 当前游戏类型不为畅玩
* 5. 当前游戏不是双下载时使用本地下载进行下载
*/
private fun isSpecialDownloadDialogAvailable(downloadEntity: DownloadEntity? = null): Boolean {
private fun isSpecialDownloadDialogAvailable(): Boolean {
if (Config.getNewApiSettingsEntity()?.install?.questionTip?.linkEntity == null) return false
if (mNewGameDetailEntity == null || mGameEntity == null) return false
if (mGameEntity?.getApk()?.size != 1) return false
if (downloadEntity?.asVGame() == true) return false
if (downloadEntity?.isSimulatorGame() == true) return false
if (downloadEntity?.isLocalDownloadInDualDownloadMode() == true) return false
if (GameUtils.shouldPerformAsVGame(mGameEntity!!)) return false
return true
}
@ -2617,6 +2585,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
if (fragment == null) {
if (!visibilityViewModel.specialDownloadVisibleLiveData.hasObservers()) {
visibilityViewModel.specialDownloadVisibleLiveData.observe(viewLifecycleOwner) {
mSpecialDownloadDetailFragmentIsShowing = it
updateSpecialDownloadDialogIcon(visible = !it)
}
}
@ -2632,10 +2601,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
}
}
private fun isSpecialDownloadDetailFragmentIsShowing(): Boolean {
return childFragmentManager.findFragmentByTag(TAG_SPECIAL_DOWNLOAD_DIALOG) != null
}
override fun scrollToTop() {
val fragment = mFragmentsList.safelyGetInRelease(mBodyBinding.gamedetailVp.currentItem)
if (fragment is IScrollable && fragment.isAdded) {

View File

@ -17,7 +17,6 @@ import com.gh.common.iinterface.ISuperiorChain
import com.gh.common.prioritychain.CustomFloatingWindowHandler
import com.gh.common.prioritychain.PriorityChain
import com.gh.common.prioritychain.PullDownPushHandler
import com.gh.common.prioritychain.VideoHandler
import com.gh.common.util.DefaultSearchHintHelper
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
@ -469,10 +468,10 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
binding = FragmentCustomBinding.bind(mCachedView)
scrollCalculatorHelper = ScrollCalculatorHelper(binding.gameList, R.id.autoVideoView, 0, false)
buildPriorityChain()
scrollCalculatorHelper = ScrollCalculatorHelper(binding.gameList, R.id.autoVideoView, 0)
adapter = CustomPageAdapter(
viewModel,
viewLifecycleOwner,
@ -513,11 +512,9 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
private fun buildPriorityChain() {
val floatingWindowHandler = CustomFloatingWindowHandler(23)
val videoHandler = VideoHandler(24, scrollCalculatorHelper)
priorityChain.addHandler(pullDownPushHandler)
priorityChain.addHandler(floatingWindowHandler)
priorityChain.addHandler(videoHandler)
(parentFragment as? BaseTabWrapperFragment)?.addTabGuideHandlerIfExists(priorityChain)
viewModel.floatingWindows.observe(viewLifecycleOwner, EventObserver {

View File

@ -146,7 +146,7 @@ class CustomFoldSlideLargeImageItemAdapter(
if (dataList.isEmpty()) {
0
} else {
Int.MAX_VALUE / 2 - (Int.MAX_VALUE / 2) % dataList.size
Int.MAX_VALUE / 2 - Int.MAX_VALUE % dataList.size
}
class ImageItemViewHolder(

View File

@ -140,7 +140,7 @@ class CommonContentHomeSLideListUi(
}
binding.recyclerView.addOnScrollListener(scrollEventListener.apply {
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrollStateChanged(state: Int) {
super.onPageScrollStateChanged(state)

View File

@ -163,7 +163,7 @@ class CommonContentHomeSlideWithCardsUi(
}
})
binding.recyclerView.addOnScrollListener(ScrollEventListener(binding.recyclerView).apply {
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
_currentDataPosition = adapter.getDataPosition(position)
}

View File

@ -101,7 +101,7 @@ class NotificationColumnViewHolder(
private val scrollEventListener by lazy(LazyThreadSafetyMode.NONE) {
ScrollEventListener(binding.rvNotification).apply {
registerOnPageChangeCallback(object : OnPageChangeCallback() {
setOnPageChangeCallback(object : OnPageChangeCallback() {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
if (positionOffset > 0F) {
// position 代表的是正在移出屏幕的 itemView 的位置

View File

@ -132,7 +132,7 @@ class HomeSlideListViewHolder(
updateImmersiveColor(slideList[0].placeholderColor.hexStringToIntColor())
binding.recyclerView.addOnScrollListener(ScrollEventListener(binding.recyclerView).apply {
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
var lastStatePosition = -1
var lastScrollState = RecyclerView.SCROLL_STATE_IDLE

View File

@ -153,7 +153,7 @@ class HomeSlideWithCardsViewHolder(
}
})
binding.recyclerView.addOnScrollListener(ScrollEventListener(binding.recyclerView).apply {
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
var lastStatePosition = -1
var lastScrollState = RecyclerView.SCROLL_STATE_IDLE

View File

@ -5,6 +5,7 @@ import android.os.Handler
import android.os.Looper
import android.view.View
import android.view.ViewGroup
import androidx.core.view.forEach
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.constant.Constants
@ -14,28 +15,13 @@ import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.video.detail.CustomManager
import com.halo.assistant.HaloApp
class ScrollCalculatorHelper(
val mListRv: RecyclerView,
private val mPlayId: Int,
private val mRangeTop: Int,
private var isEnabled: Boolean = true
) {
class ScrollCalculatorHelper(val mListRv: RecyclerView, private val mPlayId: Int, private val mRangeTop: Int) {
private var mFirstVisible = -1
private var mLastVisible = 0
private var mRunnable: PlayRunnable? = null
private val mPlayHandler = Handler(Looper.getMainLooper())
var currentPlayer: AutomaticVideoView? = null
fun enableAndPlayIfValid() {
isEnabled = true
if (mListRv.isAttachedToWindow
&& mListRv.scrollState == RecyclerView.SCROLL_STATE_IDLE) {
playVideo(mListRv)
}
}
fun onScrollStateChanged(scrollState: Int) {
if (scrollState == RecyclerView.SCROLL_STATE_IDLE) {
playVideo(mListRv)
@ -94,7 +80,7 @@ class ScrollCalculatorHelper(
}
private fun playVideo(view: RecyclerView?) {
if (view == null || !view.isAttachedToWindow || !isEnabled) return
if (view == null) return
val layoutManager = view.layoutManager
var gsyBaseVideoPlayer: AutomaticVideoView
for (i in mFirstVisible until mLastVisible + 1) {

View File

@ -130,24 +130,6 @@ object PackagesManager {
return null
}
/**
* 根据游戏 ID 获取已安装的信息
*
* @param gameId 游戏 Id
* @return 如果为空:未安装
*/
fun getInstalledDataByGameId(gameId: String?): GameInstall? {
if (TextUtils.isEmpty(gameId)) {
return null
}
for (gameInstall in mInstalledList) {
if (gameInstall.id == gameId) {
return gameInstall
}
}
return null
}
/**
* 判断包名是否可以更新

View File

@ -3,12 +3,20 @@ 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.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
/**
* 小游戏-搜索页面
@ -18,21 +26,22 @@ class MiniGameSearchActivity : SearchActivity() {
override fun provideDao(): ISearchHistoryDao = MiniGameSearchDao()
override fun updateDisplayType(type: DisplayType) {
val transaction = when(type) {
DisplayType.DEFAULT -> showFragment(
SearchDefaultFragment::class.java.name,
{ MiniGameSearchDefaultFragment() }
) {
it.arguments = Bundle().also { bundle ->
bundle.putBoolean(SearchDefaultFragment.KEY_IS_GAME_SEARCH, true)
}
val transaction = supportFragmentManager.beginTransaction()
when(type) {
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 -> showFragment(
SearchGameResultFragment::class.java.name,
{ MiniGameSearchResultFragment() }
) {
it.setParams(mSearchKey ?: "", mSearchType.value)
else -> {
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

View File

@ -11,9 +11,11 @@ import com.gh.gamecenter.room.AppDatabase
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
class PackageFilterManager {
object PackageFilterManager {
private var mPackageKey = "" // 用于下次获取包名-游戏信息的 key
private val mPendingPackageNameSet by lazy { hashSetOf<String>() } // 因遇到异常而等待下次操作更新的包名列表
private val mValidPackageNameSet by lazy { hashSetOf<String>() } // 已被收录的游戏包名列表
val packageKey: String
get() = mPackageKey
@ -32,7 +34,7 @@ class PackageFilterManager {
) {
if (appendOnly) {
// 添加因为异常而没能正常更新的包名列表
packageList.addAll(PackageRepository.mPendingPackageNameSet)
packageList.addAll(mPendingPackageNameSet)
}
RetrofitManager.getInstance()
@ -42,12 +44,12 @@ class PackageFilterManager {
.subscribe(object : BiResponse<PackageFilter>() {
override fun onSuccess(data: PackageFilter) {
mPackageKey = data.key
PackageRepository.mPendingPackageNameSet.clear()
mPendingPackageNameSet.clear()
val partialPackageList = arrayListOf<String>()
if (!appendOnly) {
PackageRepository.mValidPackageNameSet.clear()
mValidPackageNameSet.clear()
tryWithDefaultCatch {
AppDatabase.getInstance().packageFilterDao().deleteAllPackageName()
}
@ -61,13 +63,13 @@ class PackageFilterManager {
}
partialPackageList.add(packageName)
PackageRepository.mValidPackageNameSet.add(packageName)
mValidPackageNameSet.add(packageName)
}
if (appendOnly) {
callbackClosure?.invoke(ArrayList(partialPackageList))
} else {
callbackClosure?.invoke(ArrayList(PackageRepository.mValidPackageNameSet))
callbackClosure?.invoke(ArrayList(mValidPackageNameSet))
}
}
@ -75,7 +77,7 @@ class PackageFilterManager {
super.onFailure(exception)
if (appendOnly) {
PackageRepository.mPendingPackageNameSet.addAll(packageList)
mPendingPackageNameSet.addAll(packageList)
} else {
if (exception is retrofit2.HttpException && exception.code() == 403) {
// 403 代表 key 过期,需要重新获取
@ -89,13 +91,28 @@ class PackageFilterManager {
for (packageEntity in packageEntityList) {
// 依然为已安装状态才加入到有效包名列表中
if (PackageUtils.isInstalled(HaloApp.getInstance(), packageEntity.packageName)) {
PackageRepository.mValidPackageNameSet.add(packageEntity.packageName)
mValidPackageNameSet.add(packageEntity.packageName)
}
}
callbackClosure?.invoke(ArrayList(PackageRepository.mValidPackageNameSet))
callbackClosure?.invoke(ArrayList(mValidPackageNameSet))
}
}
})
}
/**
* 该包名是否有效 (即是否已被光环收录)
*/
fun isPackageValid(packageName: String): Boolean {
return mValidPackageNameSet.contains(packageName)
}
/**
* 是否存在因为接口异常而导致没有查询收录情况的包名列表
*/
fun hasPendingPackage(): Boolean {
return mPendingPackageNameSet.isEmpty()
}
}

View File

@ -6,6 +6,7 @@ import android.text.TextUtils
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.common.filter.RegionSettingHelper
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.common.util.GameUtils
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.R
@ -15,29 +16,19 @@ import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.ObservableUtil
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.secondOrNull
import com.gh.gamecenter.common.utils.toArrayList
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.entity.AppEntity
import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.entity.PackageGame
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.GameInstall
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.packagehelper.PackageRepository.gameInstalled
import com.gh.gamecenter.packagehelper.PackageRepository.gameUpdate
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.Single
import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.EventBus
import org.json.JSONException
@ -83,10 +74,6 @@ object PackageRepository {
fun changeRecentVaPlayed() {
_recentVaPlayedChanged.postValue(Unit)
}
val packageFilterManager = PackageFilterManager()
var mPendingPackageNameSet = hashSetOf<String>() // 因遇到异常而等待下次操作更新的包名列表
var mValidPackageNameSet = hashSetOf<String>() // 已被收录的游戏包名列表
/**
* 预留方法,如果想手动初始化可以调用
@ -102,51 +89,18 @@ object PackageRepository {
if (gameUpdate.isNotEmpty()) gameUpdate.clear()
if (mInstalledPkgSet.isNotEmpty()) mInstalledPkgSet.clear()
Single.zip<Result<Any?>, Result<Any?>, Result<Any?>>(
Single.create { emitter ->
val list = PackageUtils.getAllPackageName(mApplication)
uploadAppList()
initFilterPackage(list) { filteredList ->
emitter.onSuccess(Result.success(null))
val list = PackageUtils.getAllPackageName(mApplication)
mInstalledPkgSet.addAll(filteredList)
notifyInstallPkgData()
loadInstalledGameDigestAndNotifyData(packageFilterManager.packageKey, filteredList)
}
uploadAppList()
initFilterPackage(list) { filteredList ->
mIsInitialisingData = false
},
Single.create { emitter ->
// 畅玩游戏更新
var allGames = VHelper.getAllVGameSnapshots()
if (allGames.isEmpty()) {
VHelper.refreshVGameSnapshot()
allGames = VHelper.getAllVGameSnapshots()
}
val allGamePkgNames = allGames.map { it.packageName }.toArrayList()
if (allGamePkgNames.isNotEmpty()) {
val packageFilterManager = PackageFilterManager()
updateFilterPackage(packageFilterManager, allGamePkgNames) {
emitter.onSuccess(Result.success(null))
loadInstalledGameDigestAndNotifyData(
packageKey = packageFilterManager.packageKey,
filteredList = allGamePkgNames,
isVGame = true
)
}
}
}
) { t1, t2 -> Result.success(null) }.subscribe(object : SingleObserver<Result<Any?>> {
override fun onSubscribe(d: Disposable) {
}
mInstalledPkgSet.addAll(filteredList)
notifyInstallPkgData()
override fun onSuccess(t: Result<Any?>) {
mIsInitialisingData = false
}
override fun onError(e: Throwable) {
}
})
loadInstalledGameDigestAndNotifyData(filteredList)
}
loadGhzsUpdate()
}
@ -159,15 +113,18 @@ object PackageRepository {
list: MutableList<String>,
callbackClosure: ((list: ArrayList<String>) -> Unit)? = null
) {
packageFilterManager.updateFilterPackages(list, false, callbackClosure)
PackageFilterManager.updateFilterPackages(list, false) {
callbackClosure?.invoke(it)
}
}
private fun updateFilterPackage(
packageFilterManager: PackageFilterManager,
list: MutableList<String>,
callbackClosure: ((list: ArrayList<String>) -> Unit)? = null
) {
packageFilterManager.updateFilterPackages(list, true, callbackClosure)
PackageFilterManager.updateFilterPackages(list, true) {
callbackClosure?.invoke(it)
}
}
/**
@ -178,8 +135,7 @@ object PackageRepository {
PackageUtils.getGhVersionName(),
PackageUtils.getGhVersionCode(),
HaloApp.getInstance().channel,
Build.VERSION.SDK_INT
)
Build.VERSION.SDK_INT)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<AppEntity>() {
@ -252,7 +208,6 @@ object PackageRepository {
*/
@SuppressLint("CheckResult")
private fun loadInstalledGameDigestAndNotifyData(
packageKey: String,
filteredList: ArrayList<String>,
isVGame: Boolean = false,
updateInstallStatus: Boolean = false
@ -267,7 +222,7 @@ object PackageRepository {
}, Any())
while (++page <= maxPageCount) {
var observable = mNewApi.getPackageGames(packageKey, page, PAGE_SIZE)
var observable = mNewApi.getPackageGames(PackageFilterManager.packageKey, page, PAGE_SIZE)
.subscribeOn(Schedulers.io())
observable.subscribe(object : BiResponse<List<PackageGame>>() {
@ -283,8 +238,7 @@ object PackageRepository {
}
for (game in validGames) {
val shouldNotifyChanges =
validateGameAndPostChanges(gh_id, game, pkgName, isVGame, updateInstallStatus)
val shouldNotifyChanges = validateGameAndPostChanges(gh_id, game, pkgName, isVGame, updateInstallStatus)
if (!isNotifyUpdate && shouldNotifyChanges) {
isNotifyUpdate = true
}
@ -305,13 +259,11 @@ object PackageRepository {
/**
* 验证游戏并且更新数据
*/
private fun validateGameAndPostChanges(
ghId: Any?,
game: GameEntity,
pkgName: String,
isVGame: Boolean,
updateInstallStatus: Boolean
): Boolean {
private fun validateGameAndPostChanges(ghId: Any?,
game: GameEntity,
pkgName: String,
isVGame: Boolean,
updateInstallStatus: Boolean): Boolean {
if (ghId == null || ghId == game.id) {
gameInstalled.add(GameInstall.transformGameInstall(game, pkgName, isVGame))
mInstalledGameList.add(game)
@ -320,8 +272,7 @@ object PackageRepository {
addCurrentlyInstalledVersionIfValid(game)
if (updateInstallStatus) {
EventBus.getDefault()
.post(EBPackage(EBPackage.TYPE_INSTALLED, pkgName, game.getApk().firstOrNull()?.version))
EventBus.getDefault().post(EBPackage(EBPackage.TYPE_INSTALLED, pkgName, game.getApk().firstOrNull()?.version))
}
if (isCanUpdate || isCanPluggable) {
@ -405,8 +356,7 @@ object PackageRepository {
) {
// 使用了镜像的游戏;插件化关闭的游戏;无需插件化
if (game.shouldUseMirrorInfo()
|| apk.plugin == "close"
) {
|| apk.plugin == "close") {
return false
}
@ -466,11 +416,8 @@ object PackageRepository {
* @param pkgName 已安装的游戏包名
* @param cachedGameEntity 缓存的游戏实体,若存在免去再请求接口的过程
*/
fun addInstalledGame(
packageFilterManager: PackageFilterManager,
pkgName: String,
cachedGameEntity: GameEntity? = null
) {
fun addInstalledGame(pkgName: String,
cachedGameEntity: GameEntity? = null) {
mInstalledPkgSet.add(pkgName)
notifyInstallPkgData()
@ -481,8 +428,7 @@ object PackageRepository {
game = cachedGameEntity,
pkgName = pkgName,
isVGame = false,
updateInstallStatus = false
)
updateInstallStatus = false)
if (containsUpdate) {
notifyGameUpdateData()
@ -490,9 +436,8 @@ object PackageRepository {
} else {
val list = arrayListOf(pkgName)
updateFilterPackage(packageFilterManager, list) {
updateFilterPackage(list) {
loadInstalledGameDigestAndNotifyData(
packageKey = packageFilterManager.packageKey,
filteredList = list,
updateInstallStatus = false
)
@ -508,11 +453,9 @@ object PackageRepository {
* @param isVGame 是否为畅玩游戏
* @param updateInstallStatus 是否更新安装状态
*/
fun addInstalledGames(
packageFilterManager: PackageFilterManager,
pkgNameList: ArrayList<String>,
isVGame: Boolean = false,
updateInstallStatus: Boolean = false,
fun addInstalledGames(pkgNameList: ArrayList<String>,
isVGame: Boolean = false,
updateInstallStatus: Boolean = false,
) {
// 畅玩游戏不添加至本地的已安装包名列表中
if (!isVGame) {
@ -522,9 +465,8 @@ object PackageRepository {
}
notifyInstallPkgData()
updateFilterPackage(packageFilterManager, pkgNameList) {
updateFilterPackage(pkgNameList) {
loadInstalledGameDigestAndNotifyData(
packageKey = packageFilterManager.packageKey,
filteredList = pkgNameList,
isVGame = isVGame,
updateInstallStatus = updateInstallStatus
@ -584,13 +526,6 @@ object PackageRepository {
changeRecentVaPlayed()
}
/**
* 是否存在因为接口异常而导致没有查询收录情况的包名列表
*/
fun hasPendingPackage(): Boolean {
return mPendingPackageNameSet.isEmpty()
}
private fun notifyGameInstallData() {
PackagesManager.initGameInstall(ArrayList(gameInstalled))
gameInstalledLiveData.postValue(ArrayList(gameInstalled))

View File

@ -63,13 +63,7 @@ class PackageViewModel(
* @param cachedGameEntity 缓存的游戏实体
*/
fun addInstalledGame(pkgName: String?, cachedGameEntity: GameEntity? = null) {
if (!TextUtils.isEmpty(pkgName)) {
mRepository.addInstalledGame(
mRepository.packageFilterManager,
pkgName!!,
cachedGameEntity
)
}
if (!TextUtils.isEmpty(pkgName)) mRepository.addInstalledGame(pkgName!!, cachedGameEntity)
}
/**
@ -87,7 +81,9 @@ class PackageViewModel(
// 未同意获取已安装应用权限时不进行数据初始化
if (!PackageHelper.isGetInstalledPackagesAgreed()) return
if (mRepository.gameInstalled.size == 0 || mRepository.hasPendingPackage()) {
if (mRepository.gameInstalled.size == 0
|| PackageFilterManager.hasPendingPackage()
) {
PackageHelper.initPackageRelatedData();
}
}

View File

@ -699,6 +699,8 @@ class HaloPersonalFragment : BaseLazyFragment() {
} catch (e: Exception) {
} as? ITestCase)?.apply {
addInstallExternalGameButton(mStubBinding.otherItems)
addInstallPluginButton(mStubBinding.otherItems)
addInstallPlugin32Button(mStubBinding.otherItems)
}
}
@ -855,7 +857,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
}
})
addOnScrollListener(ScrollEventListener(this).apply {
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
setOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
mStubBinding.bannerIndicator.onPageScrolled(

View File

@ -10,20 +10,20 @@ import android.view.View
import androidx.annotation.RequiresApi
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.gh.common.util.*
import com.gh.gamecenter.CropImageActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.feature.selector.LocalMediaActivity
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.databinding.FragmentBackgroundPreviewBinding
import com.gh.gamecenter.feature.entity.BackgroundImageEntity
import com.gh.gamecenter.feature.selector.ChooseType
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserViewModel
import com.gh.gamecenter.qa.editor.LocalMediaActivity
import com.halo.assistant.HaloApp
import com.zhihu.matisse.Matisse
import io.reactivex.Single
@ -282,7 +282,7 @@ class BackgroundPreviewFragment : ToolbarFragment() {
startActivityForResult(
LocalMediaActivity.getIntent(
requireContext(),
ChooseType.IMAGE,
LocalMediaActivity.ChooseType.IMAGE,
1,
"个性背景"
), MEDIA_STORE_REQUEST

View File

@ -12,13 +12,12 @@ import com.gh.gamecenter.CropImageActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.feature.selector.LocalMediaActivity
import com.gh.gamecenter.common.utils.PermissionHelper
import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.common.view.GridSpacingItemColorDecoration
import com.gh.gamecenter.databinding.PersonalityBackgroundFragmentBinding
import com.gh.gamecenter.feature.selector.ChooseType
import com.gh.gamecenter.login.user.UserViewModel
import com.gh.gamecenter.qa.editor.LocalMediaActivity
import com.halo.assistant.HaloApp
import com.zhihu.matisse.Matisse
@ -76,7 +75,7 @@ class PersonalityBackgroundFragment : ToolbarFragment() {
startActivityForResult(
LocalMediaActivity.getIntent(
requireContext(),
ChooseType.IMAGE,
LocalMediaActivity.ChooseType.IMAGE,
1,
"个性背景"
), MEDIA_STORE_REQUEST

View File

@ -28,7 +28,6 @@ import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.baselist.ListFragment
import com.gh.gamecenter.common.constant.EntranceConsts.KEY_COMMENT_ID
import com.gh.gamecenter.common.eventbus.EBReuse
import com.gh.gamecenter.feature.selector.LocalMediaActivity
import com.gh.gamecenter.common.syncpage.SyncDataEntity
import com.gh.gamecenter.common.syncpage.SyncFieldConstants
import com.gh.gamecenter.common.syncpage.SyncPageRepository
@ -39,10 +38,10 @@ import com.gh.gamecenter.databinding.ItemCommentEditImageBinding
import com.gh.gamecenter.eventbus.EBCommentSuccess
import com.gh.gamecenter.feature.entity.CommentEntity
import com.gh.gamecenter.feature.eventbus.EBDeleteComment
import com.gh.gamecenter.feature.selector.ChooseType
import com.gh.gamecenter.qa.comment.CommentActivity.Companion.GAME_COLLECTION_ID
import com.gh.gamecenter.qa.comment.CommentActivity.Companion.GAME_COLLECTION_TITLE
import com.gh.gamecenter.qa.comment.CommentActivity.Companion.QUESTION_ID
import com.gh.gamecenter.qa.editor.LocalMediaActivity
import com.halo.assistant.HaloApp
import com.lightgame.utils.Util_System_Keyboard
import com.lightgame.utils.Utils
@ -495,7 +494,7 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
val maxChooseCount = 9 - mViewModel.pictureList.size
val intent = LocalMediaActivity.getIntent(
requireContext(),
ChooseType.IMAGE,
LocalMediaActivity.ChooseType.IMAGE,
maxChooseCount,
"评论列表"
)
@ -522,6 +521,11 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
return
}
if (mShowInputOnly) {
// Fuck pm
MtaHelper.onEvent("帖子详情", "评论详情-全部回复", "发送")
}
mViewModel.postPictureAndComment(content, mCommentEntity)
}

View File

@ -0,0 +1,148 @@
package com.gh.gamecenter.qa.editor
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import android.widget.ImageView
import android.widget.PopupWindow
import androidx.core.content.ContextCompat
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.updateStatusBarColor
import com.halo.assistant.HaloApp
import com.zhihu.matisse.Matisse
import com.zhihu.matisse.MimeType
import com.zhihu.matisse.internal.entity.Album
import com.zhihu.matisse.internal.entity.SelectionSpec
import com.zhihu.matisse.internal.model.AlbumCollection
/**
* 选择本地视频/图片
*/
class LocalMediaActivity : ToolBarActivity(), AlbumCollection.AlbumCallbacks {
private var mLocalMediaFragment: LocalMediaFragment? = null
private lateinit var mAlbumsSpinner: VideoAlbumsSpanner
private lateinit var mAlbumsAdapter: VideoAlbumsAdapter
private val mAlbumCollection = AlbumCollection()
private var mIsFirstAlbumLoad = true
private var mChooseType = ""
override fun getLayoutId(): Int = R.layout.activity_video_tablayout_viewpager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
mChooseType = intent.getStringExtra(EntranceConsts.KEY_TYPE) ?: ""
if (mChooseType == ChooseType.VIDEO.value) {
setNavigationTitle("本地视频")
} else {
setNavigationTitle("本地图片")
}
mLocalMediaFragment = LocalMediaFragment().apply { arguments = intent.extras }
supportFragmentManager.beginTransaction()
.replace(R.id.container, mLocalMediaFragment!!, LocalMediaFragment::class.java.name)
.commitAllowingStateLoss()
initAlbumsSpinner()
mTitleTv.setOnClickListener {
mAlbumsSpinner.show(findViewById<View>(R.id.container).height)
setPhotoNavigationTitle(true)
}
}
private fun initAlbumsSpinner() {
mAlbumsSpinner = VideoAlbumsSpanner(this)
mAlbumsAdapter = VideoAlbumsAdapter(this)
mAlbumsSpinner.setPopupAnchorView(findViewById(R.id.normal_toolbar))
mAlbumsSpinner.setAdapter(mAlbumsAdapter)
mAlbumsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
mAlbumCollection.setStateCurrentSelection(position)
mAlbumsAdapter.cursor.moveToPosition(position)
val album = Album.valueOf(mAlbumsAdapter.cursor)
if (album.isAll && SelectionSpec.getInstance().capture) {
album.addCaptureCount()
}
if (mLocalMediaFragment?.isAdded == true) {
mLocalMediaFragment?.loadVideos(album)
}
}
}
mAlbumsSpinner.setDismissListener(PopupWindow.OnDismissListener {
setPhotoNavigationTitle(false)
})
//必须加这行代码,[SelectionSpec]是单例模式下次使用必须先更新MimeType
val mimeType = if (mChooseType == ChooseType.VIDEO.value) {
MimeType.ofVideo()
} else {
MimeType.ofImage()
}
val maxChooseCount = intent.getIntExtra(EntranceConsts.KEY_CHOOSE_MAX_COUNT, 1)
Matisse.from(this).choose(mimeType).showSingleMediaType(true).maxSelectable(maxChooseCount)
mAlbumCollection.onCreate(this, this)
mAlbumCollection.loadAlbums()
}
override fun onAlbumLoad(cursor: Cursor?) {
if (mIsFirstAlbumLoad) {
mIsFirstAlbumLoad = false
mAlbumsAdapter.swapCursor(cursor)
mBaseHandler.post {
cursor?.moveToPosition(mAlbumCollection.currentSelection)
val album = Album.valueOf(cursor)
if (album.isAll && SelectionSpec.getInstance().capture) {
album.addCaptureCount()
}
if (mLocalMediaFragment?.isAdded == true) {
mLocalMediaFragment?.loadVideos(album)
}
}
}
}
override fun onAlbumReset() {
}
private fun setPhotoNavigationTitle(up: Boolean) {
val drawable = ContextCompat.getDrawable(
HaloApp.getInstance().application,
if (up) R.drawable.ic_video_arrow_up else R.drawable.ic_video_arrow_down
)
val arrowIv = findViewById<ImageView>(R.id.arrowIv)
arrowIv?.setImageDrawable(drawable)
}
override fun isAutoResetViewBackgroundEnabled(): Boolean = true
override fun onDarkModeChanged() {
super.onDarkModeChanged()
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
}
companion object {
fun getIntent(context: Context, chooseType: ChooseType, maxChooseCount: Int = 1, entrance: String): Intent {
return Intent(context, LocalMediaActivity::class.java).apply {
putExtra(EntranceConsts.KEY_TYPE, chooseType.value)
putExtra(EntranceConsts.KEY_CHOOSE_MAX_COUNT, maxChooseCount)
putExtra(EntranceConsts.KEY_ENTRANCE, entrance)
}
}
}
enum class ChooseType(val value: String) {
VIDEO("video"),
IMAGE("image")
}
}

View File

@ -0,0 +1,95 @@
package com.gh.gamecenter.qa.editor
import android.content.Context
import android.database.Cursor
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.common.util.*
import com.gh.gamecenter.R
import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toDrawable
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.databinding.LocalVideoItemBinding
import com.zhihu.matisse.internal.entity.Item
import com.zhihu.matisse.internal.ui.adapter.RecyclerViewCursorAdapter
import com.zhihu.matisse.internal.utils.PathUtils
class LocalMediaAdapter(
val context: Context,
val mChooseType: String,
val maxChooseSize: Int,
val entrance: String,
val callback: (ArrayList<Item>) -> Unit
) : RecyclerViewCursorAdapter<LocalVideoPreviewViewHolder>(null) {
private val mSelectedMediaList = arrayListOf<Item>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocalVideoPreviewViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.local_video_item, parent, false)
return LocalVideoPreviewViewHolder(LocalVideoItemBinding.bind(view))
}
override fun onBindViewHolder(holder: LocalVideoPreviewViewHolder, cursor: Cursor?, position: Int) {
val item = Item.valueOf(cursor)
holder.binding.durationTv.goneIf(mChooseType == LocalMediaActivity.ChooseType.IMAGE.value)
val path = "file:///${PathUtils.getPath(context, item.contentUri)}"
ImageUtils.displayResizeMedia(holder.binding.preview, path, 200, 200)
holder.binding.durationTv.text = TimeUtils.formatVideoDuration(item.duration / 1000)
val drawable = if (mSelectedMediaList.contains(item)) {
if (maxChooseSize == 1) {
R.drawable.ic_choose_media_selected.toDrawable()
} else {
R.drawable.ic_choose_media_bg.toDrawable()
}
} else {
R.drawable.ic_choose_media_normal.toDrawable()
}
holder.binding.checkImageView.setImageDrawable(drawable)
if (mSelectedMediaList.contains(item) && maxChooseSize > 1) {
holder.binding.chooseCountTv.visibility = View.VISIBLE
holder.binding.chooseCountTv.text = (mSelectedMediaList.indexOf(item) + 1).toString()
} else {
holder.binding.chooseCountTv.visibility = View.GONE
}
holder.itemView.setOnClickListener {
if (mSelectedMediaList.contains(item)) {
mSelectedMediaList.remove(item)
notifyDataSetChanged()
callback.invoke(mSelectedMediaList)
} else {
if (maxChooseSize == 1) {
mSelectedMediaList.clear()
}
if (mSelectedMediaList.size < maxChooseSize) {
mSelectedMediaList.add(item)
notifyDataSetChanged()
callback.invoke(mSelectedMediaList)
} else {
if (mChooseType == LocalMediaActivity.ChooseType.IMAGE.value) {
ToastUtils.showToast("至多选择${maxChooseSize}张图片")
} else {
ToastUtils.showToast("至多选择${maxChooseSize}条视频")
}
}
}
if (entrance == "发帖子" || entrance == "发提问帖" || entrance == "发视频帖") {
val publishContentType = if (entrance == "发帖子") "帖子" else if (entrance == "发提问帖") "提问帖" else "视频帖"
val publishMediaType = if (mChooseType == LocalMediaActivity.ChooseType.IMAGE.value) "图片" else "视频"
NewLogUtils.logChooseMedia("click_radio_button", publishContentType, publishMediaType)
}
}
}
override fun getItemViewType(position: Int, cursor: Cursor?): Int {
return 0
}
fun getSelectedMediaList(): ArrayList<Item> {
return mSelectedMediaList
}
}
class LocalVideoPreviewViewHolder(val binding: LocalVideoItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)

View File

@ -0,0 +1,191 @@
package com.gh.gamecenter.qa.editor
import android.app.Activity
import android.content.Intent
import android.database.Cursor
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import androidx.core.os.bundleOf
import androidx.recyclerview.widget.GridLayoutManager
import com.gh.common.util.NewLogUtils
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.dip2px
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
import com.gh.gamecenter.common.view.GridSpacingItemDecoration
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.databinding.FragmentLocalMediaBinding
import com.gh.gamecenter.entity.LocalVideoEntity
import com.zhihu.matisse.internal.entity.Album
import com.zhihu.matisse.internal.entity.Item
import com.zhihu.matisse.internal.model.AlbumMediaCollection
import com.zhihu.matisse.internal.model.SelectedItemCollection
import com.zhihu.matisse.internal.ui.BasePreviewActivity
import com.zhihu.matisse.internal.ui.SelectedPreviewActivity
import com.zhihu.matisse.internal.utils.PathUtils
import com.zhihu.matisse.ui.MatisseActivity
class LocalMediaFragment : BaseFragment<Any>(), AlbumMediaCollection.AlbumMediaCallbacks {
private lateinit var mBinding: FragmentLocalMediaBinding
private lateinit var mAdapter: LocalMediaAdapter
private var mAlbumMediaCollection: AlbumMediaCollection? = null
private var mChooseType = ""
override fun getLayoutId(): Int = 0
override fun getInflatedLayout(): View {
mBinding = FragmentLocalMediaBinding.inflate(LayoutInflater.from(requireContext()), null, false)
return mBinding.root
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mChooseType = arguments?.getString(EntranceConsts.KEY_TYPE) ?: ""
// mBinding.reuseNoneData.reuseNoneDataTv.text = "暂无数据~"
mBinding.listRv.layoutManager = GridLayoutManager(requireContext(), 3)
mBinding.listRv.addItemDecoration(GridSpacingItemDecoration(3, 4F.dip2px(), false))
val maxChooseCount = arguments?.getInt(EntranceConsts.KEY_CHOOSE_MAX_COUNT, 1)
mAdapter = LocalMediaAdapter(
requireContext(), mChooseType, maxChooseCount
?: 1, mEntrance
) {
mBinding.previewTv.isEnabled = it.isNotEmpty()
mBinding.confirmTv.isEnabled = it.isNotEmpty()
if (it.isEmpty()) {
mBinding.previewTv.setTextColor(R.color.text_instance.toColor(requireContext()))
mBinding.confirmTv.alpha = 0.6f
} else {
mBinding.previewTv.setTextColor(R.color.text_secondary.toColor(requireContext()))
mBinding.confirmTv.alpha = 1f
}
mBinding.numTv.text = "(${it.size}/${mAdapter.maxChooseSize})"
}
mBinding.numTv.text = "(0/${mAdapter.maxChooseSize})"
mBinding.listRv.adapter = mAdapter
mBinding.listRefresh.isEnabled = false
val publishContentType = if (mEntrance == "发帖子") "帖子" else if (mEntrance == "发提问帖") "提问帖" else "视频帖"
val publishMediaType = if (mChooseType == LocalMediaActivity.ChooseType.IMAGE.value) "图片" else "视频"
mBinding.previewTv.setOnClickListener {
if (mChooseType == LocalMediaActivity.ChooseType.VIDEO.value) {
val intent = PreviewVideoActivity.getIntent(requireContext(), mAdapter.getSelectedMediaList())
requireActivity().startActivityForResult(intent, PREVIEW_VIDEO)
NewLogUtils.logChooseMedia("click_preview", publishContentType, publishMediaType)
} else {
val intent = Intent(requireContext(), SelectedPreviewActivity::class.java)
val bundle = bundleOf(
SelectedItemCollection.STATE_SELECTION to mAdapter.getSelectedMediaList(),
SelectedItemCollection.STATE_COLLECTION_TYPE to SelectedItemCollection.COLLECTION_IMAGE
)
intent.putExtra(BasePreviewActivity.EXTRA_DEFAULT_BUNDLE, bundle)
startActivityForResult(intent, PREVIEW_IMAGE)
}
}
mBinding.confirmTv.setOnClickListener {
NewLogUtils.logChooseMedia("click_confirm", publishContentType, publishMediaType)
val intent = Intent()
if (mChooseType == LocalMediaActivity.ChooseType.VIDEO.value) {
val localVideoList = arrayListOf<LocalVideoEntity>()
mAdapter.getSelectedMediaList().forEach {
val path = PathUtils.getPath(requireContext(), it.contentUri)
if (path == null) {
toast("视频已不存在,请重新选择")
return@forEach
}
val id = MD5Utils.getUrlMD5(path) + System.currentTimeMillis()
val format = getFileFormat(it.mimeType)
localVideoList.add(
LocalVideoEntity(
id,
path,
contentUri = it.contentUri,
duration = it.duration,
format = format,
size = it.size
)
)
}
intent.putExtra(LocalVideoEntity::class.java.name, localVideoList)
} else {
val data = mAdapter.getSelectedMediaList().map { it.contentUri }.toList()
val path = data.map { PathUtils.getPath(requireContext(), it) }.toList()
intent.putParcelableArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION, ArrayList<Uri>(data))
intent.putStringArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION_PATH, ArrayList<String>(path))
}
requireActivity().setResult(Activity.RESULT_OK, intent)
requireActivity().finish()
}
}
private fun getFileFormat(mimeType: String?): String {
var format = ""
tryWithDefaultCatch {
if (mimeType != null) {
val split = mimeType.split("/")
format = if (split.count() >= 2) {
split[1]
} else {
mimeType
}
}
}
return format
}
override fun onAlbumMediaReset() {
mAdapter.swapCursor(null)
}
override fun onAlbumMediaLoad(cursor: Cursor?) {
mAdapter.swapCursor(cursor)
mBinding.reuseNoneData.reuseNoneData.visibility = View.GONE
mBinding.reuseLlLoading.root.visibility = View.GONE
mBinding.reuseNoConnection.root.visibility = View.GONE
mBinding.listRefresh.isRefreshing = false
}
fun loadVideos(album: Album) {
mAlbumMediaCollection?.onDestroy()
mAlbumMediaCollection = AlbumMediaCollection()
mAlbumMediaCollection?.onCreate(requireActivity(), this@LocalMediaFragment)
mAlbumMediaCollection?.load(album)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (data == null) return
if (requestCode == PREVIEW_IMAGE) {
val bundleExtra = data.getBundleExtra(BasePreviewActivity.EXTRA_RESULT_BUNDLE)
val resultApply = data.getBooleanExtra(BasePreviewActivity.EXTRA_RESULT_APPLY, false)
val items = bundleExtra?.getParcelableArrayList<Item>(SelectedItemCollection.STATE_SELECTION)
if (resultApply && !items.isNullOrEmpty()) {
mAdapter.getSelectedMediaList().clear()
mAdapter.getSelectedMediaList().addAll(items)
mAdapter.notifyDataSetChanged()
mBinding.numTv.text = "(${items.size}/${mAdapter.maxChooseSize})"
}
} else if (requestCode == PREVIEW_VIDEO) {
requireActivity().setResult(Activity.RESULT_OK, data)
requireActivity().finish()
}
}
override fun onDestroy() {
super.onDestroy()
mAlbumMediaCollection?.onDestroy()
}
companion object {
const val PREVIEW_VIDEO = 100
const val PREVIEW_IMAGE = 101
}
}

View File

@ -0,0 +1,36 @@
package com.gh.gamecenter.qa.editor
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.R
import com.zhihu.matisse.internal.entity.Item
class PreviewVideoActivity : BaseActivity() {
override fun getLayoutId(): Int {
return R.layout.activity_amway
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DisplayUtils.transparentStatusBar(this)
val containerFragment = supportFragmentManager.findFragmentByTag(PreviewVideoFragment::class.java.name)
?: PreviewVideoFragment().with(intent.extras)
// 若 placeholder 外层为 RelativeLayout 的话,会出现莫名的偏移
supportFragmentManager.beginTransaction()
.replace(R.id.placeholder, containerFragment, PreviewVideoFragment::class.java.name)
.commitAllowingStateLoss()
}
companion object {
fun getIntent(context: Context, videos: ArrayList<Item>): Intent {
val intent = Intent(context, PreviewVideoActivity::class.java)
intent.putExtra(EntranceConsts.KEY_VIDEO_LIST, videos)
return intent
}
}
}

View File

@ -0,0 +1,229 @@
package com.gh.gamecenter.qa.editor
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder
import com.facebook.drawee.generic.RoundingParams
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.gamecenter.common.base.fragment.BaseFragment
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.common.view.GridSpacingItemColorDecoration
import com.gh.gamecenter.CropImageActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.databinding.FragmentPreviewVideoBinding
import com.gh.gamecenter.databinding.ItemVideoSelectorBinding
import com.gh.gamecenter.entity.LocalVideoEntity
import com.gh.gamecenter.video.poster.PosterEditActivity
import com.gh.gamecenter.video.upload.view.UploadVideoActivity
import com.lightgame.adapter.BaseRecyclerAdapter
import com.shuyu.gsyvideoplayer.GSYVideoManager
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
import com.zhihu.matisse.internal.entity.Item
import com.zhihu.matisse.internal.utils.PathUtils
class PreviewVideoFragment : BaseFragment<Any>() {
private lateinit var mBinding: FragmentPreviewVideoBinding
private var mVideoItems: ArrayList<Item> = arrayListOf()
private var mProcessingDialog: WaitingDialogFragment? = null
private lateinit var mVideoSelectorAdapter: VideoSelectorAdapter
private val mLocalVideoList = arrayListOf<LocalVideoEntity>()
override fun getLayoutId(): Int = 0
override fun getInflatedLayout(): View {
mBinding = FragmentPreviewVideoBinding.inflate(LayoutInflater.from(requireContext()), null, false)
return mBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mVideoItems = arguments?.getParcelableArrayList<Item>(EntranceConsts.KEY_VIDEO_LIST)
?: arrayListOf()
if (mVideoItems.isNotEmpty()) {
mVideoItems.forEach {
val path = PathUtils.getPath(requireContext(), it.contentUri)
val id = MD5Utils.getUrlMD5(path) + System.currentTimeMillis()
val format = getFileFormat(it.mimeType)
val localVideoEntity = LocalVideoEntity(
id = id,
filePath = path,
contentUri = it.contentUri,
duration = it.duration,
format = format,
size = it.size
)
mLocalVideoList.add(localVideoEntity)
}
initVideo(mLocalVideoList[0])
}
mBinding.numTv.text = "(1/${mVideoItems.size})"
mVideoSelectorAdapter = VideoSelectorAdapter(requireContext(), mLocalVideoList) { entity, position ->
mBinding.videoView.release()
mBinding.numTv.text = "(${position + 1}/${mVideoItems.size})"
initVideo(entity)
}
mBinding.videoSelectorRv.adapter = mVideoSelectorAdapter
mBinding.videoSelectorRv.layoutManager =
LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
mBinding.videoSelectorRv.addItemDecoration(
GridSpacingItemColorDecoration(
requireContext(),
4,
0,
R.color.transparent
)
)
mBinding.confirmTv.setOnClickListener {
val intent = Intent()
intent.putExtra(LocalVideoEntity::class.java.name, mLocalVideoList)
requireActivity().setResult(Activity.RESULT_OK, intent)
requireActivity().finish()
}
mBinding.changeCoverTv.setOnClickListener {
val item = mVideoItems[mVideoSelectorAdapter.selectPosition]
val intent =
PosterEditActivity.getIntentByPath(requireContext(), PathUtils.getPath(requireContext(), item.uri))
startActivityForResult(intent, UploadVideoActivity.REQUEST_CODE_IMAGE_CROP)
}
mBinding.backBtn.setOnClickListener { requireActivity().finish() }
}
private fun getFileFormat(mimeType: String?): String {
var format = ""
tryWithDefaultCatch {
if (mimeType != null) {
val split = mimeType.split("/")
format = if (split.count() >= 2) {
split[1]
} else {
mimeType
}
}
}
return format
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (data == null || resultCode != Activity.RESULT_OK) return
if (requestCode == UploadVideoActivity.REQUEST_CODE_IMAGE_CROP) {
val imagePath = data.getStringExtra(CropImageActivity.RESULT_CLIP_PATH) ?: ""
if (imagePath.isNotEmpty()) {
uploadImage(imagePath)
}
}
}
private fun uploadImage(imagePath: String) {
mProcessingDialog = WaitingDialogFragment.newInstance("图片上传中...", false)
mProcessingDialog?.show(requireActivity().supportFragmentManager, WaitingDialogFragment::class.java.name)
UploadImageUtils.uploadImage(
UploadImageUtils.UploadType.poster,
imagePath,
object : UploadImageUtils.OnUploadImageListener {
override fun onSuccess(imageUrl: String) {
mProcessingDialog?.dismiss()
mLocalVideoList[mVideoSelectorAdapter.selectPosition].poster = imageUrl
mBinding.videoView.updateThumb(imageUrl)
}
override fun onError(e: Throwable?) {
mProcessingDialog?.dismiss()
ToastUtils.showToast("上传失败")
}
override fun onProgress(total: Long, progress: Long) {}
})
}
private fun initVideo(entity: LocalVideoEntity) {
GSYVideoOptionBuilder()
.setIsTouchWiget(false)
.setUrl(entity.filePath)
.setRotateViewAuto(false)
.setCacheWithPlay(false)
.setRotateWithSystem(false)
.setReleaseWhenLossAudio(true)
.setLooping(false)
.setShowFullAnimation(false)
.build(mBinding.videoView)
if (entity.poster.isNotEmpty()) {
mBinding.videoView.updateThumb(entity.poster)
} else {
mBinding.videoView.updateThumb("file:///${PathUtils.getPath(requireContext(), entity.contentUri)}")
}
}
class VideoSelectorAdapter(
context: Context,
val localVideoList: ArrayList<LocalVideoEntity>,
val callback: (LocalVideoEntity, Int) -> Unit
) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
var selectPosition: Int = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return VideoSelectorViewHolder(
ItemVideoSelectorBinding.inflate(
LayoutInflater.from(mContext),
parent,
false
)
)
}
override fun getItemCount(): Int = localVideoList.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is VideoSelectorViewHolder) {
val item = localVideoList[position]
holder.binding.previewBorder.goneIf(selectPosition != position)
setPreviewBorder(holder.binding.preview, selectPosition == position)
ImageUtils.display(holder.binding.preview, "file:///${PathUtils.getPath(mContext, item.contentUri)}")
holder.binding.root.setOnClickListener {
selectPosition = position
callback.invoke(localVideoList[selectPosition], selectPosition)
notifyDataSetChanged()
}
}
}
private fun setPreviewBorder(view: SimpleDraweeView, isSelected: Boolean) {
val params = RoundingParams()
params.setBorder(
if (isSelected) R.color.black.toColor() else R.color.transparent.toColor(),
if (isSelected) 1f.dip2px().toFloat() else 0f
)
params.setCornersRadius(4f.dip2px().toFloat())
val build = GenericDraweeHierarchyBuilder.newInstance(mContext.resources)
.setRoundingParams(params)
.build()
view.hierarchy = build
}
}
class VideoSelectorViewHolder(val binding: ItemVideoSelectorBinding) : RecyclerView.ViewHolder(binding.root)
override fun onResume() {
super.onResume()
GSYVideoManager.onResume()
}
override fun onPause() {
super.onPause()
GSYVideoManager.onPause()
}
override fun onDestroy() {
super.onDestroy()
GSYVideoManager.releaseAllVideos()
}
}

View File

@ -1,4 +1,4 @@
package com.gh.gamecenter.feature.selector.widget
package com.gh.gamecenter.qa.editor
import android.content.Context
import android.util.AttributeSet
@ -8,11 +8,12 @@ import android.view.View
import android.widget.ImageView
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.selector.R
import com.gh.gamecenter.R
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
open class PreviewVideoView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
: StandardGSYVideoPlayer(context, attrs) {
class PreviewVideoView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
StandardGSYVideoPlayer(context, attrs) {
var thumbImage: SimpleDraweeView = findViewById(R.id.thumbImage)
@ -24,8 +25,8 @@ open class PreviewVideoView @JvmOverloads constructor(context: Context, attrs: A
if (mStartButton is ImageView) {
val imageView = mStartButton as ImageView
when (mCurrentState) {
CURRENT_STATE_PLAYING -> imageView.setImageResource(R.drawable.icon_preview_video_pause)
CURRENT_STATE_ERROR -> imageView.setImageResource(R.drawable.icon_preview_video_play)
GSYVideoView.CURRENT_STATE_PLAYING -> imageView.setImageResource(R.drawable.icon_preview_video_pause)
GSYVideoView.CURRENT_STATE_ERROR -> imageView.setImageResource(R.drawable.icon_preview_video_play)
else -> imageView.setImageResource(R.drawable.icon_preview_video_play)
}
}
@ -33,7 +34,7 @@ open class PreviewVideoView @JvmOverloads constructor(context: Context, attrs: A
override fun onClickUiToggle(e: MotionEvent?) {
if (mCurrentState == CURRENT_STATE_PLAYING) {
if (mStartButton.visibility == VISIBLE) {
if (mStartButton.visibility == View.VISIBLE) {
changeUiToPlayingClear()
} else {
changeUiToPlayingShow()
@ -47,8 +48,8 @@ open class PreviewVideoView @JvmOverloads constructor(context: Context, attrs: A
override fun onSurfaceUpdated(surface: Surface) {
super.onSurfaceUpdated(surface)
if (mThumbImageViewLayout != null && mThumbImageViewLayout.visibility == VISIBLE) {
mThumbImageViewLayout.visibility = INVISIBLE
if (mThumbImageViewLayout != null && mThumbImageViewLayout.visibility == View.VISIBLE) {
mThumbImageViewLayout.visibility = View.INVISIBLE
}
}
@ -57,7 +58,7 @@ open class PreviewVideoView @JvmOverloads constructor(context: Context, attrs: A
}
override fun setViewShowState(view: View?, visibility: Int) {
if (view === mThumbImageViewLayout && visibility != VISIBLE) {
if (view === mThumbImageViewLayout && visibility != View.VISIBLE) {
return
}
super.setViewShowState(view, visibility)

View File

@ -1,4 +1,4 @@
package com.gh.gamecenter.feature.selector
package com.gh.gamecenter.qa.editor
import android.content.Context
import android.database.Cursor
@ -7,17 +7,12 @@ import android.view.View
import android.view.ViewGroup
import android.widget.CursorAdapter
import android.widget.TextView
import com.gh.gamecenter.common.R
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.R
import com.zhihu.matisse.internal.entity.Album
class VideoAlbumsAdapter(context: Context) : CursorAdapter(context, null) {
private var selectedPosition = 0
override fun newView(context: Context?, cursor: Cursor?, parent: ViewGroup?): View {
val inflate = LayoutInflater.from(context)
return inflate.inflate(R.layout.video_albums_item, parent, false)
@ -25,14 +20,8 @@ class VideoAlbumsAdapter(context: Context) : CursorAdapter(context, null) {
override fun bindView(view: View, context: Context, cursor: Cursor?) {
val album = Album.valueOf(cursor)
view.findViewById<View>(R.id.checkIv).goneIf(cursor?.position != selectedPosition)
view.findViewById<TextView>(R.id.album_name).text = album.getDisplayName(context)
view.findViewById<TextView>(R.id.album_media_count).text = album.count.toString()
view.findViewById<SimpleDraweeView>(R.id.album_cover).setImageURI(album.coverUri)
}
fun updateSelectedPosition(position: Int) {
selectedPosition = position
}
}

View File

@ -1,4 +1,4 @@
package com.gh.gamecenter.feature.selector
package com.gh.gamecenter.qa.editor
import android.content.Context
import android.graphics.drawable.ColorDrawable
@ -11,13 +11,11 @@ import android.widget.PopupWindow
import androidx.appcompat.widget.ListPopupWindow
import androidx.core.content.ContextCompat
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.R
import com.gh.gamecenter.R
class VideoAlbumsSpanner(val context: Context) {
private var mListPopupWindow: ListPopupWindow =
CustomListPopupWindow(context, R.style.PosterListPopupWindow)
private var mListPopupWindow: ListPopupWindow = CustomListPopupWindow(context, R.style.PosterListPopupWindow)
private lateinit var mAdapter: CursorAdapter
@ -30,14 +28,7 @@ class VideoAlbumsSpanner(val context: Context) {
mListPopupWindow.dismiss()
onItemSelectedListener?.onItemSelected(parent, view, position, id)
}
mListPopupWindow.setBackgroundDrawable(
ColorDrawable(
ContextCompat.getColor(
context,
R.color.transparent
)
)
)
mListPopupWindow.setBackgroundDrawable(ColorDrawable(ContextCompat.getColor(context, R.color.transparent)))
}
fun setDismissListener(listener: PopupWindow.OnDismissListener) {
@ -56,15 +47,13 @@ class VideoAlbumsSpanner(val context: Context) {
fun show(popupHeight: Int) {
if (mListPopupWindow.isShowing) return
if (popupHeight > 0) mListPopupWindow.height = popupHeight
mListPopupWindow.animationStyle = R.style.popup_window_ease_in_and_out_anim_style
// 去掉ListPopupWindow默认动画
mListPopupWindow.animationStyle = 0
mListPopupWindow.show()
val containerView = mListPopupWindow.listView as? ViewGroup
val params = containerView?.layoutParams as FrameLayout.LayoutParams
params.height = 280F.dip2px()
containerView.setPadding(8F.dip2px(), 0, 0, 4F.dip2px())
containerView.clipToPadding = false
containerView.background = ColorDrawable(ContextCompat.getColor(context, R.color.ui_surface_fixed_dark))
val params = containerView?.layoutParams as ViewGroup.LayoutParams
params.height = 280f.dip2px()
containerView.background = ColorDrawable(ContextCompat.getColor(context, R.color.ui_surface))
containerView.layoutParams = params
val parentContainer = containerView.parent as FrameLayout

View File

@ -24,10 +24,8 @@ import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.CommunityEntity
import com.gh.gamecenter.common.entity.LocalVideoEntity
import com.gh.gamecenter.common.entity.NotificationUgc
import com.gh.gamecenter.common.mvvm.Status
import com.gh.gamecenter.feature.selector.LocalMediaActivity
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.runOnUiThread
@ -36,7 +34,6 @@ import com.gh.gamecenter.databinding.FragmentVideoPublishBinding
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.feature.entity.ForumVideoEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.selector.ChooseType
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.qa.BbsType
import com.gh.gamecenter.qa.dialog.ChooseActivityDialogFragment
@ -44,6 +41,7 @@ import com.gh.gamecenter.qa.dialog.ChooseForumActivity
import com.gh.gamecenter.qa.dialog.ChooseSectionDialogFragment
import com.gh.gamecenter.qa.dialog.InputUrlDialogFragment
import com.gh.gamecenter.qa.editor.GameActivity
import com.gh.gamecenter.qa.editor.LocalMediaActivity
import com.gh.gamecenter.video.poster.PosterEditActivity
import com.gh.gamecenter.video.upload.OnUploadListener
import com.gh.gamecenter.video.upload.UploadManager
@ -119,7 +117,7 @@ class VideoPublishFragment : ToolbarFragment(), KeyboardHeightObserver {
startActivityForResult(
LocalMediaActivity.getIntent(
requireContext(),
ChooseType.VIDEO,
LocalMediaActivity.ChooseType.VIDEO,
1,
"发视频帖"
), BaseRichEditorActivity.INSERT_MEDIA_VIDEO_CODE
@ -287,7 +285,7 @@ class VideoPublishFragment : ToolbarFragment(), KeyboardHeightObserver {
startActivityForResult(
LocalMediaActivity.getIntent(
requireContext(),
ChooseType.VIDEO,
LocalMediaActivity.ChooseType.VIDEO,
1,
"发视频帖"
), BaseRichEditorActivity.INSERT_MEDIA_VIDEO_CODE

View File

@ -29,7 +29,6 @@ import com.gh.gamecenter.entity.DeviceDialogEntity;
import com.gh.gamecenter.entity.DialogEntity;
import com.gh.gamecenter.entity.DiscoveryGameCardEntity;
import com.gh.gamecenter.entity.DiscoveryGameCardLabel;
import com.gh.gamecenter.entity.DiverterEntity;
import com.gh.gamecenter.entity.FollowCommonContentCollection;
import com.gh.gamecenter.entity.FollowDynamicEntity;
import com.gh.gamecenter.entity.FollowUserEntity;
@ -108,7 +107,6 @@ import com.gh.gamecenter.feature.entity.BackgroundImageEntity;
import com.gh.gamecenter.feature.entity.CommentEntity;
import com.gh.gamecenter.feature.entity.CommentnumEntity;
import com.gh.gamecenter.feature.entity.ConcernEntity;
import com.gh.gamecenter.feature.entity.FloatingWindowEntity;
import com.gh.gamecenter.feature.entity.ForumVideoEntity;
import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.feature.entity.LibaoEntity;
@ -128,6 +126,7 @@ import com.gh.gamecenter.feature.entity.SimulatorEntity;
import com.gh.gamecenter.feature.entity.UserEntity;
import com.gh.gamecenter.feature.entity.ViewsEntity;
import com.gh.gamecenter.feature.entity.WXSubscribeMsgConfig;
import com.gh.gamecenter.feature.entity.FloatingWindowEntity;
import com.gh.gamecenter.gamedetail.entity.BigEvent;
import com.gh.gamecenter.gamedetail.entity.NewGameDetailEntity;
import com.gh.gamecenter.home.custom.model.CustomPageData;
@ -3359,7 +3358,7 @@ public interface ApiService {
* 页面数据聚合[底部tab+多tab导航页+默认数据]
*/
@GET("app/data_union")
Single<DataUnionEntity> getDataUnion(@Query("diverter") String diverter);
Single<DataUnionEntity> getDataUnion();
/**
* 底部tab
@ -3391,16 +3390,4 @@ public interface ApiService {
*/
@GET("game_lists/hot_columns")
Single<List<SubjectEntity>> getHotColumns();
/**
* 分流器列表信息
*/
@GET("app/{module}/diverter")
Single<List<DiverterEntity>> getDiverterList(@Header("Install-First-Access") String isInstallFirstAccess, @Path("module") String module);
/**
* 访问分流页面,更新分流访问次数
*/
@PATCH("app/{module}/diverter_visit_time")
Single<ResponseBody> patchDiverterVisitTime(@Path("module") String module, @Body RequestBody body);
}

View File

@ -1,6 +1,9 @@
package com.gh.gamecenter.search
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Shader
import android.graphics.Typeface
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.text.TextUtils
@ -15,6 +18,7 @@ import androidx.viewpager.widget.PagerAdapter
import com.gh.common.constant.Config
import com.gh.common.exposure.ExposureManager
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.BaseFragment
@ -30,7 +34,7 @@ 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.DiscoveryTagEntity
import com.gh.gamecenter.feature.entity.HotTagEntity
import com.gh.gamecenter.feature.entity.SettingsEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.google.android.flexbox.FlexboxLayout
@ -42,7 +46,7 @@ import org.json.JSONObject
open class SearchDefaultFragment : BaseFragment<Any>() {
private var mSearchDiscoveryTagList: List<DiscoveryTagEntity>? = null
private var mHotTagList: List<HotTagEntity>? = null
protected var mRankList: List<SettingsEntity.Search.RankList>? = null
protected lateinit var mBinding: FragmentSearchDefaultBinding
@ -59,28 +63,28 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
// FlexboxLayout:maxLine 不符合需求
protected val mFlexMaxHeight = DisplayUtils.dip2px(57F)
private val mSearchDiscoveryTagClickListener: (Int) -> Unit = {
val tag = mSearchDiscoveryTagList!![it]
val keyword = tag.keyword
if (keyword.isNotEmpty()) {
PageSwitchDataHelper.pushCurrentPageData(
hashMapOf(
Pair(PageSwitchDataHelper.PAGE_BUSINESS_TYPE, "游戏搜索-搜索发现"),
Pair(PageSwitchDataHelper.PAGE_BUSINESS_ID, tag.id ?: ""),
Pair(PageSwitchDataHelper.PAGE_BUSINESS_NAME, tag.text ?: " ")
)
private val mHotTagClickListener: (Int) -> Unit = {
val tag = mHotTagList!![it]
NewFlatLogUtils.logSearchHotTagClick(
tag.name ?: "",
tag.type ?: "",
tag.link ?: "",
tag.text ?: ""
)
DataLogUtils.uploadHotTagLog(context, tag.name)
PageSwitchDataHelper.pushCurrentPageData(
hashMapOf(
Pair(PageSwitchDataHelper.PAGE_BUSINESS_TYPE, "游戏搜索-热门标签"),
Pair(PageSwitchDataHelper.PAGE_BUSINESS_ID, tag.id ?: ""),
Pair(PageSwitchDataHelper.PAGE_BUSINESS_NAME, tag.name ?: " ")
)
SensorsBridge.trackEvent("SearchLabelClick", "label_name", tag.text ?: "", "label_id", tag.id ?: "")
SensorsBridge.trackSearchDiscoveryClick(
labelName = tag.text ?: "",
labelId = tag.id ?: "",
searchContent = keyword,
position = it
)
mViewModel?.add(keyword)
EventBus.getDefault().post(EBSearch("history", keyword))
Util_System_Keyboard.hideSoftKeyboardByIBinder(context, mBinding.historyFlex.windowToken)
}
)
SensorsBridge.trackEvent("SearchLabelClick", "label_name", tag.name ?: "", "label_id", tag.id ?: "")
val exposureEvent = ExposureEvent.createEvent(
null,
source = listOf(ExposureSource("首页搜索", ""), ExposureSource("热门标签", tag.name ?: ""))
)
DirectUtils.directToLinkPage(requireContext(), tag, "(搜索-${tag.name})", "", exposureEvent) // 不需要path
}
override fun getLayoutId(): Int {
@ -133,16 +137,16 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
}
mViewModel?.isExistRankList = mRankList?.isNotEmpty() == true
mSearchDiscoveryTagList = Config.getSettings()?.search?.discoveryTag
mViewModel?.isExistSearchDiscoveryTag = mSearchDiscoveryTagList?.isNotEmpty() == true
mHotTagList = Config.getSettings()?.search?.hotTag
mViewModel?.isExistHotTag = mHotTagList?.isNotEmpty() == true
updateHistorySearchView(null)
mViewModel?.historySearchLiveData?.observe(viewLifecycleOwner) {
updateHistorySearchView(it)
}
mBinding.searchDiscoveryTagFlexContainer.setLimitHeight(mFlexMaxHeight)
createFlexContent(mBinding.searchDiscoveryTagFlex, getTagListString(), clickListener = mSearchDiscoveryTagClickListener)
mBinding.hotTagFlexContainer.setLimitHeight(mFlexMaxHeight)
createFlexContent(mBinding.hotTagFlex, getTagListString(), true, clickListener = mHotTagClickListener)
initHeadView()
initRankViewPager()
}
@ -171,12 +175,12 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
})
}
}
mBinding.searchDiscoveryHeadContainer.headTitle.text = getString(R.string.search_hot)
mBinding.searchDiscoveryHeadContainer.headTitle.textSize = 16F
mBinding.searchDiscoveryHeadContainer.headActionTv.visibility = View.GONE
mBinding.searchDiscoveryTagHeadContainer.headTitle.text = getString(R.string.search_discovery_tag)
mBinding.searchDiscoveryTagHeadContainer.headTitle.textSize = 16F
mBinding.searchDiscoveryTagHeadContainer.headActionTv.visibility = View.GONE
mBinding.hotHeadContainer.headTitle.text = getString(R.string.search_hot)
mBinding.hotHeadContainer.headTitle.textSize = 16F
mBinding.hotHeadContainer.headActionTv.visibility = View.GONE
mBinding.hotTagHeadContainer.headTitle.text = getString(R.string.search_hot_tag)
mBinding.hotTagHeadContainer.headTitle.textSize = 16F
mBinding.hotTagHeadContainer.headActionTv.visibility = View.GONE
}
protected open fun initRankViewPager() {
@ -311,8 +315,8 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
mBinding.historyHeadContainer.root.visibility =
if (mViewModel?.isExistHistory == true) View.VISIBLE else View.GONE
mBinding.historyFlex.visibility = if (mViewModel?.isExistHistory == true) View.VISIBLE else View.GONE
mBinding.searchDiscoveryTagHeadContainer.root.layoutParams =
(mBinding.searchDiscoveryTagHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
mBinding.hotTagHeadContainer.root.layoutParams =
(mBinding.hotTagHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
setMargins(
0,
if (mViewModel?.isExistHistory == true) 16F.dip2px() else 0,
@ -320,21 +324,21 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
0
)
}
mBinding.searchDiscoveryHeadContainer.root.layoutParams =
(mBinding.searchDiscoveryHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
mBinding.hotHeadContainer.root.layoutParams =
(mBinding.hotHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
setMargins(
0,
if (mViewModel?.isExistHistory == false && mViewModel?.isExistSearchDiscoveryTag == false) 16F.dip2px() else 0,
if (mViewModel?.isExistHistory == false && mViewModel?.isExistHotTag == false) 16F.dip2px() else 0,
0,
0
)
}
mBinding.searchDiscoveryTagHeadContainer.root.visibility =
if (mViewModel?.isExistSearchDiscoveryTag == true) View.VISIBLE else View.GONE
mBinding.searchDiscoveryTagFlex.visibility = if (mViewModel?.isExistSearchDiscoveryTag == true) View.VISIBLE else View.GONE
mBinding.searchDiscoveryHeadContainer.root.visibility =
mBinding.hotTagHeadContainer.root.visibility =
if (mViewModel?.isExistHotTag == true) View.VISIBLE else View.GONE
mBinding.hotTagFlex.visibility = if (mViewModel?.isExistHotTag == true) View.VISIBLE else View.GONE
mBinding.hotHeadContainer.root.visibility =
if (mViewModel?.isExistHotSearch == true) View.VISIBLE else View.GONE
mBinding.searchDiscoveryList.visibility = if (mViewModel?.isExistHotSearch == true) View.VISIBLE else View.GONE
mBinding.hotList.visibility = if (mViewModel?.isExistHotSearch == true) View.VISIBLE else View.GONE
mBinding.rankTabLayout.visibility = if (mViewModel?.isExistRankList == true) View.VISIBLE else View.GONE
mBinding.rankTabIndicator.visibility = if (mViewModel?.isExistRankList == true) View.VISIBLE else View.GONE
mBinding.rankViewPager.visibility = if (mViewModel?.isExistRankList == true) View.VISIBLE else View.GONE
@ -356,9 +360,9 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
private fun getTagListString(): List<String> {
val list = ArrayList<String>()
if (mSearchDiscoveryTagList != null) {
for (entity in mSearchDiscoveryTagList!!) {
entity.text?.let { list.add(it) }
if (mHotTagList != null) {
for (entity in mHotTagList!!) {
entity.name?.let { list.add(it) }
}
}
return list
@ -367,6 +371,7 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
fun createFlexContent(
flexView: FlexboxLayout,
contentList: List<String>?,
isHotTag: Boolean = false,
clickListener: (Int) -> Unit
) {
@ -380,12 +385,16 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
val params = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 24F.dip2px())
flexCell.layoutParams = params
flexCell.setSingleLine()
flexCell.ellipsize = TextUtils.TruncateAt.END
flexCell.gravity = Gravity.CENTER
flexCell.textSize = 12F
flexCell.text = StringUtils.shrinkStringWithDot(contentList[index], 6)
flexCell.setTextColor(R.color.text_secondary.toColor(requireContext()))
if (isHotTag && !mHotTagList.isNullOrEmpty() && mHotTagList!![index].isGuessSearch) {
createSmartHotTagStyle(flexCell, contentList[index])
} else {
flexCell.setSingleLine()
flexCell.ellipsize = TextUtils.TruncateAt.END
flexCell.gravity = Gravity.CENTER
flexCell.textSize = 12F
flexCell.text = StringUtils.shrinkStringWithDot(contentList[index], 6)
flexCell.setTextColor(R.color.text_secondary.toColor(requireContext()))
}
flexCell.setPadding(8F.dip2px(), 0, 8F.dip2px(), 0)
flexCell.background = if (mIsDarkModeOn) GradientDrawable().apply {
setStroke(0.5F.dip2px(), Color.parseColor("#21FFFFFF"))
@ -397,6 +406,30 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
}
}
private fun createSmartHotTagStyle(flexCell: TextView, name: String) {
flexCell.setDrawableStart(R.drawable.ic_smart_search)
flexCell.compoundDrawablePadding = 4F.dip2px()
flexCell.gravity = Gravity.CENTER_VERTICAL
flexCell.typeface = Typeface.DEFAULT_BOLD
flexCell.textSize = 12F
flexCell.text = StringUtils.shrinkStringWithDot(name, 6)
flexCell.setTextColor(Color.WHITE)
val colors =
intArrayOf(R.color.text_FFB749.toColor(requireContext()), R.color.text_FF6D3C.toColor(requireContext()))
val position = floatArrayOf(0F, 1F)
val linearGradient = LinearGradient(
0F,
0F,
flexCell.paint.textSize * flexCell.text.length,
0F,
colors,
position,
Shader.TileMode.CLAMP
)
flexCell.paint.shader = linearGradient
flexCell.invalidate()
}
private fun postExposureEvent(index: Int) {
mRankList?.safelyGetInRelease(index)?.content?.forEach {
if (it.link.type == "game") {
@ -411,24 +444,17 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
super.onDarkModeChanged()
initHeadView()
mBinding.rootContainer.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
mBinding.searchDiscoveryList.adapter?.run {
mBinding.hotList.adapter?.run {
notifyItemRangeChanged(0, itemCount)
}
mViewModel?.historySearchLiveData?.value?.let { updateHistorySearchView(it) }
createFlexContent(mBinding.searchDiscoveryTagFlex, getTagListString(), clickListener = mSearchDiscoveryTagClickListener)
createFlexContent(mBinding.hotTagFlex, getTagListString(), true, clickListener = mHotTagClickListener)
}
protected open fun provideDao(): ISearchHistoryDao = SearchHistoryDao(requireContext().applicationContext)
protected open fun provideAdapter(pageRatio: Float): PagerAdapter =
SearchDefaultRankListAdapter(
requireContext(),
mViewModel!!,
mRankList!!,
pageRatio,
mIsGameSearch,
mSourceEntrance
)
SearchDefaultRankListAdapter(requireContext(), mRankList!!, pageRatio, mIsGameSearch, mSourceEntrance)
private fun provideViewModel(): SearchDefaultViewModel {
val factory = SearchDefaultViewModel.Factory(provideDao())

View File

@ -6,27 +6,23 @@ import android.view.ViewGroup
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.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.eventbus.EBSearch
import com.gh.gamecenter.feature.entity.SettingsEntity
import com.lightgame.adapter.BaseRecyclerAdapter
import com.lightgame.utils.Util_System_Keyboard
import org.greenrobot.eventbus.EventBus
import org.json.JSONException
import org.json.JSONObject
class SearchDefaultRankAdapter(
context: Context,
private val mViewModel: SearchDefaultViewModel,
private val mRankList: SettingsEntity.Search.RankList,
private val mIsGameSearch: Boolean
private val mIsGameSearch: Boolean,
) : BaseRecyclerAdapter<SearchDefaultRankAdapter.SearchDefaultRankItemViewHolder>(context) {
override fun getItemCount() = minOf(mRankList.content.size, 20)
override fun getItemCount() = minOf(mRankList.content.size, 10)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
SearchDefaultRankItemViewHolder(parent.toBinding())
@ -38,8 +34,7 @@ class SearchDefaultRankAdapter(
icon.goneIf(!mRankList.isShowIcon) {
icon.display(if (rank.link.type == "game") gameEntity?.icon else rank.icon)
}
val labelName = if (rank.link.type == "game") gameEntity?.name else rank.name.ifBlank { rank.link.text }
name.text = labelName
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()
@ -65,31 +60,18 @@ class SearchDefaultRankAdapter(
root.setOnClickListener {
val linkEntity = rank.link
if (linkEntity.type == "game_search") {
mViewModel.add(linkEntity.text ?: "")
EventBus.getDefault().post(EBSearch(SearchType.RANK.value, linkEntity.text))
} else {
DirectUtils.directToLinkPage(
mContext,
linkEntity,
"游戏搜索-搜索榜单",
"${mRankList.title}-${rank.name}",
rank.exposureEvent
)
}
DirectUtils.directToLinkPage(
mContext,
linkEntity,
"游戏搜索-搜索榜单",
"${mRankList.title}-${rank.name}",
rank.exposureEvent
)
Util_System_Keyboard.hideSoftKeyboardByIBinder(mContext, it.windowToken)
// 是否来源于游戏搜索
if (mIsGameSearch) {
val searchType = if (linkEntity.type == "game_search") {
SearchType.RANK.toChinese()
} else {
""
}
NewFlatLogUtils.logSearchClickRankDetail(
linkEntity.link ?: "",
searchType,
rank.name,
(position + 1).toString(),
linkEntity.link ?: "",
@ -107,8 +89,6 @@ class SearchDefaultRankAdapter(
val trackEvent = JSONObject()
try {
trackEvent.put("text", labelName)
trackEvent.put("search_content", linkEntity.link)
trackEvent.put("game_name", gameEntity?.name)
trackEvent.put("game_id", gameEntity?.id)
trackEvent.put("list_name", mRankList.title)

View File

@ -11,7 +11,6 @@ import com.gh.gamecenter.feature.entity.SettingsEntity
class SearchDefaultRankListAdapter(
private val mContext: Context,
private val mViewModel: SearchDefaultViewModel,
private val mRankList: List<SettingsEntity.Search.RankList>,
private val mPageWidth: Float,
private val mIsGameSearch: Boolean,
@ -32,7 +31,7 @@ class SearchDefaultRankListAdapter(
view!!.findViewById<RecyclerView>(R.id.rankContainer).run {
layoutManager = LinearLayoutManager(mContext)
adapter = SearchDefaultRankAdapter(mContext, mViewModel, mRankList[position], mIsGameSearch)
adapter = SearchDefaultRankAdapter(mContext, mRankList[position], mIsGameSearch)
}
return view
}

View File

@ -10,7 +10,7 @@ class SearchDefaultViewModel(private val dao: ISearchHistoryDao) : ViewModel() {
val historySearchLiveData = MutableLiveData<List<String>>()
var isExistHotSearch: Boolean = false
var isExistSearchDiscoveryTag: Boolean = false
var isExistHotTag: Boolean = false
var isExistHistory: Boolean = false
var isExistRankList: Boolean = false

View File

@ -76,7 +76,7 @@ class SearchSubjectItemViewHolder(var binding: SearchSubjectItemBinding) : Recyc
val exposureSources = arrayListOf<ExposureSource>().apply {
add(ExposureSource("首页搜索"))
add(ExposureSource(type, key))
add(ExposureSource("专题", "${entity.name}+${entity.columnId}"))
add(ExposureSource("专题", entity.name))
}
val exposureEvent = ExposureEvent.createEvent(game, exposureSources)
exposureList.add(exposureEvent)

View File

@ -68,12 +68,6 @@ class SearchGameResultAdapter(
val positionAndPackageMap = HashMap<String, Int>()
private val adIdSet = hashSetOf<String>() // 记录展示过的广告id
fun clearAdIdSet() {
adIdSet.clear()
}
override fun setListData(updateData: MutableList<SearchItemData>?) {
exposureEventArray = SparseArray(updateData?.size ?: 0)
// 记录游戏位置
@ -222,7 +216,6 @@ class SearchGameResultAdapter(
is SearchGameAdItemViewHolder -> {
val adEntity = mEntityList[position].ad
val adConfig = mEntityList[position].adConfig
val slotId = adEntity?.slotId ?: ""
val adContainer = holder.binding.adContainer
val screenWidthInDp = DisplayUtils.getScreenWidthInDp(fragment.activity)
@ -231,36 +224,7 @@ class SearchGameResultAdapter(
// 广告 slotId 没有变,不管它
} else {
adContainer.tag = slotId
val onAdShowAction: () -> Unit = {
if (!adIdSet.contains(adConfig?.id)) {
SensorsBridge.trackEvent("ThirdPartyAdShow",
json {
"ad_source" to adEntity?.sourceName
"ad_id" to slotId
"ad_format" to adConfig?.typeChinese
"ad_placement" to "搜索结果"
"ad_space_id" to adConfig?.id
"ad_space_name" to adConfig?.name
"position" to adConfig?.position
}
)
}
adIdSet.add(adConfig?.id ?: "")
}
val onAdClickAction = {
SensorsBridge.trackEvent("ThirdPartyAdClick",
json {
"ad_source" to adEntity?.sourceName
"ad_id" to slotId
"ad_format" to adConfig?.typeChinese
"ad_placement" to "搜索结果"
"ad_space_id" to adConfig?.id
"ad_space_name" to adConfig?.name
"position" to adConfig?.position
}
)
}
AdDelegateHelper.requestThirdPartyFlowAd(fragment, slotId, adContainer, screenWidthInDp, onAdShowAction, onAdClickAction) {
AdDelegateHelper.requestThirdPartyFlowAd(fragment, slotId, adContainer, screenWidthInDp) {
}
}

View File

@ -354,7 +354,6 @@ open class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultV
this.mKey = key
this.mType = type
mAdapter?.key = key
mAdapter?.clearAdIdSet()
mListViewModel?.updateSearchKeyWithType(key, type)
mListViewModel?.clearSearchSubjects()
mListViewModel?.load(LoadType.REFRESH)

View File

@ -188,7 +188,7 @@ class SearchGameResultViewModel(
list: List<GameEntity>
) {
thirdPartyAdList.forEach {
decoratedItemDataList.add(it.position - 1, SearchItemData(ad = it.thirdPartyAd, adConfig = it))
decoratedItemDataList.add(it.position - 1, SearchItemData(ad = it.thirdPartyAd))
SPUtils.setLong(Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + it.position, System.currentTimeMillis())
}
postResultList(decoratedItemDataList, list)
@ -209,7 +209,7 @@ class SearchGameResultViewModel(
if ((showThirdPartyAd && adConfig?.thirdPartyAd != null)
|| (showOwnerAd && adConfig?.ownerAd == null && adConfig?.thirdPartyAd != null && showOnFailed)
) {
decoratedItemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd, adConfig = adConfig))
decoratedItemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd))
SPUtils.setLong(
Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + adConfig.position,
System.currentTimeMillis()
@ -254,7 +254,7 @@ class SearchGameResultViewModel(
)
} else if (showOnFailed && adConfig.thirdPartyAd != null) {
// 自有广告为空时,显示第三方广告
decoratedItemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd, adConfig = adConfig))
decoratedItemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd))
SPUtils.setLong(
Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + adConfig.position,
System.currentTimeMillis()

View File

@ -9,18 +9,20 @@ import android.view.Gravity
import android.view.View
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.PopupWindow
import android.widget.TextView
import androidx.core.view.isVisible
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.LazyFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.BugFixedPopupWindow
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.doOnEnd
import com.gh.gamecenter.core.utils.doOnStart
import com.gh.gamecenter.databinding.FragmentGameServerTestV2Binding
import com.gh.gamecenter.databinding.LayoutGameServerTestV2SettingBinding
import com.gh.gamecenter.databinding.LayoutGameServerTestV2SettingGuideBinding
import com.gh.gamecenter.feature.entity.PageLocation
import com.gh.gamecenter.mygame.MyGameActivity
@ -68,7 +70,7 @@ class GameServerTestV2Fragment : LazyFragment() {
if (SPUtils.getBoolean(Constants.SP_SHOW_GAME_SERVER_TEST_V2_SETTING_GUIDE, true)) {
mBaseHandler.post {
showSettingView {
showGuide()
showGuidePopupWindow()
}
}
SPUtils.setBoolean(Constants.SP_SHOW_GAME_SERVER_TEST_V2_SETTING_GUIDE, false)
@ -291,19 +293,6 @@ class GameServerTestV2Fragment : LazyFragment() {
}.start()
}
private fun showGuide() {
mBinding?.settingGuideContainer?.setOnClickListener {
dismissGuide()
}
mBinding?.settingGuideContainer?.isVisible = true
}
private fun dismissGuide() {
mBinding?.settingGuideIv?.animate()?.alpha(0F)?.setDuration(200L)?.doOnEnd {
mBinding?.settingGuideContainer?.isVisible = false
}?.start()
}
private fun getItemTextView(type: String): TextView {
return TextView(requireContext()).apply {
text = type
@ -343,11 +332,22 @@ class GameServerTestV2Fragment : LazyFragment() {
.commitAllowingStateLoss()
}
override fun onBackPressed(): Boolean {
if (mBinding?.settingGuideContainer?.isVisible == true) {
dismissGuide()
return true
private fun showGuidePopupWindow(): PopupWindow {
val guideBinding = LayoutGameServerTestV2SettingGuideBinding.inflate(layoutInflater)
return BugFixedPopupWindow(
guideBinding.root,
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
).apply {
isFocusable = true
isTouchable = true
isOutsideTouchable = true
animationStyle = R.style.popup_window_ease_in_and_out_anim_style
showAsDropDown(mBinding?.optionIv, 0, (-4F).dip2px())
}
}
override fun onBackPressed(): Boolean {
if (mSettingBinding != null) {
dismissSettingView()
return true

View File

@ -16,12 +16,11 @@ import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.databinding.PieceBottomTabBinding
import com.gh.gamecenter.entity.BottomTab
import com.gh.gamecenter.feature.utils.SentryHelper
/**
* 底部Tab 基类
*/
abstract class BaseBottomTabFragment<T : ViewBinding> : ToolbarFragment() {
abstract class BaseBottomTabFragment<T: ViewBinding>: ToolbarFragment() {
protected var mViewPager: ViewPager2? = null
protected var mBottomTabContainer: LinearLayout? = null
@ -45,7 +44,6 @@ abstract class BaseBottomTabFragment<T : ViewBinding> : ToolbarFragment() {
protected fun initBottomTab(bottomTabList: List<BottomTab>) {
mBottomTabBindingList.clear()
mBottomTabContainer?.run {
visibility = View.VISIBLE
removeAllViews()
bottomTabList.forEachIndexed { index, bottomTab ->
addView(
@ -63,13 +61,6 @@ abstract class BaseBottomTabFragment<T : ViewBinding> : ToolbarFragment() {
.apply {
tabTv.text = bottomTab.name
if (!TextUtils.isEmpty(bottomTab.jsCode)) {
tabLottie.setFailureListener {
SentryHelper.onEvent(
SENTRY_ID_BOTTOM_TAB_LOTTIE_LOAD_FAILED,
BOTTOM_TAB_ID, bottomTab.id,
BOTTOM_TAB_NAME, bottomTab.name
)
}
tabLottie.setAnimationFromJson(bottomTab.jsCode, bottomTab.id + bottomTab.name)
}
if (bottomTab.iconSelector != 0) {
@ -87,11 +78,6 @@ abstract class BaseBottomTabFragment<T : ViewBinding> : ToolbarFragment() {
protected fun initViewPager() {
mViewPager?.run {
isUserInputEnabled = false
// 去掉默认动画
setPageTransformer { page, _ ->
page.translationX = 0F
page.alpha = 1F
}
adapter = provideAdapter()
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
@ -136,13 +122,6 @@ abstract class BaseBottomTabFragment<T : ViewBinding> : ToolbarFragment() {
protected open fun onPageSelected(position: Int) {
checkIndex(position)
}
protected open fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
protected open fun onPageScrollStateChanged(state: Int) {}
companion object {
private const val SENTRY_ID_BOTTOM_TAB_LOTTIE_LOAD_FAILED = "bottom_tab_lottie_load_failed"
private const val BOTTOM_TAB_ID = "bottom_tab_id"
private const val BOTTOM_TAB_NAME = "bottom_tab_name"
}
}

View File

@ -14,45 +14,32 @@ import com.gh.gamecenter.fragment.ReloadFragment
class MainFragmentStateAdapter(private val mFragment: Fragment) : BaseDiffFragmentStateAdapter<BottomTab>(mFragment) {
override fun createFragment(data: BottomTab?, position: Int): Fragment {
if (data == null) return ReloadFragment()
val bundle = Bundle()
val superiorChain = if (mFragment is ISuperiorChain) mFragment else null
mFragment.arguments?.let { bundle.putAll(it) }
bundle.putBoolean(EntranceConsts.KEY_IS_HOME, true)
bundle.putString(EntranceConsts.KEY_BOTTOM_TAB_ID, data.id)
bundle.putString(EntranceConsts.KEY_BOTTOM_TAB_NAME, data.name)
bundle.putInt(EntranceConsts.KEY_POSITION, position)
val exposureSourceList = arrayListOf(ExposureSource("底部tab", data.name))
data.diverter?.let {
exposureSourceList.add(
ExposureSource(
"分流器",
"${it.diverterData.diverterName}+${it.diverterData.diverterId}"
)
)
}
bundle.putParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST, exposureSourceList)
bundle.putBoolean(EntranceConsts.KEY_IS_FROM_MAIN_WRAPPER, true)
return if (data.link == null) {
ReloadFragment()
} else {
when (data.link!!.type) {
if (data != null) {
val bundle = Bundle()
val superiorChain = if (mFragment is ISuperiorChain) mFragment else null
mFragment.arguments?.let { bundle.putAll(it) }
if (data.link == null) return ReloadFragment()
bundle.putBoolean(EntranceConsts.KEY_IS_HOME, true)
bundle.putString(EntranceConsts.KEY_BOTTOM_TAB_ID, data.id)
bundle.putString(EntranceConsts.KEY_BOTTOM_TAB_NAME, data.name)
bundle.putInt(EntranceConsts.KEY_POSITION, position)
bundle.putParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST, arrayListOf(ExposureSource("底部tab", data.name)))
bundle.putBoolean(EntranceConsts.KEY_IS_FROM_MAIN_WRAPPER, true)
return when (data.link.type) {
ViewPagerFragmentHelper.TYPE_CUSTOM_PAGE -> {
bundle.putParcelable(LinkEntity::class.java.simpleName, data.link)
SearchToolbarTabWrapperFragment().setSuperiorChain(superiorChain).apply { arguments = bundle }
}
ViewPagerFragmentHelper.TYPE_MULTI_TAB_NAV -> {
bundle.putParcelable(BottomTab.SearchStyle::class.java.simpleName, data.searchStyle)
bundle.putString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, data.link!!.link)
bundle.putString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, data.link!!.text)
bundle.putString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, data.link.link)
bundle.putString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, data.link.text)
SearchToolbarTabWrapperFragment().setSuperiorChain(superiorChain).apply { arguments = bundle }
}
else -> ViewPagerFragmentHelper.createFragment(mFragment, bundle, data.link!!, false)
else -> ViewPagerFragmentHelper.createFragment(mFragment, bundle, data.link, false)
}
} else {
return ReloadFragment()
}
}

View File

@ -13,8 +13,6 @@ import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.text.color
import androidx.core.view.doOnNextLayout
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.ethanhua.skeleton.Skeleton
import com.ethanhua.skeleton.SkeletonScreen
import com.gh.common.iinterface.ISuperiorChain
import com.gh.common.prioritychain.BottomTabGuideHandler
import com.gh.common.prioritychain.GlobalPriorityChainHelper
@ -50,8 +48,6 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
private var mBottomTabGuideHandler: BottomTabGuideHandler? = null
private var mBottomTabGuidePopupWindow: PopupWindow? = null
private var mSkeletonScreen: SkeletonScreen? = null
override fun getLayoutId(): Int = 0
override fun getInflatedLayout(): View = mBinding.root
override fun provideAdapter(): FragmentStateAdapter = mAdapter
@ -67,24 +63,18 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
super.onCreate(savedInstanceState)
DisplayUtils.transparentStatusBar(requireActivity())
initSkeleton()
mBinding.viewShadow.visibility = if (mIsDarkModeOn) View.GONE else View.VISIBLE
buildPriorityChain()
mViewModel?.bottomTabListLiveData?.observe(this) {
mSkeletonScreen?.hide()
mBottomTabList.clear()
mBottomTabList.addAll(it)
mViewPager?.offscreenPageLimit = it.size
initBottomTab(mBottomTabList)
showBottomTabGuideIfExists()
mAdapter.submitList(mBottomTabList)
val defaultBottomTabIndex = mViewModel!!.defaultBottomTabIndex
val defaultBottomTab = mBottomTabList.getOrNull(defaultBottomTabIndex) ?: return@observe
mViewPager?.doOnNextLayout {
mViewModel?.handleBypassVisit(defaultBottomTab)
setCurrentItem(defaultBottomTabIndex)
setCurrentItem(mViewModel!!.defaultBottomTabIndex)
}
}
}
@ -94,18 +84,6 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
mPriorityChain.addHandler(mBottomTabGuideHandler!!)
}
private fun initSkeleton() {
mSkeletonScreen = Skeleton.bind(mBinding.skeleton)
.shimmer(true)
.angle(Constants.SHIMMER_ANGLE)
.color(R.color.ui_skeleton_highlight)
.duration(Constants.SHIMMER_DURATION)
.maskWidth(Constants.MASK_WIDTH)
.gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
.load(R.layout.fragment_main_skeleton)
.show()
}
private fun showBottomTabGuideIfExists() {
val guidePosition = mBottomTabList.indexOfFirst { it.guide != null }
if (guidePosition != -1) {
@ -216,9 +194,6 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
if (bottomTab?.guide != null) {
dismissBottomTabGuide()
}
bottomTab?.let {
mViewModel?.handleBypassVisit(it)
}
playTabAnimation(toCheck)
changeBottomTabStyle(toCheck)
EventBus.getDefault().post(EBReuse(Constants.FINISH_PULL_DOWN_PUSH))

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