Compare commits

...

55 Commits

Author SHA1 Message Date
88bfd0258b refactor: 根据va版本设置测试还是正式打包 2024-04-24 17:30:39 +08:00
bc9d557005 refactor: targetSDKVersion 还原 2024-04-24 16:41:35 +08:00
de982928b0 refactor!: 临时降低targetSDKVersion用于测试目的 2024-04-22 08:59:28 +08:00
82ef0ce1be feat: VA合并 2024-04-19 17:32:51 +08:00
798b19d9d7 Merge branch 'feat/remove_useless_activity' into 'dev'
feat: 移除已被弃用的 activity 及其相关的代码 (没有依赖、非通用跳转、已无入口等)

See merge request halo/android/assistant-android!1632
2024-04-19 16:14:12 +08:00
5c47d3cda8 feat: 移除已被弃用的 activity 及其相关的代码 (没有依赖、非通用跳转、已无入口等) 2024-04-19 16:14:12 +08:00
aea64c0602 Merge branch 'fix/GHZSCY-5231' into 'dev'
fix:【光环助手】轮播banner刷新时蒙层消失 https://jira.shanqu.cc/browse/GHZSCY-5231

See merge request halo/android/assistant-android!1631
2024-04-18 17:48:51 +08:00
4abc0a3edb fix:【光环助手】轮播banner刷新时蒙层消失 https://jira.shanqu.cc/browse/GHZSCY-5231 2024-04-18 17:48:50 +08:00
ded940412e Merge branch 'feat/remove_useless_dependencies' into 'dev'
feat: 移除无用依赖

See merge request halo/android/assistant-android!1630
2024-04-18 13:59:24 +08:00
9971651fe1 feat: 移除无用依赖
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-04-18 13:53:25 +08:00
c771bad1ea Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	dependencies.gradle
2024-04-16 17:01:37 +08:00
e5dbdb154f Merge branch 'fix/GHZS-5218' into 'release'
fix: 游戏提示解析包错误问题 https://jira.shanqu.cc/browse/GHZS-5218

See merge request halo/android/assistant-android!1628
2024-04-16 15:05:02 +08:00
2b91545d34 fix: 游戏提示解析包错误问题 https://jira.shanqu.cc/browse/GHZS-5218
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-04-16 15:03:12 +08:00
f8703b9fe1 chore: 版本更新至 5.34.7 2024-04-16 14:34:40 +08:00
58cc8c7f3c Merge branch 'fix/GHZS-5218' into 'release'
fix: 游戏提示解析包错误问题 https://jira.shanqu.cc/browse/GHZS-5218

See merge request halo/android/assistant-android!1625
2024-04-16 14:33:44 +08:00
79cf1566b2 fix: 游戏提示解析包错误问题 https://jira.shanqu.cc/browse/GHZS-5218 2024-04-16 14:32:19 +08:00
47a98f22b5 Merge branch 'feature-fix-sentry-379733' into 'release'
fix: 修复文章分享埋点上报造成的空指针问题

See merge request halo/android/assistant-android!1627
2024-04-16 11:35:29 +08:00
71453054d9 fix: 修复文章分享埋点上报造成的空指针问题 2024-04-16 11:35:29 +08:00
61ae86e40a Merge branch 'hotfix/v5.34.6-1036/null_pointer_crash' into 'release'
fix: 修复空指针闪退问题...

See merge request halo/android/assistant-android!1626
2024-04-16 11:34:47 +08:00
89de5f24bf fix: 修复空指针闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/380027/events/ee8c112a97a940beb59a2d733d228dd9/?project=22 2024-04-16 11:19:40 +08:00
5c8a275b3e Merge branch 'fix/build_scripts' into 'dev'
build: 默认使用极光推送

See merge request halo/android/assistant-android!1624
2024-04-16 09:26:45 +08:00
405fd6c698 build: 默认使用极光推送 2024-04-16 09:22:59 +08:00
d70c8f2b78 Merge branch 'fix/build_gradle' into 'dev'
build: 默认使用极光推送

See merge request halo/android/assistant-android!1623
2024-04-15 18:09:19 +08:00
2700b309dd build: 默认使用极光推送 2024-04-15 18:08:09 +08:00
832509a124 fix: 修复下载模块回调两次 downloadComplete 的问题
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-04-15 17:50:38 +08:00
36e69ece10 Merge branch 'feature-GHZS-4991' into 'dev'
feat: 闪指H5落地页新增获取光环游戏数据及相关优化—客户端 https://jira.shanqu.cc/browse/GHZS-4991

See merge request halo/android/assistant-android!1585
2024-04-15 16:15:53 +08:00
7d56f92535 feat: 闪指H5落地页新增获取光环游戏数据及相关优化—客户端 https://jira.shanqu.cc/browse/GHZS-4991 2024-04-15 15:46:28 +08:00
9fe58a72c7 Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	dependencies.gradle
2024-04-15 15:13:09 +08:00
4c79c49506 Merge branch 'feat/GHZS-3758' into 'release'
feat: targetSDK 调整至 30

See merge request halo/android/assistant-android!1514
2024-04-15 15:08:25 +08:00
c4a622a55c fix: 合并冲突
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-04-15 15:06:53 +08:00
3a02823ea9 Merge branch 'feat/GHZS-4988' into 'dev'
feat: 重构图片加载相关代码 https://jira.shanqu.cc/browse/GHZS-4988

See merge request halo/android/assistant-android!1622
2024-04-15 13:49:46 +08:00
7d816c00c4 feat: 重构图片加载相关代码 https://jira.shanqu.cc/browse/GHZS-4988 2024-04-15 10:02:15 +08:00
1214a6fb13 Merge branch 'feature-fix-sentry-376330' into 'release'
fix: 修复开服日历反馈在低版本Android系统中,SimpleDateFormat的日期格式兼容问题

See merge request halo/android/assistant-android!1621
2024-04-12 16:32:52 +08:00
e90053bdc9 fix: 修复开服日历反馈在低版本Android系统中,SimpleDateFormat的日期格式兼容问题 2024-04-12 16:29:48 +08:00
de9980af6a Merge branch 'feat/refactor_do_on_main_process_implementation' into 'dev'
feat: 重构限制主进程执行的相关代码

See merge request halo/android/assistant-android!1620
2024-04-12 15:29:54 +08:00
ec6ad35ade feat: 重构限制主进程执行的相关代码 2024-04-12 14:52:46 +08:00
c199487c51 Merge branch 'chen/202404/fix-common-content-reuse' into 'release'
fix:修复通用内容合集显示错乱问题(考虑极端情况:数据完全相同,样式不同)

See merge request halo/android/assistant-android!1619
2024-04-12 13:48:25 +08:00
a1ac427540 fix:修复通用内容合集显示错乱问题(考虑极端情况:数据完全相同,样式不同) 2024-04-12 13:45:51 +08:00
1e2755c82c Merge branch 'hotfix/v5.34.5-1035/game_detail_crash' into 'release'
fix: 修复游戏详情页闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/376726/?project=22

See merge request halo/android/assistant-android!1618
2024-04-12 10:58:14 +08:00
a05e31705f fix: 修复游戏详情页闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/376726/?project=22 2024-04-12 10:37:38 +08:00
62f2bb40df Merge branch 'hotfix/v5.34.5-1035/forum_article_ask_list_crash' into 'release'
fix: 修复论坛详情页闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/378960/?project=22

See merge request halo/android/assistant-android!1617
2024-04-12 09:52:06 +08:00
eabb277c7b fix: 修复论坛详情页闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/378960/?project=22 2024-04-12 09:45:36 +08:00
fb7cdd5ce7 Merge branch 'feature-GHZS-4956' into 'dev'
feat: 内容卡片新增提示弹窗—客户端 https://jira.shanqu.cc/browse/GHZS-4956

See merge request halo/android/assistant-android!1595
2024-04-11 17:31:58 +08:00
3bbfd676fb feat: 内容卡片新增提示弹窗—客户端 https://jira.shanqu.cc/browse/GHZS-4956 2024-04-11 17:31:58 +08:00
7be6af5f08 Merge branch 'chen/202404/GHZS-5197' into 'release'
fix:【光环助手】同一页面使用相同样式组件的图片复用 https://jira.shanqu.cc/browse/GHZS-5197

See merge request halo/android/assistant-android!1616
2024-04-11 15:50:29 +08:00
982f5faf97 fix:【光环助手】同一页面使用相同样式组件的图片复用 https://jira.shanqu.cc/browse/GHZS-5197 2024-04-11 15:47:58 +08:00
81c8469e7b Merge branch 'feat/GHZS-5075' into 'dev'
feat: 搜索页面专区文案修改—客户端 https://jira.shanqu.cc/browse/GHZS-5075

See merge request halo/android/assistant-android!1615
2024-04-10 15:50:54 +08:00
2e03e9f4f5 feat: 搜索页面专区文案修改—客户端 https://jira.shanqu.cc/browse/GHZS-5075 2024-04-10 15:50:54 +08:00
6ab10a0eee Merge branch 'feat/GHZS-5050' into 'dev'
feat: 消息推送:接入极光消息推送系统—客户端 https://jira.shanqu.cc/browse/GHZS-5050

See merge request halo/android/assistant-android!1613
2024-04-10 14:46:35 +08:00
23f7d1f32c feat: 消息推送:接入极光消息推送系统—客户端 https://jira.shanqu.cc/browse/GHZS-5050 2024-04-10 14:46:35 +08:00
93f5343106 Merge branch 'feat/GHZS-5150' into 'dev'
feat: 下拉推送弹窗规则优化—客户端 https://jira.shanqu.cc/browse/GHZS-5150

See merge request halo/android/assistant-android!1614
2024-04-10 14:41:45 +08:00
6846a61dd5 feat: 下拉推送弹窗规则优化—客户端 https://jira.shanqu.cc/browse/GHZS-5150 2024-04-10 14:41:45 +08:00
6ebae66fc7 Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	dependencies.gradle
2024-04-07 13:44:54 +08:00
18246edd46 Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	dependencies.gradle
2024-04-02 11:23:44 +08:00
796848a23c chore: 版本更新至 5.35.0 2024-03-29 11:01:32 +08:00
235 changed files with 3558 additions and 6042 deletions

4
.gitignore vendored
View File

@ -9,4 +9,6 @@ build/
release-app/
test-app/
scripts/apk-channel/
app/src/test/java/com/gh/gamecenter
app/src/test/java/com/gh/gamecenter
app/src/main/assets-debug/
app/src/main/assets-release/

3
.gitmodules vendored
View File

@ -11,3 +11,6 @@
[submodule "ndownload"]
path = ndownload
url = ../../../android/ndownload.git
[submodule "vasdk"]
path = vasdk
url = ../../../sdg/android/vasdk.git

View File

@ -75,7 +75,7 @@ android {
versionName rootProject.ext.versionName
applicationId rootProject.ext.applicationId
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt'
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt', rootProject.ext.va_proguard_rules
String CORE_EVENT_GAME_CATEGORY = ""
@ -164,6 +164,15 @@ android {
flavorDimensions("env", "region")
sourceSets {
debug {
assets.srcDirs += 'src/main/assets-debug'
}
release {
assets.srcDirs += 'src/main/assets-release'
}
publish {
java.srcDirs = ['src/main/java', "src/default/java"]
}
@ -345,8 +354,6 @@ dependencies {
})
implementation "com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-exo_player2:$gsyVideo"
// implementation "androidx.work:work-runtime:${workManager}"
implementation "com.llew.huawei:verifier:${verifier}"
teaImplementation "com.bytedance.applog:RangersAppLog-Lite-cn:${bytedanceApplog}"
@ -359,8 +366,6 @@ dependencies {
implementation "com.lg:easyfloat:${easyFloat}"
implementation "io.github.florent37:shapeofview:${shapeOfView}"
implementation "com.lg:apksig:${apksig}"
implementation "com.lg:gid:${gid}"
@ -372,7 +377,7 @@ dependencies {
kapt "com.alibaba:arouter-compiler:$arouterVersion"
implementation project(':ndownload')
implementation project(':vspace-bridge:vspace')
implementation project(':vspace-bridge')
implementation (project(':module_common')) {
exclude group: 'androidx.swiperefreshlayout'
@ -412,13 +417,22 @@ dependencies {
exclude group: 'androidx.swiperefreshlayout'
}
internalImplementation(project(':module_internal_test'))
// 根据BUILD_PUSH_TYPE决定使用哪个推送SDK目前默认使用阿里云推送
def pushProject = findProperty('BUILD_PUSH_TYPE') == 'jg'
? project(':feature:jg_push') : project(':feature:acloud_push')
implementation(pushProject) {
exclude group: 'androidx.swiperefreshlayout'
}
implementation(project(":va-lib"))
implementation(project(':va-main')) {
exclude group: 'androidx.swiperefreshlayout'
}
debugImplementation "com.bytedance.tools.codelocator:codelocator-core:2.0.3"
compileOnly project(":va-core")
compileOnly project(":va-plugin-host-lib")
implementation project(":va-plugin-host")
implementation project(":va-archive")
}
File propFile = file('sign.properties')
@ -489,6 +503,13 @@ andResGuard {
// 打开这个开关会合并所有哈希值相同的资源,但请不要过度依赖这个功能去除去冗余资源
mergeDuplicatedRes = true
whiteList = [
"R.xml.jpush*",
"R.drawable.jpush*",
"R.layout.jpush*",
"R.layout.push*",
"R.string.jg*",
"R.style.MyDialogStyle",
"R.style.JPushTheme",
"R.drawable.icon",
"R.drawable.ic_bar_back",
"R.drawable.toolbar_search_icon",

View File

@ -1,32 +1,85 @@
package com.gh.vspace
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.Keep
import com.gh.gamecenter.R
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.databinding.LayoutPersonalOtherItemBinding
import com.gh.vspace.installexternalgames.InstallExternalGameActivity
import com.lg.vspace.VaApp
import com.lg.vspace.plugin.host.PluginHelper
import com.lightgame.utils.Utils
import com.lightgame.utils.toast.ToastHelper
import com.lody.virtual.client.core.VirtualCore
import java.io.File
@Keep
class ExternalGameUsage : IExternalGamesUsage {
override fun addInstallExternalGameButton(viewParent: ViewGroup) {
class ExternalGameUsage : ITestCase {
private fun buttonTemplate(viewParent: ViewGroup, id: Int, fn: (LayoutPersonalOtherItemBinding) -> Unit) {
val context = viewParent.context
viewParent.findViewById<View>(R.id.install_game_from_external) ?: run {
viewParent.findViewById<View>(id) ?: run {
val binding = LayoutPersonalOtherItemBinding.inflate(LayoutInflater.from(context)).apply {
root.id = R.id.install_game_from_external
titleTv.text = context.getString(R.string.title_install_external_game)
iconIv.setImageResource(R.drawable.ic_personal_my_game)
root.setOnClickListener {
VHelper.connectService {
context.startActivity(
InstallExternalGameActivity.getIntent(context)
.apply { flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK })
}
}
root.id = id
fn(this)
}
viewParent.addView(binding.root, 0)
}
}
override fun addInstallExternalGameButton(viewParent: ViewGroup) {
val context = viewParent.context
buttonTemplate(viewParent, R.id.install_game_from_external) {
it.titleTv.text = context.getString(R.string.title_install_external_game)
it.iconIv.setImageResource(R.drawable.ic_personal_my_game)
it.root.setOnClickListener {
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位插件")
PluginHelper.getInstance().updatePlugin(file, VHelper.getCwBaseLogParams())
} 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()) {
Utils.log(VHelper.LOG_TAG, "有本地更新文件: 32位插件")
VirtualCore.get().updatePlugin(file.absolutePath, "artifacts32.zip",
VHelper.getCwBaseLogParams().let {
val bundle = Bundle()
for ((key, value) in it) {
bundle.putString(key, value)
}
bundle
})
} else {
ToastUtils.showToast("data/local/tmp没有push文件")
}
}
}
}
}

View File

@ -25,6 +25,11 @@ class ExternalGameAdapter(private val games: List<ExternalGameUiState>, private
路径:${item.apkPath}
""".trimIndent()
}
holder.update.setOnClickListener {
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_INSTALL)
}
holder.install.goneIf(item.isInstalled) {
holder.install.setOnClickListener {
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_INSTALL)

View File

@ -8,4 +8,5 @@ class ExternalGameViewHolder(binding: LayoutExternalGameItemBinding) : RecyclerV
val install = binding.btnInstall
val uninstall = binding.btnUninstall
val start = binding.btnStart
val update = binding.btnUpdate
}

View File

@ -16,6 +16,7 @@ import com.gh.gamecenter.databinding.FragmentInstallExternalGamesBinding
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lg.vspace.VirtualAppManager
import com.lightgame.download.DownloadEntity
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
@ -105,6 +106,15 @@ 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.install(requireContext(), DownloadEntity().apply {
externalGameUiState.externalGameEntity.apply {
packageName = apkPackageName
path = apkPath
}
}, true)
if (VHelper.showDialogIfVSpaceIsNeeded(
requireContext(),
"",
@ -144,7 +154,9 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
com.gh.gamecenter.BuildConfig.VERSION_NAME,
HaloApp.getInstance().channel,
"",
""
"",
com.lg.core.BuildConfig.VERSION_NAME,
HaloApp.getInstance().oaid
)
requireActivity().startActivity(intent)
}

View File

@ -24,6 +24,14 @@
android:visibility="gone"
tools:visibility="visible" />
<Button
android:id="@+id/btn_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_update"
android:visibility="visible"
tools:visibility="visible" />
<Button
android:id="@+id/btn_uninstall"
android:layout_width="wrap_content"

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

@ -2,6 +2,7 @@
<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

@ -86,7 +86,30 @@
com.tencent.qqmini,
com.tencent.qqmini.minigame.external,
com.tencent.qqmini.minigame.opensdk,
com.tencent.qqmini.union.ad" />
com.tencent.qqmini.union.ad,
com.lg.vspace,
io.lg.va.common,
com.va.floating,
com.lg.cloud,
com.lg.archive,
com.lg.vclient,
com.va.realname,
com.lg.vspace.flavor,
com.lg.update,
com.lg.login,
com.lg.accelerator,
com.lody.virtual,
com.lg.core,
com.lg.ads,
com.lg.common,
com.lg.vspace.network,
com.lody.virtual.lib.res,
com.va.host,
com.lg.vspace.plugin.host,
com.lg.plugin.constant,
com.bytedance.tools.codelocator,
org.chickenhook.restrictionbypass,
com.lody.virtual.sandhook,com.lg.vspace.common" />
<!-- 去掉 SDK 一些流氓权限 -->
<uses-permission
@ -317,14 +340,6 @@
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" />
<activity
android:name="com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.answer.edit.AnswerEditActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.InfoActivity"
android:screenOrientation="portrait" />
@ -333,10 +348,6 @@
android:name=".qa.questions.invite.QuestionsInviteActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.myqa.MyAskActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.questions.edit.QuestionEditActivity"
android:screenOrientation="portrait" />
@ -374,10 +385,6 @@
android:name="com.gh.gamecenter.qa.article.edit.ArticleEditActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.article.MyArticleActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.article.draft.ArticleDraftActivity"
android:screenOrientation="portrait" />
@ -416,10 +423,6 @@
android:name="com.gh.gamecenter.history.HistoryActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.personalhome.rating.RatingActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.gamedetail.rating.logs.CommentLogsActivity"
android:screenOrientation="portrait" />
@ -492,9 +495,6 @@
android:name=".gamedetail.fuli.kaifu.ServersSubscribedGameListActivity"
android:screenOrientation="portrait" />
<activity
android:name=".qa.answer.draft.AnswerDraftActivity"
android:screenOrientation="portrait" />
<activity
android:name=".gamedetail.rating.RatingFoldActivity"
android:screenOrientation="portrait" />
@ -506,10 +506,6 @@
android:name=".video.poster.PosterEditActivity"
android:screenOrientation="portrait" />
<activity
android:name=".video.poster.PosterClipActivity"
android:screenOrientation="portrait" />
<activity
android:name=".forum.detail.ForumDetailActivity"
android:screenOrientation="portrait" />
@ -804,7 +800,8 @@
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />

View File

@ -203,6 +203,10 @@ object AdDelegateHelper {
return mDownloadManagerAd != null && !isMatchAdFreeRule(mDownloadManagerAd) && isMatchDownloadManagerAdDisplayRule()
}
fun shouldShowHelperLaunchAd(): Boolean {
return mVGameLaunchAd != null && !isMatchAdFreeRule(mVGameLaunchAd) && isMatchAdDisplayRule(mVGameLaunchAd, Constants.SP_LAST_HELPER_LAUNCH_AD_SHOW_TIME)
}
/**
* 是否需要显示游戏搜索广告
*/
@ -247,10 +251,11 @@ object AdDelegateHelper {
/**
* 是否大于广告管理展示间隔时长
*/
private fun isMatchDownloadManagerAdDisplayRule(): Boolean {
mDownloadManagerAd?.displayRule?.run {
private fun isMatchDownloadManagerAdDisplayRule(): Boolean = isMatchAdDisplayRule(mDownloadManagerAd, Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME)
private fun isMatchAdDisplayRule(adConfig: AdConfig?, spKey: String): Boolean {
adConfig?.displayRule?.run {
if (adDisplayInterval > 0) {
val lastShowTime = SPUtils.getLong(Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME, 0L)
val lastShowTime = SPUtils.getLong(spKey, 0L)
val durationInMinutes = (System.currentTimeMillis() - lastShowTime).toFloat() / 1000 / 60
return durationInMinutes > adDisplayInterval
} else {

View File

@ -0,0 +1,44 @@
package com.gh.ad
import android.content.Context
import android.view.View
import android.view.ViewGroup
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.utils.goneIf
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.lg.vspace.ui.launcher.ILaunchAd
@Route(path = RouteConsts.provider.vaAd, name = "畅玩启动页广告")
class LaunchAdImpl : ILaunchAd {
override fun init(context: Context?) {
}
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) {
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())
}
}
}
}
}
}

View File

@ -129,7 +129,7 @@ abstract class BaseRichEditorViewModel(application: Application) : AndroidViewMo
for (key in imageUrlMap.keys) {
// 文件格式为 HEIC 时,使用经 OSS 转码的图片作为预览图片
if (FileUtils.getFileMimeType(getApplication(), key.decodeURI())?.lowercase(Locale.CHINA)?.contains("heic") == true) {
val transformedImgUrl = ImageUtils.getTransformedUrl(imageUrlMap[key], 5000) ?: ""
val transformedImgUrl = ImageUtils.getIdealImageUrl(imageUrlMap[key], 5000) ?: ""
map[MD5Utils.getUrlMD5(key)] = transformedImgUrl
mapImages[transformedImgUrl.decodeURI()] = imageUrlMap[key] ?: ""
} else {

View File

@ -15,8 +15,11 @@ import com.gh.gamecenter.SplashScreenActivity
import com.gh.gamecenter.authorization.AuthorizationActivity
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.utils.PackageFlavorHelper
import com.gh.gamecenter.feedback.view.suggest.SuggestionActivity
import com.gh.gamecenter.login.view.LoginActivity
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lg.vspace.ui.launcher.LaunchActivity
// TODO移动到对应的模块
class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
@ -37,6 +40,7 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
&& activity !is SkipActivity
&& activity !is AuthorizationActivity
&& activity !is SplashAdActivity
&& activity !is SuggestionActivity
) {
activity.startActivity(SplashAdActivity.getIntent(activity))
}
@ -73,6 +77,8 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
}
if (activity is AppCompatActivity
&& activity !is LaunchActivity
&& activity !is LoginActivity
&& activity !is SplashScreenActivity
&& activity !is SkipActivity
&& activity !is AuthorizationActivity

View File

@ -220,7 +220,7 @@ class DefaultJsApi(
runOnUiThread {
// 若畅玩列表中安装了,优先启动畅玩游戏
if (VHelper.isInstalled(packageName)) {
if (!VHelper.showDialogIfVSpaceIsNeeded(context, "", "", "", "")) {
VHelper.validateVSpaceBeforeAction(context, packageName, null) {
VHelper.launch(context, packageName)
}
} else {

View File

@ -2,17 +2,16 @@ package com.gh.common
import com.gh.common.exposure.ExposureManager
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.AdHelper
import com.gh.common.videolog.VideoRecordUtils
import com.gh.download.DownloadDataHelper
import com.gh.gamecenter.common.loghub.LoghubUtils
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.doOnMainProcessOnly
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.entity.TimeEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.schedulers.Schedulers
import kotlin.concurrent.fixedRateTimer
@ -26,7 +25,6 @@ object FixedRateJobHelper {
private const val DOWNLOAD_HEARTBEAT_PERIOD: Long = 60 * 1000L
private const val DOWNLOAD_HEARTBEAT_SHEET_PERIOD: Long = 15 * 1000L
private const val STARTUP_AD: Long = 30 * 60 * 1000L
private var mExecuteCount: Int = 0
@ -34,58 +32,56 @@ object FixedRateJobHelper {
@JvmStatic
fun begin() {
doOnMainProcessOnly {
// 时间检查每15秒检查一次
fixedRateTimer("Global-Fixed-Rate-Timer", initialDelay = 100, period = CHECKER_PERIOD) {
val elapsedTime = mExecuteCount * CHECKER_PERIOD
// 时间校对10分钟一次
if (elapsedTime % TIME_PERIOD == 0L) {
RetrofitManager.getInstance().api.time
.subscribeOn(Schedulers.io())
.subscribe(object : Response<TimeEntity>() {
override fun onResponse(response: TimeEntity?) {
val serverTime = response?.time
serverTime?.let {
timeDeltaBetweenServerAndClient = it * 1000 - System.currentTimeMillis()
}
// 时间检查每15秒检查一次
fixedRateTimer("Global-Fixed-Rate-Timer", initialDelay = 100, period = CHECKER_PERIOD) {
val elapsedTime = mExecuteCount * CHECKER_PERIOD
// 时间校对10分钟一次
if (elapsedTime % TIME_PERIOD == 0L) {
RetrofitManager.getInstance().api.time
.subscribeOn(Schedulers.io())
.subscribe(object : Response<TimeEntity>() {
override fun onResponse(response: TimeEntity?) {
val serverTime = response?.time
serverTime?.let {
timeDeltaBetweenServerAndClient = it * 1000 - System.currentTimeMillis()
}
})
}
// 提交曝光数据
if (elapsedTime % EXPOSURE_PERIOD == 0L) {
ExposureManager.commitSavedExposureEvents(true)
}
// 分片检测下载进度
if (elapsedTime % DOWNLOAD_HEARTBEAT_SHEET_PERIOD == 0L) {
tryCatchInRelease {
val upload = (mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_PERIOD == 0L
DownloadDataHelper.uploadDownloadHeartbeat(upload)
}
}
// 提交普通 loghub 数据
if (elapsedTime % LOGHUB_PERIOD == 0L) {
runOnUiThread {
LoghubUtils.commitSavedLoghubEvents(true)
}
}
// 更新游戏屏蔽信息
if (elapsedTime % REGION_SETTING_PERIOD == 0L) {
if (HaloApp.getInstance().isRunningForeground) {
RegionSettingHelper.getRegionSetting()
}
}
// 提交视频浏览记录数据
if (elapsedTime % VIDEO_RECORD_PERIOD == 0L) {
VideoRecordUtils.commitVideoRecord()
}
mExecuteCount++
}
})
}
// 提交曝光数据
if (elapsedTime % EXPOSURE_PERIOD == 0L) {
ExposureManager.commitSavedExposureEvents(true)
}
// 分片检测下载进度
if (elapsedTime % DOWNLOAD_HEARTBEAT_SHEET_PERIOD == 0L) {
tryCatchInRelease {
val upload = (mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_PERIOD == 0L
DownloadDataHelper.uploadDownloadHeartbeat(upload)
}
}
// 提交普通 loghub 数据
if (elapsedTime % LOGHUB_PERIOD == 0L) {
runOnUiThread {
LoghubUtils.commitSavedLoghubEvents(true)
}
}
// 更新游戏屏蔽信息
if (elapsedTime % REGION_SETTING_PERIOD == 0L) {
if (HaloApp.getInstance().isRunningForeground) {
RegionSettingHelper.getRegionSetting()
}
}
// 提交视频浏览记录数据
if (elapsedTime % VIDEO_RECORD_PERIOD == 0L) {
VideoRecordUtils.commitVideoRecord()
}
mExecuteCount++
}
}
}

View File

@ -18,7 +18,15 @@ class LandPageAddressHandler : DownloadChainHandler() {
}
DialogUtils.showLandPageAddressDialog(context, gameEntity) {// 跳转第三方落地页
DirectUtils.directToExternalBrowser(context, gameEntity.landPageAddressDialog!!.link!!)
if (gameEntity.isLandPageAddressDialogShowOnly()) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(asVGame, null)
}
} else {
DirectUtils.directToExternalBrowser(context, gameEntity.landPageAddressDialog!!.link!!)
}
}
}
} else {

View File

@ -16,7 +16,7 @@ class ValidateVSpaceHandler : DownloadChainHandler() {
}
if (asVGame) {
VHelper.validateVSpaceBeforeAction(context, gameEntity) {
VHelper.validateVSpaceBeforeAction(context,gameEntity.getUniquePackageName(), gameEntity) {
closure.invoke()
}
} else {

View File

@ -21,14 +21,17 @@ import com.gh.gamecenter.common.utils.EnvHelper;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.SPUtils;
import com.gh.gamecenter.core.utils.UrlFilterUtils;
import com.gh.gamecenter.entity.AppEntity;
import com.gh.gamecenter.entity.GameGuidePopupEntity;
import com.gh.gamecenter.entity.NewApiSettingsEntity;
import com.gh.gamecenter.entity.NewSettingsEntity;
import com.gh.gamecenter.entity.VNewSetting;
import com.gh.gamecenter.entity.VSetting;
import com.gh.gamecenter.feature.entity.SettingsEntity;
import com.gh.gamecenter.feature.entity.SimulatorEntity;
import com.gh.gamecenter.feature.utils.ContentBlockedHelper;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.gh.gamecenter.retrofit.service.VApiService;
import com.gh.vspace.VHelper;
import com.halo.assistant.HaloApp;
@ -39,8 +42,12 @@ import org.json.JSONObject;
import java.io.IOException;
import java.util.Locale;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.BehaviorSubject;
import okhttp3.ResponseBody;
public class Config {
@ -69,6 +76,10 @@ public class Config {
private static NewApiSettingsEntity.NightMode mNightModeSetting;
private static SimulatorEntity mNewSimulatorEntity;
private static VSetting mVSetting;
private static VNewSetting mVNewSetting;
private static AppEntity mNew32UpdateEntity;
public static BehaviorSubject<VNewSetting> vNewSettingSubject = BehaviorSubject.create();
private static GameGuidePopupEntity mGameGuidePopupEntity;
private static SharedPreferences mDefaultSharedPreferences;
@ -197,6 +208,27 @@ public class Config {
return mVSetting;
}
@Nullable
public static VNewSetting getVNewSettingEntity() {
if (mVNewSetting == null) {
try {
String json = SPUtils.getString(Constants.SP_V_NEW_SETTINGS);
if (!TextUtils.isEmpty(json)) {
mVNewSetting = GsonUtils.fromJson(json, VNewSetting.class);
vNewSettingSubject.onNext(mVNewSetting);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return mVNewSetting;
}
@Nullable
public static AppEntity getNew32UpdateEntity() {
return mNew32UpdateEntity;
}
/**
* 请求网络数据,尝试刷新畅玩相关配置
*/
@ -217,6 +249,36 @@ public class Config {
});
}
@SuppressLint("CheckResult")
public static void getNewSetting() {
VApiService vApi = RetrofitManager.getInstance().getVApi();
vApi.getNewSettings(BuildConfig.VERSION_NAME, Build.VERSION.SDK_INT).flatMap(new Function<VNewSetting, SingleSource<AppEntity>>() {
@Override
public SingleSource<AppEntity> apply(VNewSetting data) throws Exception {
mVNewSetting = data;
vNewSettingSubject.onNext(mVNewSetting);
SPUtils.setString(Constants.SP_V_NEW_SETTINGS, GsonUtils.toJson(data));
if (data.getVa() != null && data.getVa().getArch32() != null) {
String versionNameByPackageName = PackageUtils.getVersionNameByPackageName(data.getVa().getArch32().getPackageName());
return vApi.getNewPackageUpdate(
BuildConfig.VERSION_NAME,
versionNameByPackageName != null ? versionNameByPackageName : "",
HaloApp.getInstance().getChannel()
);
}
return Single.error(new IllegalStateException("VNewSetting entity is not expected"));
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BiResponse<AppEntity>() {
@Override
public void onSuccess(AppEntity data) {
mNew32UpdateEntity = data;
}
});
}
@Nullable
public static GameGuidePopupEntity getGameGuidePopupEntity() {
return mGameGuidePopupEntity;
@ -271,6 +333,7 @@ public class Config {
});
refreshVSettingEntity();
getNewSetting();
RetrofitManager.getInstance()
.getApi().getGameGuidePopup(Build.MANUFACTURER, Build.VERSION.RELEASE, Build.MODEL, channel, BuildConfig.VERSION_NAME)

View File

@ -23,6 +23,7 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
private var mDialog: GameEntity.Dialog? = null
private var mBinding: DialogGameOffServiceBinding? = null
private var mCallback: (() -> Unit)? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -44,6 +45,7 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
titleTv.text = title
contentTv.text = HtmlCompat.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY)
okTv.setOnClickListener {
mCallback?.invoke()
dismissAllowingStateLoss()
}
@ -64,7 +66,6 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
siteTv.text = site.text
siteTv.paintFlags = siteTv.paintFlags or Paint.UNDERLINE_TEXT_FLAG
siteTv.setOnClickListener {
// MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)")
dismissAllowingStateLoss()
}
@ -83,11 +84,13 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
const val KEY_DIALOG = "dialog"
@JvmStatic
fun getInstance(dialog: GameEntity.Dialog) = GameOffServiceDialogFragment().apply {
arguments = Bundle().apply {
putParcelable(KEY_DIALOG, dialog)
fun getInstance(dialog: GameEntity.Dialog, callback: (() -> Unit)? = null) =
GameOffServiceDialogFragment().apply {
arguments = Bundle().apply {
putParcelable(KEY_DIALOG, dialog)
}
mCallback = callback
}
}
}
}

View File

@ -1,89 +0,0 @@
package com.gh.common.prioritychain
import androidx.recyclerview.widget.RecyclerView
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.gamecenter.common.base.fragment.BaseLazyFragment
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IFloatingWindowProvider
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
import com.gh.gamecenter.floatingwindow.FloatingWindowEntity
import com.gh.gamecenter.fragment.WelcomeDialogFragment
import com.lightgame.utils.Utils
class FloatingWindowHandler(priority: Int) : PriorityChainHandler(priority) {
private var mFragment: BaseLazyFragment? = null
private var mRecyclerView: RecyclerView? = null
private var mWindowList: ArrayList<FloatingWindowEntity>? = null
fun setData(windowList: ArrayList<FloatingWindowEntity>?) {
mWindowList = windowList
if (mFragment != null) {
doPreProcess()
}
}
fun setView(
fragment: BaseLazyFragment,
recyclerView: RecyclerView
) {
mFragment = fragment
mRecyclerView = recyclerView
if (mWindowList != null) {
doPreProcess()
}
}
private fun doPreProcess() {
Utils.log(TAG, "FloatingWindowHandler preProcess windowSize is -> ${mWindowList?.size}")
if (getStatus() == STATUS_PENDING) {
if (!mWindowList.isNullOrEmpty()) {
updateStatus(STATUS_VALID)
process()
} else {
processNext()
}
} else {
if (!mWindowList.isNullOrEmpty()) {
updateStatus(STATUS_VALID)
} else {
updateStatus(STATUS_INVALID)
}
}
}
override fun onProcess(): Boolean {
when (getStatus()) {
STATUS_VALID -> {
val floatingWindowProvider =
ARouter.getInstance().build(RouteConsts.provider.floatingwindow)
.navigation() as? IFloatingWindowProvider<WelcomeDialogEntity>
// 强校验所有条件均通过才能显示
if (floatingWindowProvider == null || mFragment == null || mFragment?.isAdded == false || mRecyclerView == null) {
processNext()
return false
}
floatingWindowProvider.showFloatingWindowOnly(
mFragment!!,
mRecyclerView!!,
mWindowList!!,
) {
val welcomeDialog = WelcomeDialogFragment.getInstance(it, true, mFragment)
welcomeDialog.show(mFragment!!.childFragmentManager, "WelcomeDialog")
}
}
STATUS_INVALID -> {
processNext()
}
}
return false
}
}

View File

@ -1,8 +1,6 @@
package com.gh.common.prioritychain
import android.graphics.Bitmap
import androidx.fragment.app.FragmentActivity
import com.gh.gamecenter.common.callback.BiCallback
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
@ -21,20 +19,19 @@ class WelcomeDialogHandler(priority: Int) : PriorityChainHandler(priority) {
// 判断启动本次应用是否已经弹窗,不是的话弹启动弹窗
if (HaloApp.get(MainWrapperViewModel.SHOULD_SHOW_OPENING_DIALOG, false) == null) {
HaloApp.put(MainWrapperViewModel.SHOULD_SHOW_OPENING_DIALOG, false)
ImageUtils.getBitmap(this.welcomeDialogEntity!!.icon, object : BiCallback<Bitmap, Boolean> {
override fun onFirst(first: Bitmap) {
val idealUrl = ImageUtils.getIdealImageUrl(this.welcomeDialogEntity!!.icon, 0, true) ?: ""
ImageUtils.prefetchToDiskCache(idealUrl) { isSuccess ->
if (isSuccess) {
if (getStatus() == STATUS_PENDING) {
updateStatus(STATUS_VALID)
process()
} else {
updateStatus(STATUS_VALID)
}
}
override fun onSecond(second: Boolean) {
} else {
processNext()
}
})
}
} else {
processNext()
}

View File

@ -8,6 +8,7 @@ import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.IFlavorProvider
import com.halo.assistant.HaloApp
import com.va.host.HostUtils
@Route(path = RouteConsts.provider.app, name = "Application暴露服务")
class AppProviderImpl : IAppProvider {
@ -86,4 +87,6 @@ class AppProviderImpl : IAppProvider {
override fun setSkippingThirdParty(isSkippingThirdParty: Boolean) {
HaloApp.getInstance().isSkippingThirdParty = isSkippingThirdParty
}
override fun getPluginVersion(): String = HostUtils.getPluginVersion()
}

View File

@ -6,11 +6,12 @@ import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
import com.gh.gamecenter.core.utils.ProcessUtil
@Route(path = RouteConsts.provider.packageUtils, name = "PackageUtils暴露服务")
class PackageUtilsProviderImpl : IPackageUtilsProvider {
override fun obtainProcessName(context: Context): String? {
return PackageUtils.obtainProcessName(context)
override fun obtainProcessName(): String? {
return ProcessUtil.getCurrentProcessName()
}
override fun getGhVersionName(): String {

View File

@ -50,8 +50,6 @@ object ArchiveDownloadButtonHelper {
}
downloadBtn.setOnClickListener {
when {
// 检查是否已安装畅玩助手
!VHelper.isVSpaceInstalled(context) -> showVSpaceTipDialog(context, gameEntity)
// 检查是否已安装游戏
!VHelper.isInstalled(packageName) -> {
// 检查游戏是否在安装中

View File

@ -533,7 +533,7 @@ public class CommentUtils {
} else {
ImageUtils.display(holder.commentUserBadgeIv, "");
}
ImageUtils.displayIcon(holder.commentUserIconDv, userInfo.getIcon());
ImageUtils.display(holder.commentUserIconDv, userInfo.getIcon());
} else {
if (entity.getMe() != null && entity.getMe().isContentOwner()) {
holder.commentAuthorTv.setVisibility(View.VISIBLE);
@ -549,7 +549,7 @@ public class CommentUtils {
if (TextUtils.isEmpty(entity.getUser().getIcon())) {
ImageUtils.display(holder.commentUserIconDv, R.drawable.user_default_icon_comment);
} else {
ImageUtils.displayIcon(holder.commentUserIconDv, entity.getUser().getIcon());
ImageUtils.display(holder.commentUserIconDv, entity.getUser().getIcon());
}
}
}

View File

@ -125,9 +125,7 @@ public class DataUtils {
HaloApp.getInstance().setGid(gid);
// 更新广告配置
ExtensionsKt.doOnMainProcessOnly(HaloApp.getInstance(), () -> {
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
});
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
getDeviceCertification(gid);
@ -147,11 +145,8 @@ public class DataUtils {
@Override
public void onFailure(String s) {
MtaHelper.onEventWithBasicDeviceInfo("开发辅助", "GID 获取异常", s);
// 更新广告配置
ExtensionsKt.doOnMainProcessOnly(HaloApp.getInstance(), () -> {
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
});
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
}
});
}

View File

@ -636,7 +636,12 @@ public class DialogUtils {
binding.closeIv.setOnClickListener(v -> dialog.dismiss());
binding.urlTv.setText(gameEntity.getLandPageAddressDialog().getLink());
binding.downloadBtn.setText(context.getString(R.string.dialog_land_page_address_confirm));
String downloadText = gameEntity.isLandPageAddressDialogShowOnly()
? "下载(" + gameEntity.getApk().get(0).getSize() + ""
: context.getString(R.string.dialog_land_page_address_confirm);
binding.downloadBtn.setText(downloadText);
binding.downloadBtn.setOnClickListener(v -> {
listener.onConfirm();
dialog.dismiss();

View File

@ -508,11 +508,18 @@ object DownloadObserver {
"space_schema_type",
if (downloadEntity.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) "32位" else "64位"
)
} else if(downloadEntity.gameId == Constants.HALO_FUN_NEW_32_GAME_ID) {
SensorsBridge.trackEvent(
"HaloFunDownloadDone",
"space_schema_type",
"32位(新)"
)
}
if (downloadEntity.gameId != Constants.GHZS_GAME_ID
&& downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) != Constants.SIMULATOR_DOWNLOAD
&& downloadEntity.gameId != Constants.HALO_FUN_GAME_ID
&& downloadEntity.gameId != Constants.HALO_FUN_NEW_32_GAME_ID
) {
val trackJson = downloadEntity.customPageTrackDataJson
val kvs = if (!trackJson.isNullOrBlank()) {

View File

@ -282,7 +282,7 @@ object GameActivityDownloadHelper {
location: String,
traceEvent: ExposureEvent
) {
VHelper.validateVSpaceBeforeAction(context, gameEntity) {
VHelper.validateVSpaceBeforeAction(context,gameEntity.getUniquePackageName(), gameEntity) {
GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) {
DialogUtils.checkDownload(
context,

View File

@ -93,12 +93,13 @@ object NewFlatLogUtils {
// 畅玩助手更新弹窗展示事件
@JvmStatic
fun logHaloFunUpdateDialogShow(gameId: String, gameName: String, gameArchitecture: String) {
fun logHaloFunUpdateDialogShow(gameId: String, gameName: String, gameArchitecture: String, targetVaVersion: String) {
val json = json {
KEY_EVENT to "halo_fun_update_dialog_show"
"game_id" to gameId
"game_name" to gameName
"game_architecture" to gameArchitecture
"target_va_version" to targetVaVersion
parseAndPutMeta().invoke(this)
}
log(json)
@ -142,12 +143,13 @@ object NewFlatLogUtils {
// 畅玩助手更新弹窗点击事件
@JvmStatic
fun logHaloFunUpdateDialogClick(dialogType: String, buttonType: String, architecture: String) {
fun logHaloFunUpdateDialogClick(dialogType: String, buttonType: String, architecture: String, targetVaVersion: String) {
val json = json {
KEY_EVENT to "halo_fun_update_dialog_click"
"dialog_type" to dialogType
KEY_BUTTON_TYPE to buttonType
"architecture" to architecture
"target_va_version" to targetVaVersion
parseAndPutMeta().invoke(this)
}
log(json)

View File

@ -888,37 +888,6 @@ public class PackageUtils {
&& !PackageUtils.isSignedByGh(HaloApp.getInstance().getApplication(), apkEntity.getPackageName());
}
/**
* 获取调用者的进程名
*
* @param context 调用者的上下文
* @return 进程名
*/
public static String obtainProcessName(Context context) {
if (PackageFlavorHelper.IS_TEST_FLAVOR) {
try {
final int pid = android.os.Process.myPid();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> listTaskInfo = am.getRunningAppProcesses();
if (listTaskInfo != null && !listTaskInfo.isEmpty()) {
for (ActivityManager.RunningAppProcessInfo info : listTaskInfo) {
if (info != null && info.pid == pid) {
return info.processName;
}
}
}
} catch (Exception e) {
// 遇到异常了让这次调用正常执行
e.printStackTrace();
return BuildConfig.APPLICATION_ID;
}
} else {
return null;
}
return null;
}
/**
* 应用是否在前台运行
*/

View File

@ -1,248 +0,0 @@
package com.gh.common.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ProgressBar;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import com.gh.gamecenter.core.utils.DisplayUtils;
import com.gh.gamecenter.R;
public class DownloadProgressBar extends ProgressBar {
public static final int MAX_LENGTH = 1000;
public static final int DOWNLOAD_NORMAL_STYLE = 0;
public static final int DOWNLOAD_IMAGE_STYLE = 2;
public enum DownloadType {
NORMAL,
NONE,
NONE_WITH_HINT,
PLUGIN,
LAUNCH_OR_OPEN,
INSTALL_NORMAL,
INSTALL_PLUGIN,
DOWNLOADING_NORMAL,
DOWNLOADING_PLUGIN,
RESERVABLE,
RESERVED,
H5_GAME,
UPDATING,
TEENAGER_MODEL,
SPECIAL_DOWNLOAD,
XAPK_UNZIPPING,
XAPK_SUCCESS,
XAPK_FAILURE,
}
private PorterDuffXfermode mDuffXFerMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 仅用于测量文字是否超出范围,不用于画文字
private TextPaint mFakeTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
private DownloadType mDownloadType;
private String mText;
private int mDownloadStyle;
private int mDefaultColor;
private int mTextSize;
private boolean mShowDownloadPercent = false;
private Rect mTextBound = new Rect();
public DownloadProgressBar(Context context) {
super(context);
}
public DownloadProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
if (attrs != null) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.DownloadProgressBar);
mDownloadStyle = ta.getInteger(R.styleable.DownloadProgressBar_downloadStyle, DOWNLOAD_NORMAL_STYLE);
mTextSize = ta.getDimensionPixelSize(R.styleable.DownloadProgressBar_textSize, DisplayUtils.sp2px(getContext(), 14));
mShowDownloadPercent = ta.getBoolean(R.styleable.DownloadProgressBar_showDownloadPercent, false);
ta.recycle();
}
setMax(MAX_LENGTH);
setProgressDrawable(getResources().getDrawable(R.drawable.game_item_btn_download_style));
}
Bitmap srcBitmap;
Canvas srcCanvas;
RectF rectF;
private void create() {
srcBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
srcCanvas = new Canvas(srcBitmap);
rectF = new RectF(0, 0, getProgress() * getWidth() / MAX_LENGTH, getMeasuredHeight());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (TextUtils.isEmpty(mText)) return;
mPaint.setColor(mDefaultColor == 0 ? ContextCompat.getColor(getContext(), R.color.text_theme) : mDefaultColor); // 初始化颜色
mPaint.setTextSize(mTextSize);
mFakeTextPaint.setTextSize(mTextSize);
mFakeTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mFakeTextPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setXfermode(null);
create();
Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
int baseline = (getHeight() - fontMetrics.bottom - fontMetrics.top) / 2;
mPaint.setTextAlign(Paint.Align.CENTER);
canvas.getClipBounds(mTextBound); //The dimensions of your canvas
int width = mTextBound.width() - 20; //10 to keep some space on the right for the "..."
String txt = TextUtils.ellipsize(mText, mFakeTextPaint, width, TextUtils.TruncateAt.END).toString();
srcCanvas.drawText(txt, getWidth() / 2, baseline, mPaint);
mPaint.setXfermode(mDuffXFerMode);
if (getProgress() != 0) {
int color = Color.WHITE;
if (DOWNLOAD_IMAGE_STYLE == mDownloadStyle) {
color = Color.BLACK;
}
mPaint.setColor(color); // 反向颜色
}
srcCanvas.drawRect(rectF, mPaint);
canvas.drawBitmap(srcBitmap, 0, 0, null);
}
public void setText(String text) {
mText = text;
invalidate();
}
public String getText() {
if (mText != null && mText.contains("%")) {
return getResources().getString(R.string.downloading);
}
return mText;
}
public void setText(@StringRes int res) {
if (mShowDownloadPercent && res == R.string.downloading) {
setText(getProgressPercent());
} else {
setText(getResources().getString(res));
}
}
public void setDownloadStyle(int downloadStyle) {
this.mDownloadStyle = downloadStyle;
}
@Override
public synchronized void setProgress(int progress) {
super.setProgress(progress);
if (getResources().getString(R.string.downloading).equals(mText)) {
setText(getProgressPercent());
}
}
private String getProgressPercent() {
return getProgress() / 10 + "%";
}
public void setDownloadType(DownloadType downloadType) {
switch (downloadType) {
case NORMAL:
case NONE_WITH_HINT:
case INSTALL_NORMAL:
case H5_GAME:
if (mDownloadStyle == DOWNLOAD_IMAGE_STYLE) {
setProgressDrawable(getResources().getDrawable(R.drawable.text_white_background));
mDefaultColor = Color.BLACK;
} else {
setProgressDrawable(getResources().getDrawable(R.drawable.download_button_normal_style));
mDefaultColor = Color.WHITE;
}
setProgress(0);
break;
case PLUGIN:
case INSTALL_PLUGIN:
setProgressDrawable(getResources().getDrawable(R.drawable.download_button_pluggable_style));
mDefaultColor = Color.WHITE;
setProgress(0);
break;
case NONE:
setProgressDrawable(getResources().getDrawable(R.drawable.button_round_gray_light));
mDefaultColor = ContextCompat.getColor(getContext(), R.color.text_tertiary);
setProgress(0);
break;
case LAUNCH_OR_OPEN:
if (mDownloadStyle == DOWNLOAD_IMAGE_STYLE) {
setProgressDrawable(getResources().getDrawable(R.drawable.detail_download_open_image_style));
mDefaultColor = Color.WHITE;
} else {
setProgressDrawable(getResources().getDrawable(R.drawable.download_button_normal_style));
mDefaultColor = Color.WHITE;
}
setProgress(0);
break;
case DOWNLOADING_NORMAL:
if (mDownloadStyle == DOWNLOAD_IMAGE_STYLE) {
setProgressDrawable(getResources().getDrawable(R.drawable.detail_downloading_normal_image_style));
mDefaultColor = Color.WHITE;
} else {
setProgressDrawable(getResources().getDrawable(R.drawable.detail_downloading_normal_style));
mDefaultColor = ContextCompat.getColor(getContext(), R.color.text_theme);
}
break;
case DOWNLOADING_PLUGIN:
setProgressDrawable(getResources().getDrawable(R.drawable.detail_downloading_normal_style));
mDefaultColor = ContextCompat.getColor(getContext(), R.color.text_theme);
break;
case RESERVABLE:
setProgressDrawable(getResources().getDrawable(R.drawable.button_reserve));
mDefaultColor = ContextCompat.getColor(getContext(), R.color.white);
break;
case UPDATING:
setProgressDrawable(getResources().getDrawable(R.drawable.download_button_updating_style));
mDefaultColor = ContextCompat.getColor(getContext(), R.color.white);
break;
case RESERVED:
setProgressDrawable(getResources().getDrawable(R.drawable.button_round_gray_light));
mDefaultColor = ContextCompat.getColor(getContext(), R.color.text_tertiary);
break;
case XAPK_FAILURE:
case XAPK_SUCCESS:
case XAPK_UNZIPPING:
setProgressDrawable(getResources().getDrawable(R.drawable.progressbar_xapk_detail_style));
mDefaultColor = ContextCompat.getColor(getContext(), R.color.white);
break;
case TEENAGER_MODEL:
case SPECIAL_DOWNLOAD:
setProgressDrawable(getResources().getDrawable(R.drawable.download_button_normal_style));
mDefaultColor = ContextCompat.getColor(getContext(), R.color.white);
break;
}
mDownloadType = downloadType;
}
public DownloadType getDownloadType() {
return mDownloadType;
}
}

View File

@ -46,7 +46,7 @@ import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.entity.CommunityEntity
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.ImageUtils.getTransformedUrl
import com.gh.gamecenter.common.utils.ImageUtils.getIdealImageUrl
import com.gh.gamecenter.common.view.DraggableBigImageView
import com.gh.gamecenter.common.view.Gh_RelativeLayout
import com.gh.gamecenter.core.runOnIoThread
@ -831,7 +831,7 @@ class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
&& !NetworkUtils.isWifiOr4GConnected(this@ImageViewerActivity)
&& !thumbnailImageUrl.contains(".gif")
) {
compressedStandardImageUrl = getTransformedUrl(thumbnailImageUrl, mLimitWidth)
compressedStandardImageUrl = getIdealImageUrl(thumbnailImageUrl, mLimitWidth)
thumbnailImageUrl = compressedStandardImageUrl ?: ""
}
val finalUrl = compressedStandardImageUrl

View File

@ -137,6 +137,9 @@ import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
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;
@ -282,6 +285,8 @@ public class MainActivity extends BaseActivity {
Config.getGhzsSettings();
} else if (Config.getVSettingEntity() == null) {
Config.refreshVSettingEntity();
} else if (Config.getVNewSettingEntity() == null) {
Config.getNewSetting();
}
// 耗时操作
@ -737,14 +742,11 @@ public class MainActivity extends BaseActivity {
ToastUtils.showToast("游戏启动中,请稍后~");
handler.postDelayed(() -> {
VHelper.postOnInitialized(() -> {
if (VHelper.isInstalled(gamePackageName)) {
VHelper.launch(this, gamePackageName, false, true);
} else {
ToastUtils.showToast("应用已被卸载!");
}
return null;
});
if(VHelper.isInnerInstalled(gamePackageName)) {
launchGame(gamePackageName).invoke();
} else {
VHelper.postOnInitialized(launchGame(gamePackageName));
}
}, 500);
break;
case KEY_MARKET_DETAILS:
@ -762,6 +764,18 @@ public class MainActivity extends BaseActivity {
}, 500);
}
@NonNull
private Function0<Unit> launchGame(String gamePackageName) {
return () -> {
if (!VHelper.isInnerInstalled(gamePackageName) && !VHelper.isInstalled(gamePackageName)) {
ToastUtils.showToast("应用已被卸载!");
} else {
VHelper.launch(this, gamePackageName, false, true);
}
return null;
};
}
/**
* 应用跳转
*/
@ -929,6 +943,8 @@ public class MainActivity extends BaseActivity {
Config.getGhzsSettings();
} else if (Config.getVSettingEntity() == null) {
Config.refreshVSettingEntity();
} else if (Config.getVNewSettingEntity() == null) {
Config.getNewSetting();
}
mPackageViewModel.checkData();
@ -939,8 +955,10 @@ public class MainActivity extends BaseActivity {
// 接收登录和登出更新事件统计的 Meta
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBReuse reuse) {
if (reuse.getType().equals(LOGIN_TAG) || reuse.getType().equals(LOGOUT_TAG)) {
boolean isLoginEvent = reuse.getType().equals(LOGIN_TAG);
if (isLoginEvent || reuse.getType().equals(LOGOUT_TAG)) {
MetaUtil.INSTANCE.refreshMeta();
VHelper.INSTANCE.updateAuthorizeInfo(isLoginEvent);
}
}

View File

@ -1,7 +1,9 @@
package com.gh.gamecenter;
import static com.gh.gamecenter.common.constant.EntranceConsts.ENTRANCE_BROWSER;
import static com.gh.gamecenter.common.constant.EntranceConsts.ENTRANCE_PUSH;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ANSWER;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ARCHIVE_LOGIN;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ARTICLE;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_CATEGORY;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_COLUMN;
@ -20,6 +22,7 @@ import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_QQ_GAME;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_QQ_GROUP;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_QQ_QUN;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_QUESTION;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_RESTART_GAME;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_SUGGESTION;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_TOOLBOX;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_UPLOAD_VIDEO;
@ -63,8 +66,10 @@ import com.gh.gamecenter.core.utils.ToastUtils;
import com.gh.gamecenter.entity.SubjectRecommendEntity;
import com.gh.gamecenter.entity.VideoLinkEntity;
import com.gh.gamecenter.feature.utils.PlatformUtils;
import com.gh.gamecenter.login.view.LoginActivity;
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel;
import com.gh.gamecenter.video.videomanager.VideoManagerActivity;
import com.gh.vspace.VHelper;
import com.gh.vspace.shortcut.OnCreateShortcutResult;
import com.gh.vspace.shortcut.ShortcutManager;
import com.gh.vspace.shortcut.ShortcutPermissionTipsDialog;
@ -129,6 +134,10 @@ public class SkipActivity extends BaseActivity {
String qaId = uri.getQueryParameter("qa_id");
String qaContentId = uri.getQueryParameter(EntranceConsts.KEY_QA_CONTENT_ID);
String qaTitle = uri.getQueryParameter(EntranceConsts.KEY_QA_TITLE);
String isFromPushString = uri.getQueryParameter(EntranceConsts.KEY_IS_FROM_PUSH);
boolean isFromPush = !TextUtils.isEmpty(isFromPushString) && isFromPushString.equals("true");
String entrance = isFromPush ? ENTRANCE_PUSH : ENTRANCE_BROWSER;
String pathName = isFromPush ? ENTRANCE_PUSH : "浏览器";
if (host != null) {
Intent intent;
@ -141,40 +150,40 @@ public class SkipActivity extends BaseActivity {
createShortcut(uri);
return;
case HOST_ARTICLE:
DirectUtils.directToArticle(this, path, ENTRANCE_BROWSER);
DirectUtils.directToArticle(this, path, entrance);
break;
case HOST_GAME:
DirectUtils.directToGameDetail(this, path, "", ENTRANCE_BROWSER, "true".equals(uri.getQueryParameter("auto_download")), to, null);
DirectUtils.directToGameDetail(this, path, "", entrance, "true".equals(uri.getQueryParameter("auto_download")), to, null);
break;
case HOST_COLUMN:
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), ENTRANCE_BROWSER, null, false);
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), entrance, null, false);
break;
case HOST_SUGGESTION:
if (!TextUtils.isEmpty(qaId)) {
DirectUtils.directToQa(this, qaTitle, qaId);
} else {
// 插件反馈跳转到意见反馈分类页
DirectUtils.directToFeedback(this, content, isQaFeedback, qaContentId, true, false, EntranceConsts.ENTRANCE_BROWSER);
DirectUtils.directToFeedback(this, content, isQaFeedback, qaContentId, true, false, entrance);
}
break;
case HOST_DOWNLOAD:
DirectUtils.directToDownloadManagerAndStartUpdate(this, path, uri.getQueryParameter(KEY_PACKAGENAME), ENTRANCE_BROWSER);
DirectUtils.directToDownloadManagerAndStartUpdate(this, path, uri.getQueryParameter(KEY_PACKAGENAME), entrance);
break;
case HOST_ANSWER:
DirectUtils.directToAnswerDetail(this, path, ENTRANCE_BROWSER, "浏览器");
DirectUtils.directToAnswerDetail(this, path, entrance, pathName);
break;
case HOST_QUESTION:
DirectUtils.directToQuestionDetail(this, path, ENTRANCE_BROWSER, "浏览器", "");
DirectUtils.directToQuestionDetail(this, path, entrance, pathName, "");
break;
case HOST_TOOLBOX:
DirectUtils.directToToolbox(this, uri.getQueryParameter("gameId"), uri.getQueryParameter("toolboxUrl"), ENTRANCE_BROWSER);
DirectUtils.directToToolbox(this, uri.getQueryParameter("gameId"), uri.getQueryParameter("toolboxUrl"), entrance);
break;
case HOST_COMMUNITY:
DirectUtils.directToHomeCommunityTab(this);
break;
// 社区文章格式一
case "community.article":
DirectUtils.directToCommunityArticle(this, uri.getQueryParameter("articleId"), uri.getQueryParameter("communityId"), ENTRANCE_BROWSER, "浏览器", "");
DirectUtils.directToCommunityArticle(this, uri.getQueryParameter("articleId"), uri.getQueryParameter("communityId"), entrance, pathName, "");
break;
// 社区文章格式二
case "communities":
@ -195,13 +204,13 @@ public class SkipActivity extends BaseActivity {
}
}
if ("articles".equals(type)) {
DirectUtils.directToCommunityArticle(this, typeId, communityId, ENTRANCE_BROWSER, "浏览器", "");
DirectUtils.directToCommunityArticle(this, typeId, communityId, entrance, pathName, "");
break;
}
break;
case HOST_VIDEO:
DirectUtils.directToVideoDetail(this, path, VideoDetailContainerViewModel.Location.HOTTEST_GAME_VIDEO.getValue(),
false, id, ENTRANCE_BROWSER, "浏览器", TextUtils.isEmpty(referer) ? "" : referer, "");
false, id, entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer, "");
break;
case HOST_UPLOAD_VIDEO://跳转上传视频
String titleParameter = uri.getQueryParameter("title");
@ -215,13 +224,13 @@ public class SkipActivity extends BaseActivity {
VideoLinkEntity linkEntity = new VideoLinkEntity(title, categoryId, link, tagActivityId, tagActivityName);
SimpleGameEntity simpleGameEntity = new SimpleGameEntity(gameId != null ? gameId : "", gameName != null ? gameName : "", "", "");
Bundle nextToBundle = VideoManagerActivity.getVideoManagerBundle(linkEntity, simpleGameEntity, EntranceConsts.ENTRANCE_BROWSER, "");
CheckLoginUtils.checkLogin(this, nextToBundle, true, EntranceConsts.ENTRANCE_BROWSER, () ->
DirectUtils.directToVideoManager(SkipActivity.this, linkEntity, simpleGameEntity, EntranceConsts.ENTRANCE_BROWSER, "浏览器"));
Bundle nextToBundle = VideoManagerActivity.getVideoManagerBundle(linkEntity, simpleGameEntity, entrance, "");
CheckLoginUtils.checkLogin(this, nextToBundle, true, entrance, () ->
DirectUtils.directToVideoManager(SkipActivity.this, linkEntity, simpleGameEntity, entrance, pathName));
break;
case HOST_VIDEO_SINGLE:
DirectUtils.directToVideoDetail(this, path, VideoDetailContainerViewModel.Location.SINGLE_VIDEO.getValue(),
false, "", ENTRANCE_BROWSER, "浏览器", TextUtils.isEmpty(referer) ? "" : referer, "");
false, "", entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer, "");
break;
case HOST_VIDEO_MORE:
gameId = uri.getQueryParameter("gameId");
@ -238,7 +247,7 @@ public class SkipActivity extends BaseActivity {
location = path;
}
DirectUtils.directToLegacyVideoDetail(this, path, location,
false, TextUtils.isEmpty(gameId) ? "" : gameId, ENTRANCE_BROWSER, "浏览器", TextUtils.isEmpty(referer) ? "" : referer,
false, TextUtils.isEmpty(gameId) ? "" : gameId, entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer,
TextUtils.isEmpty(type) ? "" : type, TextUtils.isEmpty(act) ? "" : act, TextUtils.isEmpty(paginationType) ? "page" : paginationType, TextUtils.isEmpty(fieldId) ? "" : fieldId,
TextUtils.isEmpty(sectionName) ? "" : sectionName, false, "");
break;
@ -246,10 +255,10 @@ public class SkipActivity extends BaseActivity {
DirectUtils.directToHomeVideoTab(this);
break;
case HOST_VIDEO_STREAMING_DESC:
DirectUtils.directToGameDetailVideoStreaming(this, path, ENTRANCE_BROWSER);
DirectUtils.directToGameDetailVideoStreaming(this, path, entrance);
break;
case HOST_VIDEO_COLLECTION:
DirectUtils.directToGameVideo(this, path, ENTRANCE_BROWSER, "浏览器");
DirectUtils.directToGameVideo(this, path, entrance, pathName);
break;
case HOST_QQ:
bundle = new Bundle();
@ -278,32 +287,32 @@ public class SkipActivity extends BaseActivity {
EntranceUtils.jumpActivityCompat(this, bundle);
break;
case EntranceConsts.HOST_VIDEO_DETAIL:
DirectUtils.directToVideoDetail(this, path, ENTRANCE_BROWSER, "", "");
DirectUtils.directToVideoDetail(this, path, entrance, "", "");
break;
case HOST_LIBAO:
DirectUtils.directToGiftDetail(this, path, ENTRANCE_BROWSER);
DirectUtils.directToGiftDetail(this, path, entrance);
break;
case HOST_USERHOME:
String position = uri.getQueryParameter("position");
String subTypeString = uri.getQueryParameter("sub_type");
String subGameType = uri.getQueryParameter("sub_game_type");
DirectUtils.directToHomeActivity(this, path, subTypeString, subGameType, TextUtils.isEmpty(position) ? -1 : Integer.parseInt(position), ENTRANCE_BROWSER, "浏览器");
DirectUtils.directToHomeActivity(this, path, subTypeString, subGameType, TextUtils.isEmpty(position) ? -1 : Integer.parseInt(position), entrance, pathName);
break;
case HOST_COMMUNITY_COLUMN:
CommunityEntity community = new CommunityEntity();
community.setId(uri.getQueryParameter("community_id"));
community.setName(uri.getQueryParameter("community_name"));
String columnId = uri.getQueryParameter("column_id");
DirectUtils.directToCommunityColumn(this, community, columnId, ENTRANCE_BROWSER, "");
DirectUtils.directToCommunityColumn(this, community, columnId, entrance, "");
break;
case HOST_CATEGORY:
title = uri.getQueryParameter("title");
DirectUtils.directCategoryDirectory(this, path, title, ENTRANCE_BROWSER, "浏览器");
DirectUtils.directCategoryDirectory(this, path, title, entrance, pathName);
break;
case HOST_COLUMN_COLLECTION:
DirectUtils.directToColumnCollection(this, path, -1, ENTRANCE_BROWSER, "", "", "", "", null,false);
DirectUtils.directToColumnCollection(this, path, -1, entrance, "", "", "", "", null,false);
break;
case EntranceConsts.HOST_BLOCK:
name = uri.getQueryParameter("name");
@ -315,11 +324,11 @@ public class SkipActivity extends BaseActivity {
break;
case EntranceConsts.HOST_SERVER_BLOCK:
DirectUtils.directToGameServers(this, ENTRANCE_BROWSER, "浏览器", null);
DirectUtils.directToGameServers(this, entrance, pathName, null);
break;
case EntranceConsts.HOST_AMWAY_BLOCK:
DirectUtils.directToAmway(this, null, ENTRANCE_BROWSER, "浏览器");
DirectUtils.directToAmway(this, null, entrance, pathName);
break;
case EntranceConsts.HOST_HELP:
@ -332,11 +341,11 @@ public class SkipActivity extends BaseActivity {
DirectUtils.directToQaCollection(this, name, path);
break;
case EntranceConsts.HOST_GAME_UPLOAD:
DirectUtils.directGameUpload(this, ENTRANCE_BROWSER, "浏览器");
DirectUtils.directGameUpload(this, entrance, pathName);
break;
case EntranceConsts.HOST_GAME_ZONE:
String zoneUrl = uri.getQueryParameter("url");
DirectUtils.directGameZone(this, path, zoneUrl, ENTRANCE_BROWSER);
DirectUtils.directGameZone(this, path, zoneUrl, entrance);
break;
case EntranceConsts.HOST_LINK:
try {
@ -345,7 +354,7 @@ public class SkipActivity extends BaseActivity {
byte[] linkData = Base64.decode(dataString, Base64.DEFAULT);
String linkDataString = new String(linkData, "UTF-8");
LinkEntity le = GsonUtils.INSTANCE.getGson().fromJson(linkDataString, LinkEntity.class);
DirectUtils.directToLinkPage(this, le, ENTRANCE_BROWSER, "", "");
DirectUtils.directToLinkPage(this, le, entrance, "", "");
}
} catch (Exception e) {
e.printStackTrace();
@ -360,7 +369,7 @@ public class SkipActivity extends BaseActivity {
this,
uri.getQueryParameter(EntranceConsts.KEY_GAME_ID),
uri.getQueryParameter(EntranceConsts.KEY_GAME_NAME),
EntranceConsts.ENTRANCE_BROWSER);
entrance);
break;
case EntranceConsts.HOST_GAME_CALENDAR:
DirectUtils.directToGameServerCalendar(this, uri.getQueryParameter(EntranceConsts.KEY_GAME_ID), 0);
@ -370,26 +379,26 @@ public class SkipActivity extends BaseActivity {
break;
case EntranceConsts.HOST_FORUM_DETAIL:
String sectionId = uri.getQueryParameter("section_id");
DirectUtils.directForumDetailSection(this, id, sectionId, ENTRANCE_BROWSER);
DirectUtils.directForumDetailSection(this, id, sectionId, entrance);
break;
case EntranceConsts.HOST_GAME_RATING_DETAIL:
DirectUtils.directToGameRatingDetail(this, uri.getQueryParameter(EntranceConsts.KEY_GAME_ID), uri.getQueryParameter(EntranceConsts.KEY_COMMENT_ID), ENTRANCE_BROWSER);
DirectUtils.directToGameRatingDetail(this, uri.getQueryParameter(EntranceConsts.KEY_GAME_ID), uri.getQueryParameter(EntranceConsts.KEY_COMMENT_ID), entrance);
break;
case EntranceConsts.HOST_FORUM:
DirectUtils.directToHomeCommunityTab(this);
break;
case EntranceConsts.HOST_HELP_AND_FEEDBACK:
if ("vgame".equals(suggestionType)) {
DirectUtils.directToHelpAndFeedback(this, content, isQaFeedback, qaContentId, false, true, EntranceConsts.ENTRANCE_BROWSER);
DirectUtils.directToHelpAndFeedback(this, content, isQaFeedback, qaContentId, false, true, entrance);
} else {
DirectUtils.directToHelpAndFeedback(this, content, isQaFeedback, qaContentId, true, false, EntranceConsts.ENTRANCE_BROWSER);
DirectUtils.directToHelpAndFeedback(this, content, isQaFeedback, qaContentId, true, false, entrance);
}
break;
case HOST_GAME_COLLECTION_DETAIL:
DirectUtils.directToGameCollectionDetail(this, path, ENTRANCE_BROWSER, "", null);
DirectUtils.directToGameCollectionDetail(this, path, entrance, "", null);
break;
case HOST_GAME_COLLECTION_SQUARE:
DirectUtils.directToGameCollectionSquare(this, ENTRANCE_BROWSER, "", "", "", "", "", null);
DirectUtils.directToGameCollectionSquare(this, entrance, "", "", "", "", "", null);
break;
case HOST_QQ_GAME:
String extJson = uri.getQueryParameter("ext");
@ -400,6 +409,27 @@ public class SkipActivity extends BaseActivity {
} catch (JSONException ignored) {
}
break;
case HOST_ARCHIVE_LOGIN:
String gamePkg = uri.getQueryParameter(EntranceConsts.KEY_GAME_PKG);
if(CheckLoginUtils.isLogin()) {
VHelper.INSTANCE.updateAuthorizeInfo(true);
} else {
Bundle newBundle = new Bundle();
newBundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
EntranceUtils.jumpActivity(this, null, newBundle, (resultCode, data) -> {
if(CheckLoginUtils.isLogin()) {
VHelper.INSTANCE.updateAuthorizeInfo(true);
}
VHelper.launch(this, gamePkg, false, false);
finish();
});
return;
}
break;
case HOST_RESTART_GAME:
String restartGamePkg = uri.getQueryParameter(EntranceConsts.KEY_GAME_PKG);
VHelper.launch(this, restartGamePkg, false, true);
break;
default:
EntranceUtils.jumpActivity(this, new Bundle()); // 跳转至首页
return;

View File

@ -269,9 +269,9 @@ public class WeiBoShareActivity extends Activity implements WbShareCallback {
if (ShareUtils.shareEntrance == ShareUtils.ShareEntrance.inviteFriends) {
IntegralLogHelper.INSTANCE.logInviteResult("成功", "微博");
}
if (ShareUtils.shareEntrance == ShareUtils.ShareEntrance.askNormal ||
if (ShareUtils.additionalParams != null && (ShareUtils.shareEntrance == ShareUtils.ShareEntrance.askNormal ||
ShareUtils.shareEntrance == ShareUtils.ShareEntrance.communityArticle ||
ShareUtils.shareEntrance == ShareUtils.ShareEntrance.video) {
ShareUtils.shareEntrance == ShareUtils.ShareEntrance.video)) {
com.gh.gamecenter.common.utils.NewLogUtils.logShareResult(ShareUtils.additionalParams, true);
SensorsBridge.trackArticleShareResult(
ShareUtils.additionalParams.getCustomerType(),
@ -319,9 +319,9 @@ public class WeiBoShareActivity extends Activity implements WbShareCallback {
com.gh.gamecenter.common.utils.NewLogUtils.logShareResult(ShareUtils.additionalParams, false);
}
if(ShareUtils.shareEntrance == ShareUtils.ShareEntrance.video
if(ShareUtils.additionalParams != null && (ShareUtils.shareEntrance == ShareUtils.ShareEntrance.video
|| ShareUtils.shareEntrance == ShareUtils.ShareEntrance.communityArticle
|| ShareUtils.shareEntrance == ShareUtils.ShareEntrance.askNormal)
|| ShareUtils.shareEntrance == ShareUtils.ShareEntrance.askNormal))
{
SensorsBridge.trackArticleShareResult(
ShareUtils.additionalParams.getCustomerType(),

View File

@ -205,7 +205,7 @@ public class LibaoDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
GameEntity gameEntity = mLibaoEntity.getGame().toGameEntity();
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, holder.binding.gameSubtitleTv, null, null, false, null, false, null);
} else {
holder.binding.libaodetailGameIcon.displayGameIcon(mLibaoEntity.getIcon(), null, mLibaoEntity.getGame().getIconFloat());
holder.binding.libaodetailGameIcon.displayGameIcon(mLibaoEntity.getIcon(), null, null);
}
holder.binding.libaodetailName.setText(mLibaoEntity.getName());
if (TextUtils.isEmpty(mLibaoEntity.getPlatform())) {

View File

@ -297,7 +297,7 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
if (mConcernEntity.getGame() != null) {
viewHolder.binding.newsDigestThumb.displayGameIcon(mConcernEntity.getGame().getIcon(), mConcernEntity.getGame().getIconSubscript(), mConcernEntity.getGame().getIconFloat());
} else {
viewHolder.binding.newsDigestThumb.displayGameIcon(mConcernEntity.getGameIcon(), null, mConcernEntity.getGame().getIconFloat());
viewHolder.binding.newsDigestThumb.displayGameIcon(mConcernEntity.getGameIcon(), null, null);
}
viewHolder.binding.newsDigestTitle.setText(mConcernEntity.getGameName());
NewsUtils.setNewsPublishOn(viewHolder.binding.newsDigestTime, mConcernEntity.getTime());

View File

@ -176,6 +176,15 @@ class DetailViewHolder(
private val mGameEntity: GameEntity = mViewHolder.gameEntity
private var mDownloadEntity: DownloadEntity? = null
private fun showLandPageAddressDialogIfNeeded() {
if (mGameEntity.isLandPageAddressDialog() && !mGameEntity.isLandPageAddressDialogShowOnly()) {
// 第三方落地页为开启状态并且展示状态不为“仅显示弹窗”,需要在点击确认后显示弹窗
DialogUtils.showLandPageAddressDialog(mViewHolder.context, mGameEntity) {
DirectUtils.directToExternalBrowser(mViewHolder.context, mGameEntity.landPageAddressDialog!!.link!!)
}
}
}
override fun onClick(v: View) {
v.tag = null
@ -244,13 +253,17 @@ class DetailViewHolder(
val offStatus = mGameEntity.downloadOffStatus
if (offStatus != null && "off" != offStatus) {
if ("dialog" == offStatus) {
showOffServiceDialog(mGameEntity.downloadOffDialog)
showOffServiceDialog(mGameEntity.downloadOffDialog) {
showLandPageAddressDialogIfNeeded()
}
} else if ("toast" == offStatus) {
EventBus.getDefault().post(EBReuse(GameDetailFragment.SKIP_RATING))
ToastUtils.toast("该游戏因故暂不提供下载,具体详情可在相关评论中查看,敬请谅解~")
showLandPageAddressDialogIfNeeded()
}
} else {
ToastUtils.toast("该游戏已关闭下载")
showLandPageAddressDialogIfNeeded()
}
}
@ -452,7 +465,10 @@ class DetailViewHolder(
}
}
ButtonStyle.UPDATING -> ToastUtils.toast("正在加急更新版本,敬请后续留意")
ButtonStyle.UPDATING -> {
ToastUtils.toast("正在加急更新版本,敬请后续留意")
showLandPageAddressDialogIfNeeded()
}
ButtonStyle.TEENAGER_MODE -> {
SensorsBridge.trackAdolescentModeDialogShow(
mGameEntity.id,
@ -530,8 +546,8 @@ class DetailViewHolder(
}
}
private fun showOffServiceDialog(dialog: GameEntity.Dialog?) {
val dialogFragment = GameOffServiceDialogFragment.getInstance(dialog!!)
private fun showOffServiceDialog(dialog: GameEntity.Dialog?, callback: () -> Unit) {
val dialogFragment = GameOffServiceDialogFragment.getInstance(dialog!!, callback)
dialogFragment.show((mViewHolder.context as FragmentActivity).supportFragmentManager, "off_service_dialog")
}

View File

@ -34,6 +34,6 @@ class GameImageViewHolder(var binding: GameImageItemBinding) : BaseRecyclerViewH
binding.gameImageIcon.hierarchy.roundingParams = roundingParams
}
ImageUtils.display(binding.gameImageIcon, entity.image, width)
ImageUtils.displayWithAdaptiveHeight(binding.gameImageIcon, entity.image, width)
}
}

View File

@ -301,7 +301,7 @@ public class ArticleAdapter extends ListAdapter<NewsEntity> {
viewHolder.binding.selectIv.setChecked(selectItems.contains(newsEntity.getId()));
if (newsEntity.getThumbnail() != null && newsEntity.getThumbnail().getUrl() != null) {
ImageUtils.display(viewHolder.binding.newsImage3Thumb, CollectionsKt.firstOrNull(newsEntity.getThumbnail().getUrl()),
ImageUtils.displayWithAdaptiveHeight(viewHolder.binding.newsImage3Thumb, CollectionsKt.firstOrNull(newsEntity.getThumbnail().getUrl()),
mContext.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(mContext, 40));
}
int views = newsEntity.getViews();

View File

@ -389,70 +389,21 @@ class UpdatableGameAdapter(private var mViewModel: UpdatableGameViewModel) :
updateBtn.putWidgetBusinessName("下载管理")
updateBtn.putObject(update)
updateBtn.setOnClickListener {
val str: String = updateBtn.text.toString()
val str: String = updateBtn.text
if ("更新" == str || str.contains("")) {
// 这里用 CurrentActivity 不用 view.context 的原因是
// view.context 在 5.0 以下设备会使用 TintContextWrapper 包一层导致类型转换异常
if ("更新" == str && update.isLandPageAddressDialog()) {// 第三方落地页跳转直接展示跳转弹窗
DialogUtils.showLandPageAddressDialog(it.context, update.transformGameEntity()) {// 跳转第三方落地页
DirectUtils.directToExternalBrowser(it.context, update.landPageAddressDialog!!.link!!)
if (update.isLandPageAddressDialogShowOnly()) {
updateOrPluggable(updateBtn, update, downloadEntity, pluginDesc)
} else {
DirectUtils.directToExternalBrowser(it.context, update.landPageAddressDialog!!.link!!)
}
}
return@setOnClickListener
}
(CurrentActivityHolder.getCurrentActivity() as? FragmentActivity)?.checkStoragePermissionBeforeAction(
gameId = update.id,
gameName = update.name ?: "",
gameType = update.categoryChinese,
gameFormat = update.format,
) {
DialogUtils.checkDownload(
updateBtn.context,
update.size,
update.id,
update.name ?: "",
update.categoryChinese
) { isSubscribe: Boolean ->
if (str.contains("")) {
if (update.pluggableCollection != null) {
DownloadDialog.showDownloadDialog(
updateBtn.context,
update.transformGameEntity(),
update.exposureEvent,
mViewModel.entrance,
pluginDesc + "化:" + update.name
)
return@checkDownload
} else {
updateBtn.text = "0%"
updateBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN
updateBtn.progress = 0
}
} else {
updateBtn.text = "0%"
updateBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
updateBtn.progress = 0
}
// 如果历史下载 downloadEntity 不为空,且版本与当前需要更新的不一致,先移除旧任务再执行更新
if ((downloadEntity?.isVGameDownloadInDualDownloadMode() == true
|| downloadEntity?.isLocalDownloadInDualDownloadMode() == true)
&& (update.version != downloadEntity.versionName)
) {
DownloadManager.getInstance().cancel(downloadEntity.url ?: "")
}
mViewModel.update(update, isSubscribe)
mViewModel.refreshList()
EventBus.getDefault()
.post(
EBSkip(
DownloadManagerActivity.TAG,
DownloadManagerActivity.INDEX_DOWNLOAD
)
)
}
}
updateOrPluggable(updateBtn, update, downloadEntity, pluginDesc)
} else if (updateBtn.context.getString(R.string.launch) == str) {
PackageLauncher.launchApp(updateBtn.context, packageName = update.packageName)
} else if (updateBtn.context.getString(R.string.resume) == str) {
@ -489,6 +440,68 @@ class UpdatableGameAdapter(private var mViewModel: UpdatableGameViewModel) :
}
}
private fun updateOrPluggable(
updateBtn: DownloadButton,
update: GameUpdateEntity,
downloadEntity: DownloadEntity?,
pluginDesc: String
) {
val str: String = updateBtn.text
(CurrentActivityHolder.getCurrentActivity() as? FragmentActivity)?.checkStoragePermissionBeforeAction(
gameId = update.id,
gameName = update.name ?: "",
gameType = update.categoryChinese,
gameFormat = update.format,
) {
DialogUtils.checkDownload(
updateBtn.context,
update.size,
update.id,
update.name ?: "",
update.categoryChinese
) { isSubscribe: Boolean ->
if (str.contains("")) {
if (update.pluggableCollection != null) {
DownloadDialog.showDownloadDialog(
updateBtn.context,
update.transformGameEntity(),
update.exposureEvent,
mViewModel.entrance,
pluginDesc + "化:" + update.name
)
return@checkDownload
} else {
updateBtn.text = "0%"
updateBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_PLUGIN
updateBtn.progress = 0
}
} else {
updateBtn.text = "0%"
updateBtn.buttonStyle = DownloadButton.ButtonStyle.DOWNLOADING_NORMAL
updateBtn.progress = 0
}
// 如果历史下载 downloadEntity 不为空,且版本与当前需要更新的不一致,先移除旧任务再执行更新
if ((downloadEntity?.isVGameDownloadInDualDownloadMode() == true
|| downloadEntity?.isLocalDownloadInDualDownloadMode() == true)
&& (update.version != downloadEntity.versionName)
) {
DownloadManager.getInstance().cancel(downloadEntity.url ?: "")
}
mViewModel.update(update, isSubscribe)
mViewModel.refreshList()
EventBus.getDefault()
.post(
EBSkip(
DownloadManagerActivity.TAG,
DownloadManagerActivity.INDEX_DOWNLOAD
)
)
}
}
}
private fun generateExposureEvent(updateEntity: GameUpdateEntity) {
updateEntity.exposureEvent =
createEvent(updateEntity.transformGameEntity(), mExposureSource)

View File

@ -34,7 +34,9 @@ class AppEntity(
*/
var alert: String? = null,
// 关联64位更新
var relation: AppEntity? = null
var relation: AppEntity? = null,
@SerializedName("_id")
var id: String? = null
) : Parcelable {
fun isAlertEveryTime() = alert == "EVERY_TIME_OPEN"

View File

@ -36,6 +36,8 @@ data class CommonCollectionEntity(
@Parcelize
data class CommonCollectionContentEntity(
@SerializedName("_id")
private val _id: String? = null,
val title: String = "",
val style: String = "",
val image: String = "",
@ -45,4 +47,8 @@ data class CommonCollectionContentEntity(
var addedContent1: String? = "",
@SerializedName("added_content_2")
var addedContent2: String? = "",
) : Parcelable
) : Parcelable {
val id: String
get() = _id ?: ""
}

View File

@ -92,6 +92,11 @@ data class GameUpdateEntity(
return landPageAddressDialog?.let { it.status == "on" } ?: false
}
/**
* 第三方落地页的状态是否为“仅显示弹窗”
*/
fun isLandPageAddressDialogShowOnly(): Boolean = landPageAddressDialog?.showOnly == true
fun transformGameEntity(): GameEntity {
val gameEntity = GameEntity()
gameEntity.id = id

View File

@ -8,6 +8,8 @@ data class PullDownPush(
val id: String = "",
@SerializedName("pop_switch")
val popSwitch: String = "",
@SerializedName("put_away_switch")
val putAwaySwitch: String = "", // 自动收起never永不、video_finished视频播放完毕视频必填、nn秒后5-15秒后
val description: String = "",
@SerializedName("img_url")
val imgUrl: String = "",

View File

@ -0,0 +1,42 @@
package com.gh.gamecenter.entity
import com.google.gson.annotations.SerializedName
class VNewSetting {
@SerializedName("va")
var va: Va? = null
@SerializedName("va_plugin")
var vaPlugin: VaPlugin? = null
class Va(
@SerializedName("32-bit")
val arch32: VaArch? = null,
)
class VaArch(
val size: String,
@SerializedName("package")
val packageName: String,
@SerializedName("version")
val versionName: String,
@SerializedName("version_code")
val versionCode: Int,
val url: String
)
data class VaPlugin(
@SerializedName("_id")
val id: String?,
@SerializedName("version_name")
val versionName: String?,
@SerializedName("change_log")
var changeLog: String?,
@SerializedName("url_32")
val url32: String?,
@SerializedName("url_64")
val url64: String?,
)
}

View File

@ -134,9 +134,11 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
override fun onLoadRefresh() {
super.onLoadRefresh()
mBinding.nestedScrollNoConnection.root.visibility = View.GONE
mBinding.nestedScrollNoneData.root.visibility = View.GONE
mBinding.nestedScrollDataException.root.visibility = View.GONE
if (::mBinding.isInitialized) {
mBinding.nestedScrollNoConnection.root.visibility = View.GONE
mBinding.nestedScrollNoneData.root.visibility = View.GONE
mBinding.nestedScrollDataException.root.visibility = View.GONE
}
// Fixhttps://sentry.shanqu.cc/organizations/lightgame/issues/288994/?project=22&query=LazyListFragment&statsPeriod=14d
// Fragment在内存泄露的情况下调用requireView()会触发崩溃这里替换为getView()方法
// TODO 解决Fragment内存泄露的问题
@ -145,9 +147,11 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
override fun onLoadDone() {
super.onLoadDone()
mBinding.nestedScrollNoConnection.root.visibility = View.GONE
mBinding.nestedScrollNoneData.root.visibility = View.GONE
mBinding.nestedScrollDataException.root.visibility = View.GONE
if (::mBinding.isInitialized) {
mBinding.nestedScrollNoConnection.root.visibility = View.GONE
mBinding.nestedScrollNoneData.root.visibility = View.GONE
mBinding.nestedScrollDataException.root.visibility = View.GONE
}
view?.setBackgroundColor(Color.TRANSPARENT)
mBaseHandler.postDelayed(Runnable {
tryCatchInRelease {
@ -159,25 +163,31 @@ class ForumArticleAskListFragment : LazyListFragment<AnswerEntity, ForumArticleA
override fun onLoadError() {
super.onLoadError()
mBinding.nestedScrollNoConnection.root.visibility = View.VISIBLE
mBinding.nestedScrollNoneData.root.visibility = View.GONE
mBinding.nestedScrollDataException.root.visibility = View.GONE
if (::mBinding.isInitialized) {
mBinding.nestedScrollNoConnection.root.visibility = View.VISIBLE
mBinding.nestedScrollNoneData.root.visibility = View.GONE
mBinding.nestedScrollDataException.root.visibility = View.GONE
}
view?.setBackgroundColor(Color.TRANSPARENT)
}
override fun onLoadEmpty() {
super.onLoadEmpty()
mBinding.nestedScrollNoConnection.root.visibility = View.GONE
mBinding.nestedScrollNoneData.root.visibility = View.VISIBLE
mBinding.nestedScrollDataException.root.visibility = View.GONE
if (::mBinding.isInitialized) {
mBinding.nestedScrollNoConnection.root.visibility = View.GONE
mBinding.nestedScrollNoneData.root.visibility = View.VISIBLE
mBinding.nestedScrollDataException.root.visibility = View.GONE
}
view?.setBackgroundColor(Color.TRANSPARENT)
}
override fun loadNotFound() {
super.loadNotFound()
mBinding.nestedScrollNoConnection.root.visibility = View.GONE
mBinding.nestedScrollNoneData.root.visibility = View.GONE
mBinding.nestedScrollDataException.root.visibility = View.VISIBLE
if (::mBinding.isInitialized) {
mBinding.nestedScrollNoConnection.root.visibility = View.GONE
mBinding.nestedScrollNoneData.root.visibility = View.GONE
mBinding.nestedScrollDataException.root.visibility = View.VISIBLE
}
}
override fun hideRefreshingLayout() {

View File

@ -1,37 +1,26 @@
package com.gh.gamecenter.fragment
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.app.Dialog
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import android.preference.PreferenceManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.animation.PathInterpolator
import android.widget.RelativeLayout
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.common.util.DirectUtils
import com.gh.common.util.LogUtils
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.base.fragment.BaseLazyFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
import com.gh.gamecenter.common.view.WrapContentDraweeView
import com.gh.gamecenter.core.provider.IFloatingWindowProvider
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.addListener
import com.gh.gamecenter.databinding.DialogWelcomeBinding
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
import com.halo.assistant.HaloApp
@ -44,12 +33,6 @@ class WelcomeDialogFragment : BaseDialogFragment() {
private var mDismissListener: (() -> Unit)? = null
private var mShowEnterAnimation: Boolean = false
private var mShowExitAnimation: Boolean = false
// 触发此 dialogFragment 的 fragment可能为空
private var mTriggerFragment: BaseLazyFragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -67,11 +50,6 @@ class WelcomeDialogFragment : BaseDialogFragment() {
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
dialog.setContentView(root)
if (mShowEnterAnimation) {
dialog.window?.setDimAmount(0F)
} else {
dialog.window?.setDimAmount(0.5F)
}
dialog.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
return dialog
}
@ -93,22 +71,6 @@ class WelcomeDialogFragment : BaseDialogFragment() {
mWelcomeEntity?.let {
DirectUtils.directToLinkPage(requireContext(), it, EntranceConsts.ENTRANCE_WELCOME, "", "首页弹窗")
if (mShowEnterAnimation) {
val floatingWindowProvider =
ARouter.getInstance().build(RouteConsts.provider.floatingwindow)
.navigation() as? IFloatingWindowProvider<WelcomeDialogEntity>
floatingWindowProvider?.logWindowClicked(
action = "点击弹窗跳转页面",
windowId = mWelcomeEntity?.floatingWindowId ?: "",
source = "首页",
gameId = "",
gameName = "",
linkId = mWelcomeEntity?.link ?: "",
linkType = mWelcomeEntity?.type ?: "",
linkText = mWelcomeEntity?.text ?: ""
)
}
}
dismissAllowingStateLoss()
@ -123,10 +85,6 @@ class WelcomeDialogFragment : BaseDialogFragment() {
} else {
mBinding.ivClose.visibility = View.VISIBLE
}
if (mShowEnterAnimation) {
performAnimation(true)
}
}
mBinding.ivOpeningCover.registerLoadingCallback(null)
@ -134,33 +92,11 @@ class WelcomeDialogFragment : BaseDialogFragment() {
})
mBinding.ivCloseBackup.setOnClickListener {
val floatingWindowProvider =
ARouter.getInstance().build(RouteConsts.provider.floatingwindow)
.navigation() as? IFloatingWindowProvider<WelcomeDialogEntity>
// 来源 fragment 是否不可见
if (mTriggerFragment?.isCurrentlyVisible() == false) {
mShowExitAnimation = false
} else {
floatingWindowProvider?.showHiddenWindow(requireActivity())
}
if (mShowExitAnimation) {
dismissWithAnimation()
} else {
dismissAllowingStateLoss()
}
dismissAllowingStateLoss()
}
mBinding.ivClose.setOnClickListener { mBinding.ivCloseBackup.performClick() }
ImageUtils.displayWithoutMemoryCache(mBinding.ivOpeningCover, mWelcomeEntity?.icon)
// 弹起启动弹窗时,把右下角悬浮窗置为隐藏
val floatingWindowProvider =
ARouter.getInstance().build(RouteConsts.provider.floatingwindow)
.navigation() as? IFloatingWindowProvider<WelcomeDialogEntity>
floatingWindowProvider?.hideWindow(requireActivity())
return mBinding.root
}
@ -180,132 +116,14 @@ class WelcomeDialogFragment : BaseDialogFragment() {
mDismissListener = dismissListener
}
/**
* 显示动画
* @param isEnterAnimation 是否为进入动画
*/
private fun performAnimation(isEnterAnimation: Boolean) {
// 贝塞尔曲线需要 Android 版本大于 Android 5.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val screenWidth = DisplayUtils.getScreenWidth(requireActivity())
val screenHeight = DisplayUtils.getScreenHeight(requireActivity())
val statusBarHeight = DisplayUtils.getStatusBarHeight(requireContext().resources)
// 最大宽度为 300dp
val maxWidth = 300F
val initialWidth = 1F
val containerWidth = mBinding.container.width
val containerHeight = containerWidth / mBinding.ivOpeningCover.aspectRatio + 54F.dip2px()
val location = IntArray(2)
mBinding.container.getLocationOnScreen(location)
val xOffsetToTheScreen = location[0]
// 由于显示的时机问题mBinding.container.getLocationOnScreen(location) 获取到的纵座标不一定是真实在屏幕的高度,这里手动计算
val yOffsetToTheScreen = (screenHeight - containerHeight) / 2 + statusBarHeight
val scaleRatio = initialWidth / maxWidth
// 获取动画原点的 X, Y 座标,由于 scale 会变化,所以需要结合 scale 进行计算
val initialX = (screenWidth - 40F.dip2px() - xOffsetToTheScreen) - (containerWidth * (1 - scaleRatio)) / 2
val initialY =
(screenHeight - 156F.dip2px() - yOffsetToTheScreen) - (containerHeight * (1 - scaleRatio)) / 2 + statusBarHeight
val startX = if (isEnterAnimation) initialX else 0F
val startY = if (isEnterAnimation) initialY else 0F
val startScale = if (isEnterAnimation) scaleRatio else 1F
val endScale = if (isEnterAnimation) 1F else scaleRatio
val endX = if (isEnterAnimation) 0F else initialX
val endY = if (isEnterAnimation) 0F else initialY
val enteringTranslationXInterpolator = PathInterpolator(0.4F, 1.6F, 0.4F, 1.24F)
val enteringTranslationYInterpolator = PathInterpolator(0.4F, 1.8F, 0.4F, 1.24F)
val exitingTranslationXInterpolator = PathInterpolator(0.6F, -0.24F, 0.6F, -0.6F)
val exitingTranslationYInterpolator = PathInterpolator(0.6F, -0.24F, 0.6F, -0.2F)
val enteringScaleInterpolator = PathInterpolator(0.61F, 1F, 0.88F, 1F)
val exitingScaleInterpolator = PathInterpolator(0.12F, 0F, 0.39F, 0F)
val translationXAnimator =
ObjectAnimator.ofFloat(mBinding.container, "translationX", startX, endX).apply {
interpolator =
if (isEnterAnimation) enteringTranslationXInterpolator else exitingTranslationXInterpolator
}
val translationYAnimator =
ObjectAnimator.ofFloat(mBinding.container, "translationY", startY, endY).apply {
interpolator =
if (isEnterAnimation) enteringTranslationYInterpolator else exitingTranslationYInterpolator
}
val scaleXAnimator = ObjectAnimator.ofFloat(mBinding.container, "scaleX", startScale, endScale).apply {
addUpdateListener {
val dimAmount = it.animatedValue as Float / 2
dialog?.window?.setDimAmount(dimAmount)
// 避免与原有悬浮窗重叠,退出动画执行到 95% 进度后隐藏
if (!isEnterAnimation && (it.animatedValue as Float) < 0.05F) {
mBinding.container.visibility = View.GONE
} else {
mBinding.container.visibility = View.VISIBLE
}
}
}
val scaleYAnimator = ObjectAnimator.ofFloat(mBinding.container, "scaleY", startScale, endScale)
val scaleAnimatorSet = AnimatorSet().apply {
playTogether(scaleXAnimator, scaleYAnimator)
interpolator = if (isEnterAnimation) enteringScaleInterpolator else exitingScaleInterpolator
}
mBinding.root.pivotX = mBinding.root.width / 2F
mBinding.root.pivotY = mBinding.root.height / 2F
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
val translationAnimatorSet = AnimatorSet().apply {
playTogether(translationXAnimator, translationYAnimator)
}
AnimatorSet().apply {
playTogether(
scaleAnimatorSet,
translationAnimatorSet
)
addListener(
onStart = {
mBinding.container.isClickable = false
mBinding.ivOpeningCover.isClickable = false
mBinding.ivClose.isClickable = false
},
onEnd = {
if (!isEnterAnimation) {
dismissAllowingStateLoss()
}
mBinding.container.isClickable = true
mBinding.ivOpeningCover.isClickable = true
mBinding.ivClose.isClickable = true
}
)
duration = ANIMATION_DURATION
}.start()
}
}
private fun dismissWithAnimation() {
performAnimation(false)
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
// 仅不显示进入动画的首页弹窗记录 id
if (!mShowEnterAnimation) {
val sp = PreferenceManager.getDefaultSharedPreferences(context?.applicationContext)
// 首页弹窗记录 id
val sp = PreferenceManager.getDefaultSharedPreferences(context?.applicationContext)
SPUtils.setString(sp, Constants.SP_LAST_OPENING_ID, mWelcomeEntity?.id)
SPUtils.setLong(sp, Constants.SP_LAST_OPENING_TIME, mWelcomeEntity?.time ?: 0L)
}
SPUtils.setString(sp, Constants.SP_LAST_OPENING_ID, mWelcomeEntity?.id)
SPUtils.setLong(sp, Constants.SP_LAST_OPENING_TIME, mWelcomeEntity?.time ?: 0L)
mDismissListener?.invoke()
LogUtils.uploadWelcomeDialog(
@ -320,14 +138,8 @@ class WelcomeDialogFragment : BaseDialogFragment() {
companion object {
const val TAG = "welcome_dialog"
const val ANIMATION_DURATION = 800L
@JvmStatic
fun getInstance(
welcomeEntity: WelcomeDialogEntity?,
withAnimation: Boolean = false,
triggerFragment: BaseLazyFragment? = null
) = WelcomeDialogFragment().apply {
fun getInstance(welcomeEntity: WelcomeDialogEntity?) = WelcomeDialogFragment().apply {
arguments = Bundle()
arguments?.putParcelable(TAG, welcomeEntity)
LogUtils.uploadWelcomeDialog(
@ -338,21 +150,6 @@ class WelcomeDialogFragment : BaseDialogFragment() {
welcomeEntity?.text
)
mTriggerFragment = triggerFragment
// 低于 Android 5.0 禁用动画,因为贝塞尔曲线需要 5.0+ 支持
mShowEnterAnimation = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
false
} else {
withAnimation
}
mShowExitAnimation = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
false
} else {
withAnimation || welcomeEntity?.shouldShowExitAnimation == true
}
SensorsBridge.trackEvent("HomeDialogShow")
}
}

View File

@ -29,7 +29,6 @@ import com.gh.gamecenter.common.constant.ItemViewType
import com.gh.gamecenter.common.entity.ExposureEntity
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.ImageUtils.display
import com.gh.gamecenter.common.view.ScrollEventListener
import com.gh.gamecenter.common.viewholder.FooterViewHolder
import com.gh.gamecenter.core.utils.DisplayUtils
@ -437,8 +436,8 @@ class GameCollectionSquareAdapter(
binding.run {
val context = root.context
poster.setTag(ImageUtils.TAG_TARGET_WIDTH, mPosterWidth)
display(poster, gamesCollectionEntity.cover)
display(userIv, gamesCollectionEntity.user?.icon)
ImageUtils.display(poster, gamesCollectionEntity.cover)
ImageUtils.display(userIv, gamesCollectionEntity.user?.icon)
titleTv.text = gamesCollectionEntity.title
gamesCollectionEntity.games?.take(3)?.forEachIndexed { index, game ->
when (index) {

View File

@ -285,95 +285,114 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
linkType = contentCardEntity.type ?: "",
linkId = contentCardEntity.id
)
val path = "游戏详情->内容卡片"
when (contentCardEntity.type) {
"func_server" -> {
if (contentCardEntity.server != null) {
requireContext().startActivity(
ServersCalendarActivity.getIntent(
requireContext(),
mViewModel.game!!, contentCardEntity.server!!,
mNewGameDetailEntity?.me
)
val dialog = contentCardEntity.dialog
if (dialog != null) {// 展示内容卡片提示弹窗
DialogHelper.showDialog(
context = requireContext(),
title = dialog.title ?: "",
content = dialog.body ?: "",
confirmText = requireContext().getString(R.string.confirm),
cancelText = requireContext().getString(R.string.cancel),
confirmClickCallback = {
jumpToContentCardLink(contentCardEntity)
}
)
} else {
jumpToContentCardLink(contentCardEntity)
}
}
private fun jumpToContentCardLink(contentCardEntity: ContentCardEntity) {
val path = "游戏详情->内容卡片"
when (contentCardEntity.type) {
"func_server" -> {
if (contentCardEntity.server != null) {
requireContext().startActivity(
ServersCalendarActivity.getIntent(
requireContext(),
mViewModel.game!!, contentCardEntity.server!!,
mNewGameDetailEntity?.me
)
}
)
}
}
"func_libao" -> {
mBodyBinding.gamedetailVp.currentItem = 0
mBodyBinding.gamedetailAppbar.setExpanded(false, true)
val fragment = mFragmentsList[0]
if (fragment is DescFragment && fragment.isAdded) {
fragment.scrollToLibao()
}
"func_libao" -> {
mBodyBinding.gamedetailVp.currentItem = 0
mBodyBinding.gamedetailAppbar.setExpanded(false, true)
val fragment = mFragmentsList[0]
if (fragment is DescFragment && fragment.isAdded) {
fragment.scrollToLibao()
}
}
"func_related_version" -> {
mBodyBinding.gamedetailVp.currentItem = 0
mBodyBinding.gamedetailAppbar.setExpanded(false, true)
val fragment = mFragmentsList[0]
if (fragment is DescFragment && fragment.isAdded) {
fragment.scrollToRelatedVersion()
}
"func_related_version" -> {
mBodyBinding.gamedetailVp.currentItem = 0
mBodyBinding.gamedetailAppbar.setExpanded(false, true)
val fragment = mFragmentsList[0]
if (fragment is DescFragment && fragment.isAdded) {
fragment.scrollToRelatedVersion()
}
}
"func_zone" -> {
val gameDetailEntity = mViewModel.gameDetailLiveData.value?.data
if (contentCardEntity.zoneTab && gameDetailEntity?.zone != null && gameDetailEntity.zone!!.style == "link") {
requireContext().startActivity(
WebActivity.getIntent(
requireContext(),
gameDetailEntity.zone!!.link,
true
)
"func_zone" -> {
val gameDetailEntity = mViewModel.gameDetailLiveData.value?.data
if (contentCardEntity.zoneTab && gameDetailEntity?.zone != null && gameDetailEntity.zone!!.style == "link") {
requireContext().startActivity(
WebActivity.getIntent(
requireContext(),
gameDetailEntity.zone!!.link,
true
)
}
)
}
}
"func_bbs" -> {
val funcBbs = contentCardEntity.funcBbs
funcBbs?.let {
DirectUtils.directForumDetail(requireContext(), it.link, path)
}
"func_bbs" -> {
val funcBbs = contentCardEntity.funcBbs
funcBbs?.let {
DirectUtils.directForumDetail(requireContext(), it.link, path)
}
}
"func_tool_kit" -> {
if (contentCardEntity.toolkit.isNotEmpty()) {
contentCardEntity.toolkit.safelyGetInRelease(0)?.let {
val url = it.url
if (url != null && url.contains(Config.URL_ARTICLE)) {
val newsId = url.substring(url.lastIndexOf("/") + 1, url.length - 5) // 5: ".html"
val intent = NewsDetailActivity.getIntentById(requireContext(), newsId, path)
requireContext().startActivity(intent)
} else {
requireContext().startActivity(
WebActivity.getWebByCollectionTools(
requireContext(),
it,
false
)
"func_tool_kit" -> {
if (contentCardEntity.toolkit.isNotEmpty()) {
contentCardEntity.toolkit.safelyGetInRelease(0)?.let {
val url = it.url
if (url != null && url.contains(Config.URL_ARTICLE)) {
val newsId = url.substring(url.lastIndexOf("/") + 1, url.length - 5) // 5: ".html"
val intent = NewsDetailActivity.getIntentById(requireContext(), newsId, path)
requireContext().startActivity(intent)
} else {
requireContext().startActivity(
WebActivity.getWebByCollectionTools(
requireContext(),
it,
false
)
}
)
}
}
}
else -> DirectUtils.directToLinkPage(
requireContext(),
contentCardEntity.toLinkEntity(),
mEntrance,
path,
ExposureEvent.createEvent(
null,
listOf(
ExposureSource("游戏详情", mGameEntity?.id ?: ""),
ExposureSource("内容卡片", contentCardEntity.id)
)
),
"游戏详情页-内容卡片"
)
}
else -> DirectUtils.directToLinkPage(
requireContext(),
contentCardEntity.toLinkEntity(),
mEntrance,
path,
ExposureEvent.createEvent(
null,
listOf(
ExposureSource("游戏详情", mGameEntity?.id ?: ""),
ExposureSource("内容卡片", contentCardEntity.id)
)
),
"游戏详情页-内容卡片"
)
}
}
override fun getLayoutId(): Int = 0
override fun getInflatedLayout(): View {
@ -424,12 +443,13 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
.load(R.layout.fragment_gamedetail_skeleton)
.show()
val gameId = args.getString(EntranceConsts.KEY_GAMEID) ?: ""
val factory = GameDetailViewModel.Factory(
HaloApp.getInstance().application,
args.getString(EntranceConsts.KEY_GAMEID),
gameId,
args.getParcelable(GameEntity.TAG)
)
mViewModel = viewModelProviderFromParent(factory)
mViewModel = viewModelProviderFromParent(factory, gameId)
mPackageViewModel = viewModelProvider(PackageViewModel.Factory())
mUserViewModel = viewModelProvider(UserViewModel.Factory(HaloApp.getInstance().application))
@ -784,7 +804,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
}
SensorsBridge.trackEventWithExposureSource(
"GameDetailPageShow",
mTraceEvent?.source,
mTraceEvent?.source ?: listOf(ExposureSource(mEntrance)),
"game_id", mGameEntity?.id ?: "",
"game_name", mGameEntity?.name ?: "",
"download_status", mGameEntity?.downloadStatusChinese ?: "",

View File

@ -15,6 +15,7 @@ import com.gh.common.util.CheckLoginUtils
import com.gh.gamecenter.feature.utils.ConcernUtils
import com.gh.common.util.LibaoUtils
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.livedata.NonStickyMutableLiveData
import com.gh.gamecenter.common.mvvm.Resource
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
@ -30,10 +31,7 @@ import com.gh.gamecenter.feature.entity.LibaoStatusEntity
import com.gh.gamecenter.feature.entity.SimpleGame
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.feature.utils.ContentBlockedHelper
import com.gh.gamecenter.gamedetail.entity.BigEvent
import com.gh.gamecenter.gamedetail.entity.CustomColumn
import com.gh.gamecenter.gamedetail.entity.DetailEntity
import com.gh.gamecenter.gamedetail.entity.NewGameDetailEntity
import com.gh.gamecenter.gamedetail.entity.*
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp

View File

@ -123,7 +123,7 @@ class DescFragment: LazyFragment(), IScrollable {
val gameDetailFactory =
GameDetailViewModel.Factory(HaloApp.getInstance().application, mGameEntity?.id, mGameEntity)
val gameDetailViewModel: GameDetailViewModel = viewModelProviderFromParent(gameDetailFactory)
val gameDetailViewModel: GameDetailViewModel = viewModelProviderFromParent(gameDetailFactory, mGameEntity?.id ?: "")
mNewDetailEntity = gameDetailViewModel.gameDetailLiveData.value?.data
val factory = DescViewModel.Factory(HaloApp.getInstance().application, mGameEntity)

View File

@ -20,6 +20,7 @@ import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.databinding.DialogGameDetailMoreBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.GameDetailViewModel
import com.halo.assistant.HaloApp
class GameDetailMoreDialog : BaseDraggableDialogFragment() {
@ -29,7 +30,15 @@ class GameDetailMoreDialog : BaseDraggableDialogFragment() {
private var mGameEntity: GameEntity? = null
private var mShowConcernIcon = false
private var mIsConcerned = false
private val mViewModel: GameDetailViewModel by lazy { viewModelProviderFromParent() }
private val mViewModel: GameDetailViewModel by lazy {
viewModelProviderFromParent(
GameDetailViewModel.Factory(
HaloApp.getInstance().application,
mGameEntity?.id,
mGameEntity
), mGameEntity?.id ?: ""
)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

View File

@ -54,8 +54,18 @@ class ContentCardEntity(
var relatedVersion: Boolean = false,
var toolkit: ArrayList<ToolBoxEntity> = ArrayList(),
@SerializedName("func_bbs")
val funcBbs: LinkEntity? = null
val funcBbs: LinkEntity? = null,
val dialog: Dialog? = null
) {
@Keep
class Dialog(
@SerializedName("_id")
val id: String? = "",
val title: String? = "",
val body: String? = ""
)
fun toLinkEntity(): LinkEntity {
return LinkEntity(
name = name,

View File

@ -65,7 +65,7 @@ class FuLiFragment : LazyFragment(), IScrollable {
GameDetailViewModel.Factory(HaloApp.getInstance().application, gameEntity?.id, gameEntity)
shouldScroolToLibao = arguments?.getBoolean(EntranceConsts.KEY_SCROLL_TO_LIBAO) ?: false
mGameDetailViewModel = viewModelProviderFromParent(gameDetailFactory)
mGameDetailViewModel = viewModelProviderFromParent(gameDetailFactory, gameEntity?.id ?: "")
mFuLiViewModel = viewModelProvider()
super.onFragmentFirstVisible()

View File

@ -146,7 +146,7 @@ class ServersCalendarDetailDialog : DialogFragment() {
val serverCalendarList = adapter.selectedServerCalendarList
serverCalendarList.forEachIndexed { index, entity ->
if (index != 0) builder.append("")
builder.append("${entity.getFormatTime("YYYY年MM月dd日")}开服信息有误:${entity.getNote()}")
builder.append("${entity.getFormatTime("yyyy年MM月dd日")}开服信息有误:${entity.getNote()}")
}
HelpAndFeedbackBridge.startSuggestionActivity(
it.context,

View File

@ -32,7 +32,7 @@ class CustomCommonCollectionAdapter(
}
override fun getKey(t: CommonCollectionContentEntity): String {
return t.title
return "${_data.data.layout}-${t.id}"
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomCommonCollectionItemViewHolder {

View File

@ -82,7 +82,7 @@ class CustomHomeGameCollectionSlideAdapter(
} else {
gUser.goneIf(true)
}
ImageUtils.display(coverImage, subject.image, false)
ImageUtils.display(coverImage, subject.image)
titleTv.text = subject.title

View File

@ -27,7 +27,7 @@ class CustomBigImageRecommendViewHolder(
if (item is CustomContentCardItem) {
val contentCard = item.data
binding.run {
ImageUtils.display(poster, contentCard.img, shouldAutoPlayAnimatedImage = false)
ImageUtils.display(poster, contentCard.img)
recommendTag.goneIf(contentCard.recommendTag.isEmpty())
recommendTextTwo.goneIf(contentCard.secondLineRecommend.isEmpty())
recommendTag.text = contentCard.recommendTag

View File

@ -109,7 +109,7 @@ class CustomHomeGameItemViewHolder(
}
binding.gameBrief.text = game.recommendText
binding.gameImage.visibleIf(game.showImage) {
ImageUtils.display(binding.gameImage, game.homeSetting.image, false)
ImageUtils.display(binding.gameImage, game.homeSetting.image)
val hierarchy = binding.gameImage.hierarchy
try {
hierarchy.setPlaceholderImage(ColorDrawable(game.homeSetting.placeholderColor.hexStringToIntColor()))

View File

@ -1,8 +1,10 @@
package com.gh.gamecenter.home.custom.viewholder
import android.graphics.Color
import android.graphics.drawable.Animatable
import android.graphics.drawable.ColorDrawable
import android.view.View
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.imagepipeline.image.ImageInfo
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
@ -45,16 +47,19 @@ class CustomHomeSlideListItemViewHolder(val binding: HomeSlideListItemCustomBind
GameItemViewHolder.initGameSubtitleAndAdLabel(it, binding.includeGame.gameSubtitleTv)
}
binding.bottomGradient.visibility = View.GONE
ImageUtils.addLimitWidthAndLoad(
if (homeSlide.image != binding.slideBackground.tag) {
binding.bottomGradient.visibility = View.GONE
}
binding.slideBackground.setTag(ImageUtils.TAG_TARGET_WIDTH, mImageWith)
ImageUtils.displayWithCallback(
binding.slideBackground,
homeSlide.image,
mImageWith,
object : ImageUtils.OnImageloadListener {
override fun onLoadFinal(imageInfo: ImageInfo?) {
object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
binding.bottomGradient.visibility = View.VISIBLE
}
})
}
)
val hierarchy = binding.slideBackground.hierarchy
try {

View File

@ -1,18 +1,19 @@
package com.gh.gamecenter.home.custom.viewholder
import android.graphics.Color
import android.graphics.drawable.Animatable
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.GradientDrawable
import android.view.View
import androidx.core.graphics.ColorUtils
import androidx.core.view.isVisible
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.imagepipeline.image.ImageInfo
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.RandomUtils
import com.gh.gamecenter.databinding.HomeSubSlideListItemBinding
import com.gh.gamecenter.databinding.HomeSubSlideListItemCustomBinding
import com.gh.gamecenter.entity.HomeSlide
import com.gh.gamecenter.feature.game.GameItemViewHolder
@ -52,7 +53,9 @@ class CustomHomeSubSlideListItemViewHolder(val binding: HomeSubSlideListItemCust
val startColor = Color.HSVToColor(colorHSV)
val endColor = ColorUtils.setAlphaComponent(startColor, 0)
binding.slideMask.visibility = View.GONE
if (homeSlide.image != binding.slideBackground.tag) {
binding.slideMask.visibility = View.GONE
}
binding.slideMask.background = GradientDrawable().apply {
gradientType = GradientDrawable.LINEAR_GRADIENT
orientation = GradientDrawable.Orientation.BOTTOM_TOP
@ -60,17 +63,18 @@ class CustomHomeSubSlideListItemViewHolder(val binding: HomeSubSlideListItemCust
}
}
ImageUtils.addLimitWidthAndLoad(
binding.slideBackground.setTag(ImageUtils.TAG_TARGET_WIDTH, mImageWith)
ImageUtils.displayWithCallback(
binding.slideBackground,
homeSlide.image,
mImageWith,
object : ImageUtils.OnImageloadListener {
override fun onLoadFinal(imageInfo: ImageInfo?) {
object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
if (homeSlide.placeholderColor.isNotEmpty() && homeSlide.linkGame != null) {
binding.slideMask.visibility = View.VISIBLE
}
}
})
}
)
val hierarchy = binding.slideBackground.hierarchy
try {

View File

@ -1,12 +1,17 @@
package com.gh.gamecenter.home.slide
import android.graphics.Color
import android.graphics.drawable.Animatable
import android.graphics.drawable.ColorDrawable
import android.view.View
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.imagepipeline.image.ImageInfo
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.core.utils.RandomUtils
import com.gh.gamecenter.databinding.HomeSlideListItemBinding
import com.gh.gamecenter.entity.HomeSlide
@ -42,16 +47,19 @@ class HomeSlideListItemViewHolder(val binding: HomeSlideListItemBinding) : BaseR
GameItemViewHolder.initGameSubtitleAndAdLabel(it, binding.includeGame.gameSubtitleTv)
}
binding.bottomGradient.visibility = View.GONE
ImageUtils.addLimitWidthAndLoad(
if (homeSlide.image != binding.slideBackground.tag) {
binding.bottomGradient.visibility = View.GONE
}
binding.slideBackground.setTag(ImageUtils.TAG_TARGET_WIDTH, mImageWith)
ImageUtils.displayWithCallback(
binding.slideBackground,
homeSlide.image,
mImageWith,
object : ImageUtils.OnImageloadListener {
override fun onLoadFinal(imageInfo: ImageInfo?) {
object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
binding.bottomGradient.visibility = View.VISIBLE
}
})
}
)
val hierarchy = binding.slideBackground.hierarchy
try {

View File

@ -1,11 +1,13 @@
package com.gh.gamecenter.home.slide
import android.graphics.Color
import android.graphics.drawable.Animatable
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.GradientDrawable
import android.view.View
import androidx.core.graphics.ColorUtils
import androidx.core.view.isVisible
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.imagepipeline.image.ImageInfo
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
@ -51,7 +53,9 @@ class HomeSubSlideListItemViewHolder(val binding: HomeSubSlideListItemBinding) :
val startColor = Color.HSVToColor(colorHSV)
val endColor = ColorUtils.setAlphaComponent(startColor, 0)
binding.slideMask.visibility = View.GONE
if (homeSlide.image != binding.slideBackground.tag) {
binding.slideMask.visibility = View.GONE
}
binding.slideMask.background = GradientDrawable().apply {
gradientType = GradientDrawable.LINEAR_GRADIENT
orientation = GradientDrawable.Orientation.BOTTOM_TOP
@ -59,17 +63,18 @@ class HomeSubSlideListItemViewHolder(val binding: HomeSubSlideListItemBinding) :
}
}
ImageUtils.addLimitWidthAndLoad(
binding.slideBackground.setTag(ImageUtils.TAG_TARGET_WIDTH, mImageWith)
ImageUtils.displayWithCallback(
binding.slideBackground,
homeSlide.image,
mImageWith,
object : ImageUtils.OnImageloadListener {
override fun onLoadFinal(imageInfo: ImageInfo?) {
object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
if (homeSlide.placeholderColor.isNotEmpty() && homeSlide.linkGame != null) {
binding.slideMask.visibility = View.VISIBLE
}
}
})
}
)
val hierarchy = binding.slideBackground.hierarchy
try {

View File

@ -369,7 +369,7 @@ class AutomaticVideoView @JvmOverloads constructor(context: Context, attrs: Attr
}
fun updateThumb(url: String) {
ImageUtils.display(thumbImage, url, false)
ImageUtils.display(thumbImage, url)
}
/********************************各类UI的状态显示*********************************************/

View File

@ -169,7 +169,7 @@ class InfoAdapter extends ListAdapter<NewsEntity> {
viewHolder.binding.newsImage3Title.setTextColor(ContextCompat.getColor(viewHolder.itemView.getContext(), R.color.title));
if (newsEntity.getThumbnail() != null && newsEntity.getThumbnail().getUrl() != null) {
ImageUtils.display(viewHolder.binding.newsImage3Thumb, CollectionsKt.firstOrNull(newsEntity.getThumbnail().getUrl()),
ImageUtils.displayWithAdaptiveHeight(viewHolder.binding.newsImage3Thumb, CollectionsKt.firstOrNull(newsEntity.getThumbnail().getUrl()),
mContext.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(mContext, 40));
}
int views = newsEntity.getViews();

View File

@ -150,7 +150,7 @@ class OriginalAdapter extends ListAdapter<NewsEntity> {
viewHolder.binding.newsImage3Title.setTextColor(ContextCompat.getColor(viewHolder.itemView.getContext(), R.color.title));
if (newsEntity.getThumbnail() != null && newsEntity.getThumbnail().getUrl() != null) {
ImageUtils.display(viewHolder.binding.newsImage3Thumb, CollectionsKt.firstOrNull(newsEntity.getThumbnail().getUrl()),
ImageUtils.displayWithAdaptiveHeight(viewHolder.binding.newsImage3Thumb, CollectionsKt.firstOrNull(newsEntity.getThumbnail().getUrl()),
mContext.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(mContext, 40));
}
int views = newsEntity.getViews();

View File

@ -16,6 +16,7 @@ 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
@ -26,6 +27,7 @@ import com.gh.gamecenter.livedata.Event
import com.gh.gamecenter.manager.PackagesManager
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.android.schedulers.AndroidSchedulers
@ -58,6 +60,8 @@ object PackageRepository {
@Volatile
private var mIsInitialisingData = false
var installedPkgRefreshed = false
var vaPkgRefreshed = false
val gameUpdateLiveData = MutableLiveData<List<GameUpdateEntity>>()
val gameInstalledLiveData = MutableLiveData<List<GameInstall>>()
@ -79,13 +83,20 @@ object PackageRepository {
*/
@JvmStatic
fun initData() {
Utils.log("xxx", "PackageRepository::initData::mIsInitialisingData = $mIsInitialisingData")
if (mIsInitialisingData) return
mIsInitialisingData = true
installedPkgRefreshed = false
vaPkgRefreshed = false
runOnIoThread {
if (gameInstalled.isNotEmpty()) gameInstalled.clear()
if (mInstalledGameList.isNotEmpty()) mInstalledGameList.clear()
if (gameUpdate.isNotEmpty()) gameUpdate.clear()
if (gameUpdate.isNotEmpty()) {
gameUpdate.clear()
Utils.log("xxx", "清除更新数据")
}
if (mInstalledPkgList.isNotEmpty()) mInstalledPkgList.clear()
val list = PackageUtils.getAllPackageName(mApplication)
@ -93,15 +104,38 @@ object PackageRepository {
uploadAppList()
initFilterPackage(list) { filteredList ->
mIsInitialisingData = false
mInstalledPkgList.addAll(filteredList)
notifyInstallPkgData()
loadInstalledGameDigestAndNotifyData(filteredList)
Utils.log("xxx", "PackageRepository::filteredList::${filteredList}")
loadInstalledGameDigestAndNotifyData(filteredList) {
installedPkgRefreshed = true
mIsInitialisingData = !(installedPkgRefreshed && vaPkgRefreshed)
}
}
loadGhzsUpdate()
// 畅玩游戏更新
var allGames = VHelper.getAllVGameSnapshots()
if (allGames.isNullOrEmpty()) {
VHelper.refreshVGameSnapshot()
allGames = VHelper.getAllVGameSnapshots()
}
val allGamePkgNames = allGames.map { it.packageName }.toArrayList()
if (allGamePkgNames.isNotEmpty()) {
notifyInstallPkgData()
updateFilterPackage(allGamePkgNames) {
Utils.log("xxx", "PackageRepository::filteredList::${allGamePkgNames}")
loadInstalledGameDigestAndNotifyData(
filteredList = allGamePkgNames,
onWorkerThreadOnly = false,
isVGame = true
) {
vaPkgRefreshed = true
mIsInitialisingData = !(installedPkgRefreshed && vaPkgRefreshed)
}
}
}
}
}
@ -134,7 +168,8 @@ 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>() {
@ -209,6 +244,7 @@ object PackageRepository {
filteredList: ArrayList<String>,
onWorkerThreadOnly: Boolean = false,
isVGame: Boolean = false,
loadFinishCallback: (() -> Unit)? = null
) {
var isNotifyUpdate = false
val maxPageCount = (filteredList.size / PAGE_SIZE) + 1
@ -217,6 +253,7 @@ object PackageRepository {
val latch = ObservableUtil.latch(maxPageCount, {
if (isNotifyUpdate || gameUpdateLiveData.value == null) notifyGameUpdateData()
notifyGameInstallData()
loadFinishCallback?.invoke()
}, Any())
while (++page <= maxPageCount) {

View File

@ -3,9 +3,10 @@ package com.gh.gamecenter.packagehelper
import android.app.Application
import android.text.TextUtils
import androidx.lifecycle.*
import com.gh.gamecenter.feature.entity.GameInstall
import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.feature.entity.GameInstall
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import kotlin.collections.set
class PackageViewModel(
@ -79,6 +80,7 @@ class PackageViewModel(
if (mRepository.gameInstalled.size == 0
|| PackageFilterManager.hasPendingPackage()
) {
Utils.log("xxx", "PackageViewModel call initData")
mRepository.initData()
}
}

View File

@ -60,7 +60,7 @@ import com.gh.gamecenter.room.AppDatabase
import com.gh.gamecenter.setting.SettingBridge
import com.gh.gamecenter.wrapper.MainWrapperFragment
import com.gh.gamecenter.wrapper.MainWrapperViewModel
import com.gh.vspace.IExternalGamesUsage
import com.gh.vspace.ITestCase
import com.google.android.material.appbar.AppBarLayout
import com.halo.assistant.HaloApp
import com.jakewharton.rxbinding2.view.RxView
@ -695,7 +695,11 @@ class HaloPersonalFragment : BaseLazyFragment() {
(try {
Class.forName("com.gh.vspace.ExternalGameUsage")?.newInstance()
} catch (e: Exception) {
} as? IExternalGamesUsage)?.addInstallExternalGameButton(mStubBinding.otherItems)
} as? ITestCase)?.apply {
addInstallExternalGameButton(mStubBinding.otherItems)
addInstallPluginButton(mStubBinding.otherItems)
addInstallPlugin32Button(mStubBinding.otherItems)
}
}
mStubBinding.settingItem.run {

View File

@ -492,7 +492,7 @@ class UserHomeFragment : ToolbarFragment() {
// 设置有边框挂件的头像
userIcon.display(personalData.iconBorder?.url, personalData.icon, "")
ImageUtils.displayIcon(userSmallIcon, personalData.icon)
ImageUtils.display(userSmallIcon, personalData.icon)
authTv.setOnClickListener {
personalData.auth?.link?.let { link ->

View File

@ -1,65 +0,0 @@
package com.gh.gamecenter.personalhome.rating
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.lifecycle.ViewModelProviders
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.R
import com.gh.gamecenter.common.baselist.ListActivity
import com.gh.gamecenter.common.baselist.NormalListViewModel
import com.gh.gamecenter.common.utils.updateStatusBarColor
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.Single
class RatingActivity : ListActivity<MyRating, NormalListViewModel<MyRating>>() {
private var mAdapter: RatingAdapter? = null
private var mUserId: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
mUserId = intent.getStringExtra(EntranceConsts.KEY_USER_ID)
super.onCreate(savedInstanceState)
if (mUserId == UserManager.getInstance().userId) {
setNavigationTitle("我的评分")
} else {
setNavigationTitle("Ta的评分")
}
updateStatusBarColor(R.color.ui_surface, R.color.ui_surface)
}
override fun provideListAdapter(): RatingAdapter {
if (mAdapter == null) mAdapter = RatingAdapter(this, mEntrance, mListViewModel)
return mAdapter!!
}
override fun provideDataSingle(page: Int): Single<MutableList<MyRating>> {
return RetrofitManager.getInstance().api.getMyRating(mUserId, page, "view:default")
}
override fun provideListViewModel(): NormalListViewModel<MyRating> {
val factory = NormalListViewModel.Factory(HaloApp.getInstance().application, this)
return ViewModelProviders.of(this, factory)
.get(NormalListViewModel::class.java) as NormalListViewModel<MyRating>
}
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, userId: String, entrance: String, path: String): Intent {
val intent = Intent(context, RatingActivity::class.java)
intent.putExtra(EntranceConsts.KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
intent.putExtra(EntranceConsts.KEY_USER_ID, userId)
return intent
}
}
}

View File

@ -1,88 +0,0 @@
package com.gh.gamecenter.personalhome.rating
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.constant.ItemViewType
import com.gh.common.util.NewsUtils
import com.gh.gamecenter.core.utils.NumberUtils
import com.gh.gamecenter.common.utils.fromHtml
import com.gh.gamecenter.common.utils.setTextWithHighlightedTextWrappedInsideWrapper
import com.gh.gamecenter.GameDetailActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.viewholder.FooterViewHolder
import com.gh.gamecenter.adapter.viewholder.PersonalHomeRatingViewHolder
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.baselist.NormalListViewModel
import com.gh.gamecenter.databinding.PersonalHomeRatingBinding
class RatingAdapter(
context: Context,
private val mEntrance: String,
private val mListViewModel: NormalListViewModel<MyRating>
) : ListAdapter<MyRating>(context) {
override fun getItemViewType(position: Int): Int {
return if (position == itemCount - 1) {
ItemViewType.ITEM_FOOTER
} else {
ItemViewType.ITEM_BODY
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view: View
return when (viewType) {
ItemViewType.ITEM_FOOTER -> {
view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)
FooterViewHolder(view)
}
else -> {
view = mLayoutInflater.inflate(R.layout.personal_home_rating, parent, false)
PersonalHomeRatingViewHolder(PersonalHomeRatingBinding.bind(view))
}
}
}
override fun getItemCount(): Int {
return if (mEntityList == null || mEntityList.isEmpty()) 0 else mEntityList.size + 1
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is PersonalHomeRatingViewHolder -> {
val entity = mEntityList[holder.adapterPosition]
val historyEntity = entity.transformHistoryEntity()
holder.binding.comment.text =
if (historyEntity.count.reply > 0) NumberUtils.transSimpleCount(historyEntity.count.reply) else ""
holder.binding.vote.isChecked = historyEntity.me.isVoted
holder.binding.vote.text =
if (historyEntity.count.vote > 0) NumberUtils.transSimpleCount(historyEntity.count.vote) else ""
holder.binding.ratingStart.rating = historyEntity.comment.star.toFloat()
holder.binding.userCommand.text = (mContext.getString(
R.string.personal_home_rating_command,
NewsUtils.getFormattedTime(entity.time),
entity.game.name
)).fromHtml()
holder.binding.content.setTextWithHighlightedTextWrappedInsideWrapper(
text = entity.content,
copyClickedText = true
)
holder.itemView.setOnClickListener {
GameDetailActivity.startGameDetailActivity(
mContext,
entity.game.id,
mEntrance,
isSkipGameComment = true
)
}
}
is FooterViewHolder -> {
holder.initItemPadding()
holder.initFooterViewHolder(mListViewModel, mIsLoading, mIsNetworkError, mIsOver)
}
}
}
}

View File

@ -1,71 +0,0 @@
package com.gh.gamecenter.qa.answer.detail;
import static com.gh.gamecenter.common.constant.Constants.GAME_DETAIL_COME_IN;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.gh.gamecenter.common.base.activity.ToolBarActivity;
import com.gh.gamecenter.common.constant.EntranceConsts;
import com.gh.gamecenter.entity.SpecialColumn;
import com.halo.assistant.HaloApp;
/**
* Created by khy on 10/04/18.
*/
public class AnswerDetailActivity extends ToolBarActivity {
public static final String TAG = "AnswerDetailActivity";
@Override
public boolean showToolbarAtLeft() {
if (HaloApp.get(GAME_DETAIL_COME_IN, false) != null) {
return true;
}
return super.showToolbarAtLeft();
}
@NonNull
public static Intent getIntent(Context context, String answerId, String entrance, String path) {
return getIntent(context, answerId, entrance, path, false, null);
}
@NonNull
public static Intent getIntent(Context context, String answerId, String entrance, String path, boolean isOpenCommentManager) {
return getIntent(context, answerId, entrance, path, isOpenCommentManager, null);
}
@NonNull
public static Intent getIntent(Context context, String answerId, String entrance, String path, SpecialColumn specialColumn) {
return getIntent(context, answerId, entrance, path, false, specialColumn);
}
@NonNull
public static Intent getIntent(Context context, String answerId, String entrance, String path, boolean isOpenCommentManager, SpecialColumn specialColumn) {
Bundle bundle = new Bundle();
bundle.putString(EntranceConsts.KEY_ANSWER_ID, answerId);
bundle.putString(EntranceConsts.KEY_ENTRANCE, mergeEntranceAndPath(entrance, path));
bundle.putBoolean(EntranceConsts.KEY_SHOW_ANSWER_COMMENT, isOpenCommentManager);
bundle.putString(EntranceConsts.KEY_PATH, path);
bundle.putParcelable(EntranceConsts.KEY_DATA, specialColumn);
return getTargetIntent(context, AnswerDetailActivity.class, AnswerDetailContainerFragment.class, bundle);
}
@NonNull
public static Intent getRecommendsIntent(Context context, String answerId, String entrance, String path) {
Bundle bundle = new Bundle();
bundle.putString(EntranceConsts.KEY_ANSWER_ID, answerId);
bundle.putString(EntranceConsts.KEY_ENTRANCE, mergeEntranceAndPath(entrance, path));
bundle.putBoolean(EntranceConsts.KEY_RECOMMENDS_CONTENTS, true);
bundle.putString(EntranceConsts.KEY_PATH, path);
return getTargetIntent(context, AnswerDetailActivity.class, AnswerDetailContainerFragment.class, bundle);
}
@Override
protected Intent provideNormalIntent() {
return getTargetIntent(this, AnswerDetailActivity.class, AnswerDetailContainerFragment.class);
}
}

View File

@ -1,121 +0,0 @@
package com.gh.gamecenter.qa.answer.detail
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.common.util.SyncDataBetweenPageHelper
import com.gh.gamecenter.common.utils.observeNonNull
import com.gh.gamecenter.common.utils.viewModelProviderFromParent
import com.gh.gamecenter.databinding.FragmentAnswerDetailContainerBinding
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
class AnswerDetailContainerFragment : ToolbarFragment() {
private lateinit var mFragmentAdapter: AnswerDetailFragmentStatePagerAdapter
private lateinit var mContainerViewModel: AnswerDetailContainerViewModel
private lateinit var mBinding: FragmentAnswerDetailContainerBinding
private val fragments = ArrayList<AnswerDetailFragment>()
// 是否已经传了 argument 给第一个子 fragment
private var mHasPassedOneTimeArgumentToChild = false
override fun getLayoutId(): Int = 0
override fun getInflatedLayout(): View {
return FragmentAnswerDetailContainerBinding.inflate(LayoutInflater.from(requireContext()), null, false).apply {
mBinding = this
}.root
}
override fun onMenuItemClick(menuItem: MenuItem?) {
fragmentManager?.fragments?.let {
for (fragment in it) {
if (fragment is AnswerDetailFragment && fragment.isResumed) {
fragment.onMenuItemClick(menuItem!!)
}
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mContainerViewModel = viewModelProviderFromParent()
val answerId = arguments?.getString(EntranceConsts.KEY_ANSWER_ID) ?: ""
if (!mContainerViewModel.answerIdList.contains(answerId)) {
mContainerViewModel.answerIdList.add(answerId)
}
val tag = "android:switcher:${mBinding.viewpager.id}:"
mFragmentAdapter = AnswerDetailFragmentStatePagerAdapter(parentFragmentManager) { id, position ->
var fragment = childFragmentManager.findFragmentByTag("${tag}${position}") as? AnswerDetailFragment
if (fragment == null) {
fragment = AnswerDetailFragment().apply {
if (mHasPassedOneTimeArgumentToChild) {
this@AnswerDetailContainerFragment.arguments?.putBoolean(
EntranceConsts.KEY_SHOW_ANSWER_COMMENT,
false
)
this@AnswerDetailContainerFragment.arguments?.putBoolean(
EntranceConsts.KEY_RECOMMENDS_CONTENTS,
false
)
}
// 将外部的 argument 传给里面的 fragment
this.arguments = this@AnswerDetailContainerFragment.arguments
this.arguments?.putString(EntranceConsts.KEY_ANSWER_ID, id)
mHasPassedOneTimeArgumentToChild = true
fragments.add(this)
}
}
fragment
}
mFragmentAdapter.answerIdList = ArrayList(mContainerViewModel.answerIdList)
mBinding.viewpager.adapter = mFragmentAdapter
mContainerViewModel.answerListChange.observeNonNull(this) {
mFragmentAdapter.answerIdList = ArrayList(mContainerViewModel.answerIdList)
try {
mFragmentAdapter.notifyDataSetChanged()
} catch (e: Exception) {
e.printStackTrace()
}
}
mContainerViewModel.scroll.observeNonNull(this) {
val currentItem = mBinding.viewpager.currentItem
when (it) {
AnswerDetailContainerViewModel.SCROLL_TO_NEXT_ANSWER -> {
if (currentItem == mContainerViewModel.answerIdList.size) {
toast("到底了")
return@observeNonNull
} else {
mBinding.viewpager.currentItem = currentItem + 1
}
}
AnswerDetailContainerViewModel.SCROLL_TO_PREVIOUS_ANSWER -> {
if (currentItem == mContainerViewModel.answerIdList.size) {
toast("到顶了")
return@observeNonNull
} else {
mBinding.viewpager.currentItem = currentItem - 1
}
}
}
}
}
override fun onBackPressed(): Boolean {
val answerDetail = fragments[0].mViewModel.answerDetail
if (SyncDataBetweenPageHelper.setResultAndFinish(requireActivity(), answerDetail)) {
return true
}
return super.onBackPressed()
}
}

View File

@ -48,7 +48,6 @@ import com.gh.gamecenter.feature.entity.Questions
import com.gh.gamecenter.feature.entity.UserEntity
import com.gh.gamecenter.help.HelpAndFeedbackBridge
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity
import com.gh.gamecenter.qa.comment.CommentActivity
import com.gh.gamecenter.qa.dialog.MoreFunctionPanelDialog
import com.gh.gamecenter.qa.editor.OnLinkClickListener
@ -854,44 +853,6 @@ open class AnswerDetailFragment : ToolbarFragment() {
}
}
}
mBinding.statusTv.setOnClickListener {
mViewModel.answerDetail?.let {
when (mAnswerStatus) {
ANSWERED_MY_ANSWER -> editAnswer(it)
ANSWERED_NOT_MY_ANSWER -> {
startActivityForResult(
AnswerDetailActivity.getIntent(
context,
mViewModel.answerDetail!!.me.myAnswerId,
mEntrance,
"答案详情"
), ANSWER_PATCH_REQUEST
)
}
NOT_ANSWERED_YET -> ifLogin("回答详情-[我来回答]") {
checkStoragePermissionBeforeAction {
val question = mViewModel.answerDetail!!.question
startActivityForResult(
AnswerEditActivity.getIntent(requireContext(), question, true, question.communityName),
ANSWER_POST_REQUEST
)
}
}
NOT_ANSWERED_BUT_HAVE_DRAFT -> ifLogin("回答详情-[继续回答]") {
checkStoragePermissionBeforeAction {
val question = mViewModel.answerDetail!!.question
startActivityForResult(
AnswerEditActivity.getIntent(requireContext(), question, true, question.communityName),
ANSWER_POST_REQUEST
)
}
}
}
}
}
mBinding.userIconIv.setOnClickListener {
DirectUtils.directToHomeActivity(requireContext(), mViewModel.answerDetail!!.user.id, mEntrance, "回答详情")
}
@ -1014,19 +975,6 @@ open class AnswerDetailFragment : ToolbarFragment() {
requireActivity().startActivityForResult(intent, CommentActivity.REQUEST_CODE)
}
private fun editAnswer(answerDetail: AnswerDetailEntity) {
startActivityForResult(
AnswerEditActivity.getIntent(
requireContext(),
mAnswerId,
answerDetail.question,
answerDetail.content,
answerDetail.community.name
),
ANSWER_PATCH_REQUEST
)
}
@SuppressLint("DefaultLocale", "SetTextI18n")
private fun updateView(answerDetail: AnswerDetailEntity) {
initMenu()
@ -1301,12 +1249,6 @@ open class AnswerDetailFragment : ToolbarFragment() {
}
}
interface CommentListener {
fun onCountChange(count: Int)
fun onCommentDraftChange(draft: String)
fun onCommentSuccess(commentId: String)
}
companion object {
private const val ANSWER_STATUS_UNKNOWN = 0
private const val ANSWERED_MY_ANSWER = 1

View File

@ -1,20 +0,0 @@
package com.gh.gamecenter.qa.answer.detail
import androidx.fragment.app.FragmentManager
class AnswerDetailFragmentStatePagerAdapter(
fm: FragmentManager,
private val mCreateNewAnswerDetailFragment: (answerId: String, position: Int) -> AnswerDetailFragment
) : androidx.fragment.app.FragmentStatePagerAdapter(fm) {
var answerIdList = arrayListOf<String>()
override fun getItem(position: Int): androidx.fragment.app.Fragment {
return mCreateNewAnswerDetailFragment.invoke(answerIdList[position], position)
}
override fun getCount(): Int {
return answerIdList.size
}
}

View File

@ -1,18 +0,0 @@
package com.gh.gamecenter.qa.answer.draft
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.constant.EntranceConsts
class AnswerDraftActivity : ToolBarActivity() {
companion object {
fun getIntent(context: Context, answerId: String? = null): Intent {
val bundle = Bundle()
bundle.putString(EntranceConsts.KEY_ANSWER_ID, answerId)
return getTargetIntent(context, AnswerDraftActivity::class.java, AnswerDraftFragment::class.java, bundle)
}
}
}

View File

@ -1,189 +0,0 @@
package com.gh.gamecenter.qa.answer.draft;
import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.gamecenter.common.callback.OnListClickListener;
import com.gh.gamecenter.common.constant.ItemViewType;
import com.gh.gamecenter.common.utils.DialogHelper;
import com.gh.gamecenter.common.utils.ImageUtils;
import com.gh.gamecenter.common.utils.PermissionHelper;
import com.gh.gamecenter.R;
import com.gh.gamecenter.common.viewholder.FooterViewHolder;
import com.gh.gamecenter.common.baselist.ListAdapter;
import com.gh.gamecenter.common.baselist.ListViewModel;
import com.gh.gamecenter.common.baselist.LoadType;
import com.gh.gamecenter.databinding.AnswerDraftItemBinding;
import com.gh.gamecenter.login.user.UserManager;
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity;
import com.gh.gamecenter.feature.entity.AnswerEntity;
import com.gh.gamecenter.qa.myqa.AnswerDraftViewHolder;
import com.gh.gamecenter.common.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.lightgame.utils.Utils;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import retrofit2.HttpException;
/**
* Created by khy on 20/12/17.
*/
class AnswerDraftAdapter extends ListAdapter<AnswerEntity> {
private OnListClickListener mListClickListener;
private ListViewModel mListViewModel;
AnswerDraftAdapter(Context context,
OnListClickListener listClickListener,
ListViewModel longClickListener) {
super(context);
mListClickListener = listClickListener;
mListViewModel = longClickListener;
}
@Override
protected boolean areItemsTheSame(AnswerEntity oldItem, AnswerEntity newItem) {
return !TextUtils.isEmpty(oldItem.getId()) && oldItem.getId().equals(newItem.getId());
}
@Override
protected boolean areContentsTheSame(AnswerEntity oldItem, AnswerEntity newItem) {
return oldItem == newItem;
}
@Override
protected void setListData(List<AnswerEntity> updateData) {
if (updateData != null && mEntityList != null && updateData.size() == mEntityList.size()) {
mEntityList = new ArrayList<>(updateData);
notifyDataSetChanged();
return;
}
super.setListData(updateData);
}
@Override
public int getItemViewType(int position) {
if (position == getItemCount() - 1) return ItemViewType.ITEM_FOOTER;
return ItemViewType.ITEM_BODY;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case ItemViewType.ITEM_FOOTER:
view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false);
return new FooterViewHolder(view, mListClickListener);
case ItemViewType.ITEM_BODY:
view = mLayoutInflater.inflate(R.layout.answer_draft_item, parent, false);
return new AnswerDraftViewHolder(AnswerDraftItemBinding.bind(view));
default:
return null;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case ItemViewType.ITEM_BODY:
AnswerDraftViewHolder draftViewHolder = (AnswerDraftViewHolder) holder;
AnswerEntity answerEntity = mEntityList.get(position);
AnswerDraftItemBinding binding = draftViewHolder.getBinding();
SimpleDraweeView img = binding.answerDraftItemImg;
binding.answerDraftItemTitle.setText(answerEntity.getQuestions().getTitle());
binding.answerDraftItemContent.setText(answerEntity.getBrief());
binding.answerDraftItemCommunityName.setText(answerEntity.getCommunityName());
List<String> images = answerEntity.getImages();
if (images.size() > 0) {
for (int i = 0; i < images.size(); i++) {
if (!images.get(i).contains(".gif")) {
img.setVisibility(View.VISIBLE);
ImageUtils.display(img, images.get(i));
break;
}
if (i == images.size() - 1) {
img.setVisibility(View.GONE);
}
}
} else {
img.setVisibility(View.GONE);
}
binding.answerDraftItemDelete.setOnClickListener(v -> {
DialogHelper.showDialog(mContext, "警告", "确定要删除回答草稿吗?删除之后不可恢复", "确定", "取消", () -> deleteAnswerDraft(answerEntity), () -> {
}, false, "", "");
});
draftViewHolder.itemView.setOnClickListener(v -> {
PermissionHelper.checkStoragePermissionBeforeAction(
mContext, "", "", "", "",
() -> {
if (mContext instanceof AnswerDraftActivity) {
// 不需要回传任何数据
((AnswerDraftActivity) mContext).setResult(Activity.RESULT_OK);
((AnswerDraftActivity) mContext).finish();
} else if (answerEntity.getAnswerId().isEmpty()) {
mContext.startActivity(AnswerEditActivity.Companion.getIntent(
mContext,
answerEntity.getQuestions(),
answerEntity.getId(),
true,
answerEntity.getCommunityName()));
} else {
mContext.startActivity(AnswerEditActivity.Companion.getIntent(
mContext,
answerEntity.getAnswerId(),
answerEntity.getQuestions(),
"",// 会自动获取草稿所以该数据可以不填
answerEntity.getCommunityName(),
true,
true));
}
});
});
break;
case ItemViewType.ITEM_FOOTER:
FooterViewHolder footerViewHolder = (FooterViewHolder) holder;
footerViewHolder.initItemPadding();
footerViewHolder.initFooterViewHolder(mListViewModel, mIsLoading, mIsNetworkError, mIsOver);
break;
}
}
@Override
public int getItemCount() {
return mEntityList == null || mEntityList.isEmpty() ? 0 : mEntityList.size() + FOOTER_ITEM_COUNT;
}
private void deleteAnswerDraft(AnswerEntity entity) {
RetrofitManager.getInstance()
.getApi()
.deleteAnswerDrafts(UserManager.getInstance().getUserId(), entity.getId())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<ResponseBody>() {
@Override
public void onResponse(ResponseBody response) {
mListViewModel.load(LoadType.REFRESH);
}
@Override
public void onFailure(HttpException e) {
Utils.toast(mContext, R.string.loading_network_error);
}
});
}
}

View File

@ -1,97 +0,0 @@
package com.gh.gamecenter.qa.answer.draft;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.gh.gamecenter.common.constant.EntranceConsts;
import com.gh.gamecenter.core.utils.UrlFilterUtils;
import com.gh.gamecenter.common.view.CustomDividerItemDecoration;
import com.gh.gamecenter.R;
import com.gh.gamecenter.common.baselist.ListAdapter;
import com.gh.gamecenter.common.baselist.ListFragment;
import com.gh.gamecenter.common.baselist.LoadType;
import com.gh.gamecenter.common.baselist.NormalListViewModel;
import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.login.user.UserManager;
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity;
import com.gh.gamecenter.feature.entity.AnswerEntity;
import com.gh.gamecenter.retrofit.RetrofitManager;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import io.reactivex.Observable;
/**
* Created by khy on 20/12/17.
*/
public class AnswerDraftFragment extends ListFragment<AnswerEntity, NormalListViewModel> {
private AnswerDraftAdapter mAdapter;
@Nullable
private String mAnswerId;
public static AnswerDraftFragment getInstance(String entrance) {
AnswerDraftFragment fragment = new AnswerDraftFragment();
Bundle args = new Bundle();
args.putString(EntranceConsts.KEY_ENTRANCE, entrance);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
Bundle arguments = getArguments();
if (arguments != null) {
mAnswerId = arguments.getString(EntranceConsts.KEY_ANSWER_ID);
}
super.onCreate(savedInstanceState);
if (getActivity() instanceof AnswerDraftActivity) {
setNavigationTitle("回答草稿");
}
}
@Override
protected ListAdapter provideListAdapter() {
return mAdapter == null ? mAdapter = new AnswerDraftAdapter(getContext(),
this,
mListViewModel) : mAdapter;
}
@Override
protected RecyclerView.ItemDecoration getItemDecoration() {
Drawable insetDivider = ContextCompat.getDrawable(requireContext(), R.drawable.divider_item_line_space_16);
CustomDividerItemDecoration itemDecoration = new CustomDividerItemDecoration(requireContext(), false, false, true, false);
if (insetDivider != null) {
itemDecoration.setDrawable(insetDivider);
}
return itemDecoration;
}
@Override
public Observable<List<AnswerEntity>> provideDataObservable(int page) {
return RetrofitManager.getInstance().getApi().getAnswerDrafts(
UserManager.getInstance().getUserId(),
UrlFilterUtils.getFilterQuery("answer_id", mAnswerId),
page);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBReuse reuse) {
if (AnswerEditActivity.ANSWER_DRAFT_CHANGE_TAG.equals(reuse.getType())) {
mListRv.scrollToPosition(0);
mBaseHandler.postDelayed(() -> mListViewModel.load(LoadType.REFRESH), 100);
}
}
}

View File

@ -1,573 +0,0 @@
package com.gh.gamecenter.qa.answer.edit
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Message
import android.text.TextUtils
import android.view.Gravity
import android.view.MenuItem
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.base.BaseRichEditorActivity
import com.gh.common.util.*
import com.gh.gamecenter.ImageViewerActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.NotificationUgc
import com.gh.gamecenter.common.mvvm.Status
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.DrawableView
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.databinding.FragmentAnswerEditBinding
import com.gh.gamecenter.feature.entity.Questions
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
import com.gh.gamecenter.qa.answer.draft.AnswerDraftActivity
import com.gh.gamecenter.video.VideoVerifyItemViewHolder
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
import com.halo.assistant.HaloApp
import org.json.JSONObject
/**
* Created by khy on 10/04/18.
*/
@Deprecated("V5.0废弃")
class AnswerEditActivity : BaseRichEditorActivity<AnswerEditViewModel>(), KeyboardHeightObserver {
private lateinit var mMenuDraft: MenuItem
private lateinit var mMenuPost: MenuItem
private lateinit var mBinding: FragmentAnswerEditBinding
private var mProcessingDialog: WaitingDialogFragment? = null
private var mUploadImageCancelDialog: DialogHelper.DialogAlertDefaultBindingWrapper? = null
private var mCommunityName: String? = null
private var mOpenAnswerInNewPage: Boolean = false
private var mImageViewList: ArrayList<SimpleDraweeView>? = null
override fun mtaEventName(): String {
return "回答详情" // issues 定的就是回答详情
}
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
if (msg.what == AUTO_SAVE_DRAFT) {
saveDraft(false)
mBaseHandler.sendEmptyMessageDelayed(AUTO_SAVE_DRAFT, SAVE_DRAFTS_INTERVAL_TIME.toLong())
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == ANSWER_DRAFT_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
mViewModel.getUserAnswerDrafts()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setToolbarMenu(R.menu.menu_answer_post)
mMenuDraft = mToolbar.menu.findItem(R.id.menu_draft)
mMenuPost = mToolbar.menu.findItem(R.id.menu_answer_post)
mCommunityName = intent?.getStringExtra(EntranceConsts.KEY_COMMUNITY_NAME)
mOpenAnswerInNewPage = intent?.getBooleanExtra(EntranceConsts.KEY_ANSWER_OPEN_IN_NEW_PAGE, false)!!
mBinding = FragmentAnswerEditBinding.bind(mContentView)
onClickView()
addObserver()
initQuestionContent()
if (TextUtils.isEmpty(mViewModel.answerId)) {
mBaseHandler.sendEmptyMessageDelayed(AUTO_SAVE_DRAFT, SAVE_DRAFTS_INTERVAL_TIME.toLong()) // 启动自动保存草稿
}
mRichEditor.setOnTextChangeListener { t ->
mBinding.appBar.setExpanded(false, true)
mBinding.answerPlaceholder.visibility =
if (t.contains("<img src") || !TextUtils.isEmpty(mRichEditor.text)) {
View.GONE
} else View.VISIBLE
checkPostButtonEnable()
}
mRichEditor.setOnInitialLoadListener { isReady ->
if (isReady) {
requestFocusAndMoveCursorToEnd()
}
}
if (!TextUtils.isEmpty(mViewModel.answerId)) {
setNavigationTitle(getString(R.string.answer_patch_title))
mViewModel.cacheAnswerContent = mViewModel.answerContent
mMenuDraft.isVisible = true
if (intent.getBooleanExtra(EntranceConsts.KEY_SHOW_EDIT_DRAFT, false)) {
mViewModel.getUserAnswerDrafts()
} else {
mRichEditor.setHtml(mViewModel.answerContent, false)
}
} else {
setNavigationTitle(getString(R.string.answer_edit_title))
mViewModel.getUserAnswerDrafts()
mMenuDraft.isVisible = false
}
checkPostButtonEnable()
mImageViewList = arrayListOf(
findViewById(R.id.question_images_1),
findViewById(R.id.question_images_2),
findViewById(R.id.question_images_3)
)
}
override fun provideViewModel(): AnswerEditViewModel {
val factory = AnswerEditViewModel.Factory(
HaloApp.getInstance().application,
intent?.getStringExtra(EntranceConsts.KEY_ANSWER_ID),
intent?.getStringExtra(EntranceConsts.KEY_ANSWER_CONTENT),
intent?.getStringExtra(EntranceConsts.KEY_DRAFT_ID),
intent?.getParcelableExtra(Questions::class.java.simpleName) ?: Questions()
)
mViewModel = ViewModelProviders.of(this, factory).get(AnswerEditViewModel::class.java)
return mViewModel
}
override fun getLayoutId(): Int {
return R.layout.fragment_answer_edit
}
override fun onKeyboardHeightChanged(height: Int, orientation: Int) {
super.onKeyboardHeightChanged(height, orientation)
if (height > 0) mBinding.appBar.setExpanded(false, true)
}
override fun onMenuItemClick(item: MenuItem?): Boolean {
if (item?.itemId == R.id.menu_answer_post && !ClickUtils.isFastDoubleClick(R.id.menu_answer_post, 5000)) {
readyPost()
} else if (item?.itemId == R.id.menu_draft) {
startActivityForResult(AnswerDraftActivity.getIntent(this, mViewModel.answerId), ANSWER_DRAFT_REQUEST_CODE)
}
return super.onMenuItemClick(item)
}
private fun addObserver() {
mViewModel.postLiveData.observeNonNull(this) {
if (it.status == Status.SUCCESS) {
MtaHelper.onEvent("发表答案", "提交成功", mCommunityName)
if (mViewModel.checkIsAllUploadedAndToast()) {
toast("发布成功")
}
var answerId: String? = null
tryWithDefaultCatch {
answerId = JSONObject(it.data).getString("_id")
}
if (answerId == null) {
answerId = mViewModel.answerId
}
val data = Intent()
data.putExtra(EntranceConsts.KEY_ANSWER_CONTENT, getReplaceRealContent())
data.putExtra(EntranceConsts.KEY_ANSWER_ID, answerId ?: mViewModel.answerId)
setResult(Activity.RESULT_OK, data)
if (mOpenAnswerInNewPage) {
val intent = AnswerDetailActivity
.getIntent(this, answerId, mEntrance, "编辑答案")
startActivity(intent)
}
finish()
AppExecutor.uiExecutor.executeWithDelay(Runnable {
NotificationHelper.showNotificationHintDialog(NotificationUgc.ANSWER)
}, 1000)
} else if (it.status == Status.ERROR) {
val errorString = it.exception?.response()?.errorBody()?.string()
ErrorHelper.handleErrorWithCustomizedHandler(this, errorString, customizedHandler = { code ->
when (code) {
403037 -> consume {
if (TextUtils.isEmpty(mViewModel.draftId)) {
DialogHelper.showDialog(this, "发布失败", "问题已被删除,无法发布回答", "好吧", "", { finish() })
} else {
DialogHelper.showDialog(this,
"发布失败",
"问题已被删除,需要删除草稿吗?",
"删除草稿",
"暂不",
{
mViewModel.deleteAnswerDraft()
finish()
})
}
}
else -> false
}
})
}
}
mViewModel.processDialog.observeNonNull(this) {
if (it.isShow) {
if (mProcessingDialog?.dialog?.isShowing == true) {
mProcessingDialog?.uploadWaitingHint(it.msg)
} else {
mProcessingDialog = WaitingDialogFragment.newInstance(it.msg, false)
mProcessingDialog?.show(supportFragmentManager, null) {
if (mViewModel.uploadImageSubscription != null && !mViewModel.uploadImageSubscription!!.isDisposed) {
mUploadImageCancelDialog = DialogHelper.showDialog(
this, "提示", "图片正在上传中,确定取消吗?",
"确定", "取消", {
mViewModel.uploadImageSubscription?.dispose()
mUploadImageCancelDialog?.dismiss()
mProcessingDialog?.dismiss()
}, extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
)
}
}
}
} else {
mUploadImageCancelDialog?.dismiss()
mProcessingDialog?.dismiss()
}
}
mViewModel.deleteDraftLiveDate.observe(this, Observer {
if (it == true) {
setResult(Activity.RESULT_OK)
finish()
}
})
mViewModel.draftsLiveData.observe(this, Observer {
mRichEditor.setHtml(it, false)
requestFocusAndMoveCursorToEnd()
checkPostButtonEnable()
})
mViewModel.saveDraftsLiveData.observeNonNull(this) {
if (it) {
val data = Intent()
data.putExtra(EntranceConsts.KEY_ANSWER_CONTENT, getReplaceRealContent())
setResult(SAVE_DRAFTS, data)
finish()
} else {
showDraftFailureDialog()
}
}
}
private fun requestFocusAndMoveCursorToEnd() {
try {
mRichEditor.scrollTo(0, 10000000)
mRichEditor.postDelayed({
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(mRichEditor, InputMethodManager.SHOW_IMPLICIT)
mRichEditor.focusEditor()
}, 400)
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun initQuestionContent() {
val question = mViewModel.question
question.title = HtmlUtils.filterHtmlLabel(question.title)
val video = if (!question.videos.isNullOrEmpty()) question.videos[0] else null
val videoSize = if (video != null) 1 else 0
mBinding.answerPlaceholder.text =
if (!question.description.isNullOrEmpty() || question.images.size > 0 || question.videos.isNotEmpty()) {
"请撰写回答(下拉查看问题详情)..."
} else "请撰写回答..."
mBinding.appBar.setExpanded(false)
mBinding.questionTitle.text = question.title
mBinding.questionDes.initWidth(resources.displayMetrics.widthPixels - 40F.dip2px())
mBinding.questionDes.maxLines = 3
mBinding.questionDes.setOriginalText(question.description)
mBinding.questionDes.goneIf(question.description.isNullOrEmpty())
mBinding.videoPlay.visibleIf(video != null)
mBinding.videoStatus.visibleIf(video != null && video.status != "pass")
mBinding.videoDuration.visibleIf(video?.status == "pass")
if (video?.status == "pass") {
mBinding.videoDuration.background = DrawableView.getOvalDrawable(R.color.black_alpha_50, 999f)
mBinding.videoDuration.text = video.duration
} else {
val status = if (!question.me.isContentOwner && !question.me.isModerator && video?.status == "fail") {
"pending"
} else video?.status ?: ""
VideoVerifyItemViewHolder.setVideoStatus(mBinding.videoStatus, status)
}
if (video != null) {
if (video.status == "pass") {
mBinding.questionImages1.display(video.poster)
} else {
mBinding.questionImages1.setImageResource(R.drawable.community_video_default_poster)
}
}
question.images.let { images ->
for (i in images.indices) {
val index = i + videoSize // view index
val position = index - videoSize // data index
if (images.size > position) {
when (index) {
0 -> ImageUtils.display(mBinding.questionImages1, images[position])
1 -> ImageUtils.display(mBinding.questionImages2, images[position])
2 -> {
ImageUtils.display(mBinding.questionImages3, images[position])
if (images.size + videoSize > 3) {
mBinding.questionImages3Mask.visibility = View.VISIBLE
mBinding.questionImages3Desc.visibility = View.VISIBLE
mBinding.questionImages3Desc.text = "+${images.size + videoSize - 3}"
}
}
}
}
}
mBinding.questionImagesContainer.visibility = if (images.size + videoSize > 0) {
View.VISIBLE
} else View.GONE
}
}
private fun readyPost() {
ifLogin("回答编辑-提交") {
mRichEditor.hideLinkStyle()
mRichEditor.postDelayed({
val answerContent = getReplaceRealContent()
mRichEditor.showLinkStyle()
if (mRichEditor.hasPlaceholderImage()) {
ToastUtils.showToast("图片上传ing")
return@postDelayed
}
if (checkData(answerContent)) {
mViewModel.postAnswer(answerContent)
}
}, 100)
}
}
private fun checkData(answerContent: String, isShowToast: Boolean = true): Boolean {
val answerLength = HtmlUtils.stripHtml(answerContent).length
if (answerLength < MIN_ANSWER_TEXT_LENGTH) {
if (isShowToast) ToastUtils.showToast(
getString(R.string.answer_beneath_length_limit),
if (mIsKeyBoardShow) Gravity.CENTER else -1
)
return false
} else if (answerLength > MAX_ANSWER_TEXT_LENGTH) {
if (isShowToast) ToastUtils.showToast("回答最多输入10000个字", if (mIsKeyBoardShow) Gravity.CENTER else -1)
return false
}
return true
}
private fun getReplaceRealContent(): String {
var answerContent = mRichEditor.html
for (s in mViewModel.mapImages.keys) {
val netUrl = mViewModel.mapImages[s]
if (netUrl != null) {
answerContent = answerContent.replace(FILE_HOST + s, netUrl)
}
}
return answerContent
}
private fun checkPostButtonEnable() {
val answerContent = getReplaceRealContent()
val isEnabled = checkData(answerContent, false)
mMenuPost.actionView?.alpha = if (isEnabled) 1f else 0.6f
}
override fun handleBackPressed(): Boolean {
return if (TextUtils.isEmpty(UserManager.getInstance().token)) {
false
} else if (!TextUtils.isEmpty(mViewModel.answerId)
&& TextUtils.isEmpty(mRichEditor.text)
&& !mRichEditor.html.contains("<img src")
)
false
else if (!TextUtils.isEmpty(mViewModel.answerId)) {
consume { showPatchBackDialog() }
} else if (TextUtils.isEmpty(mViewModel.answerId)
&& !TextUtils.isEmpty(mViewModel.cacheAnswerContent)
&& !mRichEditor.html.contains("<img src")
&& TextUtils.isEmpty(mRichEditor.text)
) {
consume {
DialogHelper.showDialog(this, "提示", "当前内容为空,退出即会删除该草稿,确定退出吗?", "确定", "取消", {
mViewModel.deleteAnswerDraft()
})
}
} else if (!TextUtils.isEmpty(mViewModel.cacheAnswerContent)
&& mViewModel.cacheAnswerContent == mRichEditor.html
) {
false
} else {
consume { saveDraft(true) }
}
}
override fun onDestroy() {
mProcessingDialog?.dismissAllowingStateLoss()
mProcessingDialog = null
super.onDestroy()
}
private fun showDraftFailureDialog() {
DialogHelper.showDialog(this, "提示", "确定退出?已撰写的内容将会丢失?", "继续撰写", "退出", cancelClickCallback = { finish() })
}
private fun showPatchBackDialog() {
DialogHelper.showDialog(this, "提示", "是否保存修改内容用于下次编辑?", "保存并退出", "不保存", { saveDraft(true) }, { finish() })
}
/**
* [forcedExit] -> 强行退出当前页面,不考虑接口请求成功与否
*/
private fun saveDraft(forcedExit: Boolean) {
val editContent = getReplaceRealContent()
if (mRichEditor.hasPlaceholderImage()) return
if (TextUtils.isEmpty(UserManager.getInstance().token)) {
return
} else if (forcedExit && TextUtils.isEmpty(editContent)) {
finish()
return
} else if (!forcedExit && TextUtils.isEmpty(editContent)) {
return
}
mViewModel.saveAnswerDrafts(editContent, forcedExit)
}
private fun onClickView() {
val videoSize = if (!mViewModel.question.videos.isNullOrEmpty()) 1 else 0
mBinding.questionImages1.setOnClickListener {
val question = mViewModel.question
if (!question.videos.isNullOrEmpty()) {
val videoEntity = question.videos[0]
if (videoEntity.status == "pass") {
DirectUtils.directToVideoDetail(
this,
videoEntity.id,
VideoDetailContainerViewModel.Location.SINGLE_VIDEO.value,
path = "回答详情"
)
} else if (videoEntity.status == "pending" ||
(!question.me.isContentOwner
&& !question.me.isModerator
&& videoEntity.status == "fail")
) {
toast("视频正在审核中")
} else if (videoEntity.status == "fail") {
toast("视频审核未通过")
}
} else {
showQuestionImageDetail(0)
}
}
mBinding.questionImages2.setOnClickListener {
showQuestionImageDetail(1 - videoSize)
}
mBinding.questionImages3.setOnClickListener {
showQuestionImageDetail(2 - videoSize)
}
}
private fun showQuestionImageDetail(position: Int) {
val images = ArrayList(mViewModel.question.images)
if (position <= images.size) {
val intent = ImageViewerActivity.getIntent(this, images, position, mImageViewList, "$mEntrance+(回答编辑)")
startActivity(intent)
}
}
override fun getVideoGuideKey(): String = ""
companion object {
const val SAVE_DRAFTS = 110
const val AUTO_SAVE_DRAFT = 1
const val SAVE_DRAFTS_INTERVAL_TIME = 15000
const val SAVE_DRAFTS_TOAST_COUNT = 3
const val MIN_ANSWER_TEXT_LENGTH = 6
const val MAX_ANSWER_TEXT_LENGTH = 10000
const val ANSWER_DRAFT_REQUEST_CODE = 112
const val ANSWER_DRAFT_CHANGE_TAG = "ANSWER_DRAFT_CHANGE_TAG"
/**
* 撰写回答
*/
fun getIntent(
context: Context,
question: Questions?,
showInNewPage: Boolean?,
communityName: String?,
showHintBackground: Boolean = false
): Intent {
val intent = Intent(context, AnswerEditActivity::class.java)
intent.putExtra(EntranceConsts.KEY_ANSWER_OPEN_IN_NEW_PAGE, showInNewPage)
intent.putExtra(EntranceConsts.KEY_COMMUNITY_NAME, communityName)
intent.putExtra(EntranceConsts.KEY_HINT, showHintBackground)
intent.putExtra(Questions::class.java.simpleName, question)
return intent
}
/**
* 撰写回答(存在回答草稿)
*/
fun getIntent(
context: Context,
question: Questions?,
draftId: String?,
showInNewPage: Boolean?,
communityName: String?
): Intent {
val intent = Intent(context, AnswerEditActivity::class.java)
intent.putExtra(EntranceConsts.KEY_ANSWER_OPEN_IN_NEW_PAGE, showInNewPage)
intent.putExtra(EntranceConsts.KEY_DRAFT_ID, draftId)
intent.putExtra(EntranceConsts.KEY_COMMUNITY_NAME, communityName)
intent.putExtra(Questions::class.java.simpleName, question)
return intent
}
/**
* 撰写回答
*/
fun getIntent(context: Context, question: Questions?, communityName: String?): Intent {
val intent = Intent(context, AnswerEditActivity::class.java)
intent.putExtra(EntranceConsts.KEY_COMMUNITY_NAME, communityName)
intent.putExtra(Questions::class.java.simpleName, question)
return intent
}
/**
* 修改回答
*/
fun getIntent(
context: Context,
answerId: String?,
question: Questions?,
content: String?,
communityName: String?,
showEditDraft: Boolean = false,
showInNewPage: Boolean = false
): Intent {
val intent = Intent(context, AnswerEditActivity::class.java)
intent.putExtra(EntranceConsts.KEY_ANSWER_ID, answerId)
intent.putExtra(EntranceConsts.KEY_ANSWER_CONTENT, content)
intent.putExtra(EntranceConsts.KEY_COMMUNITY_NAME, communityName)
intent.putExtra(EntranceConsts.KEY_SHOW_EDIT_DRAFT, showEditDraft)
intent.putExtra(Questions::class.java.simpleName, question)
intent.putExtra(EntranceConsts.KEY_ANSWER_OPEN_IN_NEW_PAGE, showInNewPage)
return intent
}
}
}

View File

@ -1,212 +0,0 @@
package com.gh.gamecenter.qa.answer.edit
import android.app.Application
import android.text.TextUtils
import androidx.lifecycle.*
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.common.syncpage.SyncDataEntity
import com.gh.gamecenter.common.syncpage.SyncFieldConstants
import com.gh.gamecenter.common.syncpage.SyncPageRepository
import com.gh.gamecenter.R
import com.gh.gamecenter.common.eventbus.EBReuse
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.common.mvvm.Resource
import com.gh.base.BaseRichEditorViewModel
import com.gh.base.RichType
import com.gh.gamecenter.common.utils.tryWithDefaultCatch
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.qa.entity.AnswerDraftEntity
import com.gh.gamecenter.feature.entity.Questions
import com.gh.gamecenter.common.retrofit.Response
import com.lightgame.utils.Utils
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import okhttp3.ResponseBody
import okhttp3.internal.http.RealResponseBody
import org.greenrobot.eventbus.EventBus
import org.json.JSONException
import org.json.JSONObject
import retrofit2.HttpException
@Deprecated("V5.0废弃")
class AnswerEditViewModel(
application: Application,
var answerId: String?, // 以mAnswerId为标识如果mAnswerId不为空则是-修改答案(不需要保存草稿) 为空则是-编写答案
var answerContent: String?,
var draftId: String?,
var question: Questions
) : BaseRichEditorViewModel(application) {
private var mPostDraftsCount: Int = 0
var cacheAnswerContent: String? = null
val postLiveData = MediatorLiveData<Resource<String>>()
val deleteDraftLiveDate = MediatorLiveData<Boolean>()
val draftsLiveData = MediatorLiveData<String>()
val saveDraftsLiveData = MediatorLiveData<Boolean>() // 自动保存不会回调
fun postAnswer(editContent: String) {
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
val content = JSONObject()
try {
content.put("content", editContent)
} catch (e: Throwable) {
e.printStackTrace()
}
val body = RequestBody.create(MediaType.parse("application/json"), content.toString())
val observable = if (!TextUtils.isEmpty(answerId)) {
if (editContent == answerContent) { // 内容不变不需要请求服务器,直接返回成功即可
val responseBody = RealResponseBody("", 0, null)
Single.just<ResponseBody>(responseBody).toObservable()
} else {
mApi.patchQuestionAnswer(body, answerId)
}
} else {
mApi.postQuestionAnswer(body, question.id)
}
observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false))
val data = response?.string()
postLiveData.postValue(Resource.success(data))
EventBus.getDefault().post(EBReuse(AnswerEditActivity.ANSWER_DRAFT_CHANGE_TAG))
if (TextUtils.isEmpty(answerId)) {
syncAnswerCount()
}
}
override fun onFailure(e: HttpException?) {
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", false))
postLiveData.postValue(Resource.error(e))
}
})
}
private fun syncAnswerCount() {
SyncPageRepository.postSyncData(
SyncDataEntity(
question.id,
SyncFieldConstants.ANSWER_COUNT,
++question.answerCount,
checkInherited = true,
checkFieldEntity = true
)
)
}
fun deleteAnswerDraft() {
if (draftId.isNullOrEmpty()) {
deleteDraftLiveDate.postValue(true)
return
}
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("删除中...", true))
mApi
.deleteAnswerDrafts(UserManager.getInstance().userId, draftId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("删除中...", false))
deleteDraftLiveDate.postValue(true)
EventBus.getDefault().post(EBReuse(AnswerEditActivity.ANSWER_DRAFT_CHANGE_TAG))
}
override fun onFailure(e: HttpException?) {
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("删除中...", false))
deleteDraftLiveDate.postValue(false)
Utils.toast(getApplication(), R.string.loading_network_error)
}
})
}
fun getUserAnswerDrafts() {
mApi
.getUserAnswerDrafts(
question.id,
UrlFilterUtils.getFilterQuery("answer_id", answerId),
Utils.getTime(getApplication())
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<AnswerDraftEntity>() {
override fun onResponse(draft: AnswerDraftEntity?) {
if (draft?.content != null) {
draftsLiveData.postValue(draft.content)
cacheAnswerContent = draft.content
}
draftId = draft?.id
if (!TextUtils.isEmpty(draft?.answerId)) { // answerId不为空 表示已经提交过答案了
answerId = draft?.answerId
}
}
})
}
fun saveAnswerDrafts(editContent: String, forcedExit: Boolean) {
val content = JSONObject()
try {
content.put("content", editContent)
content.put("question_id", question.id)
if (!answerId.isNullOrEmpty()) {
content.put("answer_id", answerId)
}
} catch (e: JSONException) {
e.printStackTrace()
}
val body = RequestBody.create(MediaType.parse("application/json"), content.toString())
mApi
.postAnswerDrafts(body, UserManager.getInstance().userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
super.onResponse(response)
if (forcedExit) {
saveDraftsLiveData.postValue(true)
if (checkIsAllUploadedAndToast()) {
Utils.toast(getApplication(), "回答已保存到草稿箱")
}
EventBus.getDefault().post(EBReuse(AnswerEditActivity.ANSWER_DRAFT_CHANGE_TAG))
} else {
if (mPostDraftsCount >= AnswerEditActivity.SAVE_DRAFTS_TOAST_COUNT) {
mPostDraftsCount = 0
Utils.toast(getApplication(), "回答已保存到草稿箱")
} else {
mPostDraftsCount++
}
cacheAnswerContent = editContent
}
}
override fun onFailure(e: HttpException?) {
super.onFailure(e)
if (forcedExit) saveDraftsLiveData.postValue(false)
}
})
}
override fun getRichType(): RichType = RichType.ANSWER
class Factory(
private val mApplication: Application,
private val answerId: String?,
private val answerContent: String?,
private val draftId: String?,
private val question: Questions
) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return AnswerEditViewModel(mApplication, answerId, answerContent, draftId, question) as T
}
}
}

View File

@ -1,23 +0,0 @@
package com.gh.gamecenter.qa.article
import android.content.Context
import android.content.Intent
import android.os.Bundle
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.constant.EntranceConsts
class MyArticleActivity : ToolBarActivity() {
companion object {
const val PUBLISH_ARTICLE_REQUEST_CODE = 102
@JvmStatic
fun getIntent(context: Context, userId: String, entrance: String, path: String): Intent {
val bundle = Bundle()
bundle.putString(EntranceConsts.KEY_USER_ID, userId)
bundle.putString(EntranceConsts.KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
return getTargetIntent(context, MyArticleActivity::class.java, MyArticleFragment::class.java, bundle)
}
}
}

View File

@ -1,100 +0,0 @@
package com.gh.gamecenter.qa.article
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.constant.ItemViewType
import com.gh.gamecenter.common.syncpage.ISyncAdapterHandler
import com.gh.gamecenter.R
import com.gh.gamecenter.common.viewholder.FooterViewHolder
import com.gh.gamecenter.common.baselist.ListAdapter
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.databinding.CommunityAnswerItemBinding
import com.gh.gamecenter.forum.home.ForumArticleAskItemViewHolder
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
import com.gh.gamecenter.feature.entity.ArticleEntity
import com.gh.gamecenter.qa.questions.newdetail.NewQuestionDetailActivity
class MyArticleAdapter(
context: Context,
private val mEntrance: String,
private val mPath: String
) : ListAdapter<ArticleEntity>(context), ISyncAdapterHandler {
override fun getItemViewType(position: Int): Int {
if (position == itemCount - 1) {
return ItemViewType.ITEM_FOOTER
}
return ItemViewType.ITEM_BODY
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view: View
return when (viewType) {
ItemViewType.ITEM_FOOTER -> {
view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)
FooterViewHolder(view)
}
else -> {
view = mLayoutInflater.inflate(R.layout.community_answer_item, parent, false)
ForumArticleAskItemViewHolder(CommunityAnswerItemBinding.bind(view))
}
}
}
override fun getItemCount(): Int {
return if (mEntityList.size == 0) 0 else mEntityList.size + 1
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is ForumArticleAskItemViewHolder) {
val entity = mEntityList[position]
holder.bindForumArticleItem(entity, mEntrance, mPath, position)
holder.binding.run {
userIcon.visibility = View.GONE
userName.visibility = View.GONE
userBadgeIcon.visibility = View.GONE
userBadgeName.visibility = View.GONE
concernBtn.visibility = View.GONE
timeContainer.visibility = View.GONE
title.layoutParams = (title.layoutParams as ViewGroup.MarginLayoutParams).apply {
topMargin = 20F.dip2px()
}
}
holder.itemView.setOnClickListener {
if (entity.type == "question") {
mContext.startActivity(NewQuestionDetailActivity.getIntent(mContext, entity.id, mEntrance, mPath))
} else {
mContext.startActivity(
ArticleDetailActivity.getIntent(
mContext,
entity.community,
entity.id,
mEntrance,
mPath
)
)
}
}
} else if (holder is FooterViewHolder) {
holder.initFooterViewHolder(mIsLoading, mIsNetworkError, mIsOver)
holder.initItemPadding()
}
}
override fun areContentsTheSame(oldItem: ArticleEntity?, newItem: ArticleEntity?): Boolean {
return oldItem?.id == newItem?.id
}
override fun areItemsTheSame(oldItem: ArticleEntity?, newItem: ArticleEntity?): Boolean {
return oldItem == newItem
}
override fun getSyncData(position: Int): Pair<String, Any>? {
if (position >= mEntityList.size) return null
val entity = mEntityList[position]
return Pair(entity.id, entity)
}
}

View File

@ -1,139 +0,0 @@
package com.gh.gamecenter.qa.article
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.MenuItem
import android.view.View
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.R
import com.gh.gamecenter.common.baselist.ListFragment
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.baselist.NormalListViewModel
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.checkStoragePermissionBeforeAction
import com.gh.gamecenter.common.utils.ifLogin
import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.common.utils.toDrawable
import com.gh.gamecenter.common.view.CustomDividerItemDecoration
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.qa.article.edit.ArticleEditActivity
import com.gh.gamecenter.feature.entity.ArticleEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.Observable
class MyArticleFragment : ListFragment<ArticleEntity, NormalListViewModel<ArticleEntity>>() {
private var mTargetUserId = ""
private var mAdapter: MyArticleAdapter? = null
override fun provideListAdapter(): MyArticleAdapter {
if (mAdapter == null) {
val path = if (mTargetUserId == UserManager.getInstance().userId) {
"我的帖子"
} else {
"Ta的帖子"
}
mAdapter = MyArticleAdapter(requireContext(), mEntrance, path)
}
return mAdapter!!
}
override fun provideDataObservable(page: Int): Observable<MutableList<ArticleEntity>>? {
return RetrofitManager.getInstance().api.getMyArticleAndQuestion(mTargetUserId, page)
.flatMap { list ->
Observable.create { emitter ->
val articleList = list.map { it.transformArticleEntity() }.toMutableList()
emitter.onNext(articleList)
emitter.onComplete()
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == MyArticleActivity.PUBLISH_ARTICLE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
mListViewModel.load(LoadType.REFRESH)
}
}
override fun provideListViewModel(): NormalListViewModel<ArticleEntity> {
val factory = NormalListViewModel.Factory(HaloApp.getInstance().application, this)
return ViewModelProviders.of(this, factory)
.get(NormalListViewModel::class.java) as NormalListViewModel<ArticleEntity>
}
override fun onCreate(savedInstanceState: Bundle?) {
mTargetUserId = arguments?.getString(EntranceConsts.KEY_USER_ID) ?: ""
super.onCreate(savedInstanceState)
if (activity is MyArticleActivity) {
if (mTargetUserId == UserManager.getInstance().userId) {
setNavigationTitle("我的帖子")
initMenu(R.menu.menu_article_publich)
} else {
setNavigationTitle("Ta的帖子")
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mCachedView.setBackgroundColor(R.color.ui_surface.toColor(requireContext()))
}
override fun onMenuItemClick(item: MenuItem?) {
if (item?.itemId == R.id.menu_article_publish) {
ifLogin("个人主页-Ta的文章-发文章") {
checkStoragePermissionBeforeAction {
startActivityForResult(
ArticleEditActivity.getIntent(requireContext()),
MyArticleActivity.PUBLISH_ARTICLE_REQUEST_CODE
)
}
}
}
}
override fun addSyncPageObserver(): Boolean {
return true
}
override fun provideSyncAdapter(): MyArticleAdapter? {
return mAdapter
}
override fun getItemDecoration(): RecyclerView.ItemDecoration {
val itemDecoration = CustomDividerItemDecoration(
requireContext(),
onlyDecorateTheFirstItem = false,
notDecorateTheFirstItem = false,
notDecorateTheLastItem = true,
notDecorateTheFirstTwoItems = false
)
itemDecoration.setDrawable(R.drawable.divider_item_line_space_16.toDrawable(requireContext())!!)
return itemDecoration
}
override fun onDarkModeChanged() {
super.onDarkModeChanged()
if (mListRv != null && mListRv.itemDecorationCount > 0) {
mListRv.removeItemDecorationAt(0)
mListRv.addItemDecoration(itemDecoration)
}
}
companion object {
@JvmStatic
fun getInstance(entrance: String?, userId: String): MyArticleFragment {
val fragment = MyArticleFragment()
val args = Bundle()
args.putString(EntranceConsts.KEY_ENTRANCE, entrance)
args.putString(EntranceConsts.KEY_USER_ID, userId)
fragment.arguments = args
return fragment
}
}
}

View File

@ -32,7 +32,6 @@ import com.gh.gamecenter.feature.entity.ArticleDraftEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.qa.BbsType
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity
import com.gh.gamecenter.qa.article.draft.ArticleDraftActivity
import com.gh.gamecenter.qa.dialog.ChooseActivityDialogFragment
import com.gh.gamecenter.qa.dialog.ChooseForumActivity
@ -222,7 +221,7 @@ class ArticleEditActivity : BaseRichEditorActivity<ArticleEditViewModel>(), Keyb
SaveDraftType.AUTO -> {
if (pair.second) {
if (mPostDraftsCount >= AnswerEditActivity.SAVE_DRAFTS_TOAST_COUNT) {
if (mPostDraftsCount >= SAVE_DRAFTS_TOAST_COUNT) {
mPostDraftsCount = 0
Utils.toast(this, "帖子已保存到草稿箱")
} else {
@ -769,6 +768,7 @@ class ArticleEditActivity : BaseRichEditorActivity<ArticleEditViewModel>(), Keyb
companion object {
const val SAVE_DRAFTS_INTERVAL_TIME = 15000
const val ARTICLE_DRAFT_REQUEST_CODE = 105
const val SAVE_DRAFTS_TOAST_COUNT = 3
const val ARTICLE_DRAFT_CHANGE_TAG = "ANSWER_DRAFT_CHANGE_TAG"
const val ARTICLE_POSTED_TAG = "ARTICLE_POSTED_TAG"

View File

@ -16,7 +16,6 @@ import com.gh.gamecenter.core.utils.doOnEnd
import com.gh.gamecenter.databinding.ActivityCommentBinding
import com.gh.gamecenter.feature.entity.CommentEntity
import com.gh.gamecenter.gamecollection.detail.conversation.GameCollectionCommentConversationFragment
import com.gh.gamecenter.qa.answer.detail.AnswerDetailFragment
import com.gh.gamecenter.qa.comment.conversation.CommentConversationFragment
import com.lightgame.utils.Util_System_Keyboard
@ -54,7 +53,7 @@ class CommentActivity : BaseActivity() {
val useReplyApi: Boolean = intent.getBooleanExtra(USE_REPLY_API, false)
mShowInputOnly = intent.getBooleanExtra(SHOW_INPUT_ONLY, false)
val commentCallback = object : AnswerDetailFragment.CommentListener {
val commentCallback = object : CommentListener {
override fun onCountChange(count: Int) {
resultIntent.putExtra(COMMENT_COUNT, count)
setResult(Activity.RESULT_OK, resultIntent)
@ -466,4 +465,10 @@ class CommentActivity : BaseActivity() {
return intent
}
}
interface CommentListener {
fun onCountChange(count: Int)
fun onCommentDraftChange(draft: String)
fun onCommentSuccess(commentId: String)
}
}

View File

@ -38,7 +38,6 @@ 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.qa.answer.detail.AnswerDetailFragment
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
@ -95,7 +94,7 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
var mOffset: Int = 0
var mCommentCount: Int = 0
var mAdapter: ListAdapter<CommentEntity>? = null
var mCommentListener: AnswerDetailFragment.CommentListener? = null
var mCommentListener: CommentActivity.CommentListener? = null
private fun findView() {
commentContainer = mCachedView.findViewById(R.id.comment_container)
@ -357,7 +356,7 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
commentSendBtn.isEnabled = enable
}
fun setCommentListener(listener: AnswerDetailFragment.CommentListener) {
fun setCommentListener(listener: CommentActivity.CommentListener) {
mCommentListener = listener
}
@ -784,9 +783,8 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
showSoftKeyboardOnStartUp: Boolean,
commentCount: Int,
showInputOnly: Boolean,
listener: AnswerDetailFragment.CommentListener
)
: NewCommentFragment {
listener: CommentActivity.CommentListener
): NewCommentFragment {
return NewCommentFragment().apply {
mCommentListener = listener
with(
@ -809,7 +807,7 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
showInputOnly: Boolean,
useReplyApi: Boolean,
commentEntity: CommentEntity?,
listener: AnswerDetailFragment.CommentListener
listener: CommentActivity.CommentListener
)
: NewCommentFragment {
val commentType = if (useReplyApi) {
@ -841,7 +839,7 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
showInputOnly: Boolean,
useReplyApi: Boolean,
commentEntity: CommentEntity?,
listener: AnswerDetailFragment.CommentListener
listener: CommentActivity.CommentListener
)
: NewCommentFragment {
val commentType = if (useReplyApi) {
@ -874,7 +872,7 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
showInputOnly: Boolean,
isStairsComment: Boolean,
useReplyApi: Boolean,
listener: AnswerDetailFragment.CommentListener
listener: CommentActivity.CommentListener
)
: Fragment {
return if (isStairsComment) {
@ -927,7 +925,7 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
showInputOnly: Boolean,
useReplyApi: Boolean,
commentEntity: CommentEntity?,
listener: AnswerDetailFragment.CommentListener
listener: CommentActivity.CommentListener
)
: NewCommentFragment {
val commentType = if (useReplyApi) {

View File

@ -14,11 +14,7 @@ import com.gh.common.util.DirectUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.OnCommentCallBackListener
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.common.utils.FastClickUtils
import com.gh.gamecenter.common.utils.ImageUtils.display
import com.gh.gamecenter.common.utils.TextHelper
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.ifLogin
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.CenterImageSpan
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.NumberUtils.transSimpleCount
@ -56,7 +52,7 @@ class StairsCommentViewHolder(
}
if (entity.user.badge != null) {
binding.sdvUserBadge.visibility = View.VISIBLE
display(binding.sdvUserBadge, entity.user.badge!!.icon)
ImageUtils.display(binding.sdvUserBadge, entity.user.badge!!.icon)
} else {
binding.sdvUserBadge.visibility = View.GONE
}

View File

@ -52,7 +52,7 @@ public class AnswerViewHolder extends BaseRecyclerViewHolder<AnswerEntity> {
binding.askAnswerItemVotecount.setText(context.getString(R.string.ask_vote_count, NumberUtils.transSimpleCount(entity.getVote())));
UserEntity user = entity.getUser();
binding.askAnswerItemUsername.setText(user.getName());
ImageUtils.displayIcon(binding.askAnswerItemUsericon, user.getIcon());
ImageUtils.display(binding.askAnswerItemUsericon, user.getIcon());
if (user.getAuth() != null) {
ImageUtils.display(binding.askAnswerItemUserBadge, user.getAuth().getIcon());
} else {
@ -126,7 +126,7 @@ public class AnswerViewHolder extends BaseRecyclerViewHolder<AnswerEntity> {
}));
binding.tvBadgeName.setOnClickListener(v -> binding.sdvUserBadge.performClick());
ImageUtils.displayIcon(binding.askAnswerItemUsericon, user.getIcon());
ImageUtils.display(binding.askAnswerItemUsericon, user.getIcon());
if (user.getAuth() != null) {
ImageUtils.display(binding.askAnswerItemUserBadge, user.getAuth().getIcon());
} else {

View File

@ -1,11 +0,0 @@
package com.gh.gamecenter.qa.entity
import com.google.gson.annotations.SerializedName
class AnswerDraftEntity(
@SerializedName("_id")
var id: String = "",
val content: String = "",
@SerializedName("answer_id")
val answerId: String = ""
)

View File

@ -1,6 +0,0 @@
package com.gh.gamecenter.qa.myqa
import com.gh.gamecenter.common.base.BaseRecyclerViewHolder
import com.gh.gamecenter.databinding.AnswerDraftItemBinding
class AnswerDraftViewHolder(val binding: AnswerDraftItemBinding) : BaseRecyclerViewHolder<Any>(binding.root)

View File

@ -1,40 +0,0 @@
package com.gh.gamecenter.qa.myqa;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
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.ExtensionsKt;
/**
* Created by khy on 10/04/18.
*/
public class MyAskActivity extends ToolBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ExtensionsKt.updateStatusBarColor(this, R.color.ui_surface, R.color.ui_surface);
}
@Override
protected boolean isAutoResetViewBackgroundEnabled() {
return true;
}
@Override
protected void onDarkModeChanged() {
super.onDarkModeChanged();
ExtensionsKt.updateStatusBarColor(this, R.color.ui_surface, R.color.ui_surface);
}
public static Intent getIntent(Context context) {
Bundle bundle = new Bundle();
bundle.putString(EntranceConsts.KEY_ENTRANCE, "(我的光环)+(我的问答)");
return getTargetIntent(context, MyAskActivity.class, MyAskWrapperFragment.class, bundle);
}
}

View File

@ -1,65 +0,0 @@
package com.gh.gamecenter.qa.myqa;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.gh.gamecenter.R;
import com.gh.gamecenter.common.base.fragment.BaseFragment_TabLayout;
import com.gh.gamecenter.common.constant.EntranceConsts;
import com.gh.gamecenter.core.utils.MtaHelper;
import com.gh.gamecenter.login.user.UserManager;
import com.gh.gamecenter.qa.article.MyArticleFragment;
import com.gh.gamecenter.qa.draft.CommunityDraftWrapperActivity;
import java.util.List;
/**
* Created by khy on 20/12/17.
*/
public class MyAskWrapperFragment extends BaseFragment_TabLayout {
@Override
protected void initFragmentList(List<Fragment> fragments) {
String entrance = null;
if (getArguments() != null) entrance = getArguments().getString(EntranceConsts.KEY_ENTRANCE);
fragments.add(MyAnswerFragment.getInstance(entrance));
fragments.add(MyArticleFragment.getInstance(entrance, UserManager.getInstance().getUserId()));
}
@Override
protected void initTabTitleList(List<String> tabTitleList) {
tabTitleList.add("我的回答");
tabTitleList.add("我的帖子");
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setNavigationTitle(R.string.my_forum);
initMenu(R.menu.menu_my_ask_wrapper);
if (mDividerLineView != null) {
mDividerLineView.setVisibility(View.VISIBLE);
}
}
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
MtaHelper.onEvent("我的光环_新", "我的问答", mTabTitleList.get(position) + "Tab");
}
@Override
public void onMenuItemClick(MenuItem menuItem) {
super.onMenuItemClick(menuItem);
if (menuItem.getItemId() == R.id.menu_draft) {
MtaHelper.onEvent("我的光环_新", "我的问答", "草稿");
startActivity(CommunityDraftWrapperActivity.getIntent(requireContext()));
}
}
}

View File

@ -40,7 +40,6 @@ import com.gh.gamecenter.feature.entity.Permissions
import com.gh.gamecenter.feature.entity.QuestionDraftEntity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.qa.BbsType
import com.gh.gamecenter.qa.answer.edit.AnswerEditActivity
import com.gh.gamecenter.qa.article.draft.ArticleDraftActivity
import com.gh.gamecenter.qa.article.edit.ArticleEditActivity
import com.gh.gamecenter.qa.dialog.ChooseActivityDialogFragment
@ -470,7 +469,7 @@ class QuestionEditActivity : BaseRichEditorActivity<QuestionEditViewModel>(),
}
SaveDraftType.AUTO -> {
if (pair.second) {
if (mPostDraftsCount >= AnswerEditActivity.SAVE_DRAFTS_TOAST_COUNT) {
if (mPostDraftsCount >= SAVE_DRAFTS_TOAST_COUNT) {
mPostDraftsCount = 0
Utils.toast(this, "问题已保存到草稿箱")
} else {
@ -920,6 +919,7 @@ class QuestionEditActivity : BaseRichEditorActivity<QuestionEditViewModel>(),
companion object {
const val QUESTION_POSTED_TAG = "QUESTION_POSTED_TAG"
const val QUESTION_DRAFT_REQUEST_CODE = 105
const val SAVE_DRAFTS_TOAST_COUNT = 3
const val QUESTION_DRAFT_CHANGE_TAG = "ANSWER_DRAFT_CHANGE_TAG"
const val SAVE_DRAFTS_INTERVAL_TIME = 15000

View File

@ -34,7 +34,7 @@ public class QuestionsInviteViewHolder extends BaseRecyclerViewHolder<InviteEnti
public void initQuestionsInviteViewHolder(Context context, InviteEntity entity, String path) {
setClickData(entity);
ImageUtils.displayIcon(binding.questionsinviteItemIcon, entity.getIcon());
ImageUtils.display(binding.questionsinviteItemIcon, entity.getIcon());
binding.questionsinviteItemName.setText(entity.getName());
if (!TextUtils.isEmpty(entity.getDescription())) {
binding.questionsinviteItemDes.setVisibility(View.VISIBLE);

View File

@ -21,7 +21,7 @@ public class ActivitySkipReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ExtensionsKt.doOnMainProcessOnly(context, () -> {
ExtensionsKt.doOnMainProcessOnly(() -> {
if (ACTION_ACTIVITY_SKIP.equals(intent.getAction())) {
Bundle bundle = intent.getExtras();
if (HaloApp.getInstance().isRunningForeground && bundle != null) {
@ -41,6 +41,8 @@ public class ActivitySkipReceiver extends BroadcastReceiver {
context.startActivity(SplashScreenActivity.getSplashScreenIntent(context, bundle));
}
}
return null;
});
}

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