Compare commits
275 Commits
v5.7.4-495
...
feature-is
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a7d588206 | |||
| 42ae45c743 | |||
| 3246dd0d70 | |||
| 06ac1fd8b0 | |||
| 81da40d786 | |||
| 9eb919b3cf | |||
| b4cbff3d6a | |||
| c7dfac8f46 | |||
| 08af4a99f8 | |||
| f3a358eb2d | |||
| 6abac72ee7 | |||
| b027c57a7c | |||
| 84b876394d | |||
| 3fb031c329 | |||
| e46afac397 | |||
| fdf2c80667 | |||
| d12a1037a2 | |||
| 056400d4d1 | |||
| 26cbdeaf2d | |||
| 6a5f7f8284 | |||
| f272e486f8 | |||
| 7b0514c055 | |||
| 909e7f33a8 | |||
| 677511b119 | |||
| 26a2605cd7 | |||
| b02f650a34 | |||
| e1d82e7fbd | |||
| 4263f53315 | |||
| f235959372 | |||
| 7bc6655b99 | |||
| 7ecc227df5 | |||
| 3046d33f91 | |||
| a32829fd0d | |||
| 4819bf3ddf | |||
| c2e02d356d | |||
| dafaeef184 | |||
| a9917c9201 | |||
| c0b61822c0 | |||
| a16a16cbdf | |||
| 0decb62237 | |||
| cdedea5002 | |||
| 88c4ebe5a0 | |||
| 10cbcdd768 | |||
| 7afbfb30a2 | |||
| 090a567887 | |||
| e55faee9fe | |||
| 362e34be8a | |||
| bf1e5586b0 | |||
| bad10158bd | |||
| 5cc58e2182 | |||
| fd836137a5 | |||
| b122e460cc | |||
| 3b29fcbef7 | |||
| 9f60a2ba86 | |||
| 8df7b3d9ee | |||
| e2040f9a2d | |||
| e39cd494b5 | |||
| f70b721441 | |||
| 877acf54f4 | |||
| a31d7a06f7 | |||
| f52937830b | |||
| b5202cc931 | |||
| dd2bfbc53f | |||
| d2f3cdadf6 | |||
| 73a88f9099 | |||
| a86c957872 | |||
| 45588a2580 | |||
| 3b55269319 | |||
| 01966a87ec | |||
| b4a8e5c68d | |||
| aeb7842299 | |||
| e0bcf947bf | |||
| 30bf685962 | |||
| 1e6fa023dc | |||
| b5920fc409 | |||
| 16ceb7115e | |||
| 279ed66270 | |||
| 9bfa8a33c8 | |||
| 99bd4da08a | |||
| 4824814981 | |||
| 10237d2fde | |||
| c1b236080e | |||
| 83d16a16b8 | |||
| 52ccffb97a | |||
| 9ed9e22df4 | |||
| 5aa29782cc | |||
| 82fcde1245 | |||
| eab945acfc | |||
| 8ed57cbfb8 | |||
| d3ed6d750b | |||
| bb4878eab4 | |||
| 53d8444c85 | |||
| 7db009a3cd | |||
| 4932fc2d7b | |||
| ca55ac02b7 | |||
| c535ffb2e0 | |||
| 9c6eb22d9d | |||
| 9ec6ec0281 | |||
| 327441e62b | |||
| ae3f07a3ee | |||
| f967e1f283 | |||
| ba1308c568 | |||
| 3144e3b007 | |||
| ec1c5713ad | |||
| 15adc93340 | |||
| c9b27f6ebe | |||
| cff7f7d2e2 | |||
| cb5d0c4840 | |||
| dea6abe399 | |||
| 20c792d4fa | |||
| b8cbd5a0fb | |||
| 0a34f23e62 | |||
| 7413b4e4ac | |||
| d2025c32c9 | |||
| 5c5dd35409 | |||
| b509e9046e | |||
| 46e99434c9 | |||
| b6ff94aed3 | |||
| 25e0bd19bc | |||
| fe5b398fad | |||
| 417ed1401e | |||
| 48698f06cd | |||
| b70a7eaf8b | |||
| ad86d7bbcc | |||
| a2eb550099 | |||
| e736855a4a | |||
| 0b49f531ac | |||
| c36f4d9abf | |||
| db72b0a5c9 | |||
| b19d21fc39 | |||
| 2d172d70ad | |||
| cc434771c0 | |||
| f5a9502261 | |||
| c48d970b0a | |||
| 9a53c7a84e | |||
| ce17ae2d2b | |||
| d97f65e9b3 | |||
| 9f1f3a2d66 | |||
| 4c9609ba52 | |||
| 270203266f | |||
| edc326ff3c | |||
| 0856b8a2ab | |||
| 8f95517dd7 | |||
| c828f3f479 | |||
| b90d026a74 | |||
| 819beb779c | |||
| de31dcaf0b | |||
| 587c217b7c | |||
| b03e86f903 | |||
| ea80942937 | |||
| 06153cbf58 | |||
| 0b94f777a2 | |||
| 3d6917cd5d | |||
| e4300ab315 | |||
| ed80533198 | |||
| 4b5c741ff9 | |||
| 0e9f267117 | |||
| 02bb977cc0 | |||
| c4a89b9302 | |||
| cde9401b36 | |||
| edcb4a949e | |||
| a5c113e527 | |||
| 048bdbc367 | |||
| 1e287f56e2 | |||
| 2aacab80a6 | |||
| 25a325f7f7 | |||
| 6c6a7f0677 | |||
| a052f981c5 | |||
| 5042bddec7 | |||
| 0803e61828 | |||
| 119f304e2f | |||
| 3db6f93b73 | |||
| 3719f5e1cd | |||
| cbae38b41d | |||
| 021886c3cb | |||
| 6d62dd7fd1 | |||
| 20d28525cf | |||
| a406127cda | |||
| 3301b30ec2 | |||
| f761715ebd | |||
| 1f0216662a | |||
| f483f1effc | |||
| cf5b0bcd41 | |||
| 4e51830c58 | |||
| 830a45e6d2 | |||
| 24c32b7a4b | |||
| 7e30f1702d | |||
| 68ae4bf1b2 | |||
| 0b757f24d1 | |||
| 99d0525c0a | |||
| 4f3ec7aa18 | |||
| bd228459fa | |||
| c9227c20a2 | |||
| 5270bc3ed7 | |||
| e1de3dc873 | |||
| 9303f534d9 | |||
| 629a694279 | |||
| 0ef0ed7c50 | |||
| 48d335ad67 | |||
| 231434caeb | |||
| 220fd340ce | |||
| 5badb44e3e | |||
| 82d405c14c | |||
| 2157dcd51a | |||
| 872d9d89c5 | |||
| dae4543a82 | |||
| 60204d9ab2 | |||
| 0c86965260 | |||
| d0ad110d9e | |||
| 5cd88cdb7f | |||
| 60acd1bac4 | |||
| 990efacb89 | |||
| 7076a6acaa | |||
| acc4d6d8ab | |||
| 0a3ae4379d | |||
| 8197f161c0 | |||
| 0cd5f0d640 | |||
| 790093b585 | |||
| 72a5d2881a | |||
| 7eabb1098c | |||
| 7a295a5d05 | |||
| da26247d30 | |||
| 010ce39e20 | |||
| 9320059a76 | |||
| 3003a310a0 | |||
| 91af5e6fe6 | |||
| d02dfbdaf7 | |||
| c3e06cc1ff | |||
| 3e86e368d8 | |||
| df231d1530 | |||
| 006f71def7 | |||
| 047dc9a7ae | |||
| 05abf00994 | |||
| c8278f6364 | |||
| 8cd951c669 | |||
| c43700e4d6 | |||
| fa2174319e | |||
| 4d6a71c8be | |||
| b99e579ccd | |||
| 01eb074df1 | |||
| f6473b0e5e | |||
| e244797e7d | |||
| f267908122 | |||
| 32a4fda9bc | |||
| cdfda4d963 | |||
| c3b850972f | |||
| 89f8aebefe | |||
| 52eca3b1ab | |||
| 0e26943d25 | |||
| 0a8bef8ac3 | |||
| a8fa4cf872 | |||
| 775f454e38 | |||
| b7de326a21 | |||
| 5b0d2e8294 | |||
| ec34de4675 | |||
| 0f6aa5ca9f | |||
| b0cdd1029e | |||
| e554e9ca5f | |||
| ff879454c1 | |||
| 7d3baaa501 | |||
| 5a57a58f0a | |||
| e01bfb4676 | |||
| de8234868a | |||
| 9220f13c9e | |||
| 10a3ed7f15 | |||
| 554eb671b2 | |||
| 9f2e46d876 | |||
| d2efb8391c | |||
| ac04cc4525 | |||
| 03855609c1 | |||
| 2408af31d9 | |||
| 3012bf6a46 | |||
| e07529846c | |||
| 010c41c3c9 | |||
| d7a81d2268 |
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -1,7 +1,7 @@
|
||||
[submodule "libraries/LGLibrary"]
|
||||
path = libraries/LGLibrary
|
||||
url = git@git.ghzs.com:android/common-library.git
|
||||
url = git@git.shanqu.cc:android/common-library.git
|
||||
branch = master
|
||||
[submodule "assistant_flutter"]
|
||||
path = assistant_flutter
|
||||
url = git@git.ghzs.com:halo/android/flutter-module.git
|
||||
url = git@git.shanqu.cc:halo/android/flutter-module.git
|
||||
|
||||
15
README.md
15
README.md
@ -14,9 +14,9 @@
|
||||
4. 遵循最小改动原则,在提交代码前务必先检查变动的代码,尽量以可控的变动规模来构成一个 commit ,以便日后追踪问题
|
||||
5. 代码规范可参考 [AOSP Java 风格](https://source.android.com/setup/contribute/code-style)
|
||||
6. 尽量使用 Kotlin 来写新文件
|
||||
7. 尽量不要使用 DataBinding,因为回影响编译性能
|
||||
7. 尽量不要使用 DataBinding
|
||||
8. Commit 前请确保不带入非项目必须文件,可手动修改 [.gitignore](https://stackoverflow.com/questions/8527597/how-do-i-ignore-files-in-a-directory-in-git) 文件忽略
|
||||
9. 新页面请勿使用 ButterKnife 来进行 View 获取和绑定,请使用 ViewBinding
|
||||
9. 优先使用 ViewBinding 获取 View 对象
|
||||
10. No AsyncTask!
|
||||
|
||||
### 公用部分
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
### 首次拉取项目代码
|
||||
|
||||
`git clone -b dev git@git.ghzs.com:halo/android/assistant-android.git --recursive`
|
||||
`git clone -b dev git@git.shanqu.cc:halo/android/assistant-android.git --recursive`
|
||||
|
||||
### git 版本管理
|
||||
|
||||
@ -45,8 +45,8 @@
|
||||
|
||||
### 第三方appkey等配置
|
||||
|
||||
* 修改`gradle.properties`文件将各种key填入其中,实现统一管理
|
||||
* 通过gradle文件内的resValue/buildConfigField/manifestPlaceHolder方式实现编译期间修改,具体情况请参考``./build.gradle``和``./app/build.gradle``配置
|
||||
* 修改 `gradle.properties` 文件将各种key填入其中,实现统一管理
|
||||
* 通过 gradle 文件内的 resValue/buildConfigField/manifestPlaceHolder 方式实现编译期间修改,具体情况请参考 ``./build.gradle`` 和 ``./app/build.gradle`` 配置
|
||||
|
||||
### 混淆配置
|
||||
|
||||
@ -55,11 +55,8 @@
|
||||
|
||||
### APK打包配置
|
||||
|
||||
* 本项目使用了 [VasDolly](https://github.com/Tencent/VasDolly) 作为渠道包实现方案
|
||||
* 打包命令,具体参数请见相应文件:
|
||||
|
||||
> 打内部测试包:`./scripts/test_build.sh`
|
||||
> 打正式发布包:`./scripts/build_with_simple_backup.sh`
|
||||
> 打邮件测试包:`./scripts/jenkins_build.sh`
|
||||
|
||||
### TODO
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This comment exists for a reason, do not delete
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android' // kotlin
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-parcelize'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'AndResGuard'
|
||||
|
||||
@ -9,13 +9,9 @@ import groovy.xml.XmlUtil
|
||||
|
||||
android {
|
||||
|
||||
androidExtensions {
|
||||
experimental = true
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
dataBinding = true
|
||||
viewBinding true
|
||||
dataBinding true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
@ -48,6 +44,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
multiDexEnabled true
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
@ -92,8 +89,10 @@ android {
|
||||
|
||||
/**
|
||||
* Build Time 供区分 jenkins 打包时间用
|
||||
* IS_NIGHT_MODE_ON 供区分夜间模式功能是否启用
|
||||
*/
|
||||
buildConfigField "long", "BUILD_TIME", "0"
|
||||
buildConfigField "boolean", "IS_NIGHT_MODE_ON", "true"
|
||||
}
|
||||
|
||||
// gradle 2.2以上默认同时启用v1和v2(优先用于Android N)
|
||||
@ -138,7 +137,7 @@ android {
|
||||
variantFilter { variant ->
|
||||
def names = variant.flavors*.name
|
||||
def isDebugType = variant.buildType.name == "debug"
|
||||
if ((names.contains("tea") || name.contains("gdt")) && isDebugType) {
|
||||
if ((names.contains("tea")) && isDebugType) {
|
||||
setIgnore(true)
|
||||
}
|
||||
}
|
||||
@ -155,9 +154,6 @@ android {
|
||||
tea {
|
||||
java.srcDirs = ['src/main/java', 'src/tea/java']
|
||||
}
|
||||
gdt {
|
||||
java.srcDirs = ['src/main/java', 'src/gdt/java']
|
||||
}
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
@ -186,13 +182,6 @@ android {
|
||||
|
||||
manifestPlaceholders.put("APPLOG_SCHEME", "rangersapplog.byAx6uYt".toLowerCase())
|
||||
}
|
||||
|
||||
gdt {
|
||||
dimension "env"
|
||||
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
@ -210,7 +199,6 @@ repositories {
|
||||
dependencies {
|
||||
|
||||
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
|
||||
gdtImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/gdt/libs')
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
|
||||
@ -218,6 +206,7 @@ dependencies {
|
||||
debugImplementation "com.squareup.okhttp3:logging-interceptor:${okHttp}"
|
||||
// debugImplementation "com.gu.android:toolargetool:${toolargetool}" // 需要使用调试时才启用
|
||||
debugImplementation "com.github.nichbar:WhatTheStack:${whatTheStack}"
|
||||
debugImplementation "io.github.didi.dokit:dokitx:${dokit}"
|
||||
|
||||
implementation "androidx.core:core-ktx:${core}"
|
||||
implementation "androidx.fragment:fragment-ktx:${fragment}"
|
||||
@ -346,7 +335,7 @@ dependencies {
|
||||
|
||||
implementation "com.louiscad.splitties:splitties-fun-pack-android-base-with-views-dsl:${splitties}"
|
||||
|
||||
compileOnly "com.github.axen1314.lancet:lancet-base:$lancet_version"
|
||||
compileOnly "com.github.axen1314.lancet:lancet-base:${lancet_version}"
|
||||
|
||||
implementation project(':libraries:LGLibrary')
|
||||
implementation project(':libraries:QQShare')
|
||||
@ -606,4 +595,4 @@ project.afterEvaluate {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,10 +220,6 @@
|
||||
-keepattributes Signature
|
||||
-keepattributes Annotation
|
||||
|
||||
### 广点通
|
||||
-dontwarn com.qq.gdt.action.**
|
||||
-keep class com.qq.gdt.action.** {*;}
|
||||
|
||||
### AndroidX
|
||||
-keep class androidx.core.app.CoreComponentFactory { *; }
|
||||
|
||||
@ -267,5 +263,4 @@
|
||||
-keep class com.ut.**{*;}
|
||||
-keep class com.ta.**{*;}
|
||||
|
||||
-keep class com.gh.gamecenter.GdtHelper { *; }
|
||||
-keep class com.gh.gamecenter.TeaHelper { *; }
|
||||
@ -94,10 +94,6 @@
|
||||
@androidx.annotation.Keep *;
|
||||
}
|
||||
|
||||
### 广点通
|
||||
-dontwarn com.qq.gdt.action.**
|
||||
-keep class com.qq.gdt.action.* {*;}
|
||||
|
||||
### 阿里云上传
|
||||
-keep class com.alibaba.sdk.android.oss.* { *; }
|
||||
-dontwarn okio.**
|
||||
@ -124,8 +120,7 @@
|
||||
-keep class com.ut.*{*;}
|
||||
-keep class com.ta.*{*;}
|
||||
|
||||
### GDT & TEA
|
||||
-keep class com.gh.gamecenter.GdtHelper { *; }
|
||||
### TEA
|
||||
-keep class com.gh.gamecenter.TeaHelper { *; }
|
||||
|
||||
### 阿里云日志
|
||||
@ -147,6 +142,9 @@
|
||||
### emoji4j
|
||||
-keep class emoji4j.* {*;}
|
||||
|
||||
### dokit
|
||||
-keep class com.didichuxing.** {*;}
|
||||
|
||||
# Flutter模块
|
||||
-keep class com.gh.common.util.DirectUtils {
|
||||
public static void directToQa(...);
|
||||
|
||||
@ -1,77 +0,0 @@
|
||||
package com.gh.gamecenter
|
||||
|
||||
import android.app.Application
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import com.gh.common.util.ToastUtils
|
||||
import com.lightgame.utils.Utils
|
||||
import com.qq.gdt.action.GDTAction
|
||||
import org.json.JSONObject
|
||||
|
||||
/**
|
||||
* 广点通辅助类 [https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/403]
|
||||
*
|
||||
* 更换帐号 [https://gitlab.ghzs.com/pm/yunying/issues/893]
|
||||
*/
|
||||
object GdtHelper {
|
||||
|
||||
const val NETWORK_TYPE = "NETWORK_TYPE"
|
||||
const val PAGE_TYPE = "PAGE_TYPE"
|
||||
const val CONTENT_TYPE = "CONTENT_TYPE"
|
||||
const val CONTENT_ID = "CONTENT_ID"
|
||||
const val KEYWORD = "KEYWORD"
|
||||
const val GAME_ID = "GAME_ID"
|
||||
const val SCORE = "SCORE"
|
||||
const val PLATFORM = "PLATFORM"
|
||||
|
||||
@JvmStatic
|
||||
fun init(application: Application, channel: String) {
|
||||
if (shouldUseGdtHelper()) {
|
||||
if (channel == "GH_728") {
|
||||
GDTAction.init(application, "1111012969", "9d3d9da5b0948a317c03d08f14d445dc")
|
||||
} else if (channel == "GH_729") {
|
||||
GDTAction.init(application, "1111013063", "f53dabf458a356b101d99fc4069eb7f1")
|
||||
} else if (channel == "GH_765") {
|
||||
GDTAction.init(application, "1111327925", "588d503f0990f98f9b2394fbb795c570")
|
||||
} else {
|
||||
GDTAction.init(application, "1110680399", "f5ddaafbf520d7d7385499232a408d0a")
|
||||
}
|
||||
}
|
||||
Utils.log("init GdtHelper")
|
||||
}
|
||||
|
||||
// fun logAction(type: String) {
|
||||
// if (shouldUseGdtHelper()) {
|
||||
// GDTAction.logAction(type)
|
||||
// Utils.log("GDT", type)
|
||||
// }
|
||||
// }
|
||||
@JvmStatic
|
||||
fun logAction(type: String, vararg kv: String?) {
|
||||
try {
|
||||
val actionParam = JSONObject()
|
||||
for (i in kv.indices) {
|
||||
if (i % 2 != 0) {
|
||||
val key = kv[i - 1]
|
||||
val value = kv[i]
|
||||
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
|
||||
actionParam.put(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
Utils.log("GDT", "$type + [${kv.joinToString(" , ")}]")
|
||||
GDTAction.logAction(type, actionParam)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 确认开启的渠道条件
|
||||
private fun shouldUseGdtHelper(): Boolean {
|
||||
return true
|
||||
//
|
||||
// val channel = HaloApp.getInstance().channel
|
||||
// return !(TextUtils.isEmpty(channel) || channel.contains("GDT".toLowerCase(Locale.CHINA)))
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
@ -165,7 +165,8 @@
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.WebActivity" />
|
||||
android:name="com.gh.gamecenter.WebActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SingletonWebActivity"
|
||||
@ -388,14 +389,6 @@
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateVisible" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.questions.edit.manager.HistoryDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.questions.edit.manager.HistoryActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
@ -739,6 +732,10 @@
|
||||
android:name="com.gh.gamecenter.toolbox.ToolBoxBlockActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.qa.subject.CommunitySubjectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name="${applicationId}.wxapi.WXEntryActivity"
|
||||
android:exported="true"
|
||||
@ -762,6 +759,12 @@
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
<provider
|
||||
android:name="com.gh.gamecenter.provider.GhContentProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:enabled="true"
|
||||
android:exported="true"/>
|
||||
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -280,12 +280,8 @@ RE.replaceAllDfImage = function(imgRuleFlag, gifRuleFlag) {
|
||||
i--;
|
||||
} else {
|
||||
if(img.src.indexOf(".gif") > 0) {
|
||||
if(gifRuleFlag.indexOf(",default") > 0) {
|
||||
img.style.cssText = "max-width: 100%; display:block; margin:8px auto; height: auto;"
|
||||
img.src = img.src.split("?")[0] + gifRuleFlag
|
||||
}
|
||||
img.src = img.src.split("?")[0] + gifRuleFlag
|
||||
} else {
|
||||
img.style.cssText = "max-width: 100%; display:block; margin:8px auto; height: auto;"
|
||||
img.src = img.src.split("?")[0] + imgRuleFlag
|
||||
}
|
||||
}
|
||||
@ -301,7 +297,7 @@ RE.hideShowBigPic = function() {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if(img.src.indexOf(",thumbnail") > 0 && img.src.indexOf(".gif") == -1) {
|
||||
if (img.src.indexOf(".gif") == -1) {
|
||||
j++;
|
||||
}
|
||||
}
|
||||
@ -327,7 +323,6 @@ RE.replaceDfImageByUrl = function(imgUrl, imgRuleFlag, gifRuleFlag) {
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if (img.src.indexOf(imgUrl) != -1) {
|
||||
img.style.cssText = "max-width: 100%; display:block; margin:8px auto; height: auto;"
|
||||
if(img.src.indexOf(".gif") > 0) {
|
||||
img.src = img.src.split("?")[0] + gifRuleFlag
|
||||
} else {
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
package com.gh.base;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
@ -14,6 +17,7 @@ import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.LinearLayout;
|
||||
@ -21,7 +25,9 @@ import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.LayoutInflaterCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
@ -33,10 +39,11 @@ import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.EnvHelper;
|
||||
import com.gh.common.util.PackageFlavorHelper;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.NightModeUtils;
|
||||
import com.gh.common.util.PackageFlavorHelper;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.QuickLoginHelper;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
@ -66,10 +73,8 @@ import java.util.List;
|
||||
import kotlin.Pair;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
|
||||
/**
|
||||
* 只提供基础的服务(EventBus/ButterKnife/Share/GlobalDialog/Permissions)
|
||||
* 只提供基础的服务(EventBus/Share/GlobalDialog/Permissions)
|
||||
* <p>
|
||||
* 需要工具栏的页面请继承{@link ToolBarActivity}
|
||||
*/
|
||||
@ -82,12 +87,14 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
public final static String PLUGGABLE = "plugin";
|
||||
public final static String SIGNATURE_CONFLICT = "signature_conflict";
|
||||
public final static int ID_ROOT_INDICATOR = 999;
|
||||
public final static int ID_NIGHT_INDICATOR = 998;
|
||||
public final int MAX_BUNDLE_SIZE = 300;
|
||||
|
||||
@NonNull
|
||||
protected String mEntrance;
|
||||
|
||||
private boolean mIsExistLogoutDialog;
|
||||
protected boolean mNightMode;
|
||||
public long startPageTime = 0;
|
||||
|
||||
protected final Handler mBaseHandler = new BaseHandler(this);
|
||||
@ -127,6 +134,10 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
if (PackageFlavorHelper.IS_TEST_FLAVOR && isAutoResetViewBackgroundEnabled()) {
|
||||
LayoutInflaterCompat.setFactory2(getLayoutInflater(), new CustomLayoutInflaterFactory(this));
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (useEventBus()) EventBus.getDefault().register(this);
|
||||
@ -159,12 +170,20 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
startPageTime = System.currentTimeMillis();
|
||||
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON
|
||||
&& !NightModeUtils.INSTANCE.getSystemMode()
|
||||
&& mNightMode != NightModeUtils.INSTANCE.isNightMode(this)) {
|
||||
onNightModeChange();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@ -255,6 +274,9 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
|
||||
screenRootView.addView(view);
|
||||
screenRootView.addView(ll);
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON) {
|
||||
screenRootView.addView(getNightModeIndicatorView());
|
||||
}
|
||||
|
||||
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) ll.getLayoutParams();
|
||||
lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
|
||||
@ -262,6 +284,80 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
return screenRootView;
|
||||
}
|
||||
|
||||
private View getNightModeIndicatorView() {
|
||||
LinearLayout ll = new LinearLayout(this);
|
||||
TextView tv = new TextView(this);
|
||||
String envText = NightModeUtils.INSTANCE.isNightMode(this) ? "夜间模式" : "日间模式";
|
||||
tv.setBackground(ContextCompat.getDrawable(this, R.color.theme));
|
||||
tv.setText(envText);
|
||||
tv.setGravity(Gravity.CENTER);
|
||||
tv.setTextColor(Color.WHITE);
|
||||
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
|
||||
tv.measure(0, 0);
|
||||
tv.setAlpha(NightModeUtils.INSTANCE.isNightMode(this) ? 0.8F : 0.15F);
|
||||
tv.setId(ID_NIGHT_INDICATOR);
|
||||
int height = tv.getMeasuredHeight();
|
||||
int width = tv.getMeasuredWidth();
|
||||
tv.setPadding(DisplayUtils.dip2px(20), 0, DisplayUtils.dip2px(20), 0);
|
||||
ll.setTranslationX(DisplayUtils.dip2px(-20));
|
||||
ll.setRotation(-45);
|
||||
ll.addView(tv);
|
||||
ll.setPadding(0, (width - height) / 2, 0, (width - height) / 2);
|
||||
|
||||
if (PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
tv.setOnClickListener(v -> {
|
||||
//切换深色模式
|
||||
String mode;
|
||||
String positive;
|
||||
String negative;
|
||||
if (NightModeUtils.INSTANCE.getSystemMode()) {
|
||||
mode = "跟随系统模式";
|
||||
positive = "普通模式";
|
||||
negative = "深色模式";
|
||||
} else if (NightModeUtils.INSTANCE.getNightMode()) {
|
||||
mode = "深色模式";
|
||||
positive = "跟随系统模式";
|
||||
negative = "普通模式";
|
||||
} else {
|
||||
mode = "普通模式";
|
||||
positive = "跟随系统模式";
|
||||
negative = "深色模式";
|
||||
}
|
||||
DialogHelper.showCenterDialog(this, "选择模式", "当前为 " + mode, positive, negative, () -> {
|
||||
if (NightModeUtils.INSTANCE.getSystemMode()) {
|
||||
NightModeUtils.INSTANCE.setNightMode(false);
|
||||
NightModeUtils.INSTANCE.setSystemMode(false);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||
}
|
||||
} else {
|
||||
NightModeUtils.INSTANCE.setSystemMode(true);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
|
||||
}
|
||||
}
|
||||
NightModeUtils.INSTANCE.initNightMode();
|
||||
}, () -> {
|
||||
if (NightModeUtils.INSTANCE.getSystemMode()) {
|
||||
NightModeUtils.INSTANCE.setNightMode(true);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
|
||||
}
|
||||
} else {
|
||||
boolean nightMode = NightModeUtils.INSTANCE.getNightMode();
|
||||
NightModeUtils.INSTANCE.setNightMode(!NightModeUtils.INSTANCE.getNightMode());
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
getDelegate().setLocalNightMode(nightMode ? AppCompatDelegate.MODE_NIGHT_NO : AppCompatDelegate.MODE_NIGHT_YES);
|
||||
}
|
||||
}
|
||||
NightModeUtils.INSTANCE.setSystemMode(false);
|
||||
NightModeUtils.INSTANCE.initNightMode();
|
||||
});
|
||||
});
|
||||
}
|
||||
return ll;
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(final EBShowDialog showDialog) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
|
||||
@ -292,7 +388,8 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
DialogHelper.showCenterDialog(this, "你的账号已在另外一台设备登录"
|
||||
, StringUtils.buildString("(", model, ")")
|
||||
, "知道了", "重新登录"
|
||||
, () -> {}
|
||||
, () -> {
|
||||
}
|
||||
, () -> {
|
||||
if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(BaseActivity.this)) {
|
||||
QuickLoginHelper.startLogin(BaseActivity.this, "你的账号已在另外一台设备登录多设备-重新登录");
|
||||
@ -445,4 +542,88 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
public Pair<String, String> getBusinessId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
onNightModeChange();
|
||||
}
|
||||
|
||||
protected void onNightModeChange() {
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON) {
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(this);
|
||||
TextView tv = findViewById(ID_NIGHT_INDICATOR);
|
||||
if (tv != null) {
|
||||
tv.setText(NightModeUtils.INSTANCE.isNightMode(this) ? "夜间模式" : "日间模式");
|
||||
tv.setAlpha(NightModeUtils.INSTANCE.isNightMode(this) ? 0.8F : 0.15F);
|
||||
}
|
||||
if (isAutoResetViewBackgroundEnabled()) {
|
||||
updateStaticViewBackground(getWindow().getDecorView());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isAutoResetViewBackgroundEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动重置部分 view 的背景颜色/资源
|
||||
*
|
||||
* @param view 父 view
|
||||
*/
|
||||
private void updateStaticViewBackground(View view) {
|
||||
if (view instanceof ViewGroup) {
|
||||
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
|
||||
View child = ((ViewGroup) view).getChildAt(i);
|
||||
updateStaticViewBackground(child);
|
||||
}
|
||||
}
|
||||
|
||||
String backgroundString = (String) view.getTag(CustomLayoutInflaterFactory.TAG_BACKGROUND_ID);
|
||||
String textColorString = (String) view.getTag(CustomLayoutInflaterFactory.TAG_TEXT_COLOR_ID);
|
||||
if (backgroundString != null) {
|
||||
if (backgroundString.startsWith("#")) return;
|
||||
int backgroundId = Integer.parseInt(
|
||||
backgroundString
|
||||
.replace("@", "")
|
||||
.replace("?", "")
|
||||
);
|
||||
|
||||
if (backgroundId != 0) {
|
||||
try {
|
||||
TypedValue value = new TypedValue();
|
||||
getResources().getValue(backgroundId, value, true);
|
||||
|
||||
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
|
||||
view.setBackgroundColor(ExtensionsKt.toColor(backgroundId, this));
|
||||
} else {
|
||||
view.setBackground(ExtensionsKt.toDrawable(backgroundId, this));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (textColorString != null && view instanceof TextView) {
|
||||
if (textColorString.startsWith("#")) return;
|
||||
int textColorId = Integer.parseInt(
|
||||
textColorString
|
||||
.replace("@", "")
|
||||
.replace("?", "")
|
||||
);
|
||||
|
||||
if (textColorId != 0) {
|
||||
try {
|
||||
final ColorStateList colorStateList = ContextCompat.getColorStateList(this, textColorId);
|
||||
((TextView) view).setTextColor(colorStateList);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
@ -98,7 +99,7 @@ public abstract class BaseActivity_TabLayout extends ToolBarActivity implements
|
||||
String tabTitle = tab.getText() != null ? tab.getText().toString() : "";
|
||||
View tabView = provideTabView(i, tabTitle);
|
||||
if (tabView == null)
|
||||
tabView = BaseFragment_TabLayout.createDefaultTabCustomView(tabTitle);
|
||||
tabView = BaseFragment_TabLayout.createDefaultTabCustomView(this, tabTitle);
|
||||
tab.setCustomView(tabView);
|
||||
}
|
||||
|
||||
@ -133,4 +134,22 @@ public abstract class BaseActivity_TabLayout extends ToolBarActivity implements
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNightModeChange() {
|
||||
super.onNightModeChange();
|
||||
View container = findViewById(R.id.activity_tab_container);
|
||||
if (container != null) {
|
||||
container.setBackgroundColor(ContextCompat.getColor(this, R.color.background_white));
|
||||
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
|
||||
TabLayout.Tab tab = mTabLayout.getTabAt(i);
|
||||
if (tab != null) {
|
||||
BaseFragment_TabLayout.updateTabStyle(tab, tab.isSelected());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mDividerLineView != null) {
|
||||
mDividerLineView.setBackgroundColor(ContextCompat.getColor(this, R.color.divider));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
app/src/main/java/com/gh/base/CustomLayoutInflaterFactory.kt
Normal file
53
app/src/main/java/com/gh/base/CustomLayoutInflaterFactory.kt
Normal file
@ -0,0 +1,53 @@
|
||||
package com.gh.base
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
class CustomLayoutInflaterFactory(
|
||||
private val mAppCompatActivity: AppCompatActivity
|
||||
) : LayoutInflater.Factory2 {
|
||||
|
||||
override fun onCreateView(
|
||||
parent: View?,
|
||||
name: String,
|
||||
context: Context,
|
||||
attrs: AttributeSet
|
||||
): View? {
|
||||
|
||||
val view: View?
|
||||
|
||||
try {
|
||||
view = mAppCompatActivity.delegate.createView(parent, name, context, attrs)
|
||||
?: mAppCompatActivity.onCreateView(parent, name, context, attrs)
|
||||
?: mAppCompatActivity.layoutInflater.createView(name, null, attrs)
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
|
||||
val n = attrs.attributeCount
|
||||
for (i in 0 until n) {
|
||||
val attributeName = attrs.getAttributeName(i).toString()
|
||||
if (attributeName.contains("background")) {
|
||||
view?.setTag(TAG_BACKGROUND_ID, attrs.getAttributeValue(i))
|
||||
} else if (attributeName.contains("textColor")) {
|
||||
view?.setTag(TAG_TEXT_COLOR_ID, attrs.getAttributeValue(i))
|
||||
}
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
|
||||
return mAppCompatActivity.onCreateView(name, context, attrs)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG_BACKGROUND_ID = R.string.background_id
|
||||
const val TAG_TEXT_COLOR_ID = R.string.text_color_id
|
||||
}
|
||||
|
||||
}
|
||||
@ -91,7 +91,7 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
|
||||
}
|
||||
|
||||
override fun onActivityDestroyed(activity: Activity) {
|
||||
// do nothing
|
||||
AppManager.getInstance().finishActivity(activity)
|
||||
}
|
||||
|
||||
}
|
||||
@ -13,6 +13,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -21,6 +22,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.widget.ActionMenuView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
@ -310,4 +312,25 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
|
||||
mToolbarContainer.setVisibility(isHide ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNightModeChange() {
|
||||
super.onNightModeChange();
|
||||
if (mToolbar != null) {
|
||||
mToolbar.setBackgroundColor(ContextCompat.getColor(this, R.color.background_white));
|
||||
}
|
||||
if (mBackBtn != null) {
|
||||
if (mBackBtn instanceof ImageView) {
|
||||
((ImageView) mBackBtn).setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_bar_back));
|
||||
} else if (mBackBtn instanceof TextView) {
|
||||
((TextView) mBackBtn).setTextColor(ContextCompat.getColor(this, R.color.text_subtitle));
|
||||
}
|
||||
}
|
||||
if (mTitleTv != null) {
|
||||
mTitleTv.setTextColor(ContextCompat.getColor(this, R.color.text_black));
|
||||
}
|
||||
if (showDownloadMenu() && getMenuItem(R.id.menu_download) != null) {
|
||||
((ImageView) getMenuItem(R.id.menu_download).getActionView().findViewById(R.id.menu_download_iv)).setImageDrawable(ContextCompat.getDrawable(this, R.drawable.toolbar_download));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.gh.common.util.ClickUtils;
|
||||
import com.gh.common.util.NightModeUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.lightgame.utils.RuntimeUtils;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -28,6 +30,14 @@ import androidx.lifecycle.Lifecycle;
|
||||
|
||||
public class BaseDialogFragment extends DialogFragment {
|
||||
|
||||
protected boolean mNightMode;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(requireContext());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
@ -95,6 +105,16 @@ public class BaseDialogFragment extends DialogFragment {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
onNightModeChange();
|
||||
}
|
||||
|
||||
protected void onNightModeChange() {
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(requireContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@ -8,6 +9,7 @@ import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
@ -23,6 +25,7 @@ import com.gh.common.constant.Constants;
|
||||
import com.gh.common.syncpage.ISyncAdapterHandler;
|
||||
import com.gh.common.syncpage.SyncDataEntity;
|
||||
import com.gh.common.syncpage.SyncPageRepository;
|
||||
import com.gh.common.util.NightModeUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.eventbus.EBMiPush;
|
||||
@ -58,6 +61,8 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
|
||||
protected boolean isEverPause;
|
||||
|
||||
protected boolean mNightMode;
|
||||
|
||||
@NonNull
|
||||
protected String mEntrance = "";
|
||||
|
||||
@ -158,6 +163,12 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
if (addSyncPageObserver()) {
|
||||
initSyncPageObserver();
|
||||
}
|
||||
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON) {
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(requireContext());
|
||||
} else {
|
||||
mNightMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void initSyncPageObserver() {
|
||||
@ -230,6 +241,12 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
super.onResume();
|
||||
isEverPause = false;
|
||||
startPageTime = System.currentTimeMillis();
|
||||
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON
|
||||
&& !NightModeUtils.INSTANCE.getSystemMode()
|
||||
&& mNightMode != NightModeUtils.INSTANCE.isNightMode(requireContext())) {
|
||||
onNightModeChange();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -315,7 +332,9 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
|
||||
// 为 fragment 附加 bundle (setArgument())
|
||||
public BaseFragment with(Bundle bundle) {
|
||||
this.setArguments(bundle);
|
||||
if (!isStateSaved()) {
|
||||
this.setArguments(bundle);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -331,4 +350,16 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
|
||||
protected boolean addSyncPageObserver() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON) {
|
||||
onNightModeChange();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onNightModeChange() {
|
||||
mNightMode = NightModeUtils.INSTANCE.isNightMode(requireContext());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.base.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
@ -8,6 +9,12 @@ import android.view.View;
|
||||
import android.widget.CheckedTextView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.gh.base.adapter.FragmentAdapter;
|
||||
import com.gh.common.view.TabIndicatorView;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -20,11 +27,6 @@ import com.lightgame.view.NoScrollableViewPager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
/**
|
||||
* Created by khy on 15/03/18.
|
||||
*/
|
||||
@ -119,7 +121,7 @@ public abstract class BaseFragment_TabLayout extends NormalFragment implements V
|
||||
if (tab == null) continue;
|
||||
String tabTitle = tab.getText() != null ? tab.getText().toString() : "";
|
||||
View tabView = provideTabView(i, tabTitle);
|
||||
if (tabView == null) tabView = createDefaultTabCustomView(tabTitle);
|
||||
if (tabView == null) tabView = createDefaultTabCustomView(requireContext(), tabTitle);
|
||||
tab.setCustomView(tabView);
|
||||
}
|
||||
|
||||
@ -152,7 +154,7 @@ public abstract class BaseFragment_TabLayout extends NormalFragment implements V
|
||||
});
|
||||
}
|
||||
|
||||
private static void updateTabStyle(TabLayout.Tab tab, boolean isChecked) {
|
||||
public static void updateTabStyle(TabLayout.Tab tab, boolean isChecked) {
|
||||
View tabView = tab.getCustomView();
|
||||
if (tabView == null) {
|
||||
Utils.log("TabLayout->Tab样式不是通用样式,请检查");
|
||||
@ -171,12 +173,13 @@ public abstract class BaseFragment_TabLayout extends NormalFragment implements V
|
||||
return;
|
||||
}
|
||||
tabTitle.setTypeface(isChecked ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
|
||||
tabTitle.setTextColor(ContextCompat.getColorStateList(tabTitle.getContext(), R.color.text_tabbar_style));
|
||||
}
|
||||
|
||||
// 如果不设置View的话,无法动态设置字体样式
|
||||
@NonNull
|
||||
public static View createDefaultTabCustomView(String title) {
|
||||
View view = LayoutInflater.from(HaloApp.getInstance().getApplication().getBaseContext()).inflate(R.layout.tab_item, null);
|
||||
public static View createDefaultTabCustomView(Context context, String title) {
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.tab_item, null);
|
||||
View tabTitle = view.findViewById(R.id.tab_title);
|
||||
if (tabTitle instanceof CheckedTextView) {
|
||||
((CheckedTextView) tabTitle).setText(title);
|
||||
@ -198,4 +201,22 @@ public abstract class BaseFragment_TabLayout extends NormalFragment implements V
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNightModeChange() {
|
||||
super.onNightModeChange();
|
||||
View container = requireView().findViewById(R.id.fragment_tab_container);
|
||||
if (container != null) {
|
||||
container.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.background_white));
|
||||
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
|
||||
TabLayout.Tab tab = mTabLayout.getTabAt(i);
|
||||
if (tab != null) {
|
||||
updateTabStyle(tab, tab.isSelected());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mDividerLineView != null) {
|
||||
mDividerLineView.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.divider));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.gh.base.fragment
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager.widget.PagerAdapter
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
@ -93,7 +94,7 @@ abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeL
|
||||
val tab = mTabLayout.getTabAt(i) ?: continue
|
||||
val tabTitle = if (tab.text != null) tab.text.toString() else ""
|
||||
var tabView = provideTabView(i, tabTitle)
|
||||
if (tabView == null) tabView = BaseFragment_TabLayout.createDefaultTabCustomView(tabTitle)
|
||||
if (tabView == null) tabView = BaseFragment_TabLayout.createDefaultTabCustomView(requireContext(), tabTitle)
|
||||
tab.customView = tabView
|
||||
}
|
||||
BaseFragment_TabLayout.initTabStyle(mTabLayout, mCheckedIndex)
|
||||
@ -121,6 +122,20 @@ abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeL
|
||||
|
||||
override fun onPageScrollStateChanged(state: Int) {}
|
||||
|
||||
override fun onNightModeChange() {
|
||||
super.onNightModeChange()
|
||||
val container = requireView().findViewById<View>(R.id.fragment_tab_container)
|
||||
if (container != null) {
|
||||
container.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.background_white))
|
||||
for (i in 0 until mTabLayout.tabCount) {
|
||||
val tab = mTabLayout.getTabAt(i)
|
||||
if (tab != null) {
|
||||
BaseFragment_TabLayout.updateTabStyle(tab, tab.isSelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val PAGE_INDEX = "PAGE_INDEX"
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.gh.common
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.gh.base.GHThreadFactory
|
||||
import com.gh.common.AppExecutor.heavyWeightIoExecutor
|
||||
import com.gh.common.AppExecutor.ioExecutor
|
||||
import com.gh.common.AppExecutor.lightWeightIoExecutor
|
||||
import com.gh.common.AppExecutor.logExecutor
|
||||
@ -16,31 +17,33 @@ import java.util.concurrent.*
|
||||
* [ioExecutor] 是一个最大线程数固定的线程池,较为繁重的 IO 任务可以交给它
|
||||
* [uiExecutor] 是主线程的包裹,需要切换至主线程执行可以用它
|
||||
* [lightWeightIoExecutor] 是一个单线程的线程池,轻量级且需要保证同一线程的 IO 任务可以交给它
|
||||
* [heavyWeightIoExecutor] 重量级的线程池,一些高频调用但不用保证结果的任务可以交给它
|
||||
* [logExecutor] 只为上传 log 而使用的线程池
|
||||
*/
|
||||
object AppExecutor {
|
||||
|
||||
private val mCoreSize = Runtime.getRuntime().availableProcessors()
|
||||
private val mMinimumPoolSize = 16.coerceAtLeast(mCoreSize * 4)
|
||||
private val mMaximumPoolSize = 64.coerceAtLeast(mCoreSize * 16)
|
||||
|
||||
// TODO 因为 LinkedBlockingQueue 过大导致 MaximumPoolSize 的值几乎无效,下版本改造 [PackageRepository] 启动请求一堆游戏摘要信息的接口?
|
||||
private val mMinimumPoolSize = 6.coerceAtLeast(mCoreSize)
|
||||
private val mMaximumPoolSize = 24.coerceAtLeast(mCoreSize * 3)
|
||||
|
||||
@JvmStatic
|
||||
val uiExecutor by lazy { MainThreadExecutor() }
|
||||
|
||||
@JvmStatic
|
||||
val lightWeightIoExecutor by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LIGHT_WEIGHT_IO_THREAD")) }
|
||||
val lightWeightIoExecutor: ExecutorService by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LIGHT_WEIGHT_IO_THREAD")) }
|
||||
|
||||
@JvmStatic
|
||||
val logExecutor by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LOG_THREAD")) }
|
||||
val heavyWeightIoExecutor: ExecutorService by lazy { Executors.newFixedThreadPool(2, GHThreadFactory("GH_HEAVY_WEIGHT_IO_THREAD")) }
|
||||
|
||||
@JvmStatic
|
||||
val logExecutor: ExecutorService by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LOG_THREAD")) }
|
||||
|
||||
@JvmStatic
|
||||
val ioExecutor = ThreadPoolExecutor(
|
||||
mMinimumPoolSize,
|
||||
mMaximumPoolSize,
|
||||
20L, TimeUnit.SECONDS,
|
||||
LinkedBlockingQueue<Runnable>(1000),
|
||||
LinkedBlockingQueue(256),
|
||||
GHThreadFactory("GH_IO_THREAD"))
|
||||
|
||||
val cachedScheduler by lazy { Schedulers.from(ioExecutor) }
|
||||
@ -58,14 +61,14 @@ object AppExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnIoThread(isLightWeightTask: Boolean = false, f: () -> Unit) {
|
||||
if (isLightWeightTask) {
|
||||
AppExecutor.lightWeightIoExecutor.execute(f)
|
||||
} else {
|
||||
AppExecutor.ioExecutor.execute(f)
|
||||
fun runOnIoThread(isLightWeightTask: Boolean = false, isHeavyWightTask: Boolean = false, f: () -> Unit) {
|
||||
when {
|
||||
isLightWeightTask -> lightWeightIoExecutor.execute(f)
|
||||
isHeavyWightTask -> heavyWeightIoExecutor.execute(f)
|
||||
else -> ioExecutor.execute(f)
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnUiThread(f: () -> Unit) {
|
||||
AppExecutor.uiExecutor.execute(f)
|
||||
uiExecutor.execute(f)
|
||||
}
|
||||
@ -17,9 +17,7 @@ import com.gh.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.energy.EnergyCenterActivity
|
||||
import com.gh.gamecenter.energy.EnergyHouseActivity
|
||||
import com.gh.gamecenter.entity.Badge
|
||||
import com.gh.gamecenter.entity.MtaEvent
|
||||
import com.gh.gamecenter.entity.NotificationUgc
|
||||
import com.gh.gamecenter.entity.*
|
||||
import com.gh.gamecenter.help.QaFeedbackDialogFragment
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.personalhome.border.AvatarBorderActivity
|
||||
@ -401,7 +399,25 @@ class DefaultJsApi(var context: Context) {
|
||||
|
||||
@JavascriptInterface
|
||||
fun checkUpdateGhzs(msg: Any) {
|
||||
context.startActivity(AboutActivity.getIntent(context, true));
|
||||
context.startActivity(AboutActivity.getIntent(context, true))
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public fun clickGameActivityDownloadBtn(event: Any) {
|
||||
val gameActivityEvent = event.toString().toObject() ?: GameActivityEvent()
|
||||
GameActivityDownloadHelper.start(context, gameActivityEvent)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun isGameActivityTaskCompleted(event: Any, handler: CompletionHandler<Any>) {
|
||||
val gameActivityEvent = event.toString().toObject() ?: GameActivityEvent()
|
||||
GameActivityDownloadHelper.checkTaskComplete(context, gameActivityEvent, handler)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun postGameActivityExposureEvent(event: Any) {
|
||||
val gameActivityEvent = event.toString().toObject() ?: GameActivityEvent()
|
||||
GameActivityDownloadHelper.postExposureEvent(gameActivityEvent)
|
||||
}
|
||||
|
||||
@Keep
|
||||
@ -423,4 +439,12 @@ class DefaultJsApi(var context: Context) {
|
||||
|
||||
@Keep
|
||||
internal data class BrowseTaskEvent(var timeout: String = "", var isFinished: String = "")
|
||||
|
||||
@Keep
|
||||
data class GameActivityEvent(
|
||||
var gameId: String = "",
|
||||
var activityTitle: String = "",
|
||||
var activityId: String = "",
|
||||
var platform: String = ""
|
||||
)
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ import java.nio.charset.Charset
|
||||
object DefaultUrlHandler {
|
||||
|
||||
@JvmStatic
|
||||
fun interceptUrl(context: Context, url: String, entrance: String) : Boolean {
|
||||
fun interceptUrl(context: Context, url: String, entrance: String): Boolean {
|
||||
return interceptUrl(context, url, entrance, false)
|
||||
}
|
||||
|
||||
@ -335,6 +335,7 @@ object DefaultUrlHandler {
|
||||
EntranceUtils.HOST_UPLOAD_VIDEO_NEW -> {
|
||||
val activityName = uri.getQueryParameter("activity_name") ?: ""
|
||||
val activityId = uri.getQueryParameter("activity_id") ?: ""
|
||||
val original = uri.getQueryParameter("original") ?: ""
|
||||
val forumName = uri.getQueryParameter("forum_name") ?: ""
|
||||
val forumId = uri.getQueryParameter("forum_id") ?: ""
|
||||
val forumIcon = uri.getQueryParameter("forum_icon") ?: ""
|
||||
@ -343,11 +344,16 @@ object DefaultUrlHandler {
|
||||
val gameName = uri.getQueryParameter("game_name") ?: ""
|
||||
val icon = uri.getQueryParameter("game_icon") ?: ""
|
||||
val iconSubscript = uri.getQueryParameter("game_icon_subscript") ?: ""
|
||||
val gameEntity = if (forumType == BbsType.OFFICIAL_BBS.value) {
|
||||
GameEntity(id = gameId, mName = gameName, mIcon = icon, mIconSubscript = iconSubscript)
|
||||
val gameEntity =
|
||||
if (forumType == BbsType.OFFICIAL_BBS.value && gameId.isNotEmpty() && gameName.isNotEmpty() && icon.isNotEmpty()) {
|
||||
GameEntity(id = gameId, mName = gameName, mIcon = icon, mIconSubscript = iconSubscript)
|
||||
} else null
|
||||
val activityLabelEntity = if (activityId.isNotEmpty() && activityName.isNotEmpty()) {
|
||||
ActivityLabelEntity(id = activityId, name = activityName, original = original.ifEmpty { "false" }.toBoolean())
|
||||
} else null
|
||||
val communityEntity = if (forumId.isNotEmpty() && forumName.isNotEmpty() && forumIcon.isNotEmpty()) {
|
||||
CommunityEntity(id = forumId, name = forumName, icon = forumIcon)
|
||||
} else null
|
||||
val activityLabelEntity = ActivityLabelEntity(id = activityId, name = activityName)
|
||||
val communityEntity = CommunityEntity(id = forumId, name = forumName, icon = forumIcon)
|
||||
|
||||
context.startActivity(
|
||||
VideoPublishActivity.getIntent(
|
||||
@ -356,7 +362,8 @@ object DefaultUrlHandler {
|
||||
gameEntity,
|
||||
activityLabelEntity,
|
||||
forumType,
|
||||
false,
|
||||
disableForumSelection = false,
|
||||
isFromCommunityActivity = true,
|
||||
entrance,
|
||||
""
|
||||
)
|
||||
|
||||
@ -49,6 +49,8 @@ public class Constants {
|
||||
// 最近显示的弹窗信息
|
||||
public static final String SP_LAST_OPENING_ID = "last_opening_dialog_id";
|
||||
public static final String SP_LAST_OPENING_TIME = "last_opening_dialog_time";
|
||||
|
||||
public static final String SP_LAST_ACCEPTED_PRIVACY_DIALOG_ID = "last_accepted_privacy_dialog_id";
|
||||
|
||||
// 游戏图标和图标角标
|
||||
public static final String RAW_GAME_ICON = "raw_game_icon";
|
||||
@ -245,6 +247,8 @@ public class Constants {
|
||||
public static final String SP_MY_GAME_GUIDE = "my_game_guide";
|
||||
//微信绑定配置信息
|
||||
public static final String SP_WECHAT_CONFIG = "wechat_config";
|
||||
//游戏库导航栏小红点提示
|
||||
public static final String SP_GAME_NAVIGATION = "game_navigation";
|
||||
|
||||
//手机号码匹配规则
|
||||
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
|
||||
@ -415,4 +419,9 @@ public class Constants {
|
||||
public static final String DEFAULT_VIVO_BROWSER_HINT_URL = "https://static-web.ghzs.com/ghzs_help/help.html?content=618112ce04796e63e97643a4&from=ghzs";
|
||||
|
||||
public static final int FOLLOW_HINT_TRIGGER_HEIGHT = 10;
|
||||
|
||||
// 深色模式
|
||||
public static final String SP_NIGHT_MODE = "night_mode";
|
||||
// 跟随系统模式
|
||||
public static final String SP_SYSTEM_MODE = "system_mode";
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@ import android.widget.TextView;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.BindingAdapter;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
@ -34,6 +33,7 @@ import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.DownloadDialogHelper;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.gh.common.util.GameUtils;
|
||||
import com.gh.common.util.GameViewUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
@ -84,22 +84,18 @@ import java.util.List;
|
||||
|
||||
public class BindingAdapters {
|
||||
|
||||
@BindingAdapter("imageIcon")
|
||||
public static void loadIcon(SimpleDraweeView view, String imageUrl) {
|
||||
ImageUtils.displayIcon(view, imageUrl);
|
||||
}
|
||||
|
||||
@BindingAdapter("imageUrl")
|
||||
public static void loadImage(SimpleDraweeView view, String imageUrl) {
|
||||
ImageUtils.display(view, imageUrl);
|
||||
}
|
||||
|
||||
@BindingAdapter("setTextSize")
|
||||
public static void setTextSize(TextView view, int number) {
|
||||
view.setTextSize(number);
|
||||
}
|
||||
|
||||
@BindingAdapter("setTypeface")
|
||||
public static void setTypeface(TextView view, String type) {
|
||||
if (type == null) return;
|
||||
|
||||
@ -119,7 +115,6 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"addDetailKaiFuView", "addDetailKaiFuViewListener", "isReadyPatch"})
|
||||
public static void addDetailKaiFuView(LinearLayout view, List<ServerCalendarEntity> list
|
||||
, OnViewClickListener listener, Boolean isReadyPatch) {
|
||||
if (list == null) return;
|
||||
@ -127,13 +122,13 @@ public class BindingAdapters {
|
||||
for (int i = 0; i < list.size() + 1; i++) { // 1 is Title
|
||||
View inflate = LayoutInflater.from(view.getContext()).inflate(R.layout.kaifu_detail_item_row, null);
|
||||
KaifuDetailItemRowBinding binding = KaifuDetailItemRowBinding.bind(inflate);
|
||||
binding.setIsCloseBottom(i == list.size());
|
||||
binding.setIsReadyPatch(isReadyPatch);
|
||||
if (i == 0) {
|
||||
binding.setIsTitle(true);
|
||||
} else {
|
||||
ServerCalendarEntity serverEntity = list.get(i - 1);
|
||||
binding.setEntity(serverEntity);
|
||||
binding.getRoot().setBackgroundColor(isReadyPatch != null && isReadyPatch ? ExtensionsKt.toColor(R.color.theme) : ExtensionsKt.toColor(R.color.white));
|
||||
binding.getRoot().setPadding(DisplayUtils.dip2px(1), DisplayUtils.dip2px(1), DisplayUtils.dip2px(1), i == list.size() ? DisplayUtils.dip2px(1) : 0);
|
||||
ServerCalendarEntity serverEntity = list.get(i - 1);
|
||||
binding.timeTv.setText(i == 0 ? "时间" : serverEntity.getFormatTime("HH:mm"));
|
||||
binding.remarkTv.setText(i == 0 ? "备注" : serverEntity.getRemark());
|
||||
binding.nameTv.setText(i == 0 ? "名字" : (TextUtils.isEmpty(serverEntity.getNote()) ? "-" : serverEntity.getNote()));
|
||||
if (i != 0) {
|
||||
binding.getRoot().setOnClickListener(v -> {
|
||||
listener.onClick(v, isReadyPatch != null && isReadyPatch ? serverEntity : null);
|
||||
});
|
||||
@ -155,12 +150,10 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
// 如果超过10000,则转换为1.0W
|
||||
@BindingAdapter("transSimpleCount")
|
||||
public static void transSimpleCount(TextView view, int count) {
|
||||
view.setText(NumberUtils.transSimpleCount(count));
|
||||
}
|
||||
|
||||
@BindingAdapter("textColorFromString")
|
||||
public static void textColorFromString(TextView tv, String hexString) {
|
||||
if (TextUtils.isEmpty(hexString)) return;
|
||||
|
||||
@ -171,7 +164,6 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("visibleGone")
|
||||
public static void showHide(View view, Boolean show) {
|
||||
if (show != null && show) {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
@ -180,7 +172,6 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("goneIf")
|
||||
public static void goneIf(View view, Boolean gone) {
|
||||
if (gone != null && gone) {
|
||||
view.setVisibility(View.GONE);
|
||||
@ -192,7 +183,6 @@ public class BindingAdapters {
|
||||
/**
|
||||
* lazy 的 paddingTop
|
||||
*/
|
||||
@BindingAdapter("lazyPaddingLeft")
|
||||
public static void lazyPaddingLeft(View view, int paddingLeftInDp) {
|
||||
view.setPadding(DisplayUtils.dip2px(paddingLeftInDp), view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom());
|
||||
}
|
||||
@ -200,7 +190,6 @@ public class BindingAdapters {
|
||||
/**
|
||||
* lazy 的 paddingTop
|
||||
*/
|
||||
@BindingAdapter("lazyPaddingTop")
|
||||
public static void lazyPaddingTop(View view, int paddingTopInDp) {
|
||||
view.setPadding(view.getPaddingLeft(), DisplayUtils.dip2px(paddingTopInDp), view.getPaddingRight(), view.getPaddingBottom());
|
||||
}
|
||||
@ -208,12 +197,10 @@ public class BindingAdapters {
|
||||
/**
|
||||
* lazy 的 paddingBottom
|
||||
*/
|
||||
@BindingAdapter("lazyPaddingBottom")
|
||||
public static void lazyPaddingBottom(View view, int paddingBottomInDp) {
|
||||
view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), DisplayUtils.dip2px(paddingBottomInDp));
|
||||
}
|
||||
|
||||
@BindingAdapter("visibleInvisible")
|
||||
public static void visibleInvisible(View view, Boolean show) {
|
||||
if (show != null && show) {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
@ -222,7 +209,6 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("messageUnread")
|
||||
public static void setMessageUnread(TextView view, int unreadCount) {
|
||||
if (unreadCount < 100) {
|
||||
view.setText(String.valueOf(unreadCount));
|
||||
@ -231,7 +217,6 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("serverTypePadding")
|
||||
public static void setServerTypePadding(TextView view, String serverType) {
|
||||
int paddRight = 0;
|
||||
if (TextUtils.isEmpty(serverType)) {
|
||||
@ -249,7 +234,6 @@ public class BindingAdapters {
|
||||
view.setPadding(0, 0, paddRight, 0);
|
||||
}
|
||||
|
||||
@BindingAdapter("serverType")
|
||||
public static void setServerType(TextView view, String serverType) {
|
||||
view.setText(serverType);
|
||||
if ("删档内测".equals(serverType) || "不删档内测".equals(serverType)) {
|
||||
@ -259,26 +243,22 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("game")
|
||||
public static void setGame(View view, GameEntity gameEntity) {
|
||||
if (gameEntity != null && view instanceof GameIconView) {
|
||||
((GameIconView) view).displayGameIcon(gameEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("gameIcon")
|
||||
public static void setGameIcon(View view, GameEntity gameEntity) {
|
||||
if (gameEntity != null && view instanceof GameIconView) {
|
||||
((GameIconView) view).displayGameIcon(gameEntity.getIcon(), gameEntity.getIconSubscript());
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("articleType")
|
||||
public static void setArticleType(TextView view, String articleType) {
|
||||
NewsUtils.setNewsType(view, articleType, 0, 0);
|
||||
}
|
||||
|
||||
@BindingAdapter("detailDownloadText")
|
||||
public static void setDetailDownloadText(TextView view, GameEntity gameEntity) {
|
||||
if (gameEntity == null || gameEntity.getApk().isEmpty()) {
|
||||
view.setBackgroundResource(R.drawable.game_item_btn_pause_style);
|
||||
@ -287,7 +267,6 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("liBaoBtn")
|
||||
public static void setLiBaoBtn(TextView view, String status) {
|
||||
if (TextUtils.isEmpty(status)) return;
|
||||
switch (status) {
|
||||
@ -352,7 +331,6 @@ public class BindingAdapters {
|
||||
}
|
||||
|
||||
// 大图下的进度条
|
||||
@BindingAdapter({"downloadButton", "traceEvent", "clickCallBack", "entrance", "location"})
|
||||
public static void setDownloadButton(DownloadProgressBar progressBar,
|
||||
GameEntity gameEntity,
|
||||
ExposureEvent traceEvent,
|
||||
@ -602,6 +580,7 @@ public class BindingAdapters {
|
||||
case notfound:
|
||||
case uncertificated:
|
||||
case unqualified:
|
||||
case unavailable:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -692,13 +671,11 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("gameLabelList")
|
||||
public static void setGameLabelList(LinearLayout layout, List<TagStyleEntity> tagStyle) {
|
||||
GameViewUtils.setLabelList(layout.getContext(), layout, tagStyle);
|
||||
}
|
||||
|
||||
// 包含测试开服标签
|
||||
@BindingAdapter("setGameTags")
|
||||
public static void setGameTags(LinearLayout layout, GameEntity gameEntity) {
|
||||
try {
|
||||
if (layout.getVisibility() == View.GONE) return;
|
||||
@ -739,7 +716,6 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("setVideoDetailGameTags")
|
||||
public static void setVideoDetailGameTags(LinearLayout layout, GameEntity gameEntity) {
|
||||
try {
|
||||
ArrayList<TagStyleEntity> tagStyle = new ArrayList<>();
|
||||
@ -767,14 +743,12 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("isRefreshing")
|
||||
public static void isRefreshing(SwipeRefreshLayout layout, LoadStatus status) {
|
||||
if (status != LoadStatus.INIT_LOADING && status != LoadStatus.LIST_LOADING) {
|
||||
layout.setRefreshing(false);
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"setGameName", "isShowPlatform", "isShowSuffix"})
|
||||
public static void setGameName(TextView view, GameEntity game, boolean isShowPlatform, @Nullable Boolean isShowSuffix) {
|
||||
if (isShowSuffix == null) isShowSuffix = true; // 默认显示
|
||||
if (isShowPlatform && game.getApk().size() > 0) {
|
||||
@ -787,7 +761,6 @@ public class BindingAdapters {
|
||||
|
||||
}
|
||||
|
||||
@BindingAdapter({"setCommunityImage", "setCommunityVideoImage"})
|
||||
public static void setCommunityImage(SimpleDraweeView imageView, List<String> images, List<CommunityVideoEntity> videos) {
|
||||
if (videos.size() > 0) {
|
||||
CommunityVideoEntity videoEntity = videos.get(0);
|
||||
@ -801,7 +774,6 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"setCommunityVideoDuration"})
|
||||
public static void setCommunityVideoDuration(TextView mVideoDuration, List<CommunityVideoEntity> videos) {
|
||||
if (videos != null && videos.size() > 0) {
|
||||
CommunityVideoEntity videoEntity = videos.get(0);
|
||||
@ -813,7 +785,6 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter({"setGameTags", "setMaxGameTags"})
|
||||
public static void setGameTags(TextView view, List<TagStyleEntity> tags, int maxTags) {
|
||||
if (tags == null) {
|
||||
view.setText("");
|
||||
@ -842,7 +813,6 @@ public class BindingAdapters {
|
||||
view.setText(span);
|
||||
}
|
||||
|
||||
@BindingAdapter({"setVideoData"})
|
||||
public static void setVideoData(TextView view, int count) {
|
||||
if (count > 0) {
|
||||
view.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(view.getContext(), R.drawable.ic_video_data_up), null, null, null);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -87,7 +87,7 @@ class ApplyModeratorDialogFragment : BaseDialogFragment() {
|
||||
}
|
||||
}.show(
|
||||
activity.supportFragmentManager,
|
||||
PrivacyDialogFragment::class.java.simpleName
|
||||
ApplyModeratorDialogFragment::class.java.simpleName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,10 +129,17 @@ class CertificationDialog(context: Context, private val authDialogEntity: AuthDi
|
||||
val currentActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
|
||||
AvoidOnResultManager.getInstance(currentActivity as AppCompatActivity)
|
||||
.startForResult(ShellActivity.getIntent(context, ShellActivity.Type.REAL_NAME_INFO, null), object : Callback {
|
||||
.startForResult(
|
||||
ShellActivity.getIntent(
|
||||
context,
|
||||
ShellActivity.Type.REAL_NAME_INFO,
|
||||
).apply {
|
||||
putExtra(EntranceUtils.KEY_GAME_ID, gameId)
|
||||
}, object : Callback {
|
||||
override fun onActivityResult(resultCode: Int, data: Intent?) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val isAuthSuccess = data.getBooleanExtra(UserInfoEditFragment.AUTH_SUCCESS, false)
|
||||
val isAuthSuccess =
|
||||
data.getBooleanExtra(UserInfoEditFragment.AUTH_SUCCESS, false)
|
||||
if (isAuthSuccess) {
|
||||
listener.onConfirm()
|
||||
dismiss()
|
||||
|
||||
@ -23,6 +23,7 @@ import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DialogDeviceRemindBinding
|
||||
import com.gh.gamecenter.entity.DeviceDialogEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.google.gson.reflect.TypeToken
|
||||
@ -31,14 +32,13 @@ import com.lightgame.download.DataWatcher
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.android.synthetic.main.dialog_device_remind.view.*
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
* 设备提醒弹窗
|
||||
*/
|
||||
class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val gameEntity: GameEntity) : Dialog(context, R.style.GhAlertDialog) {
|
||||
private lateinit var view: View
|
||||
private val mBinding: DialogDeviceRemindBinding by lazy { DialogDeviceRemindBinding.inflate(layoutInflater) }
|
||||
private var currentPage = 0
|
||||
private var mSlideLooperInterval = 3000L
|
||||
private lateinit var mLooperHandle: LooperHandle
|
||||
@ -96,13 +96,12 @@ class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val g
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
view = LayoutInflater.from(context).inflate(R.layout.dialog_device_remind, null)
|
||||
setContentView(view)
|
||||
setContentView(mBinding.root)
|
||||
mDatas.addAll(entity.gallery)
|
||||
view.titleTv.text = entity.title
|
||||
view.contentTv.text = entity.content
|
||||
mBinding.titleTv.text = entity.title
|
||||
mBinding.contentTv.text = entity.content
|
||||
|
||||
view.bannerView.apply {
|
||||
mBinding.bannerView.apply {
|
||||
orientation = ViewPager2.ORIENTATION_HORIZONTAL
|
||||
mAdapter = BannerAdapter()
|
||||
val recyclerView = getChildAt(0) as RecyclerView
|
||||
@ -133,36 +132,36 @@ class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val g
|
||||
}
|
||||
val isFirst = SPUtils.getBoolean(Constants.SP_FIRST_DEVICE_REMIND, false)
|
||||
if (!isFirst) {
|
||||
view.cancelTv.isEnabled = false
|
||||
view.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_round_f5f5f5)
|
||||
mBinding.cancelTv.isEnabled = false
|
||||
mBinding.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_round_f5f5f5)
|
||||
disposable = countDownTimer(3) { finish, time ->
|
||||
if (finish) {
|
||||
view.cancelTv.isEnabled = true
|
||||
view.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_blue_oval)
|
||||
view.cancelTv.text = "我知道了"
|
||||
view.cancelTv.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
mBinding.cancelTv.isEnabled = true
|
||||
mBinding.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_blue_oval)
|
||||
mBinding.cancelTv.text = "我知道了"
|
||||
mBinding.cancelTv.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
} else {
|
||||
view.cancelTv.text = "我知道了(${time}S)"
|
||||
mBinding.cancelTv.text = "我知道了(${time}S)"
|
||||
}
|
||||
}
|
||||
|
||||
SPUtils.setBoolean(Constants.SP_FIRST_DEVICE_REMIND, true)
|
||||
} else {
|
||||
view.noRemindAgainCb.visibility = View.VISIBLE
|
||||
view.cancelTv.text = "我知道了"
|
||||
view.cancelTv.isEnabled = true
|
||||
view.cancelTv.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
view.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_blue_oval)
|
||||
mBinding.noRemindAgainCb.visibility = View.VISIBLE
|
||||
mBinding.cancelTv.text = "我知道了"
|
||||
mBinding.cancelTv.isEnabled = true
|
||||
mBinding.cancelTv.setTextColor(ContextCompat.getColor(context, R.color.white))
|
||||
mBinding.cancelTv.background = ContextCompat.getDrawable(context, R.drawable.button_blue_oval)
|
||||
}
|
||||
view.cancelTv.setOnClickListener {
|
||||
SPUtils.setBoolean(Constants.SP_NO_REMIND_AGAIN, view.noRemindAgainCb.isChecked)
|
||||
mBinding.cancelTv.setOnClickListener {
|
||||
SPUtils.setBoolean(Constants.SP_NO_REMIND_AGAIN, mBinding.noRemindAgainCb.isChecked)
|
||||
dismiss()
|
||||
}
|
||||
DownloadManager.getInstance().addObserver(dataWatcher)
|
||||
}
|
||||
|
||||
private fun addIndicator() {
|
||||
view.indicatorLl.removeAllViews()
|
||||
mBinding.indicatorLl.removeAllViews()
|
||||
mDatas.forEach { _ ->
|
||||
val indicatorView = ImageView(context).apply {
|
||||
setImageResource(R.drawable.selector_device_remind_indicator)
|
||||
@ -171,13 +170,13 @@ class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val g
|
||||
params.rightMargin = DisplayUtils.dip2px(1F)
|
||||
layoutParams = params
|
||||
}
|
||||
view.indicatorLl.addView(indicatorView)
|
||||
mBinding.indicatorLl.addView(indicatorView)
|
||||
}
|
||||
}
|
||||
|
||||
private fun slideIndicator(position: Int) {
|
||||
for (i in 0 until view.indicatorLl.childCount) {
|
||||
val childAt = view.indicatorLl.getChildAt(i)
|
||||
for (i in 0 until mBinding.indicatorLl.childCount) {
|
||||
val childAt = mBinding.indicatorLl.getChildAt(i)
|
||||
childAt.isSelected = i == position
|
||||
}
|
||||
}
|
||||
@ -210,7 +209,7 @@ class DeviceRemindDialog(context: Context, val entity: DeviceDialogEntity, val g
|
||||
|
||||
fun scrollToNextPage() {
|
||||
currentPage++
|
||||
view.bannerView.setCurrentItem(currentPage, true)
|
||||
mBinding.bannerView.setCurrentItem(currentPage, true)
|
||||
}
|
||||
|
||||
fun startScroll() {
|
||||
|
||||
@ -19,6 +19,7 @@ import com.gh.common.util.PermissionHelper.INSTALL_PERMISSION_CODE
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.gamecenter.R
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
import kotlin.random.Random
|
||||
|
||||
class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
|
||||
@ -26,7 +27,7 @@ class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
|
||||
lateinit var mView: View
|
||||
var isXapk = false
|
||||
var url: String = ""
|
||||
var mCallBack: (() -> Unit)? = null
|
||||
var mCallBack: ((isFromPermissionGrantedCallback: Boolean) -> Unit)? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
mView = inflater.inflate(R.layout.dialog_install_permission, null, false)
|
||||
@ -56,7 +57,7 @@ class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
|
||||
closeTv.setOnClickListener {
|
||||
MtaHelper.onEvent(getEvent(), getKey(), "文案样式_点击以后再说")
|
||||
if (isXapk) {
|
||||
mCallBack?.invoke()
|
||||
mCallBack?.invoke(false)
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
@ -77,9 +78,11 @@ class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (resultCode == RESULT_OK && requestCode == INSTALL_PERMISSION_CODE) {
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "")
|
||||
SPUtils.setString(Constants.SP_XAPK_URL, "")
|
||||
mCallBack?.invoke()
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
|
||||
SPUtils.setString(Constants.SP_XAPK_UNZIP_ACTIVITY, "")
|
||||
SPUtils.setString(Constants.SP_XAPK_URL, "")
|
||||
}
|
||||
mCallBack?.invoke(true)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
@ -90,27 +93,27 @@ class InstallPermissionDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun show(activity: AppCompatActivity, downloadEntity: DownloadEntity, callBack: (() -> Unit)?) {
|
||||
fun show(activity: AppCompatActivity, downloadEntity: DownloadEntity, callBack: ((isFromPermissionGrantedCallback: Boolean) -> Unit)?) {
|
||||
val isXapk = XapkInstaller.XAPK_EXTENSION_NAME == downloadEntity.path.getExtension()
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
callBack?.invoke()
|
||||
callBack?.invoke(false)
|
||||
return
|
||||
}
|
||||
val haveInstallPermission = activity.packageManager.canRequestPackageInstalls()
|
||||
if (haveInstallPermission) {
|
||||
callBack?.invoke()
|
||||
callBack?.invoke(false)
|
||||
return
|
||||
}
|
||||
if (isXapk) {
|
||||
val xapkUnzipVersions = Config.getSettings()?.permissionPopupAppliedVersions?.xapkUnzip
|
||||
if (xapkUnzipVersions?.contains(Build.VERSION.SDK_INT.toString()) == false) {
|
||||
callBack?.invoke()
|
||||
callBack?.invoke(false)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
val installVersions = Config.getSettings()?.permissionPopupAppliedVersions?.install
|
||||
if (installVersions?.contains(Build.VERSION.SDK_INT.toString()) == false) {
|
||||
callBack?.invoke()
|
||||
callBack?.invoke(false)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,10 +16,10 @@ import com.gh.common.util.PermissionHelper
|
||||
import com.gh.common.util.fromHtml
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DialogNotificationHintBinding
|
||||
import com.gh.gamecenter.entity.NotificationStyleEntity
|
||||
import com.gh.gamecenter.entity.NotificationUgc
|
||||
import com.lightgame.utils.Utils
|
||||
import kotlinx.android.synthetic.main.dialog_notification_hint.*
|
||||
import org.json.JSONArray
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
@ -30,9 +30,10 @@ import kotlin.random.Random
|
||||
class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
|
||||
private var mNotificationUgc: NotificationUgc? = null
|
||||
private val mBinding: DialogNotificationHintBinding by lazy { DialogNotificationHintBinding.inflate(layoutInflater) }
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.dialog_notification_hint, null)
|
||||
return mBinding.root
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@ -55,39 +56,41 @@ class NotificationHintDialogFragment : BaseTrackableDialogFragment() {
|
||||
val styleEntityJson = jsonObj.getJSONObject(mNotificationUgc!!.value)
|
||||
val styleEntity = GsonUtils.fromJson(styleEntityJson.toString(), NotificationStyleEntity::class.java)
|
||||
val drawableId = resources.getIdentifier(styleEntity.image, "drawable", requireContext().packageName)
|
||||
notificationIv.setImageDrawable(ContextCompat.getDrawable(requireContext(), drawableId))
|
||||
notificationTitle.text = styleEntity.title
|
||||
notificationContent.text = styleEntity.content.fromHtml()
|
||||
if (index == 0) {
|
||||
closeIv.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_notification_close_1))
|
||||
} else {
|
||||
activateTv.background = ContextCompat.getDrawable(requireContext(), R.drawable.bg_notification_open_btn_style_1)
|
||||
activateTv.text = "优雅的开启"
|
||||
}
|
||||
mBinding.run {
|
||||
notificationIv.setImageDrawable(ContextCompat.getDrawable(requireContext(), drawableId))
|
||||
notificationTitle.text = styleEntity.title
|
||||
notificationContent.text = styleEntity.content.fromHtml()
|
||||
if (index == 0) {
|
||||
closeIv.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_notification_close_1))
|
||||
} else {
|
||||
activateTv.background = ContextCompat.getDrawable(requireContext(), R.drawable.bg_notification_open_btn_style_1)
|
||||
activateTv.text = "优雅的开启"
|
||||
}
|
||||
|
||||
activateTv.setOnClickListener {
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击立即开启")
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击立即开启")
|
||||
dismissAllowingStateLoss()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
//这种方案适用于 API 26, 即8.0(含8.0)以上可以用
|
||||
val intent = Intent()
|
||||
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
|
||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID)
|
||||
try {
|
||||
startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
activateTv.setOnClickListener {
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击立即开启")
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击立即开启")
|
||||
dismissAllowingStateLoss()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
//这种方案适用于 API 26, 即8.0(含8.0)以上可以用
|
||||
val intent = Intent()
|
||||
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
|
||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID)
|
||||
try {
|
||||
startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
PermissionHelper.toPermissionSetting(requireActivity())
|
||||
}
|
||||
} else {
|
||||
PermissionHelper.toPermissionSetting(requireActivity())
|
||||
}
|
||||
} else {
|
||||
PermissionHelper.toPermissionSetting(requireActivity())
|
||||
}
|
||||
}
|
||||
|
||||
closeIv.setOnClickListener {
|
||||
dismissAllowingStateLoss()
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击关闭")
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击关闭")
|
||||
closeIv.setOnClickListener {
|
||||
dismissAllowingStateLoss()
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "点击关闭")
|
||||
MtaHelper.onEventWithBasicDeviceInfo(getEvent(), getKey(), "${styleEntity.scenes}_${styleEntity.styleNo}_点击关闭")
|
||||
}
|
||||
}
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
|
||||
@ -62,9 +62,11 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
detectionObjects?.forEach { detectionObject ->
|
||||
if (detectionObject.packages.contains(packageName)) {
|
||||
val packageLink = gameEntity?.packageDialog?.links?.find { it.buttonLink }
|
||||
LogUtils.uploadPackageCheck("pkg_check_pop_download", if (DownloadStatus.add == downloadEntity.status) "下载开始" else "下载完成",
|
||||
gameEntity, packageLink?.text ?: "", packageLink?.title
|
||||
?: "", downloadEntity.gameId, downloadEntity.getMetaExtra(Constants.GAME_NAME))
|
||||
LogUtils.uploadPackageCheck(
|
||||
"pkg_check_pop_download", if (DownloadStatus.add == downloadEntity.status) "下载开始" else "下载完成",
|
||||
gameEntity, packageLink?.text ?: "", packageLink?.title
|
||||
?: "", downloadEntity.gameId, downloadEntity.getMetaExtra(Constants.GAME_NAME)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -98,8 +100,10 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
|
||||
val spanBuilder = SpanBuilder(it.linkHintText).build()
|
||||
it.links.forEachIndexed { index, link ->
|
||||
val linkSpan = SpanBuilder(link.title ?: "").click(0, (link.title
|
||||
?: "").length, R.color.theme_font, true) {
|
||||
val linkSpan = SpanBuilder(link.title ?: "").click(
|
||||
0, (link.title
|
||||
?: "").length, R.color.theme_font, true
|
||||
) {
|
||||
LogUtils.uploadPackageCheck("pkg_check_pop_click", "点击链接", gameEntity, link.text, link.title, "", "")
|
||||
DirectUtils.directToLinkPage(requireContext(), link, "包名检测弹窗", "")
|
||||
}.build()
|
||||
@ -205,6 +209,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
if (it >= mDuration) {
|
||||
mDisposable?.dispose()
|
||||
binding.downloadBtn.isEnabled = true
|
||||
binding.downloadBtn.background = R.drawable.bg_notification_open_btn_style_2.toDrawable()
|
||||
}
|
||||
}
|
||||
val animator = ValueAnimator.ofInt(0, 100)
|
||||
@ -273,7 +278,8 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
inner class PackageCheckAdapter(val context: Context, val entities: ArrayList<DetectionObjectEntity>) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
inner class PackageCheckAdapter(val context: Context, val entities: ArrayList<DetectionObjectEntity>) :
|
||||
BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
private var index = -1
|
||||
|
||||
fun notifyPackages() {
|
||||
@ -282,7 +288,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return PackageCheckViewHolder(PackageCheckItemBinding.bind(LayoutInflater.from(context).inflate(R.layout.package_check_item, parent, false)))
|
||||
return PackageCheckViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = entities.size
|
||||
@ -290,7 +296,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is PackageCheckViewHolder) {
|
||||
val entity = entities[position]
|
||||
holder.binding.entity = entity
|
||||
holder.binding.gameNameTv.text = entity.text
|
||||
if (position <= index) {
|
||||
val isAllInstalled = checkDetectionsInstalled(mAllInstalledPackages, entity.packages)
|
||||
if (isAllInstalled) {
|
||||
@ -339,7 +345,8 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
|
||||
|
||||
if (!activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) return
|
||||
|
||||
var dialogFragment = activity.supportFragmentManager.findFragmentByTag(PackageCheckDialogFragment::class.java.simpleName) as? PackageCheckDialogFragment
|
||||
var dialogFragment =
|
||||
activity.supportFragmentManager.findFragmentByTag(PackageCheckDialogFragment::class.java.simpleName) as? PackageCheckDialogFragment
|
||||
if (dialogFragment == null) {
|
||||
dialogFragment = PackageCheckDialogFragment()
|
||||
dialogFragment.gameEntity = gameEntity
|
||||
|
||||
@ -1,157 +0,0 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.TextPaint
|
||||
import android.text.method.ScrollingMovementMethod
|
||||
import android.text.style.ClickableSpan
|
||||
import android.view.*
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.common.view.CustomLinkMovementMethod
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
|
||||
class PrivacyDialogFragment : BaseDialogFragment() {
|
||||
|
||||
// private val mLocalPrivacyHtml = "file:///android_asset/privacy_policies.html"
|
||||
// private val mLocalRegulationHtml = "file:///android_asset/user_regulation.html"
|
||||
|
||||
var containerView: View? = null
|
||||
var mCallBack: ((isSuccess: Boolean) -> Unit)? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
containerView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_privacy_protocol, null, false)
|
||||
return containerView
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
// val mWebViewPrivacy = containerView?.findViewById<WebView>(R.id.webView)
|
||||
// val mWebViewRegulation = containerView?.findViewById<WebView>(R.id.webView2)
|
||||
//
|
||||
// mWebViewPrivacy?.isHorizontalScrollBarEnabled = false
|
||||
// mWebViewRegulation?.isHorizontalScrollBarEnabled = false
|
||||
|
||||
val contentTv = containerView?.findViewById<TextView>(R.id.contentTv)
|
||||
val descTv = containerView?.findViewById<TextView>(R.id.descTv)
|
||||
contentTv?.movementMethod = ScrollingMovementMethod()
|
||||
|
||||
val skipText = SpannableStringBuilder("查看完整版的隐私政策和用户协议")
|
||||
skipText.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
val intent = WebActivity.getIntent(requireContext(), context!!.getString(R.string.privacy_policy_url), true)
|
||||
context?.startActivity(intent)
|
||||
}
|
||||
}, skipText.length - 9, skipText.length - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
|
||||
skipText.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
val intent = WebActivity.getIntent(requireContext(), context!!.getString(R.string.disclaimer_url), true)
|
||||
context?.startActivity(intent)
|
||||
}
|
||||
}, skipText.length - 4, skipText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
descTv?.movementMethod = CustomLinkMovementMethod()
|
||||
descTv?.text = skipText
|
||||
|
||||
// val mWebViewPrivacy = containerView?.findViewById<WebView>(R.id.webView)
|
||||
//
|
||||
// mWebViewPrivacy?.isHorizontalScrollBarEnabled = false
|
||||
//
|
||||
// val settingsArrayList = arrayListOf(mWebViewPrivacy?.settings, mWebViewRegulation?.settings)
|
||||
//
|
||||
// for (settings in settingsArrayList) {
|
||||
// settings?.javaScriptEnabled = true
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// settings?.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
|
||||
// }
|
||||
// // 避免提示网页有害信息不能访问
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// settings?.safeBrowsingEnabled = false
|
||||
// }
|
||||
//
|
||||
// // 适配大于屏幕宽度的页面
|
||||
// settings?.useWideViewPort = true
|
||||
// settings?.loadWithOverviewMode = true
|
||||
// settings?.domStorageEnabled = true
|
||||
//
|
||||
// // 自适应屏幕
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
// settings?.layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING
|
||||
// }
|
||||
// }
|
||||
|
||||
// mWebViewPrivacy?.webViewClient = client
|
||||
// mWebViewRegulation?.webViewClient = client
|
||||
|
||||
containerView?.findViewById<View>(R.id.refuseTv)?.setOnClickListener {
|
||||
mCallBack?.invoke(false)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
containerView?.findViewById<View>(R.id.agreeTv)?.setOnClickListener {
|
||||
mCallBack?.invoke(true)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val createDialog = super.onCreateDialog(savedInstanceState)
|
||||
createDialog.setCanceledOnTouchOutside(false)
|
||||
createDialog.setOnKeyListener(object : DialogInterface.OnKeyListener {
|
||||
override fun onKey(dialog: DialogInterface?, keyCode: Int, event: KeyEvent?): Boolean {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
val window = createDialog.window
|
||||
window?.setGravity(Gravity.CENTER)
|
||||
return createDialog
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = requireContext().resources.displayMetrics.widthPixels - 60F.dip2px()
|
||||
val height = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
dialog?.window?.setLayout(width, height)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun show(activity: AppCompatActivity, callBack: ((isSuccess: Boolean) -> Unit)?) {
|
||||
var privacyDialogFragment = activity.supportFragmentManager.findFragmentByTag(PrivacyDialogFragment::class.java.simpleName) as? PrivacyDialogFragment
|
||||
if (privacyDialogFragment != null) {
|
||||
privacyDialogFragment.mCallBack = callBack
|
||||
val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction()
|
||||
transaction.show(privacyDialogFragment)
|
||||
transaction.commit()
|
||||
} else {
|
||||
privacyDialogFragment = PrivacyDialogFragment().apply {
|
||||
mCallBack = callBack
|
||||
}
|
||||
privacyDialogFragment.show(activity.supportFragmentManager, PrivacyDialogFragment::class.java.simpleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,190 @@
|
||||
package com.gh.common.dialog
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.TextPaint
|
||||
import android.text.method.ScrollingMovementMethod
|
||||
import android.text.style.ClickableSpan
|
||||
import android.view.*
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.common.util.fromHtml
|
||||
import com.gh.common.view.CustomLinkMovementMethod
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.databinding.DialogPrivacyProtocolBinding
|
||||
import com.gh.gamecenter.entity.DialogEntity
|
||||
import com.lightgame.utils.AppManager
|
||||
import splitties.bundle.put
|
||||
|
||||
class PrivacyPolicyDialogFragment : BaseDialogFragment() {
|
||||
|
||||
private var mCallBack: ((isSuccess: Boolean) -> Unit)? = null
|
||||
private val mBinding by lazy { DialogPrivacyProtocolBinding.inflate(layoutInflater) }
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
return mBinding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mBinding.contentTv.movementMethod = ScrollingMovementMethod()
|
||||
|
||||
val privacyPolicyEntity = arguments?.get(KEY_DATA) as? DialogEntity.PrivacyPolicyEntity
|
||||
if (privacyPolicyEntity == null) {
|
||||
showPreLaunchStyle()
|
||||
} else {
|
||||
showUpdatedStyle(privacyPolicyEntity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showUpdatedStyle(privacyPolicyEntity: DialogEntity.PrivacyPolicyEntity) {
|
||||
mBinding.titleIv.visibility = View.VISIBLE
|
||||
mBinding.privacyTitleTv.text = "光环助手《隐私协议》更新"
|
||||
mBinding.contentTv.text = privacyPolicyEntity.content.fromHtml()
|
||||
|
||||
val skipText = SpannableStringBuilder("查看隐私政策详情")
|
||||
skipText.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
val intent = WebActivity.getIntent(requireContext(), context!!.getString(R.string.privacy_policy_url), true)
|
||||
context?.startActivity(intent)
|
||||
}
|
||||
}, skipText.length - 6, skipText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
mBinding.descTv.movementMethod = CustomLinkMovementMethod()
|
||||
mBinding.descTv.text = skipText
|
||||
|
||||
if (privacyPolicyEntity.alertType == "INFORM") {
|
||||
mBinding.refuseTv.visibility = View.GONE
|
||||
mBinding.agreeTv.text = "我知道了"
|
||||
mBinding.agreeTv.setOnClickListener {
|
||||
SPUtils.setString(Constants.SP_LAST_ACCEPTED_PRIVACY_DIALOG_ID, privacyPolicyEntity.id)
|
||||
mCallBack?.invoke(true)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
} else {
|
||||
mBinding.refuseTv.text = "不同意退出"
|
||||
mBinding.agreeTv.text = "同意"
|
||||
mBinding.refuseTv.setOnClickListener {
|
||||
dismissAllowingStateLoss()
|
||||
AppManager.getInstance().finishAllActivity()
|
||||
}
|
||||
mBinding.agreeTv.setOnClickListener {
|
||||
SPUtils.setString(Constants.SP_LAST_ACCEPTED_PRIVACY_DIALOG_ID, privacyPolicyEntity.id)
|
||||
mCallBack?.invoke(true)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPreLaunchStyle() {
|
||||
val skipText = SpannableStringBuilder("查看完整版的隐私政策和用户协议")
|
||||
|
||||
skipText.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
val intent = WebActivity.getIntent(requireContext(), context!!.getString(R.string.privacy_policy_url), true)
|
||||
context?.startActivity(intent)
|
||||
}
|
||||
}, skipText.length - 9, skipText.length - 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
|
||||
skipText.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = ContextCompat.getColor(requireContext(), R.color.theme_font)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
val intent = WebActivity.getIntent(requireContext(), context!!.getString(R.string.disclaimer_url), true)
|
||||
context?.startActivity(intent)
|
||||
}
|
||||
}, skipText.length - 4, skipText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
mBinding.descTv.movementMethod = CustomLinkMovementMethod()
|
||||
mBinding.descTv.text = skipText
|
||||
|
||||
mBinding.refuseTv.setOnClickListener {
|
||||
mCallBack?.invoke(false)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
mBinding.agreeTv.setOnClickListener {
|
||||
mCallBack?.invoke(true)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val createDialog = super.onCreateDialog(savedInstanceState)
|
||||
createDialog.setCanceledOnTouchOutside(false)
|
||||
createDialog.setOnKeyListener(object : DialogInterface.OnKeyListener {
|
||||
override fun onKey(dialog: DialogInterface?, keyCode: Int, event: KeyEvent?): Boolean {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
val window = createDialog.window
|
||||
window?.setGravity(Gravity.CENTER)
|
||||
return createDialog
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val width = requireContext().resources.displayMetrics.widthPixels - 60F.dip2px()
|
||||
val height = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
dialog?.window?.setLayout(width, height)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_DATA = "data"
|
||||
|
||||
@JvmStatic
|
||||
fun show(activity: FragmentActivity,
|
||||
privacyPolicyEntity: DialogEntity.PrivacyPolicyEntity? = null,
|
||||
callBack: ((isSuccess: Boolean) -> Unit)?) {
|
||||
var privacyDialogFragment = activity.supportFragmentManager.findFragmentByTag(PrivacyPolicyDialogFragment::class.java.simpleName) as? PrivacyPolicyDialogFragment
|
||||
if (privacyDialogFragment != null) {
|
||||
privacyDialogFragment.mCallBack = callBack
|
||||
val transaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction()
|
||||
transaction.show(privacyDialogFragment)
|
||||
transaction.commit()
|
||||
} else {
|
||||
privacyDialogFragment = PrivacyPolicyDialogFragment().apply {
|
||||
mCallBack = callBack
|
||||
}
|
||||
}
|
||||
privacyDialogFragment.arguments = Bundle().apply {
|
||||
put(KEY_DATA, privacyPolicyEntity)
|
||||
}
|
||||
privacyDialogFragment.show(
|
||||
activity.supportFragmentManager,
|
||||
PrivacyPolicyDialogFragment::class.java.simpleName
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@ package com.gh.common.exposure
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Keep
|
||||
@Parcelize
|
||||
@ -12,6 +12,8 @@ data class ExposureEntity(
|
||||
val gameId: String? = "",
|
||||
@SerializedName("subject_id")
|
||||
val subjectId: String? = null, // 专题 id
|
||||
@SerializedName("carousel_id")
|
||||
val carouselId: String? = "", // 轮播图 id
|
||||
val gameName: String? = "",
|
||||
val gameVersion: String? = "",
|
||||
val sequence: Int? = 0,
|
||||
@ -43,6 +45,8 @@ data class ExposureEntity(
|
||||
var categoryId: String? = null,
|
||||
@SerializedName("category_v2_id")
|
||||
var categoryV2Id: String? = null,
|
||||
@SerializedName("navigation_id")
|
||||
var navigationId: String? = null,
|
||||
|
||||
// 专题详情的来源页面和来源 id
|
||||
@SerializedName("source_page")
|
||||
@ -69,6 +73,7 @@ data class ExposureEntity(
|
||||
BLOCK_ID -> blockId = id
|
||||
CATEGORY_ID -> categoryId = id
|
||||
CATEGORY_V2_ID -> categoryV2Id = id
|
||||
NAVIGATION_ID -> navigationId = id
|
||||
}
|
||||
|
||||
containerId = null
|
||||
@ -80,5 +85,6 @@ data class ExposureEntity(
|
||||
const val BLOCK_ID = "block_id"
|
||||
const val CATEGORY_ID = "category_id"
|
||||
const val CATEGORY_V2_ID = "category_v2_id"
|
||||
const val NAVIGATION_ID = "navigation_id"
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,7 @@ import com.gh.common.util.getFirstElementDividedByDivider
|
||||
import com.gh.download.server.BrowserInstallHelper
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ package com.gh.common.exposure
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Keep
|
||||
@Parcelize
|
||||
|
||||
@ -2,7 +2,7 @@ package com.gh.common.exposure.meta
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Keep
|
||||
@Parcelize
|
||||
|
||||
@ -15,7 +15,6 @@ import com.gh.common.util.tryWithDefaultCatch
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.leon.channel.helper.ChannelReaderUtil
|
||||
import com.walkud.rom.checker.RomIdentifier
|
||||
|
||||
object MetaUtil {
|
||||
|
||||
@ -16,7 +16,7 @@ import com.gh.gamecenter.room.converter.*
|
||||
import com.gh.gamecenter.room.dao.*
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class, GamesCollectionEntity::class], version = 10, exportSchema = false)
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class, GamesCollectionEntity::class], version = 11, exportSchema = false)
|
||||
@TypeConverters(CountConverter::class,
|
||||
CommunityConverter::class,
|
||||
TimeConverter::class,
|
||||
@ -32,7 +32,8 @@ import com.halo.assistant.HaloApp
|
||||
QuestionsConverter::class,
|
||||
MeConverter::class,
|
||||
SimpleGameListConverter::class,
|
||||
TagInfoListConverter::class)
|
||||
TagInfoListConverter::class,
|
||||
ActivityLabelListConverter::class)
|
||||
|
||||
abstract class HistoryDatabase : RoomDatabase() {
|
||||
|
||||
@ -113,6 +114,12 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_10_11: Migration = object : Migration(10, 11) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("Alter TABLE GamesCollectionEntity add activityTags TEXT DEFAULT ''")
|
||||
}
|
||||
}
|
||||
|
||||
val instance by lazy {
|
||||
Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE")
|
||||
.addMigrations(MIGRATION_2_3)
|
||||
@ -123,6 +130,7 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
.addMigrations(MIGRATION_7_8)
|
||||
.addMigrations(MIGRATION_8_9)
|
||||
.addMigrations(MIGRATION_9_10)
|
||||
.addMigrations(MIGRATION_10_11)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,7 +52,6 @@ object HistoryHelper {
|
||||
historyGame.iconSubscript = updateEntity.iconSubscript
|
||||
historyGame.name = updateEntity.name
|
||||
historyGame.tagStyle = updateEntity.tagStyle
|
||||
historyGame.tag = updateEntity.tag
|
||||
return historyGame
|
||||
}
|
||||
|
||||
@ -161,6 +160,7 @@ object HistoryHelper {
|
||||
|
||||
gamesCollectionEntity.id = gamesCollectionDetailEntity.id
|
||||
gamesCollectionEntity.tags = gamesCollectionDetailEntity.tags
|
||||
gamesCollectionEntity.activityTags = gamesCollectionDetailEntity.activityTags
|
||||
gamesCollectionDetailEntity.games?.take(3)?.map { it.toSimpleGame() }?.run {
|
||||
gamesCollectionEntity.games = ArrayList(this)
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.util.*
|
||||
|
||||
@Keep
|
||||
|
||||
@ -36,7 +36,14 @@ object LoghubHelper {
|
||||
}
|
||||
|
||||
private fun createClient(logStore: String): LogProducerClient {
|
||||
val config = LogProducerConfig(ENDPOINT, PROJECT, logStore, ACCESS_KEY_ID, ACCESS_KEY_SECRET).apply {
|
||||
val config = LogProducerConfig(
|
||||
HaloApp.getInstance().applicationContext,
|
||||
ENDPOINT,
|
||||
PROJECT,
|
||||
logStore,
|
||||
ACCESS_KEY_ID,
|
||||
ACCESS_KEY_SECRET
|
||||
).apply {
|
||||
// 1 开启断点续传功能, 0 关闭
|
||||
// 每次发送前会把日志保存到本地的binlog文件,只有发送成功才会删除,保证日志上传At Least Once
|
||||
setPersistent(1)
|
||||
@ -74,17 +81,25 @@ object LoghubHelper {
|
||||
return if (!PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
LogProducerClient(config)
|
||||
} else {
|
||||
return LogProducerClient(config,
|
||||
LogProducerCallback { resultCode, reqId, errorMessage, logBytes, compressedBytes ->
|
||||
|
||||
// resultCode 返回结果代码
|
||||
// reqId 请求id
|
||||
// errorMessage 错误信息,没有为null
|
||||
// logBytes 日志大小
|
||||
// compressedBytes 压缩后日志大小
|
||||
Utils.log("LoghubHelper -> ${String.format("%s %s %s %s %s",
|
||||
LogProducerResult.fromInt(resultCode), reqId, errorMessage, logBytes, compressedBytes)}")
|
||||
})
|
||||
LogProducerClient(config) { resultCode, reqId, errorMessage, logBytes, compressedBytes ->
|
||||
// resultCode 返回结果代码
|
||||
// reqId 请求id
|
||||
// errorMessage 错误信息,没有为null
|
||||
// logBytes 日志大小
|
||||
// compressedBytes 压缩后日志大小
|
||||
Utils.log(
|
||||
"LoghubHelper -> ${
|
||||
String.format(
|
||||
"%s %s %s %s %s",
|
||||
LogProducerResult.fromInt(resultCode),
|
||||
reqId,
|
||||
errorMessage,
|
||||
logBytes,
|
||||
compressedBytes
|
||||
)
|
||||
}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,13 +12,15 @@ import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.core.view.ViewCompat
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.common.util.doOnEnd
|
||||
import com.gh.common.util.doOnStart
|
||||
import com.gh.gamecenter.R
|
||||
import kotlinx.android.synthetic.main.view_notifier.view.*
|
||||
|
||||
class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
|
||||
: FrameLayout(context, attrs, defStyle) {
|
||||
@ -65,13 +67,21 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
|
||||
var showVerticalTranslateAnimation: Boolean = true
|
||||
|
||||
private var mCardView: CardView
|
||||
private var mContentTv: TextView
|
||||
private var mIconIv: SimpleDraweeView
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.view_notifier, this)
|
||||
|
||||
ViewCompat.setTranslationZ(this, Integer.MAX_VALUE.toFloat())
|
||||
|
||||
cardView.scaleX = SCALE_MINI
|
||||
cardView.scaleY = SCALE_MINI
|
||||
mCardView = findViewById(R.id.cardView)
|
||||
mContentTv = findViewById(R.id.tvText)
|
||||
mIconIv = findViewById(R.id.ivIcon)
|
||||
|
||||
mCardView.scaleX = SCALE_MINI
|
||||
mCardView.scaleY = SCALE_MINI
|
||||
|
||||
verticalAnimationOffset = dp2px(100F)
|
||||
|
||||
@ -113,7 +123,7 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
expandAnimator.duration = DEFAULT_DURATION
|
||||
expandAnimator.addUpdateListener { a ->
|
||||
val progress = a?.animatedValue as Float
|
||||
tvText.width = (textWidth * progress).toInt()
|
||||
mContentTv.width = (textWidth * progress).toInt()
|
||||
}
|
||||
expandAnimator.doOnEnd {
|
||||
enableSwipeToDismiss()
|
||||
@ -124,46 +134,46 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
shrinkAnimator.duration = DEFAULT_DURATION
|
||||
shrinkAnimator.addUpdateListener { a ->
|
||||
val progress = a?.animatedValue as Float
|
||||
tvText.width = (textWidth * progress).toInt()
|
||||
mContentTv.width = (textWidth * progress).toInt()
|
||||
}
|
||||
shrinkAnimator.doOnEnd {
|
||||
val lp = FrameLayout.LayoutParams(cardView.layoutParams)
|
||||
val lp = FrameLayout.LayoutParams(mCardView.layoutParams)
|
||||
lp.gravity = Gravity.NO_GRAVITY
|
||||
cardView.layoutParams = lp
|
||||
mCardView.layoutParams = lp
|
||||
|
||||
disableSwipeToDismiss()
|
||||
}
|
||||
|
||||
translateToLeftAnimator = ObjectAnimator.ofFloat(cardView, "translationX", veryRight, centerX)
|
||||
translateToLeftAnimator = ObjectAnimator.ofFloat(mCardView, "translationX", veryRight, centerX)
|
||||
translateToLeftAnimator.duration = DEFAULT_DURATION
|
||||
translateToLeftAnimator.doOnEnd {
|
||||
onShowListener?.onShow()
|
||||
|
||||
val lp = FrameLayout.LayoutParams(cardView.layoutParams)
|
||||
val lp = FrameLayout.LayoutParams(mCardView.layoutParams)
|
||||
lp.gravity = Gravity.CENTER_HORIZONTAL
|
||||
cardView.layoutParams = lp
|
||||
cardView.translationX = 0f
|
||||
mCardView.layoutParams = lp
|
||||
mCardView.translationX = 0f
|
||||
|
||||
expandAnimator.start()
|
||||
}
|
||||
|
||||
translateToRightAnimator = ObjectAnimator.ofFloat(cardView, "translationX", centerX, veryRight)
|
||||
translateToRightAnimator = ObjectAnimator.ofFloat(mCardView, "translationX", centerX, veryRight)
|
||||
translateToRightAnimator.duration = DEFAULT_DURATION
|
||||
|
||||
translateUpAnimator = ObjectAnimator.ofFloat(cardView, "translationY", veryBottom + verticalAnimationOffset, veryBottom)
|
||||
translateUpAnimator = ObjectAnimator.ofFloat(mCardView, "translationY", veryBottom + verticalAnimationOffset, veryBottom)
|
||||
translateUpAnimator.duration = DEFAULT_DURATION
|
||||
translateUpAnimator.doOnStart { cardView.translationX = veryRight }
|
||||
translateUpAnimator.doOnStart { mCardView.translationX = veryRight }
|
||||
|
||||
translateDownAnimator = ObjectAnimator.ofFloat(cardView, "translationY", veryBottom, veryBottom + verticalAnimationOffset)
|
||||
translateDownAnimator = ObjectAnimator.ofFloat(mCardView, "translationY", veryBottom, veryBottom + verticalAnimationOffset)
|
||||
translateDownAnimator.duration = DEFAULT_DURATION
|
||||
|
||||
zoomInAnimator = ObjectAnimator.ofPropertyValuesHolder(cardView, PropertyValuesHolder.ofFloat("scaleX", SCALE_DEFAULT),
|
||||
zoomInAnimator = ObjectAnimator.ofPropertyValuesHolder(mCardView, PropertyValuesHolder.ofFloat("scaleX", SCALE_DEFAULT),
|
||||
PropertyValuesHolder.ofFloat("scaleY", SCALE_DEFAULT))
|
||||
zoomInAnimator.duration = DEFAULT_DURATION
|
||||
zoomInAnimator.doOnStart { cardView.translationX = veryRight }
|
||||
zoomInAnimator.doOnStart { cardView.translationY = veryBottom }
|
||||
zoomInAnimator.doOnStart { mCardView.translationX = veryRight }
|
||||
zoomInAnimator.doOnStart { mCardView.translationY = veryBottom }
|
||||
|
||||
zoomOutAnimator = ObjectAnimator.ofPropertyValuesHolder(cardView, PropertyValuesHolder.ofFloat("scaleX", SCALE_MINI),
|
||||
zoomOutAnimator = ObjectAnimator.ofPropertyValuesHolder(mCardView, PropertyValuesHolder.ofFloat("scaleX", SCALE_MINI),
|
||||
PropertyValuesHolder.ofFloat("scaleY", SCALE_MINI))
|
||||
zoomOutAnimator.duration = DEFAULT_DURATION
|
||||
zoomOutAnimator.doOnEnd { removeFromParent() }
|
||||
@ -177,7 +187,7 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
}
|
||||
|
||||
private fun enableSwipeToDismiss() {
|
||||
cardView?.setOnTouchListener(SwipeDismissTouchListener(cardView, object : SwipeDismissTouchListener.DismissCallbacks {
|
||||
mCardView?.setOnTouchListener(SwipeDismissTouchListener(mCardView, object : SwipeDismissTouchListener.DismissCallbacks {
|
||||
override fun canDismiss(): Boolean {
|
||||
return true
|
||||
}
|
||||
@ -193,7 +203,7 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
}
|
||||
|
||||
private fun disableSwipeToDismiss() {
|
||||
cardView?.setOnTouchListener(null)
|
||||
mCardView?.setOnTouchListener(null)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
@ -264,13 +274,13 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
|
||||
fun setText(text: String?) {
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
tvText.text = text
|
||||
tvText.measure(0, 0)
|
||||
textWidth = tvText.measuredWidth
|
||||
tvText.width = 0
|
||||
mContentTv.text = text
|
||||
mContentTv.measure(0, 0)
|
||||
textWidth = mContentTv.measuredWidth
|
||||
mContentTv.width = 0
|
||||
|
||||
cardView.measure(0, 0)
|
||||
cardViewWidth = cardView.measuredWidth
|
||||
mCardView.measure(0, 0)
|
||||
cardViewWidth = mCardView.measuredWidth
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,7 +294,7 @@ class NotifierView @JvmOverloads constructor(context: Context, attrs: AttributeS
|
||||
}
|
||||
|
||||
fun setIcon(url: String) {
|
||||
ImageUtils.display(ivIcon, url)
|
||||
ImageUtils.display(mIconIv, url)
|
||||
}
|
||||
|
||||
private fun dp2px(dp: Float): Int {
|
||||
|
||||
@ -91,6 +91,9 @@ class SimulatorDownloadManager private constructor() {
|
||||
DownloadStatus.unqualified == downloadEntity.status -> {
|
||||
ToastUtils.showToast("未成年人暂不允许在此时间下载游戏")
|
||||
}
|
||||
DownloadStatus.unavailable == downloadEntity.status -> {
|
||||
ToastUtils.showToast("该游戏未接入防沉迷系统,暂不支持下载")
|
||||
}
|
||||
DownloadStatus.hijack == downloadEntity.status -> {
|
||||
ToastUtils.showToast("网络劫持,请稍后重试")
|
||||
}
|
||||
|
||||
125
app/src/main/java/com/gh/common/util/AsyncImageLoader.kt
Normal file
125
app/src/main/java/com/gh/common/util/AsyncImageLoader.kt
Normal file
@ -0,0 +1,125 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import androidx.core.util.Pools
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.facebook.imagepipeline.request.Postprocessor
|
||||
|
||||
class AsyncImageLoader private constructor() {
|
||||
|
||||
fun addAsyncImage(view: SimpleDraweeView?, url: String, isAutoPlayGif: Boolean, processor: Postprocessor?) {
|
||||
try {
|
||||
val loopThread = LoopThread.getInstance()
|
||||
val params = loopThread.obtainImageParams()
|
||||
params.view = view
|
||||
params.url = url
|
||||
params.isAutoPlayGif = isAutoPlayGif
|
||||
params.processor = processor
|
||||
loopThread.addAsyncImage(params)
|
||||
} catch (e: InterruptedException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private class LoopThread private constructor() : Thread("GH_LOOP_IMAGE_LOADER") {
|
||||
|
||||
private var mIsLoop = false
|
||||
private val mRetryCount = 3
|
||||
private val mInterval = 10L
|
||||
private val mImageList = ArrayList<ImageLoadParams>()
|
||||
private val mImageListTemp = ArrayList<ImageLoadParams>()
|
||||
private val mImagePool = Pools.SynchronizedPool<ImageLoadParams>(15)
|
||||
|
||||
init {
|
||||
start()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun addAsyncImage(image: ImageLoadParams) {
|
||||
if (mIsLoop) {
|
||||
mImageListTemp.add(image)
|
||||
} else {
|
||||
mImageList.add(image)
|
||||
}
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
rxTimerWithIoThread(mInterval) {
|
||||
try {
|
||||
if (!mIsLoop) {
|
||||
runInner()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun runInner() {
|
||||
if (mImageList.isEmpty()) return
|
||||
|
||||
mIsLoop = true
|
||||
mImageList.forEach { image ->
|
||||
val width = image.view?.width ?: 0
|
||||
if (width == 0) {
|
||||
if (image.retryCount >= mRetryCount) {
|
||||
loadImage(image, true)
|
||||
} else {
|
||||
image.retryCount += 1
|
||||
mImageListTemp.add(image)
|
||||
}
|
||||
} else {
|
||||
if (image.view?.getTag(ImageUtils.TAG_TARGET_WIDTH) == null) {
|
||||
image.view?.setTag(ImageUtils.TAG_TARGET_WIDTH, width)
|
||||
}
|
||||
loadImage(image)
|
||||
}
|
||||
}
|
||||
mImageList.clear()
|
||||
|
||||
if (mImageListTemp.isNotEmpty()) {
|
||||
mImageList.addAll(mImageListTemp)
|
||||
mImageListTemp.clear()
|
||||
}
|
||||
mIsLoop = false
|
||||
}
|
||||
|
||||
|
||||
private fun loadImage(params: ImageLoadParams, isIgnoreWidth: Boolean = false) {
|
||||
ImageUtils.display(params.view, params.url, params.isAutoPlayGif, params.processor, isIgnoreWidth)
|
||||
releaseImageParams(params)
|
||||
}
|
||||
|
||||
fun obtainImageParams(): ImageLoadParams {
|
||||
var acquire = mImagePool.acquire()
|
||||
if (acquire == null) {
|
||||
acquire = ImageLoadParams()
|
||||
}
|
||||
return acquire
|
||||
}
|
||||
|
||||
private fun releaseImageParams(params: ImageLoadParams) {
|
||||
params.run {
|
||||
view = null
|
||||
url = ""
|
||||
isAutoPlayGif = false
|
||||
processor = null
|
||||
retryCount = 0
|
||||
mImagePool.release(this)
|
||||
}
|
||||
}
|
||||
|
||||
companion object : SingletonHolder<LoopThread>({ LoopThread() })
|
||||
}
|
||||
|
||||
companion object : SingletonHolder<AsyncImageLoader>({ AsyncImageLoader() })
|
||||
}
|
||||
|
||||
@Keep
|
||||
data class ImageLoadParams(
|
||||
var view: SimpleDraweeView? = null,
|
||||
var url: String = "",
|
||||
var isAutoPlayGif: Boolean = true,
|
||||
var processor: Postprocessor? = null,
|
||||
var retryCount: Int = 0
|
||||
)
|
||||
@ -141,7 +141,7 @@ object CommentHelper {
|
||||
val context = view.context
|
||||
val dialogOptions = ArrayList<String>()
|
||||
|
||||
if (isShowTop && (articleId != null || questionId != null) && commentEntity.me?.isContentAuthor == true) {
|
||||
if (isShowTop && (articleId != null || questionId != null || videoId != null) && commentEntity.me?.isContentAuthor == true) {
|
||||
dialogOptions.add(if (commentEntity.isTop) "取消置顶" else "置顶")
|
||||
}
|
||||
if (questionId != null && commentEntity.me?.isContentAuthor == true) {
|
||||
@ -158,9 +158,8 @@ object CommentHelper {
|
||||
}
|
||||
if (questionId != null &&
|
||||
commentEntity.me?.isModerator == true &&
|
||||
(commentEntity.me?.moderatorPermissions?.highlightAnswer
|
||||
?: Permissions.GUEST) > Permissions.GUEST &&
|
||||
!commentEntity.choiceness) {
|
||||
(commentEntity.me?.moderatorPermissions?.highlightAnswer ?: Permissions.GUEST) > Permissions.GUEST && !commentEntity.choiceness
|
||||
) {
|
||||
dialogOptions.add("加精选")
|
||||
}
|
||||
if (questionId != null &&
|
||||
|
||||
@ -3,16 +3,23 @@ package com.gh.common.util;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.IdCardEntity;
|
||||
import com.gh.gamecenter.entity.UserInfoEntity;
|
||||
import com.gh.gamecenter.provider.GhContentProvider;
|
||||
import com.gh.gamecenter.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.gid.GidCallback;
|
||||
@ -24,7 +31,6 @@ import com.lightgame.utils.Utils;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.sentry.Sentry;
|
||||
import io.sentry.android.core.SentryAndroid;
|
||||
@ -42,11 +48,10 @@ public class DataUtils {
|
||||
* @param channel
|
||||
*/
|
||||
public static void init(final Application context, String channel) {
|
||||
|
||||
if (CommonDebug.IS_DEBUG) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 初始化 Sentry 约占用 90ms,这里切换到子线程初始化
|
||||
AppExecutor.getIoExecutor().execute(() -> initSentry(context, channel));
|
||||
|
||||
@ -118,23 +123,23 @@ public class DataUtils {
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void initSentry(Context context, String channel) {
|
||||
SentryAndroid.init(context, options -> {
|
||||
// Sentry 疯狂报 ANR (很大一部分还是莫名奇妙的 ANR)严重影响到其它闪退日志的收集
|
||||
// 这里将它局限到只有官网渠道的包才统计 ANR
|
||||
if ("GH_206".equals(channel)) {
|
||||
if ("GH_206".equals(channel) || "GH_BETA".equals(channel)) {
|
||||
options.setAnrEnabled(true);
|
||||
options.setAnrTimeoutIntervalMillis(6000);
|
||||
} else {
|
||||
options.setAnrEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
options.setDebug(BuildConfig.DEBUG);
|
||||
options.setEnableSessionTracking(true);
|
||||
options.setEnvironment(BuildConfig.FLAVOR);
|
||||
options.setDsn("https://6b1caf0d17c1408e8680f3f73ff80bd0@sentry.shanqu.cc/22");
|
||||
|
||||
|
||||
options.setBeforeSend((event, hint) -> {
|
||||
if (BuildConfig.DEBUG) {
|
||||
return null;
|
||||
@ -143,7 +148,7 @@ public class DataUtils {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Sentry.configureScope(scope -> {
|
||||
if (BuildConfig.BUILD_TIME != 0L) {
|
||||
scope.setTag("alias", "内测版" + BuildConfig.VERSION_NAME);
|
||||
@ -203,6 +208,22 @@ public class DataUtils {
|
||||
@Override
|
||||
public void onSuccess(UserInfoEntity data) {
|
||||
SPUtils.setString(Constants.SP_DEVICE_CERTIFICATION_PREFIX + gid, GsonUtils.toJson(data));
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
IdCardEntity idCardEntity = data.getIdCard();
|
||||
|
||||
if (idCardEntity != null) {
|
||||
values.put(GhContentProvider.KEY_IS_CERTIFICATED, !TextUtils.isEmpty(data.getIdCard().getId())); // 是否认证
|
||||
values.put(GhContentProvider.KEY_IS_ADULT,
|
||||
data.getIdCard().getMinor() == null
|
||||
|| !data.getIdCard().getMinor()
|
||||
);
|
||||
} else {
|
||||
values.put(GhContentProvider.KEY_IS_CERTIFICATED, false);
|
||||
values.put(GhContentProvider.KEY_IS_ADULT, false);
|
||||
}
|
||||
|
||||
HaloApp.getInstance().getContentResolver().insert(Uri.parse("content://com.gh.gamecenter.provider/certification"), values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -200,6 +200,7 @@ public class DetailDownloadUtils {
|
||||
case notfound:
|
||||
case uncertificated:
|
||||
case unqualified:
|
||||
case unavailable:
|
||||
detailInitDownload(viewHolder, false);
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -170,6 +170,8 @@ public class DeviceUtils {
|
||||
}
|
||||
|
||||
public static String getNetwork(Context context) {
|
||||
context = context.getApplicationContext();
|
||||
|
||||
ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
if (connManager == null) return null;
|
||||
NetworkInfo info = connManager.getActiveNetworkInfo();
|
||||
|
||||
@ -44,13 +44,9 @@ import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchy;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.common.AppExecutor;
|
||||
@ -81,6 +77,7 @@ import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.Badge;
|
||||
import com.gh.gamecenter.entity.BadgeEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.PermissionsEntity;
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.entity.SimpleGameEntity;
|
||||
@ -101,6 +98,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
|
||||
public class DialogUtils {
|
||||
|
||||
public static Dialog showWaitDialog(Context context, String msg) {
|
||||
@ -846,7 +846,7 @@ public class DialogUtils {
|
||||
|
||||
LinearLayout container = new LinearLayout(context);
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
container.setBackgroundColor(Color.WHITE);
|
||||
container.setBackgroundColor(ContextCompat.getColor(context, R.color.background_white));
|
||||
container.setPadding(0, DisplayUtils.dip2px(context, 12f), 0, DisplayUtils.dip2px(context, 12f));
|
||||
|
||||
for (String option : options) {
|
||||
@ -998,7 +998,10 @@ public class DialogUtils {
|
||||
if (holder instanceof PrivacyPolicyItemViewHolder) {
|
||||
PrivacyPolicyItemViewHolder viewHolder = (PrivacyPolicyItemViewHolder) holder;
|
||||
PrivacyItemBinding binding = viewHolder.getBinding();
|
||||
binding.setData(entity.getPermissions().get(position));
|
||||
final PermissionsEntity permissionsEntity = entity.getPermissions().get(position);
|
||||
ImageUtils.display(binding.icon, permissionsEntity.getIcon());
|
||||
binding.name.setText(permissionsEntity.getName());
|
||||
binding.intro.setText(permissionsEntity.getIntro());
|
||||
GenericDraweeHierarchy hierarchy = binding.icon.getHierarchy();
|
||||
if (hierarchy != null) {
|
||||
if (position == 0) {
|
||||
@ -1397,11 +1400,12 @@ public class DialogUtils {
|
||||
} else {
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
DialogOverseaConfirmationBinding binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.dialog_oversea_confirmation, null, false);
|
||||
DialogOverseaConfirmationBinding binding = DialogOverseaConfirmationBinding.inflate(LayoutInflater.from(context), null, false);
|
||||
|
||||
View contentView = binding.getRoot();
|
||||
|
||||
binding.setGame(gameEntity);
|
||||
binding.gameIcon.displayGameIcon(gameEntity);
|
||||
binding.gameNameTv.setText(context.getString(R.string.dialog_oversea_hint, gameEntity.getName()));
|
||||
binding.urlTv.setText(gameEntity.getOverseasAddressDialog().getLink());
|
||||
binding.closeIv.setOnClickListener(v -> dialog.dismiss());
|
||||
binding.downloadBtn.setText("下载(" + gameEntity.getApk().get(0).getSize() + ")");
|
||||
@ -1438,7 +1442,7 @@ public class DialogUtils {
|
||||
params = window.getAttributes();
|
||||
params.width = (int) (context.getResources().getDisplayMetrics().widthPixels * 0.9);
|
||||
window.setAttributes(params);
|
||||
window.setBackgroundDrawableResource(R.drawable.full_dialog_background);
|
||||
window.setBackgroundDrawableResource(R.drawable.textview_white_up);
|
||||
}
|
||||
|
||||
inflate.findViewById(R.id.imprint_close).setOnClickListener(v -> dialog.dismiss());
|
||||
@ -1457,10 +1461,11 @@ public class DialogUtils {
|
||||
continue;
|
||||
}
|
||||
View item = LayoutInflater.from(context).inflate(R.layout.imprint_content_item, null);
|
||||
ImprintContentItemBinding bind = DataBindingUtil.bind(item);
|
||||
bind.setApk(apk);
|
||||
ImprintContentItemBinding bind = ImprintContentItemBinding.bind(item);
|
||||
String platform = TextUtils.isEmpty(apk.getRemark()) ? apk.getPlatformName() : apk.getPlatformName() + "\n" + apk.getRemark();
|
||||
bind.setPlatformName(platform);
|
||||
bind.imprintPlatform.setText(platform);
|
||||
bind.imprintVersion.setText(apk.getVersion());
|
||||
bind.imprintTime.setText(NewsUtils.getFormattedTime(apk.getTime() != null ? apk.getTime() : 0));
|
||||
content.addView(item, LinearLayout.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(40));
|
||||
}
|
||||
|
||||
@ -2213,7 +2218,7 @@ public class DialogUtils {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showReserveSuccess2WechatBindDialog(Context context, ConfirmListener confirmListener,CancelListener cancelListener) {
|
||||
public static void showReserveSuccess2WechatBindDialog(Context context, ConfirmListener confirmListener, CancelListener cancelListener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.DialogWindowTransparent);
|
||||
|
||||
@ -19,6 +19,7 @@ import com.gh.common.constant.Constants
|
||||
import com.gh.common.exposure.ExposureEvent
|
||||
import com.gh.common.exposure.ExposureEvent.Companion.createEvent
|
||||
import com.gh.common.exposure.ExposureManager.log
|
||||
import com.gh.common.exposure.ExposureSource
|
||||
import com.gh.common.exposure.ExposureTraceUtils.appendTrace
|
||||
import com.gh.common.exposure.ExposureType
|
||||
import com.gh.common.util.EntranceUtils.*
|
||||
@ -51,6 +52,7 @@ import com.gh.gamecenter.personalhome.home.UserHistoryViewModel
|
||||
import com.gh.gamecenter.qa.answer.detail.SimpleAnswerDetailActivity
|
||||
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.questions.newdetail.NewQuestionDetailActivity
|
||||
import com.gh.gamecenter.qa.subject.CommunitySubjectActivity
|
||||
import com.gh.gamecenter.qa.video.detail.ForumVideoDetailActivity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
@ -157,7 +159,7 @@ object DirectUtils {
|
||||
entrance: String,
|
||||
path: String,
|
||||
exposureEvent: ExposureEvent? = null,
|
||||
unknownCallback: (() -> Unit)?
|
||||
unknownCallback: (() -> Unit)?,
|
||||
) {
|
||||
when (linkEntity.type) {
|
||||
"article", "news", "文章" -> {
|
||||
@ -898,14 +900,14 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToCommunityColumn(context: Context, community: CommunityEntity?, subjectId: String, entrance: String?, path: String?) {
|
||||
// if (subjectId.isEmpty()) return
|
||||
// val bundle = Bundle()
|
||||
// bundle.putString(KEY_PATH, path)
|
||||
// bundle.putString(KEY_TO, CommunitySubjectActivity::class.java.name)
|
||||
// bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
// bundle.putString(KEY_COLUMN_ID, subjectId)
|
||||
// bundle.putParcelable(KEY_COMMUNITY_DATA, community)
|
||||
// jumpActivity(context, bundle)
|
||||
if (subjectId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_TO, CommunitySubjectActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
bundle.putString(KEY_COLUMN_ID, subjectId)
|
||||
bundle.putParcelable(KEY_COMMUNITY_DATA, community)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -1143,7 +1145,13 @@ object DirectUtils {
|
||||
* 跳转新分类
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directCatalog(context: Context, catalogId: String, catalogTitle: String, entrance: String? = null, path: String? = "") {
|
||||
fun directCatalog(
|
||||
context: Context,
|
||||
catalogId: String,
|
||||
catalogTitle: String,
|
||||
entrance: String? = null,
|
||||
path: String? = "",
|
||||
) {
|
||||
if (catalogId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, CatalogActivity::class.java.name)
|
||||
@ -1157,7 +1165,13 @@ object DirectUtils {
|
||||
* 跳转新分类2.0
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directCategoryV2(context: Context, categoryId: String, categoryTitle: String, entrance: String? = null, path: String? = "") {
|
||||
fun directCategoryV2(
|
||||
context: Context,
|
||||
categoryId: String,
|
||||
categoryTitle: String,
|
||||
entrance: String? = null,
|
||||
path: String? = "",
|
||||
) {
|
||||
if (categoryId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, CategoryV2Activity::class.java.name)
|
||||
|
||||
@ -18,13 +18,16 @@ import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.halo.assistant.HaloApp;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class DisplayUtils {
|
||||
|
||||
/**
|
||||
@ -223,6 +226,27 @@ public class DisplayUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setStatusBarColor(Activity activity, @ColorRes int colorRes) {
|
||||
Window window = activity.getWindow();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
int colorInt = ContextCompat.getColor(activity, colorRes);
|
||||
// 设置状态栏底色颜色
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
window.setStatusBarColor(colorInt);
|
||||
// 如果亮色,设置状态栏文字为黑色
|
||||
if (isLightColor(colorInt)) {
|
||||
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
} else {
|
||||
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isLightColor(@ColorInt int color) {
|
||||
return ColorUtils.calculateLuminance(color) >= 0.5;
|
||||
}
|
||||
|
||||
|
||||
private static boolean isMiuiOs() {
|
||||
String property = getSystemProperty("ro.miui.ui.version.name", "");
|
||||
|
||||
@ -166,6 +166,7 @@ object DownloadItemUtils {
|
||||
hideDownloadBtnIfNoAvailableContent: Boolean = false,
|
||||
pluginLocation: PluginLocation? = PluginLocation.only_game
|
||||
) {
|
||||
downloadBtn.background = R.drawable.download_button_normal_style.toDrawable(context)
|
||||
// 控制是否显示下载按钮
|
||||
downloadBtn.goneIf(!Config.isShowDownload(gameEntity.id) || context.getString(R.string.app_name) == gameEntity.name)
|
||||
// 青少年模式显示查看
|
||||
@ -208,7 +209,7 @@ object DownloadItemUtils {
|
||||
} else {
|
||||
text = context.getString(R.string.none)
|
||||
setTextColor(R.color.button_gray.toColor())
|
||||
setBackgroundResource(R.drawable.news_detail_comment)
|
||||
setBackgroundResource(R.drawable.button_border_gray_oval)
|
||||
if (hideDownloadBtnIfNoAvailableContent) {
|
||||
visibility = View.GONE
|
||||
}
|
||||
@ -418,6 +419,7 @@ object DownloadItemUtils {
|
||||
holder.recommendTv.text = recommendStyle.text
|
||||
if (TextUtils.isEmpty(recommendStyle.icon)) {
|
||||
holder.recommendIv.visibility = View.GONE
|
||||
holder.recommendContainer?.setPadding(6F.dip2px(), 0, 8F.dip2px(), 0)
|
||||
} else {
|
||||
holder.recommendIv.visibility = View.VISIBLE
|
||||
ImageUtils.display(holder.recommendIv, recommendStyle.icon)
|
||||
|
||||
@ -112,6 +112,7 @@ object DownloadNotificationHelper {
|
||||
|| entity.status == DownloadStatus.cancel
|
||||
|| entity.status == DownloadStatus.hijack
|
||||
|| entity.status == DownloadStatus.unqualified
|
||||
|| entity.status == DownloadStatus.unavailable
|
||||
|| entity.status == DownloadStatus.uncertificated
|
||||
|| entity.status == DownloadStatus.notfound
|
||||
|| entity.status == DownloadStatus.overflow
|
||||
@ -186,6 +187,6 @@ object DownloadNotificationHelper {
|
||||
}
|
||||
|
||||
private fun getNotificationIcon(): Int {
|
||||
return if (mShouldUseAlternativeNotificationIcon) R.drawable.ic_notification else R.mipmap.logo
|
||||
return if (mShouldUseAlternativeNotificationIcon) R.drawable.ic_download_notification else R.mipmap.logo
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,6 @@ import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
object DownloadObserver {
|
||||
|
||||
@ -109,6 +108,20 @@ object DownloadObserver {
|
||||
// 未成年
|
||||
RealNameHelper.showRealNameUnqualifiedDialog(downloadEntity)
|
||||
|
||||
// 删除任务
|
||||
downloadEntity.status = DownloadStatus.cancel
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
} else if (DownloadStatus.unavailable == downloadEntity.status) {
|
||||
// 未接入防沉迷系统
|
||||
val currentActivity = AppManager.getInstance().currentActivity() ?: return
|
||||
|
||||
DialogHelper.showDialog(
|
||||
context = currentActivity,
|
||||
title = "温馨提示",
|
||||
content = "该游戏未接入防沉迷系统,暂不支持下载",
|
||||
confirmText = "知道了",
|
||||
cancelText = "")
|
||||
|
||||
// 删除任务
|
||||
downloadEntity.status = DownloadStatus.cancel
|
||||
downloadManager.cancel(downloadEntity.url)
|
||||
@ -175,6 +188,8 @@ object DownloadObserver {
|
||||
} else {
|
||||
statDoneEvent(downloadEntity)
|
||||
|
||||
GameActivityDownloadHelper.clear()
|
||||
|
||||
EnergyTaskHelper.postEnergyTask(
|
||||
"download_game",
|
||||
downloadEntity.gameId,
|
||||
|
||||
@ -47,6 +47,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_GAMENAME = "gameName";
|
||||
public static final String KEY_PACKAGE_MD5 = "package_md5";
|
||||
public static final String HOST_ARTICLE = "article";
|
||||
public static final String HOST_INVOKE_ONLY = "invoke_only";
|
||||
public static final String HOST_UPLOAD_VIDEO = "upload_video";//上传视频
|
||||
public static final String HOST_UPLOAD_VIDEO_NEW = "upload_video_new"; // 上传视频新(AKA 发视频)
|
||||
public static final String HOST_VIDEO_SINGLE = "video_single";//指定视频-不能划动
|
||||
@ -264,6 +265,8 @@ public class EntranceUtils {
|
||||
public static final String KEY_GAME_COLLECTION_ID = "game_collection_id";//游戏单ID
|
||||
public static final String KEY_ASSIST_RES = "assist_res";
|
||||
public static final String KEY_LAST_SELECTED_POSITION = "last_selected_position";
|
||||
public static final String KEY_RECOMMEND_ID = "recommend_id";
|
||||
public static final String KEY_LAST_PAGE_DATA = "last_page_data";
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.animation.Animator
|
||||
import android.app.Activity
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
@ -20,11 +21,13 @@ import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.*
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.webkit.WebView
|
||||
import android.widget.EditText
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.SeekBar
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
@ -34,6 +37,8 @@ import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import androidx.webkit.WebSettingsCompat
|
||||
import androidx.webkit.WebViewFeature
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.DefaultUrlHandler
|
||||
@ -753,7 +758,7 @@ fun <T> Array<out T>.secondOrNull(): T? {
|
||||
fun ExpandTextView.setTextWithInterceptingInternalUrl(
|
||||
shrankText: CharSequence,
|
||||
expandedText: CharSequence,
|
||||
clickedCallback: (url: String)-> Unit
|
||||
clickedCallback: (url: String) -> Unit
|
||||
) {
|
||||
var shrankSsb = shrankText.interceptUrlSpanAndRoundImageSpan(clickedCallback)
|
||||
var expandedSsb = expandedText.interceptUrlSpanAndRoundImageSpan(clickedCallback)
|
||||
@ -881,10 +886,24 @@ fun Int.toColor(): Int {
|
||||
return ContextCompat.getColor(HaloApp.getInstance().application, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 只能传Activity的context,如果是Application的context会导致切换夜间模式变不了色
|
||||
*/
|
||||
fun Int.toColor(context: Context): Int {
|
||||
return ContextCompat.getColor(context, this)
|
||||
}
|
||||
|
||||
fun Int.toDrawable(): Drawable? {
|
||||
return ContextCompat.getDrawable(HaloApp.getInstance().application, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 只能传Activity的context,如果是Application的context会导致切换夜间模式变不了色
|
||||
*/
|
||||
fun Int.toDrawable(context: Context): Drawable? {
|
||||
return ContextCompat.getDrawable(context, this)
|
||||
}
|
||||
|
||||
fun Int.toResString(): String {
|
||||
return HaloApp.getInstance().application.resources.getString(this)
|
||||
}
|
||||
@ -1047,6 +1066,13 @@ inline fun rxTimer(interval: Long, crossinline block: (times: Long) -> Unit): Di
|
||||
}
|
||||
}
|
||||
|
||||
inline fun rxTimerWithIoThread(interval: Long, crossinline block: (times: Long) -> Unit): Disposable {
|
||||
return Observable.interval(0, interval, TimeUnit.MILLISECONDS)
|
||||
.subscribe {
|
||||
block.invoke(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun LottieAnimationView.doOnAnimationEnd(action: () -> Unit) {
|
||||
this.addAnimatorListener(object : Animator.AnimatorListener {
|
||||
override fun onAnimationRepeat(animation: Animator?) {
|
||||
@ -1165,6 +1191,20 @@ fun View.getBitmapFromView(): Bitmap? {
|
||||
return bitmap
|
||||
}
|
||||
|
||||
fun View.setRootBackgroundColor(@ColorRes res: Int) {
|
||||
if (this.id == View.NO_ID) {
|
||||
this.id = R.id.root_container
|
||||
}
|
||||
this.setBackgroundColor(res.toColor(this.context))
|
||||
}
|
||||
|
||||
fun View.setRootBackgroundDrawable(@DrawableRes res: Int) {
|
||||
if (this.id == View.NO_ID) {
|
||||
this.id = R.id.root_container
|
||||
}
|
||||
this.background = res.toDrawable(this.context)
|
||||
}
|
||||
|
||||
fun String.hexStringToIntColor(): Int {
|
||||
val colorStr = if (this.length == 9) {
|
||||
"#${this.substring(3)}"
|
||||
@ -1187,4 +1227,25 @@ fun String.lengthOfEmojiHalf(): Int {
|
||||
fun String.emojiCount(): Int {
|
||||
val onlyText = EmojiUtils.removeEmoji(this)
|
||||
return (this.length - onlyText.length) / 2
|
||||
}
|
||||
|
||||
/**
|
||||
* WebView启用强制深色模式
|
||||
*/
|
||||
fun WebView.enableForceDark(nightMode: Boolean) {
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON && WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
|
||||
WebSettingsCompat.setForceDark(settings, if (nightMode) WebSettingsCompat.FORCE_DARK_ON else WebSettingsCompat.FORCE_DARK_OFF)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 日夜间模式切换更新状态栏底色
|
||||
*/
|
||||
fun Activity.updateStatusBarColor(@ColorRes nightColor: Int, @ColorRes dayColor: Int) {
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON) {
|
||||
DisplayUtils.setStatusBarColor(
|
||||
this,
|
||||
if (NightModeUtils.isNightMode(this)) nightColor else dayColor
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,413 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.common.DefaultJsApi
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.dialog.CertificationDialog
|
||||
import com.gh.common.exposure.ExposureEvent
|
||||
import com.gh.common.exposure.ExposureManager
|
||||
import com.gh.common.exposure.ExposureSource
|
||||
import com.gh.common.exposure.ExposureType
|
||||
import com.gh.common.history.HistoryHelper
|
||||
import com.gh.common.repository.ReservationRepository
|
||||
import com.gh.common.runOnUiThread
|
||||
import com.gh.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.download.dialog.DownloadDialog
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.gh.gamecenter.entity.ApkEntity
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.PluginLocation
|
||||
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.EmptyResponse
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.teenagermode.TeenagerModeActivity
|
||||
import com.gh.gamecenter.user.ApiResponse
|
||||
import com.lightgame.download.FileUtils
|
||||
|
||||
/**
|
||||
* 游戏活动下载辅助类
|
||||
*/
|
||||
object GameActivityDownloadHelper {
|
||||
|
||||
private var mTraceEvent: ExposureEvent? = null
|
||||
private var mGameEntity: GameEntity? = null
|
||||
|
||||
fun start(context: Context, event: DefaultJsApi.GameActivityEvent) {
|
||||
if (mGameEntity != null && mGameEntity?.id == event.gameId) {
|
||||
runOnUiThread {
|
||||
handleGameEntity(context, event, mGameEntity!!)
|
||||
}
|
||||
} else {
|
||||
RetrofitManager.getInstance()
|
||||
.api
|
||||
.getGameDigest(event.gameId)
|
||||
.map(ApkActiveUtils.filterMapper)
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<GameEntity>() {
|
||||
override fun onResponse(gameEntity: GameEntity?) {
|
||||
mGameEntity = gameEntity
|
||||
gameEntity?.let {
|
||||
handleGameEntity(context, event, it)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleGameEntity(
|
||||
context: Context,
|
||||
event: DefaultJsApi.GameActivityEvent,
|
||||
gameEntity: GameEntity
|
||||
) {
|
||||
// 青少年模式
|
||||
if (isTeenageMode(context)) return
|
||||
|
||||
val entrance = "(游戏活动[${event.activityTitle}])"
|
||||
val location = "游戏活动:${event.activityTitle}-${gameEntity.name}"
|
||||
if (mTraceEvent == null) {
|
||||
val exposureSources = arrayListOf(
|
||||
ExposureSource("游戏活动", "${event.activityTitle}+${event.activityId}")
|
||||
)
|
||||
mTraceEvent = ExposureEvent.createEvent(gameEntity, exposureSources, null, ExposureType.EXPOSURE)
|
||||
}
|
||||
|
||||
mTraceEvent?.run {
|
||||
when {
|
||||
// 预约
|
||||
gameEntity.isReservable -> reserve(context, gameEntity, entrance, this)
|
||||
// 开始玩
|
||||
gameEntity.getApk().size == 0 && gameEntity.h5Link != null -> play(context, gameEntity)
|
||||
// 下载
|
||||
else -> handleDownload(context, event, gameEntity, entrance, location, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 青少年模式
|
||||
private fun isTeenageMode(context: Context): Boolean {
|
||||
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) {
|
||||
DialogHelper.showDialog(
|
||||
context,
|
||||
"提示",
|
||||
"当前处于儿童/青少年模式, \n暂不提供游戏下载",
|
||||
"退出青少年模式",
|
||||
"关闭",
|
||||
{ context.startActivity(TeenagerModeActivity.getIntent(context)) },
|
||||
{},
|
||||
DialogHelper.Config(
|
||||
centerTitle = true,
|
||||
centerContent = true
|
||||
)
|
||||
)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 预约
|
||||
private fun reserve(
|
||||
context: Context,
|
||||
gameEntity: GameEntity,
|
||||
entrance: String,
|
||||
traceEvent: ExposureEvent
|
||||
) {
|
||||
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.id)) {
|
||||
CheckLoginUtils.checkLogin(context, entrance) {
|
||||
ReservationHelper.reserve(context, gameEntity.id, object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
LogUtils.logReservation(gameEntity, traceEvent)
|
||||
clear()
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
ToastUtils.toast("游戏已成功预约")
|
||||
}
|
||||
}
|
||||
|
||||
// 开始玩(H5链接)
|
||||
private fun play(context: Context, gameEntity: GameEntity) {
|
||||
val linkEntity = gameEntity.h5Link
|
||||
val isPlay = "play" == linkEntity!!.type // 是否为开始玩
|
||||
if (isPlay) {
|
||||
HistoryHelper.insertGameEntity(gameEntity)
|
||||
}
|
||||
val i = WebActivity.getIntentForWebGame(
|
||||
context,
|
||||
gameEntity.h5Link!!.link,
|
||||
gameEntity.name,
|
||||
isPlay,
|
||||
linkEntity.closeButton
|
||||
)
|
||||
context.startActivity(i)
|
||||
}
|
||||
|
||||
// 下载
|
||||
private fun handleDownload(
|
||||
context: Context,
|
||||
event: DefaultJsApi.GameActivityEvent,
|
||||
gameEntity: GameEntity,
|
||||
entrance: String,
|
||||
location: String,
|
||||
traceEvent: ExposureEvent
|
||||
) {
|
||||
val apk = getApk(gameEntity, event, true) ?: return
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshotByUrl(apk.url)
|
||||
if (downloadEntity != null) {
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
} else {
|
||||
val str = GameUtils.getDownloadBtnText(context, gameEntity, PluginLocation.only_game)
|
||||
if (str == context.getString(R.string.download)) {
|
||||
GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity) {
|
||||
DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
|
||||
download(context, gameEntity, apk, isSubscribe, entrance, location, traceEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
DataLogUtils.uploadGameLog(context, gameEntity.id, gameEntity.name, entrance)
|
||||
} else if (str == context.getString(R.string.attempt)) {
|
||||
RealNameHelper.checkIfAuth(context, gameEntity, object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity) {
|
||||
DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
|
||||
download(context, gameEntity, apk, isSubscribe, entrance, location, traceEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
DataLogUtils.uploadGameLog(context, gameEntity.id, gameEntity.name, entrance)
|
||||
} else if (str.contains("化")) {
|
||||
if (gameEntity.pluggableCollection != null) {
|
||||
DownloadDialog.showDownloadDialog(context, gameEntity, traceEvent, entrance, location)
|
||||
} else {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity) {
|
||||
DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
|
||||
plugin(context, gameEntity, apk, entrance, location, isSubscribe, traceEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (str == context.getString(R.string.install) || str == context.getString(R.string.launch)) {
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
} else if (str == context.getString(R.string.update)) {
|
||||
DialogUtils.checkDownload(context, apk.size) { isSubscribe: Boolean ->
|
||||
update(context, gameEntity, apk, entrance, location, isSubscribe, traceEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getApk(
|
||||
gameEntity: GameEntity,
|
||||
event: DefaultJsApi.GameActivityEvent,
|
||||
isRemoveOther: Boolean
|
||||
): ApkEntity? {
|
||||
return when {
|
||||
gameEntity.getApk().isEmpty() -> null
|
||||
|
||||
gameEntity.getApk().size == 1 -> gameEntity.getApk()[0]
|
||||
|
||||
// 找出对应平台版本Apk且移除掉其他平台版本Apk
|
||||
isRemoveOther -> {
|
||||
// 当前游戏为多版本时,只保留活动指定的版本即可,方便之后判断
|
||||
var apk: ApkEntity? = null
|
||||
val iterator = gameEntity.getApk().iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val tempApk = iterator.next()
|
||||
if (tempApk.getPlatform() == event.platform) {
|
||||
apk = tempApk
|
||||
} else {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
apk
|
||||
}
|
||||
|
||||
// 找出对应平台版本Apk即可
|
||||
else -> {
|
||||
var apk: ApkEntity? = null
|
||||
run outside@{
|
||||
gameEntity.getApk().forEach {
|
||||
if (it.getPlatform() == event.platform) {
|
||||
apk = it
|
||||
return@outside
|
||||
}
|
||||
}
|
||||
}
|
||||
apk
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun download(
|
||||
context: Context,
|
||||
gameEntity: GameEntity,
|
||||
apk: ApkEntity,
|
||||
isSubscribe: Boolean,
|
||||
entrance: String,
|
||||
location: String,
|
||||
traceEvent: ExposureEvent
|
||||
) {
|
||||
val msg = FileUtils.isCanDownload(context, apk.size)
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(context, gameEntity.name, apk.getPlatform(), entrance, "下载开始", "下载")
|
||||
DownloadManager.createDownload(context, apk, gameEntity, context.getString(
|
||||
R.string.download), entrance, location, isSubscribe, traceEvent)
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
} else {
|
||||
ToastUtils.toast(msg)
|
||||
}
|
||||
}
|
||||
|
||||
// 插件化
|
||||
private fun plugin(
|
||||
context: Context,
|
||||
gameEntity: GameEntity,
|
||||
apk: ApkEntity,
|
||||
entrance: String,
|
||||
location: String,
|
||||
isSubscribe: Boolean,
|
||||
traceEvent: ExposureEvent?
|
||||
) {
|
||||
val msg = FileUtils.isCanDownload(context, apk.size)
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(context, gameEntity.name, apk.getPlatform(), entrance, "下载开始", "插件化")
|
||||
DownloadManager.createDownload(context, apk, gameEntity, "插件化", entrance, location, isSubscribe, traceEvent)
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
} else {
|
||||
ToastUtils.toast(msg)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新
|
||||
private fun update(
|
||||
context: Context,
|
||||
gameEntity: GameEntity,
|
||||
apk: ApkEntity,
|
||||
entrance: String,
|
||||
location: String,
|
||||
isSubscribe: Boolean,
|
||||
traceEvent: ExposureEvent?
|
||||
) {
|
||||
DataUtils.onGameUpdateEvent(context, gameEntity.name, apk.getPlatform(), "下载开始")
|
||||
DownloadManager.createDownload(context, apk, gameEntity, "更新", entrance, location, isSubscribe, traceEvent)
|
||||
ToastUtils.toast("${gameEntity.name}已加入下载队列")
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun postTaskComplete(gameId: String) {
|
||||
val api = RetrofitManager.getInstance().newApi
|
||||
val single = if (UserManager.getInstance().isLoggedIn) {
|
||||
api.postGameActivityTask(gameId)
|
||||
} else {
|
||||
api.postGameActivityTaskForNoLogin(gameId)
|
||||
}
|
||||
single.compose(singleToMain()).subscribe(EmptyResponse())
|
||||
}
|
||||
|
||||
// 判断是否完成任务(预约完成或者已安装且无更新)
|
||||
@SuppressLint("CheckResult")
|
||||
fun checkTaskComplete(
|
||||
context: Context,
|
||||
event: DefaultJsApi.GameActivityEvent,
|
||||
handler: CompletionHandler<Any>
|
||||
) {
|
||||
// 预约完成
|
||||
if (ReservationRepository.thisGameHasBeenReserved(event.gameId)) {
|
||||
postTaskComplete(event.gameId)
|
||||
handler.complete(true)
|
||||
return
|
||||
}
|
||||
|
||||
if (mGameEntity != null && mGameEntity?.id == event.gameId) {
|
||||
handleCheckTaskComplete(context, mGameEntity, event, handler)
|
||||
} else {
|
||||
RetrofitManager.getInstance()
|
||||
.api
|
||||
.getGameDigest(event.gameId)
|
||||
.map(ApkActiveUtils.filterMapper)
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<GameEntity>() {
|
||||
override fun onResponse(gameEntity: GameEntity?) {
|
||||
mGameEntity = gameEntity
|
||||
handleCheckTaskComplete(context, gameEntity, event, handler)
|
||||
}
|
||||
|
||||
override fun onApiFailure(e: ApiResponse<GameEntity>?) {
|
||||
super.onApiFailure(e)
|
||||
handler.complete(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCheckTaskComplete(
|
||||
context: Context,
|
||||
gameEntity: GameEntity?,
|
||||
event: DefaultJsApi.GameActivityEvent,
|
||||
handler: CompletionHandler<Any>
|
||||
) {
|
||||
if (gameEntity == null) {
|
||||
handler.complete(false)
|
||||
} else {
|
||||
val apk = getApk(gameEntity, event, false)
|
||||
if (apk == null) {
|
||||
handler.complete(false)
|
||||
} else {
|
||||
// 已安装
|
||||
if (PackageUtils.isInstalled(context, apk.packageName)) {
|
||||
// 是否可更新
|
||||
if (PackageUtils.isCanUpdate(apk, event.gameId)
|
||||
|| PackageUtils.isNonPluginUpdatable(apk, gameEntity)) {
|
||||
handler.complete(false)
|
||||
} else {
|
||||
// 已安装且无更新
|
||||
postTaskComplete(event.gameId)
|
||||
handler.complete(true)
|
||||
}
|
||||
} else {
|
||||
handler.complete(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun postExposureEvent(event: DefaultJsApi.GameActivityEvent) {
|
||||
RetrofitManager.getInstance()
|
||||
.api
|
||||
.getGameDigest(event.gameId)
|
||||
.map(ApkActiveUtils.filterMapper)
|
||||
.compose(observableToMain())
|
||||
.subscribe(object : Response<GameEntity>() {
|
||||
override fun onResponse(gameEntity: GameEntity?) {
|
||||
mGameEntity = gameEntity
|
||||
gameEntity?.let {
|
||||
val exposureSources = arrayListOf(
|
||||
ExposureSource("游戏活动", "${event.activityTitle}+${event.activityId}")
|
||||
)
|
||||
mTraceEvent = ExposureEvent.createEvent(
|
||||
gameEntity,
|
||||
exposureSources,
|
||||
null,
|
||||
ExposureType.EXPOSURE
|
||||
)
|
||||
mTraceEvent?.run { ExposureManager.log(this) }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
mTraceEvent = null
|
||||
mGameEntity = null
|
||||
}
|
||||
}
|
||||
@ -118,10 +118,9 @@ public class GameUtils {
|
||||
if (PackagesManager.INSTANCE.isCanUpdate(gameEntity.getId(), apkEntity.getPackageName())) {
|
||||
updateCount++;
|
||||
}
|
||||
if (PackagesManager.INSTANCE.isInstalled(apkEntity.getPackageName())) {
|
||||
if (PackagesManager.isInstalled(apkEntity.getPackageName())) {
|
||||
gh_id = PackageUtils.getMetaData(context, apkEntity.getPackageName(), "gh_id");
|
||||
if (gameEntity.getTag() != null && gameEntity.getTag().size() != 0
|
||||
&& !TextUtils.isEmpty(apkEntity.getGhVersion())
|
||||
if (!TextUtils.isEmpty(apkEntity.getGhVersion())
|
||||
&& !PackageUtils.isSignedByGh(context, apkEntity.getPackageName())
|
||||
&& apkEntity.isShowPlugin(pluginLocation)) {
|
||||
pluginCount++;
|
||||
@ -231,7 +230,6 @@ public class GameUtils {
|
||||
gameUpdateEntity.setPlatform(apkEntity.getPlatform());
|
||||
gameUpdateEntity.setEtag(apkEntity.getEtag());
|
||||
gameUpdateEntity.setPluggable(true);
|
||||
gameUpdateEntity.setTag(gameEntity.getTag());
|
||||
gameUpdateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
gameUpdateEntity.setBrief(gameEntity.getBrief());
|
||||
gameUpdateEntity.setPlugin(apkEntity.getPlugin());
|
||||
|
||||
@ -32,6 +32,7 @@ import com.gh.common.structure.FixedSizeLinkedHashSet
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import com.squareup.picasso.LruCache
|
||||
import com.squareup.picasso.Picasso
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
@ -60,6 +61,13 @@ object ImageUtils {
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val picasso: Picasso by lazy {
|
||||
// Picasso 的 Lru 缓存改为 5M,默认设定是 1/7 的 heap 大小,太大了
|
||||
// https://stackoverflow.com/a/20105828/4812571
|
||||
Picasso.Builder(HaloApp.getInstance()).memoryCache(LruCache(5 * 1024 * 1024)).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用动图,全局设置
|
||||
*/
|
||||
@ -393,9 +401,10 @@ object ImageUtils {
|
||||
view: SimpleDraweeView?,
|
||||
url: String?,
|
||||
isAutoPlayGif: Boolean = true,
|
||||
processor: Postprocessor? = null
|
||||
processor: Postprocessor? = null,
|
||||
isIgnoreWidth: Boolean = false
|
||||
) {
|
||||
displayInternal(view, url, isAutoPlayGif, processor)
|
||||
displayInternal(view, url, isAutoPlayGif, processor, isIgnoreWidth)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -403,7 +412,8 @@ object ImageUtils {
|
||||
view: SimpleDraweeView?,
|
||||
url: String?,
|
||||
isAutoPlayGif: Boolean = true,
|
||||
processor: Postprocessor? = null
|
||||
processor: Postprocessor? = null,
|
||||
isIgnoreWidth: Boolean = false
|
||||
) {
|
||||
mImageDecorationThread.execute {
|
||||
if (url.isNullOrEmpty()) return@execute
|
||||
@ -414,6 +424,10 @@ object ImageUtils {
|
||||
val height = view?.layoutParams?.height
|
||||
val shouldNotSaveMemoryCache = view?.getTag(TAG_NO_MEMORY_CACHE) == true
|
||||
|
||||
if (view != null && width == 0 && !isIgnoreWidth) {
|
||||
AsyncImageLoader.getInstance().addAsyncImage(view, url, isAutoPlayGif, processor)
|
||||
return@execute
|
||||
}
|
||||
var lowResUrl = ""
|
||||
var highResUrl = ""
|
||||
|
||||
@ -471,12 +485,12 @@ object ImageUtils {
|
||||
loadImageClosure(shouldLoadAsGif, highResUrl, lowResUrl)
|
||||
} else {
|
||||
if (width != null && width > 0) {
|
||||
highResUrl = resizeGif(url, view!!.width, height ?: 0)
|
||||
highResUrl = resizeGif(url, width, height ?: 0)
|
||||
loadImageClosure(shouldLoadAsGif, highResUrl, lowResUrl)
|
||||
} else {
|
||||
runOnUiThread {
|
||||
view ?: return@runOnUiThread
|
||||
highResUrl = resizeGif(url, view.width, height ?: 0)
|
||||
highResUrl = resizeGif(url, width ?: view.width, height ?: 0)
|
||||
loadImageClosure(shouldLoadAsGif, highResUrl, lowResUrl)
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ public class IntentUtils {
|
||||
"\n" +
|
||||
"光环助手官网地址:\n" +
|
||||
"\n" +
|
||||
"http://www.ghzs.com/link?source=appshare333");
|
||||
"https://www.ghzs.com/link?source=appshare333");
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ public class NetworkUtils {
|
||||
*/
|
||||
public static boolean isNetworkConnected(Context context) {
|
||||
if (context != null) {
|
||||
context = context.getApplicationContext();
|
||||
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo mNetworkInfo = mConnectivityManager
|
||||
@ -39,6 +40,7 @@ public class NetworkUtils {
|
||||
*/
|
||||
public static boolean isWifiConnected(Context context) {
|
||||
if (context != null) {
|
||||
context = context.getApplicationContext();
|
||||
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo mWiFiNetworkInfo = mConnectivityManager
|
||||
@ -108,6 +110,7 @@ public class NetworkUtils {
|
||||
*/
|
||||
public static String getConnectedType(Context context) {
|
||||
if (context != null) {
|
||||
context = context.getApplicationContext();
|
||||
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo mNetworkInfo = mConnectivityManager
|
||||
|
||||
@ -5,6 +5,7 @@ import com.gh.common.json.JsonObjectBuilder
|
||||
import com.gh.common.json.json
|
||||
import com.gh.common.loghub.LoghubUtils
|
||||
import com.gh.common.tracker.Tracker
|
||||
import com.gh.gamecenter.entity.AdditionalParamsEntity
|
||||
import com.gh.gamecenter.entity.LinkEntity
|
||||
import com.gh.gamecenter.entity.QuoteCountEntity
|
||||
import com.gh.gamecenter.entity.WechatConfigEntity
|
||||
@ -50,15 +51,17 @@ object NewLogUtils {
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun logForumContentBrowser(contentId: String, contentType: String) {
|
||||
val requestBody = hashMapOf(
|
||||
Pair("content_id", contentId),
|
||||
Pair("content_type", contentType)
|
||||
).createRequestBody()
|
||||
fun logForumContentBrowser(contentId: String, contentType: String, recommendId: String) {
|
||||
val requestMap = hashMapOf<String, Any>()
|
||||
requestMap["content_id"] = contentId
|
||||
requestMap["content_type"] = contentType
|
||||
if (recommendId.isNotBlank()) {
|
||||
requestMap["recommend_id"] = recommendId
|
||||
}
|
||||
|
||||
RetrofitManager.getInstance()
|
||||
.api
|
||||
.postBrowses(requestBody)
|
||||
.postBrowses(requestMap.toRequestBody())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(EmptyResponse<ResponseBody>())
|
||||
}
|
||||
@ -569,12 +572,21 @@ object NewLogUtils {
|
||||
|
||||
//分享结果
|
||||
@JvmStatic
|
||||
fun logShareResult(shareResult: Boolean) {
|
||||
fun logShareResult(additionalParams: AdditionalParamsEntity? = null, shareResult: Boolean) {
|
||||
val json = json {
|
||||
"location" to "分享面板"
|
||||
"event" to "share_result"
|
||||
"meta" to LogUtils.getMetaObject()
|
||||
"share_success" to shareResult
|
||||
|
||||
additionalParams?.let {
|
||||
"content_type" to it.contentType
|
||||
"content_id" to it.contentId
|
||||
"bbs_id" to it.bbsId
|
||||
"bbs_type" to it.bbsType
|
||||
"ref_user_id" to it.refUserId
|
||||
}
|
||||
|
||||
"launch_id" to Tracker.launchId
|
||||
"session_id" to Tracker.sessionId
|
||||
"timestamp" to System.currentTimeMillis() / 1000
|
||||
@ -1897,7 +1909,7 @@ object NewLogUtils {
|
||||
|
||||
//默认封面点击事件
|
||||
@JvmStatic
|
||||
fun logClickGameCollectionDefaultCoverDialog(action: String){
|
||||
fun logClickGameCollectionDefaultCoverDialog(action: String) {
|
||||
val json = json {
|
||||
"event" to "click_dialog_game_collect_chose_default_picture"
|
||||
"action" to action
|
||||
|
||||
61
app/src/main/java/com/gh/common/util/NightModeUtils.kt
Normal file
61
app/src/main/java/com/gh/common/util/NightModeUtils.kt
Normal file
@ -0,0 +1,61 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
|
||||
object NightModeUtils {
|
||||
/**
|
||||
* 当前系统是否是深色模式
|
||||
*/
|
||||
fun isNightMode(context: Context): Boolean {
|
||||
// 仅配置开启的包才提供夜间模式功能
|
||||
return if (BuildConfig.IS_NIGHT_MODE_ON) {
|
||||
val uiMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
||||
uiMode == Configuration.UI_MODE_NIGHT_YES
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取是否跟随系统,默认true
|
||||
*/
|
||||
fun getSystemMode() = SPUtils.getBoolean(Constants.SP_SYSTEM_MODE, true)
|
||||
|
||||
fun setSystemMode(nightMode: Boolean) = SPUtils.setBoolean(Constants.SP_SYSTEM_MODE, nightMode)
|
||||
|
||||
/**
|
||||
* 获取是否设置深色模式,默认false
|
||||
*/
|
||||
fun getNightMode() = SPUtils.getBoolean(Constants.SP_NIGHT_MODE, false)
|
||||
|
||||
fun setNightMode(nightMode: Boolean) = SPUtils.setBoolean(Constants.SP_NIGHT_MODE, nightMode)
|
||||
|
||||
fun initNightMode() {
|
||||
initNightMode(getSystemMode(), getNightMode())
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化App深色模式
|
||||
*
|
||||
* @param systemMode 是否是跟随系统
|
||||
* @param nightMode 是否是深色模式
|
||||
*/
|
||||
fun initNightMode(systemMode: Boolean, nightMode: Boolean) {
|
||||
// 仅配置开启的包才提供夜间模式功能
|
||||
if (BuildConfig.IS_NIGHT_MODE_ON) {
|
||||
if (systemMode) {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
} else {
|
||||
if (nightMode) {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
||||
} else {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import java.text.DecimalFormat
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object NumberUtils {
|
||||
|
||||
@ -45,8 +46,8 @@ object NumberUtils {
|
||||
fun transSimpleUsageTime(second: Long): String {
|
||||
val totalMinute = second / 60
|
||||
if (totalMinute < 60) return ((if (totalMinute == 0L) 1 else totalMinute).toString() + "分钟")
|
||||
val hour = Math.round((totalMinute / 60).toFloat())
|
||||
val minute = Math.round((totalMinute - hour * 60).toFloat())
|
||||
val hour = (totalMinute / 60).toFloat().roundToInt()
|
||||
val minute = (totalMinute - hour * 60).toFloat().roundToInt()
|
||||
return hour.toString() + "小时" + if (minute == 0) "" else minute.toString() + "分钟"
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ object OptionDialogHelper {
|
||||
val dialog = Dialog(context)
|
||||
val container = LinearLayout(context)
|
||||
container.orientation = LinearLayout.VERTICAL
|
||||
container.setBackgroundColor(Color.WHITE)
|
||||
container.setBackgroundColor(R.color.background_white.toColor(context))
|
||||
container.setPadding(0, DisplayUtils.dip2px(context, 12f), 0, DisplayUtils.dip2px(context, 12f))
|
||||
|
||||
for (type in typeList) {
|
||||
|
||||
@ -53,15 +53,23 @@ object PackageInstaller {
|
||||
// TODO 此处可能遇到 activity 是 WXEntryActivity
|
||||
// TODO 当 activity 全部出栈,但是应用还在下载游戏,下载完会唤不起安装!
|
||||
if (currentActivity is AppCompatActivity && !currentActivity.isFinishing) {
|
||||
InstallPermissionDialogFragment.show(currentActivity, downloadEntity) {
|
||||
InstallPermissionDialogFragment.show(currentActivity, downloadEntity) { isFromPermissionGrantedCallback ->
|
||||
// 取消状态栏下载完成的通知,若存在
|
||||
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
|
||||
if (isXapk) {
|
||||
XapkInstaller.install(context, downloadEntity, showUnzipToast)
|
||||
if (isFromPermissionGrantedCallback && Build.VERSION.SDK_INT >= 31) {
|
||||
val pm = context.packageManager
|
||||
val intent = pm.getLaunchIntentForPackage(context.packageName)
|
||||
val mainIntent = Intent.makeRestartActivityTask(intent!!.component)
|
||||
context.startActivity(mainIntent)
|
||||
Runtime.getRuntime().exit(0)
|
||||
} else {
|
||||
install(context, downloadEntity.isPlugin, downloadEntity.path)
|
||||
if (isXapk) {
|
||||
XapkInstaller.install(context, downloadEntity, showUnzipToast)
|
||||
} else {
|
||||
install(context, downloadEntity.isPlugin, downloadEntity.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,6 @@ public class PackageUtils {
|
||||
updateEntity.setPlatform(apkEntity.getPlatform());
|
||||
updateEntity.setEtag(apkEntity.getEtag());
|
||||
updateEntity.setBrief(gameEntity.getBrief());
|
||||
updateEntity.setTag(gameEntity.getTag());
|
||||
updateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
updateEntity.setDownload(gameEntity.getDownload());
|
||||
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
@ -131,7 +130,6 @@ public class PackageUtils {
|
||||
updateEntity.setPlatform(apkEntity.getPlatform());
|
||||
updateEntity.setEtag(apkEntity.getEtag());
|
||||
updateEntity.setBrief(gameEntity.getBrief());
|
||||
updateEntity.setTag(gameEntity.getTag());
|
||||
updateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
updateEntity.setPluginDesc(gameEntity.getPluginDesc());
|
||||
@ -741,7 +739,6 @@ public class PackageUtils {
|
||||
updateEntity.setPlatform(apkEntity.getPlatform());
|
||||
updateEntity.setEtag(apkEntity.getEtag());
|
||||
updateEntity.setBrief(gameEntity.getBrief());
|
||||
updateEntity.setTag(gameEntity.getTag());
|
||||
updateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
updateEntity.setPluginDesc(gameEntity.getPluginDesc());
|
||||
|
||||
@ -34,7 +34,7 @@ public class PicassoImageGetter implements Html.ImageGetter {
|
||||
BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();
|
||||
|
||||
Context context = HaloApp.getInstance().getApplication();
|
||||
Picasso.with(context)
|
||||
ImageUtils.getPicasso()
|
||||
.load(source)
|
||||
.transform(new CircleTransformation())
|
||||
.placeholder(ResourcesCompat.getDrawable(context.getResources(), R.drawable.personal_user_default_icon, context
|
||||
|
||||
@ -151,6 +151,43 @@ public class PostCommentUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public static void unLikeComment(
|
||||
String articleId,
|
||||
String articleCommunityId,
|
||||
String videoId,
|
||||
String questionId,
|
||||
final String commentId,
|
||||
final PostCommentListener listener) {
|
||||
Observable<ResponseBody> observable;
|
||||
|
||||
if (!TextUtils.isEmpty(questionId)) {
|
||||
observable = RetrofitManager.getInstance().getApi().postUnVoteQuestionComment(questionId, commentId);
|
||||
} else if (!TextUtils.isEmpty(articleCommunityId) && !TextUtils.isEmpty(articleId)) {
|
||||
observable = RetrofitManager.getInstance().getApi().postUnVoteArticleComment(articleCommunityId, articleId, commentId);
|
||||
} else {
|
||||
observable = RetrofitManager.getInstance().getApi().postUnVoteVideoComment(videoId, commentId);
|
||||
}
|
||||
observable
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(ResponseBody response) {
|
||||
if (listener != null) {
|
||||
listener.postSuccess(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(HttpException e) {
|
||||
if (listener != null) {
|
||||
listener.postFailed(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public static void addCommentVote(final String commentId,
|
||||
final PostCommentListener listener) {
|
||||
RetrofitManager.getInstance().getApi()
|
||||
@ -260,10 +297,11 @@ public class PostCommentUtils {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void reportQuestionComment(final String questionId,
|
||||
final String commentId,
|
||||
final String reportData,
|
||||
final PostCommentListener listener) {
|
||||
final String commentId,
|
||||
final String reportData,
|
||||
final PostCommentListener listener) {
|
||||
RequestBody body = RequestBody.create(MediaType.parse("application/json"), reportData);
|
||||
RetrofitManager.getInstance().getApi()
|
||||
.postQuestionCommentReport(questionId, commentId, body)
|
||||
|
||||
@ -28,6 +28,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.WeiBoShareActivity;
|
||||
import com.gh.gamecenter.entity.AdditionalParamsEntity;
|
||||
import com.gh.gamecenter.entity.ShareEntity;
|
||||
import com.gh.gamecenter.eventbus.EBShare;
|
||||
import com.lightgame.utils.Utils;
|
||||
@ -129,6 +130,7 @@ public class ShareUtils {
|
||||
public static String resourceId = "";//分享内容的id(事件上报用)
|
||||
public static ShareEntity shareEntity;//分享信息(事件上报用)
|
||||
private static ShareType mShareType;//分享类型(事件上报用)
|
||||
public static AdditionalParamsEntity additionalParams;//附加参数(事件上报用)
|
||||
|
||||
private WeakReference<Activity> mActivity;
|
||||
|
||||
@ -148,7 +150,7 @@ public class ShareUtils {
|
||||
if (ShareUtils.shareEntrance == ShareUtils.ShareEntrance.askNormal ||
|
||||
ShareUtils.shareEntrance == ShareEntrance.communityArticle ||
|
||||
ShareUtils.shareEntrance == ShareUtils.ShareEntrance.video) {
|
||||
NewLogUtils.logShareResult(true);
|
||||
NewLogUtils.logShareResult(ShareUtils.additionalParams, true);
|
||||
} else if (ShareUtils.shareEntrance == ShareEntrance.gameCollection) {
|
||||
String shareType;
|
||||
if (mShareType == ShareType.qq) {
|
||||
@ -176,7 +178,7 @@ public class ShareUtils {
|
||||
if (ShareUtils.shareEntrance == ShareUtils.ShareEntrance.askNormal ||
|
||||
ShareUtils.shareEntrance == ShareEntrance.communityArticle ||
|
||||
ShareUtils.shareEntrance == ShareUtils.ShareEntrance.video) {
|
||||
NewLogUtils.logShareResult(false);
|
||||
NewLogUtils.logShareResult(ShareUtils.additionalParams, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +193,7 @@ public class ShareUtils {
|
||||
if (ShareUtils.shareEntrance == ShareUtils.ShareEntrance.askNormal ||
|
||||
ShareUtils.shareEntrance == ShareEntrance.communityArticle ||
|
||||
ShareUtils.shareEntrance == ShareUtils.ShareEntrance.video) {
|
||||
NewLogUtils.logShareResult(false);
|
||||
NewLogUtils.logShareResult(ShareUtils.additionalParams, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,7 +234,7 @@ public class ShareUtils {
|
||||
public void shareInviteFriends(Activity activity, String url, String way) {
|
||||
if (activity.isFinishing()) return;
|
||||
this.mActivity = new WeakReference<>(activity);
|
||||
this.shareIcon = activity.getString(R.string.gh_icon_url);
|
||||
this.shareIcon = getHttpsUrl(activity.getString(R.string.gh_icon_url));
|
||||
this.shareUrl = url;
|
||||
this.mSummary = "卡牌神器,海量游戏下载,积分大礼,等你尝鲜";
|
||||
this.mTitle = "推荐一款好玩的游戏下载APP【光环助手】";
|
||||
@ -270,7 +272,7 @@ public class ShareUtils {
|
||||
public void showShareUserHomeWindows(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id, ShareCallBack callBack) {
|
||||
if (activity.isFinishing()) return;
|
||||
this.mActivity = new WeakReference<>(activity);
|
||||
this.shareIcon = icon;
|
||||
this.shareIcon = getHttpsUrl(icon);
|
||||
this.shareUrl = url;
|
||||
this.mSummary = shareSummary;
|
||||
this.mTitle = shareTitle;
|
||||
@ -331,7 +333,7 @@ public class ShareUtils {
|
||||
public void showShareWindowsCallback(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id, ShareCallBack callBack) {
|
||||
if (activity.isFinishing()) return;
|
||||
this.mActivity = new WeakReference<>(activity);
|
||||
this.shareIcon = icon;
|
||||
this.shareIcon = getHttpsUrl(icon);
|
||||
this.shareUrl = url;
|
||||
this.mSummary = shareSummary;
|
||||
this.mTitle = shareTitle;
|
||||
@ -416,14 +418,19 @@ public class ShareUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public void shareParamsDetail(Activity activity, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id, ShareCallBack callBack) {
|
||||
public void shareParamsDetail(Activity activity, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id) {
|
||||
shareParamsDetail(activity, url, icon, shareTitle, shareSummary, shareEntrance, id, null);
|
||||
}
|
||||
|
||||
public void shareParamsDetail(Activity activity, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id, AdditionalParamsEntity params) {
|
||||
if (activity.isFinishing()) return;
|
||||
this.mActivity = new WeakReference<>(activity);
|
||||
this.shareIcon = icon;
|
||||
this.shareIcon = getHttpsUrl(icon);
|
||||
this.shareUrl = url;
|
||||
this.mSummary = shareSummary;
|
||||
this.mTitle = shareTitle;
|
||||
this.mShareEntrance = shareEntrance;
|
||||
ShareUtils.additionalParams = params;
|
||||
ShareUtils.shareEntrance = mShareEntrance;
|
||||
ShareUtils.resourceId = id;
|
||||
ShareUtils.shareEntity = new ShareEntity(shareUrl, mTitle, mSummary);
|
||||
@ -888,6 +895,13 @@ public class ShareUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private String getHttpsUrl(String url) {
|
||||
if (url.startsWith("http://")) {
|
||||
return url.replace("http://", "https://");
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
interface OnItemClickListener {
|
||||
void onItemClick(int position);
|
||||
}
|
||||
|
||||
@ -38,23 +38,23 @@ public class UserIconUtils {
|
||||
public static String getUserIconUrl(int i) {
|
||||
switch (i) {
|
||||
case 1:
|
||||
return "http://image.ghzs666.com/pic/default_icon_1.png";
|
||||
return "https://image.ghzs666.com/pic/default_icon_1.png";
|
||||
case 2:
|
||||
return "http://image.ghzs666.com/pic/default_icon_2.png";
|
||||
return "https://image.ghzs666.com/pic/default_icon_2.png";
|
||||
case 3:
|
||||
return "http://image.ghzs666.com/pic/default_icon_3.png";
|
||||
return "https://image.ghzs666.com/pic/default_icon_3.png";
|
||||
case 4:
|
||||
return "http://image.ghzs666.com/pic/default_icon_4.png";
|
||||
return "https://image.ghzs666.com/pic/default_icon_4.png";
|
||||
case 5:
|
||||
return "http://image.ghzs666.com/pic/default_icon_5.png";
|
||||
return "https://image.ghzs666.com/pic/default_icon_5.png";
|
||||
case 6:
|
||||
return "http://image.ghzs666.com/pic/default_icon_6.png";
|
||||
return "https://image.ghzs666.com/pic/default_icon_6.png";
|
||||
case 7:
|
||||
return "http://image.ghzs666.com/pic/default_icon_7.png";
|
||||
return "https://image.ghzs666.com/pic/default_icon_7.png";
|
||||
case 8:
|
||||
return "http://image.ghzs666.com/pic/default_icon_8.png";
|
||||
return "https://image.ghzs666.com/pic/default_icon_8.png";
|
||||
default:
|
||||
return "http://image.ghzs666.com/pic/default_icon_1.png";
|
||||
return "https://image.ghzs666.com/pic/default_icon_1.png";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import android.os.Parcelable
|
||||
import androidx.annotation.Keep
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.util.*
|
||||
|
||||
@Keep
|
||||
|
||||
@ -10,6 +10,7 @@ import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupWindow
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.toColor
|
||||
import com.gh.common.util.visibleIf
|
||||
@ -74,13 +75,23 @@ class CatalogFilterView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
mOnCatalogFilterSetupListener = onCatalogFilterSetupListener
|
||||
}
|
||||
|
||||
fun setRootBackgroundColor(@ColorInt color: Int) {
|
||||
findViewById<View>(R.id.config_controller).setBackgroundColor(color)
|
||||
}
|
||||
|
||||
fun setItemTextColor(@ColorInt color: Int) {
|
||||
mTypeTv.setTextColor(color)
|
||||
mCatalogTv.setTextColor(color)
|
||||
mSizeTv.setTextColor(color)
|
||||
}
|
||||
|
||||
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
|
||||
if (highlightIt) {
|
||||
targetTextView.background = ContextCompat.getDrawable(targetTextView.context, R.drawable.bg_tag_text)
|
||||
targetTextView.setTextColor(Color.WHITE)
|
||||
} else {
|
||||
targetTextView.background = null
|
||||
targetTextView.setTextColor(ContextCompat.getColor(targetTextView.context, R.color.text_757575))
|
||||
targetTextView.setTextColor(R.color.text_757575.toColor(context))
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +101,7 @@ class CatalogFilterView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
|
||||
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
|
||||
|
||||
typeTv.setTextColor(R.color.theme_font.toColor())
|
||||
typeTv.setTextColor(R.color.theme_font.toColor(context))
|
||||
typeTv.setCompoundDrawables(null, null, drawableUp, null)
|
||||
|
||||
val inflater = LayoutInflater.from(typeTv.context)
|
||||
@ -134,7 +145,7 @@ class CatalogFilterView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
typeTv.setTextColor(R.color.text_757575.toColor())
|
||||
typeTv.setTextColor(R.color.text_757575.toColor(context))
|
||||
typeTv.setCompoundDrawables(null, null, drawableDown, null)
|
||||
}
|
||||
|
||||
@ -150,7 +161,7 @@ class CatalogFilterView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
|
||||
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
|
||||
|
||||
catalogTv.setTextColor(R.color.theme_font.toColor())
|
||||
catalogTv.setTextColor(R.color.theme_font.toColor(context))
|
||||
catalogTv.setCompoundDrawables(null, null, drawableUp, null)
|
||||
|
||||
val inflater = LayoutInflater.from(catalogTv.context)
|
||||
@ -196,7 +207,7 @@ class CatalogFilterView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
catalogTv.setTextColor(R.color.text_757575.toColor())
|
||||
catalogTv.setTextColor(R.color.text_757575.toColor(context))
|
||||
catalogTv.setCompoundDrawables(null, null, drawableDown, null)
|
||||
}
|
||||
|
||||
@ -212,7 +223,7 @@ class CatalogFilterView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
|
||||
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
|
||||
|
||||
sizeTv.setTextColor(R.color.theme_font.toColor())
|
||||
sizeTv.setTextColor(R.color.theme_font.toColor(context))
|
||||
sizeTv.setCompoundDrawables(null, null, drawableUp, null)
|
||||
|
||||
val inflater = LayoutInflater.from(sizeTv.context)
|
||||
@ -266,7 +277,7 @@ class CatalogFilterView @JvmOverloads constructor(context: Context, attrs: Attri
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
sizeTv.setTextColor(R.color.text_757575.toColor())
|
||||
sizeTv.setTextColor(R.color.text_757575.toColor(context))
|
||||
sizeTv.setCompoundDrawables(null, null, drawableDown, null)
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -17,18 +16,25 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.SubjectSettingEntity
|
||||
import com.google.android.flexbox.FlexboxLayout
|
||||
|
||||
class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
|
||||
: ConstraintLayout(context, attrs, defStyleAttr) {
|
||||
class ConfigFilterView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private var mSizeTv: TextView
|
||||
private var mPopupWindow: PopupWindow? = null
|
||||
|
||||
var newestTv: TextView
|
||||
var ratingTv: TextView //目前只在专题页面显示
|
||||
var recommendedTv: TextView
|
||||
var updateTv: TextView //更新
|
||||
var container: View
|
||||
|
||||
var sizeFilterArray: ArrayList<SubjectSettingEntity.Size>? = null
|
||||
|
||||
private var mOnConfigFilterSetupListener: OnConfigFilterSetupListener? = null
|
||||
private var mSelectionTvList: ArrayList<TextView>
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.layout_config_filter, this)
|
||||
@ -36,7 +42,11 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
mSizeTv = findViewById(R.id.size_tv)
|
||||
newestTv = findViewById(R.id.newest_tv)
|
||||
ratingTv = findViewById(R.id.rating_tv)
|
||||
updateTv = findViewById(R.id.updateTv)
|
||||
recommendedTv = findViewById(R.id.recommended_tv)
|
||||
container = findViewById(R.id.config_controller)
|
||||
|
||||
mSelectionTvList = arrayListOf(newestTv, ratingTv, updateTv, recommendedTv)
|
||||
|
||||
mSizeTv.setOnClickListener {
|
||||
mOnConfigFilterSetupListener?.onShowSortSize()
|
||||
@ -45,55 +55,85 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
|
||||
ratingTv.setOnClickListener {
|
||||
mOnConfigFilterSetupListener?.onSetupSortType(SortType.RATING)
|
||||
toggleHighlightedTextView(ratingTv, true)
|
||||
toggleHighlightedTextView(newestTv, false)
|
||||
toggleHighlightedTextView(recommendedTv, false)
|
||||
updateHighlightedTextView(ratingTv)
|
||||
}
|
||||
|
||||
updateTv.setOnClickListener {
|
||||
mOnConfigFilterSetupListener?.onSetupSortType(SortType.UPDATE)
|
||||
updateHighlightedTextView(updateTv)
|
||||
}
|
||||
|
||||
newestTv.setOnClickListener {
|
||||
mOnConfigFilterSetupListener?.onSetupSortType(SortType.NEWEST)
|
||||
toggleHighlightedTextView(ratingTv, false)
|
||||
toggleHighlightedTextView(newestTv, true)
|
||||
toggleHighlightedTextView(recommendedTv, false)
|
||||
updateHighlightedTextView(newestTv)
|
||||
}
|
||||
|
||||
recommendedTv.setOnClickListener {
|
||||
mOnConfigFilterSetupListener?.onSetupSortType(SortType.RECOMMENDED)
|
||||
toggleHighlightedTextView(ratingTv, false)
|
||||
toggleHighlightedTextView(newestTv, false)
|
||||
toggleHighlightedTextView(recommendedTv, true)
|
||||
updateHighlightedTextView(recommendedTv)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateHighlightedTextView(highlightedTv: TextView) {
|
||||
for (tv in mSelectionTvList) {
|
||||
toggleHighlightedTextView(tv, tv == highlightedTv)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateAllTextView(sortType: SortType) {
|
||||
when (sortType) {
|
||||
SortType.RECOMMENDED -> updateHighlightedTextView(recommendedTv)
|
||||
SortType.NEWEST -> updateHighlightedTextView(newestTv)
|
||||
SortType.RATING -> updateHighlightedTextView(ratingTv)
|
||||
SortType.UPDATE -> updateHighlightedTextView(updateTv)
|
||||
}
|
||||
mSizeTv.setTextColor(R.color.text_757575.toColor(context))
|
||||
}
|
||||
|
||||
fun setOnConfigSetupListener(onConfigFilterSetupListener: OnConfigFilterSetupListener) {
|
||||
mOnConfigFilterSetupListener = onConfigFilterSetupListener
|
||||
}
|
||||
|
||||
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
|
||||
if (highlightIt) {
|
||||
targetTextView.background = ContextCompat.getDrawable(targetTextView.context, R.drawable.bg_tag_text)
|
||||
targetTextView.background =
|
||||
ContextCompat.getDrawable(targetTextView.context, R.drawable.bg_tag_text)
|
||||
targetTextView.setTextColor(Color.WHITE)
|
||||
} else {
|
||||
targetTextView.background = null
|
||||
targetTextView.setTextColor(ContextCompat.getColor(targetTextView.context, R.color.text_757575))
|
||||
targetTextView.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
targetTextView.context,
|
||||
R.color.text_757575
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updatePopupWindow() {
|
||||
if (mPopupWindow != null) {
|
||||
mPopupWindow?.dismiss()
|
||||
showSelectionPopupWindow(this, mSizeTv, mSizeTv.text.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSelectionPopupWindow(containerView: View, sizeTv: TextView, sizeText: String) {
|
||||
val drawableUp = ContextCompat.getDrawable(sizeTv.context, R.drawable.ic_filter_arrow_up)
|
||||
val drawableDown = ContextCompat.getDrawable(sizeTv.context, R.drawable.ic_filter_arrow_down)
|
||||
val drawableDown =
|
||||
ContextCompat.getDrawable(sizeTv.context, R.drawable.ic_filter_arrow_down)
|
||||
drawableUp?.setBounds(0, 0, drawableUp.minimumWidth, drawableUp.minimumHeight)
|
||||
drawableDown?.setBounds(0, 0, drawableDown.minimumWidth, drawableDown.minimumHeight)
|
||||
|
||||
sizeTv.setTextColor(R.color.theme_font.toColor())
|
||||
sizeTv.setTextColor(R.color.theme_font.toColor(sizeTv.context))
|
||||
sizeTv.setCompoundDrawables(null, null, drawableUp, null)
|
||||
|
||||
val inflater = LayoutInflater.from(sizeTv.context)
|
||||
val layout = inflater.inflate(R.layout.layout_filter_size, null)
|
||||
val popupWindow = PopupWindow(
|
||||
layout,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
layout,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).apply { mPopupWindow = this }
|
||||
|
||||
val flexboxLayout = layout.findViewById<FlexboxLayout>(R.id.flexbox)
|
||||
val backgroundView = layout.findViewById<View>(R.id.background)
|
||||
@ -143,8 +183,9 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
}
|
||||
|
||||
popupWindow.setOnDismissListener {
|
||||
sizeTv.setTextColor(R.color.text_757575.toColor())
|
||||
sizeTv.setTextColor(R.color.text_757575.toColor(sizeTv.context))
|
||||
sizeTv.setCompoundDrawables(null, null, drawableDown, null)
|
||||
mPopupWindow = null
|
||||
}
|
||||
|
||||
popupWindow.isTouchable = true
|
||||
@ -173,7 +214,8 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
enum class SortType {
|
||||
RECOMMENDED,
|
||||
NEWEST,
|
||||
RATING
|
||||
RATING,
|
||||
UPDATE
|
||||
}
|
||||
|
||||
}
|
||||
@ -170,7 +170,7 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
case INSTALL_NORMAL:
|
||||
case H5_GAME:
|
||||
if (mDownloadStyle == DOWNLOAD_IMAGE_STYLE) {
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.detail_download_normal_image_style));
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.text_white_background));
|
||||
mDefaultColor = Color.BLACK;
|
||||
} else {
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.download_button_normal_style));
|
||||
@ -185,7 +185,7 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
setProgress(0);
|
||||
break;
|
||||
case NONE:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.news_detail_comment));
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.button_border_gray_oval));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.hint);
|
||||
setProgress(0);
|
||||
break;
|
||||
|
||||
@ -13,7 +13,6 @@ import android.widget.TextView
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.databind.DrawablesBindingAdapter
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.dip2px
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@ -183,7 +183,7 @@ class FilterView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
holder.binding.titleTv.setBackgroundResource(R.drawable.bg_tag_text)
|
||||
holder.binding.titleTv.setTextColor(R.color.white.toColor())
|
||||
} else {
|
||||
holder.binding.titleTv.setBackgroundColor(Color.WHITE)
|
||||
holder.binding.titleTv.setBackgroundColor(R.color.background_white.toColor(holder.binding.root.context))
|
||||
holder.binding.titleTv.setTextColor(R.color.text_777777.toColor())
|
||||
}
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.common.util.sp2px
|
||||
import com.gh.common.util.toColor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.TagStyleEntity
|
||||
import kotlin.math.ceil
|
||||
@ -43,7 +44,7 @@ class FlexLinearLayout @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
mMargin = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_itemMargin, 4f.dip2px())
|
||||
mTextSize = ta.getDimension(R.styleable.FlexLinearLayout_itemTextSize, 10f.sp2px().toFloat())
|
||||
mLastItemWidth = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_lastItemWidth, 18f.dip2px())
|
||||
mStrokeWidth = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_strokeWidth, 1f.dip2px())
|
||||
mStrokeWidth = ta.getDimensionPixelSize(R.styleable.FlexLinearLayout_strokeWidth, 0.5f.dip2px())
|
||||
|
||||
ta.recycle()
|
||||
}
|
||||
@ -107,7 +108,7 @@ class FlexLinearLayout @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
includeFontPadding = false
|
||||
textSize = DisplayUtils.px2sp(context, mTextSize).toFloat()
|
||||
gravity = Gravity.CENTER
|
||||
setTextColor(Color.parseColor("#333333"))
|
||||
setTextColor(R.color.text_title.toColor(context))
|
||||
|
||||
val params = LayoutParams(LayoutParams.WRAP_CONTENT, mItemHeight)
|
||||
params.setMargins(0, 0, mMargin, 0)
|
||||
@ -125,7 +126,7 @@ class FlexLinearLayout @JvmOverloads constructor(context: Context, attrs: Attrib
|
||||
private fun createBackgroundDrawable(): GradientDrawable {
|
||||
val gradientDrawable = GradientDrawable()
|
||||
gradientDrawable.setColor(Color.TRANSPARENT)
|
||||
gradientDrawable.setStroke(mStrokeWidth, Color.parseColor("#C2C6CC"))
|
||||
gradientDrawable.setStroke(mStrokeWidth, Color.parseColor("#CCCCCC"))
|
||||
gradientDrawable.cornerRadius = DisplayUtils.dip2px(2f).toFloat()
|
||||
return gradientDrawable
|
||||
}
|
||||
|
||||
@ -83,6 +83,10 @@ class GameIconView : CardView {
|
||||
}
|
||||
|
||||
fun displayGameIcon(icon: String?, iconSubscript: String?, goneIfEmpty: Boolean = false) {
|
||||
if (getTag(ImageUtils.TAG_TARGET_WIDTH) == null) {
|
||||
setTag(ImageUtils.TAG_TARGET_WIDTH, layoutParams.width)
|
||||
}
|
||||
|
||||
mGameIconIv?.display(icon)
|
||||
mGameIconDecorationIv?.display(iconSubscript)
|
||||
mGameIconDecorationIv?.goneIf(TextUtils.isEmpty(iconSubscript))
|
||||
|
||||
@ -12,6 +12,7 @@ import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.toColor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.TagStyleEntity
|
||||
import kotlin.math.ceil
|
||||
@ -80,7 +81,7 @@ class GameTagFlexLinearLayout @JvmOverloads constructor(context: Context, attrs:
|
||||
includeFontPadding = false
|
||||
textSize = mTextSize
|
||||
gravity = Gravity.CENTER
|
||||
setTextColor(Color.parseColor("#666666"))
|
||||
setTextColor(R.color.text_subtitle.toColor(context))
|
||||
|
||||
val params = LayoutParams(LayoutParams.WRAP_CONTENT, mItemHeight)
|
||||
params.setMargins(0, 0, mMargin, 0)
|
||||
|
||||
@ -237,6 +237,10 @@ class ImageContainerView : LinearLayout {
|
||||
} else {
|
||||
params.width = mDefaultWidth.toInt()
|
||||
params.height = mDefaultWidth.toInt()
|
||||
if (width > height) {
|
||||
val loadImageWidth = width * (mDefaultWidth.toInt() / height)
|
||||
binding.image.setTag(ImageUtils.TAG_TARGET_WIDTH, loadImageWidth.toInt())
|
||||
}
|
||||
ImageUtils.display(binding.image, url, false)
|
||||
}
|
||||
//长图
|
||||
|
||||
@ -4,11 +4,11 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.common.util.fromHtml
|
||||
import com.gh.gamecenter.GameDetailActivity
|
||||
import com.gh.gamecenter.R
|
||||
@ -23,8 +23,8 @@ class ReserveDialog : BaseDialogFragment() {
|
||||
private lateinit var mReserveList: List<SimpleGameEntity>
|
||||
private var mDismissListener: (() -> Unit)? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val binding: DialogReserveBinding = DataBindingUtil.inflate(inflater, R.layout.dialog_reserve, container, false)
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
val binding: DialogReserveBinding = DialogReserveBinding.inflate(layoutInflater, null, false)
|
||||
|
||||
mReserveList = arguments?.getParcelableArrayList(RESERVE_LIST) ?: arrayListOf()
|
||||
|
||||
@ -54,7 +54,8 @@ class ReserveDialog : BaseDialogFragment() {
|
||||
|
||||
override fun onBindViewHolder(holder: ReserveDialogItemViewHolder, position: Int) {
|
||||
val entity = mReserveList[position]
|
||||
holder.binding.game = entity
|
||||
ImageUtils.display(holder.binding.icon, entity.icon)
|
||||
holder.binding.gameNameTv.text = entity.name
|
||||
holder.itemView.setOnClickListener {
|
||||
GameDetailActivity.startGameDetailActivity(mContext, entity.id, "(预约弹窗)")
|
||||
dismissAllowingStateLoss()
|
||||
|
||||
@ -24,7 +24,6 @@ import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.HtmlUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.RichEditorUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
@ -62,8 +61,8 @@ import java.util.Locale;
|
||||
|
||||
public class RichEditor extends WebView {
|
||||
// 和 rich_editor.js 同步
|
||||
public static String IMAGE_FLAG_DEFAULT = ",default";
|
||||
public static String IMAGE_FLAG_THUMBNAIL = ",thumbnail";
|
||||
// public static String IMAGE_FLAG_DEFAULT = ",default";
|
||||
// public static String IMAGE_FLAG_THUMBNAIL = ",thumbnail";
|
||||
|
||||
private boolean mContentOwner;
|
||||
private boolean mInputEnabled;
|
||||
@ -132,7 +131,7 @@ public class RichEditor extends WebView {
|
||||
|
||||
int widthPixels = getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(40);
|
||||
mThumbnailImageWidth = widthPixels / 3;
|
||||
mDefaultImageWidth = widthPixels * 2;
|
||||
mDefaultImageWidth = widthPixels;
|
||||
}
|
||||
|
||||
@SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"})
|
||||
@ -251,13 +250,7 @@ public class RichEditor extends WebView {
|
||||
exec("javascript:RE.setHtmlByVideoStatus('" + URLEncoder.encode(contents, "UTF-8") + "');");
|
||||
|
||||
if (isLoadTbImage) {
|
||||
if (!NetworkUtils.isWifiOr4GConnected(getContext())) {
|
||||
exec("javascript:RE.replaceTbImage('" +
|
||||
ImageUtils.getLimitWidthRule(mThumbnailImageWidth) + IMAGE_FLAG_THUMBNAIL + "','" +
|
||||
ImageUtils.getWatermarkWidthGifRule(mThumbnailImageWidth) + IMAGE_FLAG_THUMBNAIL + "');");
|
||||
} else {
|
||||
replaceAllDfImageExcludeGif();
|
||||
}
|
||||
replaceAllDfImage();
|
||||
exec("javascript:RE.ImageClickListener()");
|
||||
}
|
||||
|
||||
@ -370,21 +363,21 @@ public class RichEditor extends WebView {
|
||||
|
||||
public void replaceAllDfImageExcludeGif() {
|
||||
exec("javascript:RE.replaceAllDfImage('" +
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + IMAGE_FLAG_DEFAULT + "','" +
|
||||
ImageUtils.getWatermarkWidthGifRule(mThumbnailImageWidth) + IMAGE_FLAG_THUMBNAIL + "')");
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + "','" +
|
||||
ImageUtils.getWatermarkWidthGifRule(mThumbnailImageWidth) + "')");
|
||||
}
|
||||
|
||||
|
||||
public void replaceAllDfImage() {
|
||||
exec("javascript:RE.replaceAllDfImage('" +
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + IMAGE_FLAG_DEFAULT + "','" +
|
||||
ImageUtils.getDefaultGifRule() + IMAGE_FLAG_DEFAULT + "')");
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + "','" +
|
||||
ImageUtils.getDefaultGifRule() + "')");
|
||||
}
|
||||
|
||||
public void replaceDfImageByUrl(String imgUrl) {
|
||||
exec("javascript:RE.replaceDfImageByUrl('" + imgUrl + "','" +
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + IMAGE_FLAG_DEFAULT + "','" +
|
||||
ImageUtils.getDefaultGifRule() + IMAGE_FLAG_DEFAULT + "');");
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + "','" +
|
||||
ImageUtils.getDefaultGifRule() + "');");
|
||||
}
|
||||
|
||||
public void loadCSS(String cssFile) {
|
||||
|
||||
215
app/src/main/java/com/gh/common/view/ScaleIndicatorView.kt
Normal file
215
app/src/main/java/com/gh/common/view/ScaleIndicatorView.kt
Normal file
@ -0,0 +1,215 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.animation.ArgbEvaluator
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.RectF
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.annotation.ColorInt
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
class ScaleIndicatorView : View {
|
||||
|
||||
private var argbEvaluator: ArgbEvaluator? = null
|
||||
|
||||
private var mCurrentPosition = 0
|
||||
private var mSlideProgress = 0F
|
||||
var mPageSize = 0
|
||||
var mNormalSliderWidth = 0F
|
||||
var mCheckedSliderWidth = 0F
|
||||
var mSliderHeight = 0F
|
||||
var mSliderGap = 0F
|
||||
|
||||
@ColorInt
|
||||
var mNormalColor = 0
|
||||
|
||||
@ColorInt
|
||||
var mCheckedColor = 0
|
||||
|
||||
private var mRectF = RectF()
|
||||
private var mPaint = Paint()
|
||||
|
||||
private var maxWidth = 0F
|
||||
private var minWidth = 0F
|
||||
|
||||
private val isWidthEquals
|
||||
get() = mNormalSliderWidth == mCheckedSliderWidth
|
||||
|
||||
constructor(context: Context) : super(context, null) {
|
||||
initView(null)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs, 0) {
|
||||
initView(attrs)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
|
||||
context,
|
||||
attrs,
|
||||
defStyleAttr
|
||||
) {
|
||||
initView(attrs)
|
||||
}
|
||||
|
||||
private fun initView(attrs: AttributeSet?) {
|
||||
if (attrs != null) {
|
||||
val ta = context.obtainStyledAttributes(attrs, R.styleable.ScaleIndicatorView)
|
||||
mNormalSliderWidth = ta.getDimensionPixelSize(R.styleable.ScaleIndicatorView_normalSliderWidth, 10F.dip2px()).toFloat()
|
||||
mCheckedSliderWidth = ta.getDimensionPixelSize(R.styleable.ScaleIndicatorView_checkedSliderWidth, 10F.dip2px()).toFloat()
|
||||
mSliderHeight = ta.getDimensionPixelSize(R.styleable.ScaleIndicatorView_normalSliderWidth, 10F.dip2px()).toFloat()
|
||||
mSliderGap = ta.getDimensionPixelSize(R.styleable.ScaleIndicatorView_normalSliderWidth, 10F.dip2px()).toFloat()
|
||||
mNormalColor = ta.getColor(R.styleable.ScaleIndicatorView_normalColor, Color.WHITE)
|
||||
mCheckedColor = ta.getColor(R.styleable.ScaleIndicatorView_checkedColor, Color.WHITE)
|
||||
}
|
||||
mPaint.isAntiAlias = true
|
||||
argbEvaluator = ArgbEvaluator()
|
||||
}
|
||||
|
||||
fun onPageScrolled(position: Int, positionOffset: Float) {
|
||||
if (mPageSize > 1) {
|
||||
scrollSlider(position, positionOffset)
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyDataChanged() {
|
||||
requestLayout()
|
||||
invalidate()
|
||||
}
|
||||
|
||||
private fun scrollSlider(
|
||||
position: Int,
|
||||
positionOffset: Float
|
||||
) {
|
||||
mCurrentPosition = position
|
||||
mSlideProgress = positionOffset
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
maxWidth = mNormalSliderWidth.coerceAtLeast(mCheckedSliderWidth)
|
||||
minWidth = mNormalSliderWidth.coerceAtMost(mCheckedSliderWidth)
|
||||
setMeasuredDimension(measureWidth(), measureHeight())
|
||||
}
|
||||
|
||||
private fun measureHeight() = mSliderHeight.toInt() + INDICATOR_PADDING
|
||||
|
||||
private fun measureWidth() =
|
||||
((mPageSize - 1) * mSliderGap + maxWidth + (mPageSize - 1) * minWidth).toInt() + INDICATOR_PADDING_ADDITION
|
||||
|
||||
override fun onDraw(canvas: Canvas?) {
|
||||
super.onDraw(canvas)
|
||||
if (mPageSize > 1) {
|
||||
if (isWidthEquals) {
|
||||
drawUncheckedSlider(canvas, mPageSize)
|
||||
} else {
|
||||
for (i in 0 until mPageSize) {
|
||||
drawScaleSlider(canvas, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawScaleSlider(
|
||||
canvas: Canvas?,
|
||||
i: Int
|
||||
) {
|
||||
when {
|
||||
i < mCurrentPosition -> {
|
||||
mPaint.color = mNormalColor
|
||||
val left: Float = if (mCurrentPosition == mPageSize - 1) {
|
||||
(i * mNormalSliderWidth + i * mSliderGap) + (mCheckedSliderWidth - mNormalSliderWidth) * mSlideProgress
|
||||
} else {
|
||||
(i * mNormalSliderWidth + i * mSliderGap)
|
||||
}
|
||||
mRectF.set(left, 0f, left + mNormalSliderWidth, mSliderHeight)
|
||||
canvas?.drawRoundRect(mRectF, mSliderHeight, mSliderHeight, mPaint)
|
||||
}
|
||||
i == mCurrentPosition -> {
|
||||
mPaint.color = mCheckedColor
|
||||
val slideProgress = mSlideProgress
|
||||
if (mCurrentPosition == mPageSize - 1) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
slideProgress, mCheckedColor, mNormalColor
|
||||
)
|
||||
mPaint.color = (evaluate as Int)
|
||||
val right =
|
||||
(mPageSize - 1) * (mNormalSliderWidth + mSliderGap) + mCheckedSliderWidth
|
||||
val left =
|
||||
right - mCheckedSliderWidth + (mCheckedSliderWidth - mNormalSliderWidth) * (slideProgress)
|
||||
mRectF.set(left, 0f, right, mSliderHeight)
|
||||
canvas?.drawRoundRect(mRectF, mSliderHeight, mSliderHeight, mPaint)
|
||||
} else {
|
||||
if (slideProgress < 1) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
slideProgress, mCheckedColor, mNormalColor
|
||||
)
|
||||
mPaint.color = (evaluate as Int)
|
||||
val left = i * mNormalSliderWidth + i * mSliderGap
|
||||
val right =
|
||||
left + mNormalSliderWidth + (mCheckedSliderWidth - mNormalSliderWidth) * (1 - slideProgress)
|
||||
mRectF.set(left, 0f, right, mSliderHeight)
|
||||
canvas?.drawRoundRect(mRectF, mSliderHeight, mSliderHeight, mPaint)
|
||||
}
|
||||
}
|
||||
|
||||
if (mCurrentPosition == mPageSize - 1) {
|
||||
if (slideProgress > 0) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
1 - slideProgress, mCheckedColor, mNormalColor
|
||||
)
|
||||
mPaint.color = evaluate as Int
|
||||
val left = 0f
|
||||
val right =
|
||||
left + mNormalSliderWidth + (mCheckedSliderWidth - mNormalSliderWidth) * slideProgress
|
||||
|
||||
mRectF.set(left, 0f, right, mSliderHeight)
|
||||
canvas?.drawRoundRect(mRectF, mSliderHeight, mSliderHeight, mPaint)
|
||||
}
|
||||
} else {
|
||||
if (slideProgress > 0) {
|
||||
val evaluate = argbEvaluator?.evaluate(
|
||||
1 - slideProgress, mCheckedColor, mNormalColor
|
||||
)
|
||||
mPaint.color = evaluate as Int
|
||||
val right =
|
||||
i * mNormalSliderWidth + i * mSliderGap + mNormalSliderWidth + (mSliderGap + mCheckedSliderWidth)
|
||||
val left =
|
||||
right - (mNormalSliderWidth) - (mCheckedSliderWidth - mNormalSliderWidth) * (slideProgress)
|
||||
mRectF.set(left, 0f, right, mSliderHeight)
|
||||
canvas?.drawRoundRect(mRectF, mSliderHeight, mSliderHeight, mPaint)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if ((mCurrentPosition + 1 != i || mSlideProgress == 0f)) { // 避免多余绘制
|
||||
mPaint.color = mNormalColor
|
||||
val left = i * minWidth + i * mSliderGap + (mCheckedSliderWidth - minWidth)
|
||||
mRectF.set(left, 0f, left + minWidth, mSliderHeight)
|
||||
canvas?.drawRoundRect(mRectF, mSliderHeight, mSliderHeight, mPaint)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawUncheckedSlider(
|
||||
canvas: Canvas?,
|
||||
pageSize: Int
|
||||
) {
|
||||
for (i in 0 until pageSize) {
|
||||
mPaint.color = mNormalColor
|
||||
val left = i * maxWidth + i * +mSliderGap + (maxWidth - minWidth)
|
||||
mRectF.set(left, 0f, left + minWidth, mSliderHeight)
|
||||
canvas?.drawRoundRect(mRectF, mSliderHeight, mSliderHeight, mPaint)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val INDICATOR_PADDING_ADDITION = 6
|
||||
const val INDICATOR_PADDING = 3
|
||||
}
|
||||
}
|
||||
197
app/src/main/java/com/gh/common/view/SegmentedFilterView.kt
Normal file
197
app/src/main/java/com/gh/common/view/SegmentedFilterView.kt
Normal file
@ -0,0 +1,197 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RadioButton
|
||||
import android.widget.RadioGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.gamecenter.R
|
||||
import splitties.views.dsl.core.add
|
||||
|
||||
class SegmentedFilterView : FrameLayout {
|
||||
|
||||
private var mItemWidth = 0
|
||||
private var mItemHeight = 0
|
||||
private var mTextColor: ColorStateList? =
|
||||
ContextCompat.getColorStateList(context, R.color.game_collection_rg_button_selector)
|
||||
private var mTextSize = 10F
|
||||
private var mContainerBackground: Drawable? = null
|
||||
private var mIndicatorBackground: Drawable? = null
|
||||
private var mAnimationDuration = 200
|
||||
private var mContainerPadding = 1F.dip2px()
|
||||
|
||||
private lateinit var mContainer: FrameLayout
|
||||
private lateinit var mRadioGroup: RadioGroup
|
||||
private lateinit var mIndicator: View
|
||||
private var mCallback: OnCheckedCallback? = null
|
||||
|
||||
private var mItemList = listOf<String>()
|
||||
|
||||
constructor(context: Context) : super(context, null) {
|
||||
initView(null)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs, 0) {
|
||||
initView(attrs)
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
|
||||
context,
|
||||
attrs,
|
||||
defStyleAttr
|
||||
) {
|
||||
initView(attrs)
|
||||
}
|
||||
|
||||
fun setTextColor(colorStateList: ColorStateList?) {
|
||||
if (::mRadioGroup.isInitialized) {
|
||||
for (i in 0 until mRadioGroup.childCount) {
|
||||
val radioBtn = mRadioGroup.getChildAt(i) as RadioButton
|
||||
radioBtn.setTextColor(colorStateList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setContainerBackground(drawable: Drawable?) {
|
||||
background = drawable
|
||||
}
|
||||
|
||||
fun setIndicatorBackground(drawable: Drawable?) {
|
||||
if (::mIndicator.isInitialized) {
|
||||
mIndicator.background = drawable
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView(attrs: AttributeSet?) {
|
||||
if (attrs != null) {
|
||||
val ta = context.obtainStyledAttributes(attrs, R.styleable.SegmentedFilterView)
|
||||
mContainerBackground =
|
||||
ta.getDrawable(R.styleable.SegmentedFilterView_containerBackground)
|
||||
mIndicatorBackground =
|
||||
ta.getDrawable(R.styleable.SegmentedFilterView_indicatorBackground)
|
||||
mContainerPadding = ta.getDimensionPixelSize(
|
||||
R.styleable.SegmentedFilterView_containerPadding,
|
||||
1F.dip2px()
|
||||
)
|
||||
mItemWidth = ta.getDimensionPixelSize(
|
||||
R.styleable.SegmentedFilterView_sfv_itemWidth,
|
||||
36F.dip2px()
|
||||
)
|
||||
mItemHeight = ta.getDimensionPixelSize(
|
||||
R.styleable.SegmentedFilterView_sfv_itemHeight,
|
||||
24F.dip2px()
|
||||
)
|
||||
mAnimationDuration = ta.getInt(R.styleable.SegmentedFilterView_animationDuration, 200)
|
||||
mTextColor = ta.getColorStateList(R.styleable.SegmentedFilterView_sfv_textColor)
|
||||
mTextSize = ta.getFloat(R.styleable.SegmentedFilterView_sfv_textSize, 10F)
|
||||
ta.recycle()
|
||||
}
|
||||
setPadding(mContainerPadding, mContainerPadding, mContainerPadding, mContainerPadding)
|
||||
if (mContainerBackground != null) background = mContainerBackground
|
||||
mContainer = FrameLayout(context)
|
||||
mIndicator = View(context).apply {
|
||||
background = mIndicatorBackground
|
||||
}
|
||||
mRadioGroup = RadioGroup(context).apply {
|
||||
gravity = Gravity.CENTER
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
}
|
||||
add(mContainer, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT))
|
||||
mContainer.add(mIndicator, LayoutParams(mItemWidth, mItemHeight))
|
||||
mContainer.add(
|
||||
mRadioGroup,
|
||||
LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
|
||||
)
|
||||
}
|
||||
|
||||
fun setItemList(itemList: List<String>, defaultCheckPosition: Int) {
|
||||
mItemList = itemList
|
||||
mRadioGroup.removeAllViews()
|
||||
addRadioButton()
|
||||
if (defaultCheckPosition in 0 until mRadioGroup.childCount) (mRadioGroup.getChildAt(defaultCheckPosition) as RadioButton).isChecked = true
|
||||
}
|
||||
|
||||
fun getItemList(): List<String> {
|
||||
return mItemList
|
||||
}
|
||||
|
||||
fun performClick(position: Int) {
|
||||
if (position in 0 until mRadioGroup.childCount) {
|
||||
val radioButton = mRadioGroup.getChildAt(position) as RadioButton
|
||||
radioButton.isChecked = true
|
||||
startIndicatorAnimation(radioButton.x)
|
||||
mCallback?.onItemCheck(position)
|
||||
}
|
||||
}
|
||||
|
||||
fun setChecked(position: Int) {
|
||||
if (position in 0 until mRadioGroup.childCount) {
|
||||
val radioButton = mRadioGroup.getChildAt(position) as RadioButton
|
||||
mIndicator.x = radioButton.x
|
||||
radioButton.isChecked = true
|
||||
}
|
||||
}
|
||||
|
||||
fun getCurrentPosition(): Int {
|
||||
var position = 0
|
||||
for (i in 0 until mRadioGroup.childCount) {
|
||||
val radioButton = mRadioGroup.getChildAt(i) as RadioButton
|
||||
if (radioButton.isChecked) {
|
||||
position = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return position
|
||||
}
|
||||
|
||||
fun setOnCheckedCallback(callback: OnCheckedCallback) {
|
||||
mCallback = callback
|
||||
mRadioGroup.setOnCheckedChangeListener { _, checkId ->
|
||||
for (i in 0 until mRadioGroup.childCount) {
|
||||
val radioBtn = mRadioGroup.getChildAt(i)
|
||||
if (checkId == radioBtn.id && radioBtn.x != mIndicator.x) {
|
||||
startIndicatorAnimation(radioBtn.x)
|
||||
mCallback?.onItemCheck(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addRadioButton() {
|
||||
for (item in mItemList) {
|
||||
val radioButton = RadioButton(context).apply {
|
||||
background = null
|
||||
buttonDrawable = null
|
||||
text = item
|
||||
gravity = Gravity.CENTER
|
||||
textSize = mTextSize
|
||||
setTextColor(mTextColor)
|
||||
isChecked = false
|
||||
}
|
||||
mRadioGroup.add(radioButton, LinearLayout.LayoutParams(mItemWidth, mItemHeight))
|
||||
}
|
||||
}
|
||||
|
||||
private fun startIndicatorAnimation(x: Float) {
|
||||
ValueAnimator.ofFloat(mIndicator.x, x).apply {
|
||||
interpolator = AccelerateDecelerateInterpolator()
|
||||
duration = mAnimationDuration.toLong()
|
||||
addUpdateListener {
|
||||
mIndicator.x = it.animatedValue as Float
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
interface OnCheckedCallback {
|
||||
fun onItemCheck(position: Int)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
public class TrimmedPaddingTextView extends AppCompatTextView {
|
||||
|
||||
public TrimmedPaddingTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public TrimmedPaddingTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
setIncludeFontPadding(getLineCount() > 1);
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,6 +2,7 @@ package com.gh.common.view
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.text.*
|
||||
import android.text.InputFilter.LengthFilter
|
||||
@ -14,6 +15,7 @@ import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.gamecenter.R
|
||||
import java.util.*
|
||||
@ -33,6 +35,7 @@ class VerifyEditText @JvmOverloads constructor(
|
||||
private var mEditText: EditText? = null
|
||||
private var drawableNormal: Drawable? = null
|
||||
private var drawableSelected: Drawable? = null
|
||||
private var textColor: Int
|
||||
private var mContext: Context? = null
|
||||
|
||||
|
||||
@ -58,6 +61,23 @@ class VerifyEditText @JvmOverloads constructor(
|
||||
if (drawable != null) textView.background = drawable
|
||||
}
|
||||
|
||||
fun setTextViewStyle(normal: Drawable?, selected: Drawable?, @ColorInt color: Int) {
|
||||
drawableNormal = normal
|
||||
drawableSelected = selected
|
||||
textColor = color
|
||||
var isFirst = true
|
||||
for (i in mTextViewList.indices) {
|
||||
val textView = mTextViewList[i]
|
||||
if (textView.text.isNullOrEmpty() && isFirst) {
|
||||
isFirst = false
|
||||
setTextViewBackground(textView, drawableSelected)
|
||||
} else {
|
||||
setTextViewBackground(textView, drawableNormal)
|
||||
}
|
||||
textView.setTextColor(textColor)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前输入的内容
|
||||
*
|
||||
@ -179,7 +199,7 @@ class VerifyEditText @JvmOverloads constructor(
|
||||
obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_normal)
|
||||
drawableSelected =
|
||||
obtainStyledAttributes.getDrawable(R.styleable.verify_EditText_verify_background_selected)
|
||||
val textColor = obtainStyledAttributes.getColor(
|
||||
textColor = obtainStyledAttributes.getColor(
|
||||
R.styleable.verify_EditText_verify_textColor,
|
||||
ContextCompat.getColor(context, R.color.black)
|
||||
)
|
||||
|
||||
@ -82,6 +82,8 @@ object DownloadDataHelper {
|
||||
"未实名"
|
||||
} else if (status == DownloadStatus.unqualified) {
|
||||
"未成年"
|
||||
} else if (status == DownloadStatus.unavailable) {
|
||||
"未接入防沉迷系统,暂不支持下载"
|
||||
} else if (status == DownloadStatus.redirected) {
|
||||
"重定向至最终地址"
|
||||
} else {
|
||||
|
||||
@ -73,7 +73,6 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
private static final Gson gson = new Gson();
|
||||
private static final String UPDATE_IS_READ_MARK = "update_is_read";
|
||||
private static final String DOWNLOADING_IS_READ_MARK = "downloading_is_read";
|
||||
private static final String DOWNLOADED_IS_READ_MARK = "downloaded_is_read";
|
||||
@ -349,7 +348,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, downloadType);
|
||||
|
||||
// 将下载事件放入 downloadEntity 中供下载完成时取出使用
|
||||
downloadEntity.setExposureTrace(gson.toJson(downloadExposureEvent));
|
||||
downloadEntity.setExposureTrace(GsonUtils.toJson(downloadExposureEvent));
|
||||
|
||||
if (isSubscribe) {
|
||||
DownloadManager.getInstance().subscribe(downloadEntity);
|
||||
@ -690,11 +689,13 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
public void cancel(String url, boolean isDeleteFile, boolean automatic) {
|
||||
DownloadEntity entry = mDownloadDao.get(url);
|
||||
if (entry != null) {
|
||||
if (isDeleteFile) {
|
||||
FileUtils.deleteFile(entry.getPath());
|
||||
}
|
||||
mDownloadDao.delete(url);
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "cancel==>record were deleted!");
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
if (isDeleteFile) {
|
||||
FileUtils.deleteFile(entry.getPath());
|
||||
}
|
||||
mDownloadDao.delete(url);
|
||||
Utils.log(DownloadManager.class.getSimpleName(), "cancel==>record were deleted!");
|
||||
});
|
||||
}
|
||||
if (entry != null) {
|
||||
if (automatic) {
|
||||
|
||||
@ -3,10 +3,11 @@ package com.gh.download.dialog
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.Observer
|
||||
@ -32,7 +33,6 @@ import com.lightgame.utils.AppManager
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import java.util.*
|
||||
|
||||
class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
|
||||
@ -62,17 +62,20 @@ class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
private val mDataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
if (downloadEntity.gameId == mGameEntity?.id &&
|
||||
DownloadStatus.delete != DownloadManager.getInstance().getStatus(downloadEntity.url)) {
|
||||
DownloadStatus.delete != DownloadManager.getInstance().getStatus(downloadEntity.url)
|
||||
) {
|
||||
mAdapter?.listData?.forEachIndexed { index, entity ->
|
||||
if (entity.normal?.packageName == downloadEntity.packageName
|
||||
|| entity.installed?.packageName == downloadEntity.packageName) {
|
||||
|| entity.installed?.packageName == downloadEntity.packageName
|
||||
) {
|
||||
mAdapter?.notifyItemChanged(index)
|
||||
}
|
||||
}
|
||||
|
||||
mCollectionAdapter?.listData?.forEachIndexed { index, entity ->
|
||||
if (entity.normal?.packageName == downloadEntity.packageName
|
||||
|| entity.installed?.packageName == downloadEntity.packageName) {
|
||||
|| entity.installed?.packageName == downloadEntity.packageName
|
||||
) {
|
||||
mCollectionAdapter?.notifyItemChanged(index)
|
||||
}
|
||||
}
|
||||
@ -146,8 +149,8 @@ class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
mBinding = DataBindingUtil.inflate(inflater, R.layout.dialog_download, container, false)
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
mBinding = DialogDownloadBinding.bind(layoutInflater.inflate(R.layout.dialog_download, container, false))
|
||||
mBinding.title.text = ("选择下载" + mGameEntity.pluginDesc + "版本")
|
||||
|
||||
val downloadNotice = mGameEntity.downloadAd
|
||||
@ -159,9 +162,10 @@ class DownloadDialog : BaseDraggableDialogFragment() {
|
||||
DialogUtils.showImprintDialog(requireContext(), mGameEntity, downloadNotice.title)
|
||||
} else {
|
||||
DirectUtils.directToLinkPage(
|
||||
requireContext(),
|
||||
downloadNotice,
|
||||
mEntrance, "下载多平台弹窗")
|
||||
requireContext(),
|
||||
downloadNotice,
|
||||
mEntrance, "下载多平台弹窗"
|
||||
)
|
||||
}
|
||||
// MtaHelper.onEvent(MTA_KEY, "点击", mViewModel.gameEntity.name + "_" + downloadNotice.title)
|
||||
}
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
package com.gh.download.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.base.OnViewClickListener
|
||||
import com.gh.common.exposure.ExposureEvent
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.MtaHelper
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.common.util.throwExceptionInDebug
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.NewsDetailActivity
|
||||
import com.gh.gamecenter.QaActivity
|
||||
import com.gh.gamecenter.R
|
||||
@ -18,13 +16,15 @@ import com.gh.gamecenter.entity.GameEntity
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter
|
||||
import com.lightgame.utils.Utils
|
||||
|
||||
class DownloadDialogAdapter(context: Context,
|
||||
val viewModel: DownloadViewModel,
|
||||
val listData: List<DownloadDialogItemData>,
|
||||
val isCollectionPage: Boolean,
|
||||
private val mTraceEvent: ExposureEvent?,
|
||||
private val mEntrance: String,
|
||||
private val mLocation: String) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
class DownloadDialogAdapter(
|
||||
context: Context,
|
||||
val viewModel: DownloadViewModel,
|
||||
val listData: List<DownloadDialogItemData>,
|
||||
val isCollectionPage: Boolean,
|
||||
private val mTraceEvent: ExposureEvent?,
|
||||
private val mEntrance: String,
|
||||
private val mLocation: String
|
||||
) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context) {
|
||||
|
||||
private val mPath = if (isCollectionPage) {
|
||||
"下载弹窗-二级页"
|
||||
@ -83,11 +83,13 @@ class DownloadDialogAdapter(context: Context,
|
||||
} else 0
|
||||
holder.binding.root.layoutParams = this
|
||||
}
|
||||
holder.binding.type = listData[position].section
|
||||
val section = listData[position].section
|
||||
holder.binding.title.text = if (section == DownloadDialogSectionType.OTHER) "其它版本" else "我的版本"
|
||||
holder.binding.otherVersionHint.goneIf(section != DownloadDialogSectionType.OTHER)
|
||||
}
|
||||
is DownloadDialogLinkItemViewHolder -> {
|
||||
holder.binding.links = listData[position].links
|
||||
holder.binding.clickListener = OnViewClickListener<GameEntity.PluginLink> { _, data ->
|
||||
val links = listData[position].links
|
||||
val clickListener = OnViewClickListener<GameEntity.PluginLink> { _, data ->
|
||||
when (data.linkType) {
|
||||
"dialog" -> {
|
||||
DownloadLinkDialog.showDownloadDialog(mContext, data)
|
||||
@ -109,6 +111,28 @@ class DownloadDialogAdapter(context: Context,
|
||||
|
||||
// MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", viewModel.gameEntity.name + "_" + data.title)
|
||||
}
|
||||
holder.binding.run {
|
||||
links?.let {
|
||||
leftLink.setOnClickListener { view ->
|
||||
clickListener.onClick(view, links[0])
|
||||
}
|
||||
rightLink.setOnClickListener { view ->
|
||||
clickListener.onClick(view, links[1])
|
||||
}
|
||||
}
|
||||
leftLink.visibleIf(!links.isNullOrEmpty())
|
||||
rightLink.visibleIf(links?.size ?:0 > 1)
|
||||
leftLink.text = if (links.isNullOrEmpty()) "" else links[0].title
|
||||
rightLink.text = if (links?.size ?: 0 > 1) links?.get(1)?.title else ""
|
||||
leftLink.background = GradientDrawable().apply {
|
||||
cornerRadius = 8F.dip2px().toFloat()
|
||||
setStroke(0.5F.dip2px(), R.color.divider.toColor())
|
||||
}
|
||||
rightLink.background = GradientDrawable().apply {
|
||||
cornerRadius = 8F.dip2px().toFloat()
|
||||
setStroke(0.5F.dip2px(), R.color.divider.toColor())
|
||||
}
|
||||
}
|
||||
}
|
||||
is DownloadDialogInstructionItemViewHolder -> {
|
||||
holder.bindItem(listData, position, mEntrance)
|
||||
|
||||
@ -4,10 +4,7 @@ import android.view.View
|
||||
import com.gh.base.BaseRecyclerViewHolder
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.exposure.ExposureEvent
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.util.goneIf
|
||||
import com.gh.common.util.throwExceptionInDebug
|
||||
import com.gh.common.util.toColor
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DownloadDialogInstalledItemBinding
|
||||
@ -16,15 +13,28 @@ import com.lightgame.download.DownloadStatus
|
||||
|
||||
class DownloadDialogInstalledItemViewHolder(val binding: DownloadDialogInstalledItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindInstalledItem(apkEntity: ApkEntity, viewModel: DownloadViewModel, traceEvent: ExposureEvent?, entrance: String, path: String, location: String) {
|
||||
fun bindInstalledItem(
|
||||
apkEntity: ApkEntity,
|
||||
viewModel: DownloadViewModel,
|
||||
traceEvent: ExposureEvent?,
|
||||
entrance: String,
|
||||
path: String,
|
||||
location: String
|
||||
) {
|
||||
|
||||
val gameEntity = viewModel.gameEntity
|
||||
val apkCollection = apkEntity.apkCollection
|
||||
binding.pluginDesc = gameEntity.pluginDesc
|
||||
binding.apk = if (apkCollection != null) {
|
||||
val pluginDesc = gameEntity.pluginDesc
|
||||
val apk = if (apkCollection != null) {
|
||||
ApkEntity(platformIcon = apkCollection.newIcon, platformName = apkCollection.name, remark = apkCollection.remark)
|
||||
} else apkEntity
|
||||
ImageUtils.display(binding.icon, apk.getPlatformIcon())
|
||||
binding.name.text = apk.getPlatformName()
|
||||
binding.remark.text = apk.remark
|
||||
binding.root.setBackgroundResource(R.drawable.download_dialog_item_background)
|
||||
binding.launch.text = "启动${pluginDesc}版"
|
||||
binding.pluggable.text = "${pluginDesc}此版本"
|
||||
binding.update.text = "更新${pluginDesc}版"
|
||||
|
||||
if (apkEntity.apkLink != null) {
|
||||
throwExceptionInDebug("apkLink 不应该出现在这里")
|
||||
@ -132,6 +142,5 @@ class DownloadDialogInstalledItemViewHolder(val binding: DownloadDialogInstalled
|
||||
}
|
||||
|
||||
DownloadDialogItemViewHolder.setDownloadClickListener(itemView, apkEntity, viewModel, traceEvent, entrance, path, location)
|
||||
binding.executePendingBindings()
|
||||
}
|
||||
}
|
||||
@ -32,37 +32,51 @@ import com.lightgame.utils.Utils
|
||||
|
||||
class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : BaseRecyclerViewHolder<Any>(binding.root) {
|
||||
|
||||
fun bindItem(listData: List<DownloadDialogItemData>,
|
||||
position: Int,
|
||||
viewModel: DownloadViewModel,
|
||||
isCollectionPage: Boolean,
|
||||
traceEvent: ExposureEvent?,
|
||||
entrance: String,
|
||||
path: String,
|
||||
location: String) {
|
||||
fun bindItem(
|
||||
listData: List<DownloadDialogItemData>,
|
||||
position: Int,
|
||||
viewModel: DownloadViewModel,
|
||||
isCollectionPage: Boolean,
|
||||
traceEvent: ExposureEvent?,
|
||||
entrance: String,
|
||||
path: String,
|
||||
location: String
|
||||
) {
|
||||
|
||||
val apkEntity = listData[position].normal!!
|
||||
val gameEntity = viewModel.gameEntity
|
||||
val apkLink = apkEntity.apkLink
|
||||
val apkCollection = apkEntity.apkCollection
|
||||
|
||||
binding.apk = when {
|
||||
val apk = when {
|
||||
apkLink != null -> ApkEntity(
|
||||
platformIcon = apkLink.icon,
|
||||
platformName = apkLink.name,
|
||||
remark = apkLink.remark)
|
||||
platformIcon = apkLink.icon,
|
||||
platformName = apkLink.name,
|
||||
remark = apkLink.remark
|
||||
)
|
||||
apkCollection != null -> ApkEntity(
|
||||
platformIcon = apkCollection.newIcon,
|
||||
platformName = apkCollection.name,
|
||||
recommend = apkCollection.recommend,
|
||||
remark = apkCollection.remark)
|
||||
platformIcon = apkCollection.newIcon,
|
||||
platformName = apkCollection.name,
|
||||
recommend = apkCollection.recommend,
|
||||
remark = apkCollection.remark
|
||||
)
|
||||
else -> apkEntity
|
||||
}
|
||||
ImageUtils.display(binding.icon, apk.getPlatformIcon())
|
||||
binding.name.text = apk.getPlatformName()
|
||||
binding.remark.text = apk.remark
|
||||
binding.recommendDesTv.goneIf(apk.recommend == null)
|
||||
binding.recommendDesTv.text = apk.recommend?.description
|
||||
binding.recommendLabel.goneIf(apk.recommend == null)
|
||||
binding.recommendLabelTv.text = apk.recommend?.subscript
|
||||
|
||||
|
||||
binding.containerView.setBackgroundResource(R.drawable.download_dialog_item_background)
|
||||
binding.status.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
|
||||
changeRecommendUI(apkEntity, listData, position)
|
||||
|
||||
if (apkLink != null) {
|
||||
binding.root.visibility = View.VISIBLE
|
||||
binding.downloadStatusIcon.visibility = View.GONE
|
||||
binding.status.visibility = View.VISIBLE
|
||||
binding.progressbar.visibility = View.GONE
|
||||
@ -70,7 +84,12 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
binding.remark.goneIf(apkLink.remark.isEmpty())
|
||||
|
||||
binding.status.text = "点击查看"
|
||||
binding.status.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(binding.status.context, R.drawable.download_dialog_collection_status_link), null)
|
||||
binding.status.setCompoundDrawablesWithIntrinsicBounds(
|
||||
null,
|
||||
null,
|
||||
ContextCompat.getDrawable(binding.status.context, R.drawable.download_dialog_collection_status_link),
|
||||
null
|
||||
)
|
||||
binding.containerView.setBackgroundResource(R.drawable.download_dialog_installed_background)
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.LINK)
|
||||
} else if (apkCollection != null || (!isCollectionPage && apkEntity.downloadInstruction.isNotEmpty())) {
|
||||
@ -119,11 +138,17 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
binding.status.visibility = View.VISIBLE
|
||||
|
||||
binding.status.text = "可更新"
|
||||
binding.status.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(binding.status.context, R.drawable.download_dialog_collection_status_update), null)
|
||||
binding.status.setCompoundDrawablesWithIntrinsicBounds(
|
||||
null,
|
||||
null,
|
||||
ContextCompat.getDrawable(binding.status.context, R.drawable.download_dialog_collection_status_update),
|
||||
null
|
||||
)
|
||||
binding.downloadStatusIcon.visibility = View.GONE
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.UPDATE)
|
||||
} else if (PackageUtils.getGhId(apkEntity.packageName) == gameEntity.id ||
|
||||
PackagesManager.isInstalled(apkEntity.packageName) && Config.getSettings()?.gameDownloadBlackList?.contains(apkEntity.packageName) == true) {
|
||||
PackagesManager.isInstalled(apkEntity.packageName) && Config.getSettings()?.gameDownloadBlackList?.contains(apkEntity.packageName) == true
|
||||
) {
|
||||
binding.downloadStatusIcon.visibility = View.GONE
|
||||
binding.status.visibility = View.VISIBLE
|
||||
binding.containerView.setBackgroundResource(R.drawable.download_dialog_installed_background)
|
||||
@ -143,7 +168,12 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
// 点击启动
|
||||
binding.status.text = "点击启动"
|
||||
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.LAUNCH)
|
||||
binding.status.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(binding.status.context, R.drawable.download_dialog_collection_status_launch), null)
|
||||
binding.status.setCompoundDrawablesWithIntrinsicBounds(
|
||||
null,
|
||||
null,
|
||||
ContextCompat.getDrawable(binding.status.context, R.drawable.download_dialog_collection_status_launch),
|
||||
null
|
||||
)
|
||||
}
|
||||
} else {
|
||||
binding.downloadStatusIcon.visibility = View.VISIBLE
|
||||
@ -160,7 +190,6 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
}
|
||||
|
||||
setDownloadClickListener(itemView, apkEntity, viewModel, traceEvent, entrance, path, location)
|
||||
binding.executePendingBindings()
|
||||
}
|
||||
|
||||
private fun changeRecommendUI(apkEntity: ApkEntity, listData: List<DownloadDialogItemData>, position: Int) {
|
||||
@ -171,7 +200,8 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
(binding.root.layoutParams as RecyclerView.LayoutParams).apply {
|
||||
bottomMargin = if (apkEntity.recommend != null) {
|
||||
if ((position + 1 < listData.size && listData[position + 1].normal?.recommend == null) ||
|
||||
(position + 2 < listData.size && listData[position + 2].normal?.recommend == null)) {
|
||||
(position + 2 < listData.size && listData[position + 2].normal?.recommend == null)
|
||||
) {
|
||||
20f.dip2px()
|
||||
} else 16f.dip2px()
|
||||
} else 8f.dip2px()
|
||||
@ -192,13 +222,15 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
}
|
||||
}
|
||||
|
||||
fun setDownloadClickListener(itemView: View,
|
||||
apkEntity: ApkEntity,
|
||||
viewModel: DownloadViewModel,
|
||||
traceEvent: ExposureEvent?,
|
||||
entrance: String,
|
||||
path: String,
|
||||
location: String) {
|
||||
fun setDownloadClickListener(
|
||||
itemView: View,
|
||||
apkEntity: ApkEntity,
|
||||
viewModel: DownloadViewModel,
|
||||
traceEvent: ExposureEvent?,
|
||||
entrance: String,
|
||||
path: String,
|
||||
location: String
|
||||
) {
|
||||
|
||||
val gameEntity = viewModel.gameEntity
|
||||
itemView.setOnClickListener {
|
||||
@ -215,10 +247,13 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
}
|
||||
DownloadDialogItemStatus.DOWNLOADING -> {
|
||||
// 打开下载管理界面
|
||||
it.context.startActivity(DownloadManagerActivity.getDownloadMangerIntent(
|
||||
it.context.startActivity(
|
||||
DownloadManagerActivity.getDownloadMangerIntent(
|
||||
it.context,
|
||||
apkEntity.url,
|
||||
BaseActivity.mergeEntranceAndPath(entrance, path)))
|
||||
BaseActivity.mergeEntranceAndPath(entrance, path)
|
||||
)
|
||||
)
|
||||
if (AppManager.getInstance().currentActivity() is DownloadManagerActivity) {
|
||||
viewModel.dismissLiveData.postValue(Any())
|
||||
}
|
||||
@ -237,7 +272,7 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
}
|
||||
DownloadDialogItemStatus.INSTALL -> {
|
||||
val downloadEntity = DownloadManager.getInstance().getDownloadEntityByUrl(apkEntity.url)
|
||||
?: return@setOnClickListener
|
||||
?: return@setOnClickListener
|
||||
|
||||
if (FileUtils.isEmptyFile(downloadEntity.path)) {
|
||||
Utils.toast(it.context, R.string.install_failure_hint)
|
||||
@ -300,13 +335,15 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
}
|
||||
}
|
||||
|
||||
private fun createDownloadTask(context: Context,
|
||||
apkEntity: ApkEntity,
|
||||
gameEntity: GameEntity,
|
||||
downloadMethod: String,
|
||||
traceEvent: ExposureEvent?,
|
||||
entrance: String,
|
||||
location: String) {
|
||||
private fun createDownloadTask(
|
||||
context: Context,
|
||||
apkEntity: ApkEntity,
|
||||
gameEntity: GameEntity,
|
||||
downloadMethod: String,
|
||||
traceEvent: ExposureEvent?,
|
||||
entrance: String,
|
||||
location: String
|
||||
) {
|
||||
// todo 有时间存储判断统一处理
|
||||
val msg = FileUtils.isCanDownload(context, apkEntity.size)
|
||||
if (msg.isNullOrEmpty()) {
|
||||
@ -318,13 +355,14 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, DialogUtils.ConfirmListener {
|
||||
DialogUtils.checkDownload(context, apkEntity.size) { isSubscribe ->
|
||||
DownloadManager.createDownload(
|
||||
context,
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
downloadMethod,
|
||||
entrance,
|
||||
location,
|
||||
isSubscribe, traceEvent)
|
||||
context,
|
||||
apkEntity,
|
||||
gameEntity,
|
||||
downloadMethod,
|
||||
entrance,
|
||||
location,
|
||||
isSubscribe, traceEvent
|
||||
)
|
||||
|
||||
DeviceRemindDialog.showDeviceRemindDialog(context, gameEntity)
|
||||
}
|
||||
|
||||
@ -5,12 +5,10 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DialogDownloadLinkBinding
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
@ -25,11 +23,14 @@ class DownloadLinkDialog : BaseDialogFragment() {
|
||||
super.onCreate(savedInstanceState)
|
||||
mLinkEntity = requireArguments().getParcelable(KEY_LINK_ENTITY)
|
||||
}
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val binding: DialogDownloadLinkBinding = DataBindingUtil.inflate(inflater, R.layout.dialog_download_link, container, false)
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
val binding: DialogDownloadLinkBinding = DialogDownloadLinkBinding.inflate(layoutInflater, container, false)
|
||||
binding.title.text = mLinkEntity?.title
|
||||
binding.webView.loadDataWithBaseURL(null,
|
||||
mLinkEntity?.content ?: "", "text/html", "utf-8", null)
|
||||
binding.webView.loadDataWithBaseURL(
|
||||
null,
|
||||
mLinkEntity?.content ?: "", "text/html", "utf-8", null
|
||||
)
|
||||
|
||||
binding.confirm.setOnClickListener {
|
||||
dismissAllowingStateLoss()
|
||||
|
||||
@ -5,7 +5,9 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.halo.assistant.fragment.AboutFragment;
|
||||
|
||||
/**
|
||||
@ -13,6 +15,12 @@ import com.halo.assistant.fragment.AboutFragment;
|
||||
*/
|
||||
public class AboutActivity extends NormalActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ExtensionsKt.updateStatusBarColor(this, R.color.black, R.color.white);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getIntent(Context context, boolean isUpdate) {
|
||||
Bundle bundle = new Bundle();
|
||||
@ -20,4 +28,14 @@ public class AboutActivity extends NormalActivity {
|
||||
return getTargetIntent(context, AboutActivity.class, AboutFragment.class, bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAutoResetViewBackgroundEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNightModeChange() {
|
||||
super.onNightModeChange();
|
||||
ExtensionsKt.updateStatusBarColor(this, R.color.black, R.color.white);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,10 @@ package com.gh.gamecenter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.gh.gamecenter.info.ConcernFragment;
|
||||
|
||||
/**
|
||||
@ -11,7 +14,19 @@ import com.gh.gamecenter.info.ConcernFragment;
|
||||
|
||||
public class ConcernInfoActivity extends NormalActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ExtensionsKt.updateStatusBarColor(this, R.color.black, R.color.white);
|
||||
}
|
||||
|
||||
public static Intent getIntent(Context context) {
|
||||
return getTargetIntent(context, ConcernInfoActivity.class, ConcernFragment.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNightModeChange() {
|
||||
super.onNightModeChange();
|
||||
ExtensionsKt.updateStatusBarColor(this, R.color.black, R.color.white);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,9 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.gh.base.fragment.BaseFragment_TabLayout;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.gh.gamecenter.download.DownloadFragment;
|
||||
|
||||
/**
|
||||
@ -20,6 +22,12 @@ public class DownloadManagerActivity extends NormalActivity {
|
||||
|
||||
public static final String TAG = "DownloadManagerActivity";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ExtensionsKt.updateStatusBarColor(this, R.color.black, R.color.white);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent provideNormalIntent() {
|
||||
return getTargetIntent(this, DownloadManagerActivity.class, DownloadFragment.class);
|
||||
@ -48,4 +56,10 @@ public class DownloadManagerActivity extends NormalActivity {
|
||||
bundle.putString(EntranceUtils.KEY_PACKAGENAME, packageName);
|
||||
return getTargetIntent(context, DownloadManagerActivity.class, DownloadFragment.class, bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNightModeChange() {
|
||||
super.onNightModeChange();
|
||||
ExtensionsKt.updateStatusBarColor(this, R.color.black, R.color.white);
|
||||
}
|
||||
}
|
||||
@ -75,6 +75,8 @@ class GameDetailActivity : NormalActivity() {
|
||||
})
|
||||
}
|
||||
|
||||
override fun isAutoResetViewBackgroundEnabled(): Boolean = true
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user