Compare commits
428 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d55b251c3 | |||
| 386c7b19c1 | |||
| eaaa168ee1 | |||
| d9f5811d86 | |||
| 27d3470abc | |||
| 36f7427613 | |||
| 929c117ddb | |||
| 7d6d77fae5 | |||
| 2297461d91 | |||
| a26a3bebad | |||
| 4a673de424 | |||
| a837c2ccd4 | |||
| 10ee3132fd | |||
| 783fbecb00 | |||
| de1b5ba2f3 | |||
| 9a9e288c44 | |||
| 424b48f631 | |||
| 86d1cd4e12 | |||
| e700ff4744 | |||
| 34729c8c28 | |||
| 5a08611fdd | |||
| a73da1d6e4 | |||
| 28b8c20756 | |||
| 6941821b71 | |||
| 3c2244701c | |||
| 38dc873e2e | |||
| c24ffb2489 | |||
| 929864be30 | |||
| bd87163a9b | |||
| 785c740668 | |||
| 25aa16f774 | |||
| 9ec89c0dc1 | |||
| 3e5bd2b087 | |||
| 9de6cff13b | |||
| 6b98bc9fca | |||
| cdf9b0a071 | |||
| ff57e9c759 | |||
| b253113843 | |||
| b7305337bf | |||
| 455e2ad723 | |||
| 8cf87b991b | |||
| ae0b289c3e | |||
| 9404c3349a | |||
| 28afbb8d35 | |||
| 5b24443121 | |||
| 1f9aacbbbd | |||
| d194b33a5d | |||
| 55010f0ef7 | |||
| 49fab9ed04 | |||
| 1cd1b578ec | |||
| 184c56aac5 | |||
| 7c39037472 | |||
| 786a803793 | |||
| 273f0e185d | |||
| eebc2c3940 | |||
| 3a964d629e | |||
| ff041f705e | |||
| af62fc9a68 | |||
| 6ff415cc0d | |||
| 41de94e6f5 | |||
| 60d91ca04e | |||
| 19004b2073 | |||
| 70b536e6bd | |||
| 5009678587 | |||
| a7a01bbe16 | |||
| 9b2ce51c87 | |||
| c735d4e717 | |||
| 6fb4dac45d | |||
| 3d49258b84 | |||
| c23aa12d09 | |||
| 6f6ddf9fbd | |||
| 63837b5c31 | |||
| 27e245c241 | |||
| 7775494ade | |||
| a3ce139b86 | |||
| ad470f10f4 | |||
| 302d12083b | |||
| d40dd15af4 | |||
| 440eb8a07b | |||
| 361b861d5f | |||
| b518b2961a | |||
| bfae4e1501 | |||
| d3e13dd8c6 | |||
| 073c35ca08 | |||
| 99b4373561 | |||
| 52dcea477e | |||
| 6abb8d715b | |||
| 51016b0704 | |||
| d14c150070 | |||
| f59f8a3e5b | |||
| 965be0b5cd | |||
| 716900fc5d | |||
| 14280d802e | |||
| 39924857e5 | |||
| c88bda6615 | |||
| ecb80ca70d | |||
| 51b03b78ce | |||
| a7fd029ed2 | |||
| 5beb29ad09 | |||
| e7dc2ca810 | |||
| b5ce0db1ff | |||
| c8b52902e9 | |||
| dbc4e0ac26 | |||
| a0d2860970 | |||
| 77c1a05a4a | |||
| aeee2e049d | |||
| 525b184ad4 | |||
| 76e0fe9f9a | |||
| 06ddef114c | |||
| 32cdcc1304 | |||
| 4a2b414b59 | |||
| 937497aec9 | |||
| 38d2c189e8 | |||
| 57aeacf3f5 | |||
| fe4036b768 | |||
| 5dd479c492 | |||
| 5f1ff1fc6f | |||
| b08fb1f170 | |||
| e2f6180d6d | |||
| 90d19ea381 | |||
| 13738f08eb | |||
| 1b76184946 | |||
| 711431f7c9 | |||
| 4ea3f7ccf0 | |||
| 80cd86ea29 | |||
| f87bb6cd06 | |||
| ea726a22bd | |||
| 7e3afe7d70 | |||
| 8131c58fbf | |||
| 674e32a096 | |||
| f5d42a3e01 | |||
| a079a03adc | |||
| 8485f94133 | |||
| 5d60a8f03b | |||
| ec4319b74a | |||
| 41c3f9d073 | |||
| c27990b395 | |||
| 2e9a823ee1 | |||
| 590afccae7 | |||
| 7a82780826 | |||
| c75e363a06 | |||
| 573b7b61cf | |||
| 9f9e1bc9fd | |||
| 34e11b1569 | |||
| cc7b77a8ad | |||
| ed3a75ddc0 | |||
| 983c01df57 | |||
| 9d95b7aa6b | |||
| 5319cb8679 | |||
| b4b1a63c22 | |||
| 2dfd57de80 | |||
| cbc8876656 | |||
| 4e6b8bf6b3 | |||
| da92826f6a | |||
| f1a4e429f3 | |||
| 3cd248a2c5 | |||
| 7f5dd97359 | |||
| c0ee431d1f | |||
| f56de73eb6 | |||
| a0b5cd00d5 | |||
| 66b5f3d896 | |||
| a4346a6f34 | |||
| 83894f6530 | |||
| 9b776bb029 | |||
| ea72fb09e0 | |||
| b2b390cf8b | |||
| 926abe248f | |||
| 95468cf83e | |||
| 259b93eb25 | |||
| f59646643f | |||
| 7130417e60 | |||
| 458a9f2a63 | |||
| 0f85497f75 | |||
| 3c0c6afd43 | |||
| 345cdb41bc | |||
| b78fa40eff | |||
| 193831ae7e | |||
| bcb9dc3ba8 | |||
| 7903cdc44a | |||
| a66c1ea50b | |||
| 978e8f160b | |||
| a49351a146 | |||
| 07d9b416a3 | |||
| f9edb69370 | |||
| deac313ba3 | |||
| b149f9acf2 | |||
| 7c96ba090e | |||
| 11ab908848 | |||
| 3d2978b2e5 | |||
| 7ad3a7ae92 | |||
| 9042488a65 | |||
| b08e13f05a | |||
| 6271fd4998 | |||
| 4d747a3df3 | |||
| 5ce057d40e | |||
| 1e2e8f932f | |||
| 5accb9c1f1 | |||
| 5b102d65c7 | |||
| c609ddd721 | |||
| 0c3783d127 | |||
| f702ab6115 | |||
| 7dd760e0fb | |||
| c6f3b5998c | |||
| 28440d97de | |||
| 2b2b71fe01 | |||
| f5a9e7b487 | |||
| d43842a0e6 | |||
| a557962f17 | |||
| 560c682157 | |||
| a0ae36f511 | |||
| bdee17ffc4 | |||
| 5829f09f8c | |||
| bc6fa5e7db | |||
| 1607cea9ce | |||
| 426019ea7c | |||
| 1b878a50c4 | |||
| 97525189b7 | |||
| 999947751a | |||
| 2def61ab43 | |||
| 5e07ef488c | |||
| 7af47c0caf | |||
| 1a5ed3c05f | |||
| 9cc9b09861 | |||
| cef4432d97 | |||
| 18be6acc34 | |||
| 27d0dd40d0 | |||
| b05fa626f6 | |||
| f1fc84ea5f | |||
| 3942154c05 | |||
| ff182ee3c7 | |||
| 10cc275970 | |||
| 21821d584e | |||
| 6b8716eff8 | |||
| 47434e2943 | |||
| 4c3b327cff | |||
| 3454d13e48 | |||
| 0aad7c59ee | |||
| ee8e4e0338 | |||
| a430c51c97 | |||
| b59508e9e5 | |||
| 08deac1dea | |||
| a2dc3f3d5b | |||
| 679cfab088 | |||
| 9144595aaf | |||
| 8a545180a2 | |||
| 17c5793558 | |||
| 8afc346a2c | |||
| 026bb7f67b | |||
| b971e7dbf6 | |||
| ec39ef16e4 | |||
| ae07bacbb7 | |||
| 0f0d8da6cd | |||
| 2a1c99efac | |||
| caa89d3f4c | |||
| 1602816d08 | |||
| 1062cf5924 | |||
| f6e5cd3fd7 | |||
| c675196cb2 | |||
| 8b9c2668d1 | |||
| c1a927ed88 | |||
| 4d4416c1df | |||
| f4833983c0 | |||
| 89eb99d813 | |||
| 683a68d179 | |||
| 598af67338 | |||
| d9d0ffc3b9 | |||
| 4d8e04580e | |||
| cfaddf2f22 | |||
| c72b194107 | |||
| d7f33ff8b1 | |||
| 91e491b66a | |||
| 31b7e40ab0 | |||
| f2b094fff0 | |||
| 185ee7f0f4 | |||
| f446b15f7a | |||
| 52a833f18b | |||
| 37fc68977c | |||
| 96ee71a594 | |||
| 1c2dda9353 | |||
| 96a9fd0ad7 | |||
| c53c27e350 | |||
| fd4f32bb3c | |||
| cbd2d8ed6c | |||
| 3dd06bc620 | |||
| 3a829e1cfd | |||
| 183e1a85c3 | |||
| 6b696234ab | |||
| 21ac1d1f17 | |||
| 4163b81f70 | |||
| 6c3268ce72 | |||
| 4d87f86fcd | |||
| 4a37401dc2 | |||
| 8cf90193fc | |||
| 9942a51cad | |||
| 4980d96c8c | |||
| f32c8748ed | |||
| 7b886679e1 | |||
| 2620c04b09 | |||
| c22157f2f5 | |||
| 09f02bc225 | |||
| 9fc9549a28 | |||
| 0099afad09 | |||
| 3e512634c6 | |||
| 7045354808 | |||
| dbcc97a250 | |||
| 050081b7b1 | |||
| 993d1e7635 | |||
| a86a3c1f71 | |||
| b0a192ad9a | |||
| ea7b478c6b | |||
| b673383f59 | |||
| 06ae366b74 | |||
| 6b9cf7094e | |||
| 5ae22bd2bc | |||
| e951551531 | |||
| 272e5fb6cc | |||
| 7dc17d09c1 | |||
| cfacbe739d | |||
| 0a72226ba5 | |||
| 5f22a14643 | |||
| 5562e38c2f | |||
| f9027f7a61 | |||
| 6d0e437ad4 | |||
| 3abc53d3b3 | |||
| d0e4c2c3ab | |||
| 5be50c1638 | |||
| 7c525aec79 | |||
| 63d5edf892 | |||
| c9f2cf178a | |||
| fc98de3bc0 | |||
| dd8360f5e8 | |||
| bc9b815b47 | |||
| 2a93995221 | |||
| 0e93f6521c | |||
| b3a6d0ce94 | |||
| de60d05190 | |||
| 2a2ce9a490 | |||
| 639644e3c3 | |||
| 2378e6e94e | |||
| 87d9feae70 | |||
| 4a93d129bb | |||
| 39e5e2e9f9 | |||
| 8a5f777c65 | |||
| 22c693e042 | |||
| 36d04f5841 | |||
| 409123337d | |||
| b180a210cb | |||
| 32dfdc4d08 | |||
| 4d46888995 | |||
| 69db836231 | |||
| f82b9ad308 | |||
| 3ac91b1216 | |||
| 8d4b3e0851 | |||
| 67d8f46217 | |||
| f357136936 | |||
| 9d622d2be9 | |||
| 800525227d | |||
| c9dec9a31e | |||
| 2ae4fda6e8 | |||
| 609702715f | |||
| ec7e138208 | |||
| bfd64a8bce | |||
| 5571b6481f | |||
| 6d6574988c | |||
| af8d075bf2 | |||
| b7db66e90b | |||
| 13ac4658d9 | |||
| 8ad3420822 | |||
| f842ced67e | |||
| e0081e56df | |||
| 3202764f22 | |||
| f477876359 | |||
| 86ffcb92f8 | |||
| a2088e5cd9 | |||
| 6e1247f393 | |||
| c33faa4918 | |||
| d0aeb1c411 | |||
| 485924527e | |||
| ca1bfda326 | |||
| c7c786d662 | |||
| acf9fe308c | |||
| 3b32231709 | |||
| 9dae198af2 | |||
| 29bfd5bb93 | |||
| 8da51d7f5a | |||
| 91964a0ffc | |||
| 479ef20859 | |||
| f458b7dcb8 | |||
| 2d25ff7836 | |||
| 57dd5d0584 | |||
| 757efec05e | |||
| 4979045be2 | |||
| f59af60f70 | |||
| 60bc2a02f4 | |||
| 996be3906e | |||
| 14a054bdbc | |||
| 07a9fd6273 | |||
| a067f7bc43 | |||
| a5eefbb6f4 | |||
| 8d9f83c432 | |||
| ae0df36a89 | |||
| 72539671a1 | |||
| 94277a4aeb | |||
| e276d148cf | |||
| a7152034e8 | |||
| 4a5e9da34a | |||
| 1422365cc5 | |||
| 7f55ff6340 | |||
| 4722626fb7 | |||
| 39d87ad98d | |||
| 85333b9eed | |||
| c99ae6db3e | |||
| c5be98adc2 | |||
| 5321aa2e9f | |||
| 345707ef42 | |||
| 6a9d05d916 | |||
| faf2a89706 | |||
| ada51f90f1 | |||
| 53962116d5 | |||
| 3ea52745b3 | |||
| a8f2289b27 | |||
| 6dd56b5d16 | |||
| eb739cf6cb | |||
| 4853cd9047 | |||
| 4e0f14aeed | |||
| 5e37dac0f6 | |||
| 22bfa9051a | |||
| 0a1dca3aa3 |
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,4 +1,4 @@
|
||||
[submodule "libraries/LGLibrary"]
|
||||
path = libraries/LGLibrary
|
||||
url = git@gitlab.ghzhushou.com:client/client-common.git
|
||||
url = git@gitlab.ghzhushou.com:android/common-library.git
|
||||
branch = master
|
||||
|
||||
35
CHANGELOG.md
35
CHANGELOG.md
@ -30,4 +30,37 @@
|
||||
- 删除TINKER_VERISON_NAME
|
||||
- tinker打包方式变更(以小版本作为Base包,防止与数据后台小版本更新发生冲突)
|
||||
* 社区增加版主功能(版主可以对存在的相关内容进行修改/隐藏操作,内容包括问题/回答/回答评论)
|
||||
* 社区互动引导优化(问答推荐增加`推荐关注`,回答详情增加一些交互动效)
|
||||
* 社区互动引导优化(问答推荐增加`推荐关注`,回答详情增加一些交互动效)
|
||||
|
||||
### Ver 3.6.1
|
||||
* 可以后台控制关闭资讯功能
|
||||
* 版块、分类、专题详情、游戏详情、礼包详情增加预览骨架
|
||||
* 下载按钮状态可以通过接口屏蔽相应的包
|
||||
|
||||
### Ver 3.6.2
|
||||
* 资讯/问答入口和插件功能线上控制(不可逆)
|
||||
* 首页不显示已安装的游戏
|
||||
* 插件求版本功能增加内部跳转
|
||||
* 下载面板增加公告和版本说明功能
|
||||
* 接入腾讯`广点通`(广告)
|
||||
|
||||
### ver 3.6.3
|
||||
* 社区搜索修改
|
||||
- 增加 `文章/用户` 模块
|
||||
- 增加 `搜索置顶` 功能
|
||||
* 回答详情/社区文章详情修改
|
||||
- 支持文案样式(加粗/斜体/删除线)和段落样式(引用/标题)
|
||||
- 支持关闭评论功能
|
||||
- 回答详情新增上下切换回答
|
||||
* 社区编辑框(回答/文章)修改
|
||||
- 支持批量插入图片(使用知乎Matisse实现)
|
||||
- 新增插入特殊样式,文案样式(加粗/斜体/删除线)和段落样式(引用/标题)
|
||||
* 编辑框部分 JS/CSS 使用远程文件
|
||||
|
||||
### ver 3.6.4
|
||||
* 增加浏览记录(回答/文章/资讯/游戏)
|
||||
* 回答/社区文章 增加反对功能
|
||||
* 社区编辑框增加插入文章/回答/游戏
|
||||
- 低版本兼容方案: 插入的样式默认隐藏,只有在3.6.4及以上才会显示
|
||||
* 游戏详情评分模块增加`小编评论`区域以及样式修改
|
||||
* 游戏评分增加回复功能
|
||||
|
||||
@ -69,6 +69,11 @@ android {
|
||||
buildConfigField "String", "MTA_APPKEY", "\"${MTA_APPKEY}\""
|
||||
buildConfigField "String", "TD_APPID", "\"${TD_APPID}\""
|
||||
|
||||
/**
|
||||
* Build Time 供区分 jenkins 打包时间用
|
||||
*/
|
||||
buildConfigField "long", "BUILD_TIME", "0"
|
||||
|
||||
}
|
||||
|
||||
// gradle 2.2以上默认同时启用v1和v2(优先用于Android N)
|
||||
@ -91,7 +96,7 @@ android {
|
||||
signingConfig signingConfigs.debug
|
||||
|
||||
buildConfigField "String", "EXPOSURE_REPO", "\"test\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E2\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E3\""
|
||||
}
|
||||
release {
|
||||
debuggable false
|
||||
@ -101,7 +106,7 @@ android {
|
||||
signingConfig signingConfigs.release
|
||||
|
||||
buildConfigField "String", "EXPOSURE_REPO", "\"exposure\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E2\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E3\""
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,6 +254,7 @@ dependencies {
|
||||
implementation "android.arch.lifecycle:extensions:${archLifecycleVersion}"
|
||||
implementation "android.arch.persistence.room:runtime:${archRoomVersion}"
|
||||
kapt "android.arch.persistence.room:compiler:${archRoomVersion}"
|
||||
implementation "android.arch.persistence.room:rxjava2:${archRoomVersion}"
|
||||
|
||||
implementation 'com.google.android:flexbox:0.2.2'
|
||||
|
||||
@ -273,6 +279,8 @@ dependencies {
|
||||
|
||||
implementation 'com.ethanhua:skeleton:1.1.1'
|
||||
implementation 'io.supercharge:shimmerlayout:2.1.0'
|
||||
implementation "com.tencent.mm.opensdk:wechat-sdk-android-without-mta:5.3.1"
|
||||
implementation 'com.walkud.rom.checker:RomChecker:1.0.0'
|
||||
|
||||
implementation project(':libraries:gid')
|
||||
implementation project(':libraries:LGLibrary')
|
||||
@ -280,9 +288,10 @@ dependencies {
|
||||
implementation project(':libraries:QQShare')
|
||||
implementation project(':libraries:TalkingData')
|
||||
implementation project(':libraries:UmengPush')
|
||||
implementation project(':libraries:WechatShare')
|
||||
// implementation project(':libraries:WechatShare')
|
||||
implementation project(':libraries:LogHub')
|
||||
implementation project(':libraries:im')
|
||||
implementation project(':libraries:Matisse')
|
||||
}
|
||||
File propFile = file('sign.properties')
|
||||
if (propFile.exists()) {
|
||||
|
||||
@ -41,12 +41,7 @@
|
||||
<uses-permission android:name = "android.permission.WRITE_SETTINGS" />
|
||||
|
||||
<!-- bugly with tinker -->
|
||||
<uses-permission android:name = "android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name = "android.permission.INTERNET" />
|
||||
<uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name = "android.permission.READ_LOGS" />
|
||||
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name = "android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
<supports-screens
|
||||
@ -60,7 +55,7 @@
|
||||
<application
|
||||
android:name = "com.halo.assistant.TinkerApp"
|
||||
android:allowBackup = "true"
|
||||
android:icon = "@drawable/logo"
|
||||
android:icon = "@mipmap/logo"
|
||||
android:label = "@string/app_name"
|
||||
android:resizeableActivity = "true"
|
||||
android:theme = "@style/AppCompatTheme.APP"
|
||||
@ -363,8 +358,8 @@
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity"
|
||||
android:windowSoftInputMode = "stateVisible"
|
||||
android:screenOrientation = "portrait" />
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateVisible" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.questions.edit.manager.HistoryDetailActivity"
|
||||
@ -374,6 +369,26 @@
|
||||
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" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.editor.GameActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.gamedetail.rating.RatingReplyActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
|
||||
<activity
|
||||
android:name = ".history.HistoryActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.qa.comment.CommentActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
@ -398,6 +413,14 @@
|
||||
</intent-filter >
|
||||
</activity >
|
||||
|
||||
<activity
|
||||
android:name = "${applicationId}.wxapi.WXEntryActivity"
|
||||
android:exported = "true"
|
||||
android:label = "@string/app_name"
|
||||
android:launchMode = "singleTop"
|
||||
android:screenOrientation = "portrait"
|
||||
android:theme = "@android:style/Theme.Translucent.NoTitleBar" ></activity >
|
||||
|
||||
<provider
|
||||
android:name = "android.support.v4.content.FileProvider"
|
||||
android:authorities = "${applicationId}"
|
||||
|
||||
@ -1,28 +1,163 @@
|
||||
function requestContentFocus() {
|
||||
$('#editor').focus();
|
||||
$("#editor").focus();
|
||||
}
|
||||
|
||||
function setupWhenContentEditable() {
|
||||
var editor = $('#editor');
|
||||
if (!editor[0].hasAttribute('contenteditable')) {
|
||||
return;
|
||||
var editor = $("#editor");
|
||||
if (!editor[0].hasAttribute("contenteditable")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// paste
|
||||
editor.on("paste", function(e) {
|
||||
e.preventDefault();
|
||||
var text = (e.originalEvent || e).clipboardData.getData("text/plain");
|
||||
text = text.replace(/\n/g, "<br>");
|
||||
if ("" != text) {
|
||||
document.execCommand("insertHTML", false, text);
|
||||
} else {
|
||||
window.onPasteListener.onPaste();
|
||||
}
|
||||
});
|
||||
|
||||
// paste 回调只会获取粘贴之前的光标位置,需要自己手动加上粘贴文本的长度,并保证粘贴的是纯文本
|
||||
editor.on('paste', function(e) {
|
||||
e.preventDefault();
|
||||
var text = (e.originalEvent || e).clipboardData.getData('text/plain');
|
||||
text = text.replace(/\n/g, '<br>');
|
||||
if("" != text) {
|
||||
document.execCommand("insertHTML", false, text);
|
||||
} else {
|
||||
window.onPasteListener.onPaste();
|
||||
}
|
||||
});
|
||||
|
||||
requestContentFocus();
|
||||
requestContentFocus();
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
setupWhenContentEditable();
|
||||
function getStyle(dom, name) {
|
||||
return window.getComputedStyle(dom)[name];
|
||||
}
|
||||
|
||||
function customLinkgo(self) {
|
||||
var datas = self.dataset.datas;
|
||||
console.log(datas)
|
||||
window.OnLinkClickListener.onClick(datas);
|
||||
}
|
||||
|
||||
var typeClassList = [
|
||||
"community_article-container",
|
||||
"answer-container",
|
||||
"game-container"
|
||||
];
|
||||
|
||||
function removeDomByParent(curDom) {
|
||||
if (curDom.parentElement) {
|
||||
curDom.parentElement.removeChild(curDom);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
var EditorDom = document.querySelector("#editor");
|
||||
setupWhenContentEditable();
|
||||
|
||||
document.addEventListener("keydown", function(e) {
|
||||
var event = e || window.event;
|
||||
|
||||
if (event.keyCode === 8) {
|
||||
var s = document.getSelection();
|
||||
var r = s.getRangeAt(0);
|
||||
|
||||
if (r.startOffset === r.endOffset && r.endOffset === 0) {
|
||||
var preDOM = s.focusNode.previousElementSibling;
|
||||
|
||||
if (
|
||||
preDOM &&
|
||||
preDOM instanceof Element &&
|
||||
preDOM.nodeName === "IMG" &&
|
||||
getStyle(preDOM, "display") === "block"
|
||||
) {
|
||||
preDOM.parentElement.removeChild(preDOM);
|
||||
}
|
||||
}
|
||||
|
||||
var customDom = s.focusNode;
|
||||
if (customDom) {
|
||||
if (
|
||||
r.startContainer.nodeName.toLowerCase() === "blockquote" &&
|
||||
r.startOffset === 0
|
||||
) {
|
||||
RE.formatBlock();
|
||||
e.preventDefault();
|
||||
} else if (
|
||||
customDom.nodeName === "#text" &&
|
||||
customDom.previousElementSibling &&
|
||||
typeClassList.indexOf(customDom.previousElementSibling.className) >
|
||||
-1 &&
|
||||
r.startOffset === 1
|
||||
) {
|
||||
var needDeleteDom = customDom.previousElementSibling;
|
||||
needDeleteDom.insertAdjacentElement(
|
||||
"afterend",
|
||||
document.createElement("br")
|
||||
);
|
||||
} else if (
|
||||
customDom instanceof Element &&
|
||||
customDom.childNodes[s.focusOffset] &&
|
||||
customDom.childNodes[s.focusOffset].previousElementSibling &&
|
||||
typeClassList.indexOf(
|
||||
customDom.childNodes[s.focusOffset].previousElementSibling.className
|
||||
) > -1
|
||||
) {
|
||||
customDom =
|
||||
customDom.childNodes[s.focusOffset].previousElementSibling;
|
||||
customDom.parentElement.removeChild(customDom);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("keyup", function(e) {
|
||||
var event = e || window.event;
|
||||
if (event.keyCode === 13) {
|
||||
var s = document.getSelection();
|
||||
var curDom = s.focusNode;
|
||||
var preDom = curDom.previousElementSibling;
|
||||
|
||||
if (
|
||||
curDom.nodeName.toLowerCase() === "blockquote" &&
|
||||
preDom.nodeName.toLowerCase() === "blockquote"
|
||||
) {
|
||||
if (
|
||||
preDom.childNodes.length > 1 ||
|
||||
(preDom.childNodes.length === 1 &&
|
||||
preDom.childNodes[0].tagName !== "BR")
|
||||
) {
|
||||
curDom.style.marginTop = 0;
|
||||
preDom.style.marginBottom = 0;
|
||||
} else if (
|
||||
(curDom.childNodes.length === 0 ||
|
||||
(curDom.childNodes.length === 1 &&
|
||||
curDom.childNodes[0].tagName === "BR")) &&
|
||||
(preDom.childNodes.length === 0 ||
|
||||
(preDom.childNodes.length === 1 &&
|
||||
preDom.childNodes[0].tagName === "BR"))
|
||||
) {
|
||||
|
||||
removeDomByParent(curDom);
|
||||
|
||||
var startQuoteDom = preDom.previousElementSibling;
|
||||
startQuoteDom && startQuoteDom.nodeName.toLowerCase() === "blockquote"
|
||||
? (startQuoteDom.style.marginBottom = "10px")
|
||||
: null;
|
||||
|
||||
var range = document.createRange();
|
||||
range.selectNode(preDom);
|
||||
s.removeAllRanges();
|
||||
s.addRange(range);
|
||||
|
||||
RE.formatBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("selectionchange", function(e) {
|
||||
var event = e || window.event;
|
||||
var targetDom = event.target.activeElement;
|
||||
if (targetDom.id === "editor" && targetDom.lastElementChild) {
|
||||
if (typeClassList.indexOf(targetDom.lastElementChild.className) > -1) {
|
||||
var brDom = document.createElement("br");
|
||||
EditorDom.appendChild(brDom);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -1,16 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="user-scalable=no">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" type="text/css" href="normalize.css">
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<!--<link rel="stylesheet" type="text/css" href="https://resource.ghzs.com/css/halo_app.css">-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="editor" contenteditable="true"></div>
|
||||
<script type="text/javascript" src="zepto.min.js"></script>
|
||||
<script type="text/javascript" src="rich_editor.js"></script>
|
||||
<script type="text/javascript" src="content.js"></script>
|
||||
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/10.15.0/lazyload.min.js"></script>-->
|
||||
<!--<script type="text/javascript" src="content.js"></script>-->
|
||||
<!--<script type="text/javascript" src="https://resource.ghzs.com/js/halo_app.js"></script>-->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// alert("")
|
||||
|
||||
var RE = {};
|
||||
|
||||
RE.currentSelection = {
|
||||
@ -22,6 +24,17 @@ RE.currentSelection = {
|
||||
"endContainer": 0,
|
||||
"endOffset": 0};
|
||||
|
||||
// 引用远端的JS 和 CSS
|
||||
var script = document.createElement("script")
|
||||
script.src = "https://resource.ghzs.com/js/halo.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
|
||||
document.body.appendChild(script)
|
||||
|
||||
var style = document.createElement("link")
|
||||
style.rel = "stylesheet"
|
||||
style.type = "text/css"
|
||||
style.href = "https://resource.ghzs.com/css/halo.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
|
||||
document.head.appendChild(style)
|
||||
|
||||
RE.editor = document.getElementById('editor');
|
||||
|
||||
document.addEventListener("selectionchange", function() { RE.backuprange(); });
|
||||
@ -94,16 +107,8 @@ RE.setInputEnabled = function(inputEnabled) {
|
||||
RE.editor.contentEditable = String(inputEnabled);
|
||||
}
|
||||
|
||||
RE.setFocusByEnd = function() {
|
||||
//alert("111111")
|
||||
// var txt =RE.editor.createTextRange();
|
||||
// ("22222")
|
||||
// txt.moveStart('character',-1);
|
||||
// ("333333")
|
||||
// txt.collapse(true);
|
||||
// ("444444")
|
||||
// txt.select();
|
||||
// alert("ddddddd")
|
||||
RE.formatBlock = function() {
|
||||
document.execCommand('formatBlock', false, 'p');
|
||||
}
|
||||
|
||||
RE.undo = function() {
|
||||
@ -166,6 +171,7 @@ RE.setFontSize = function(fontSize){
|
||||
|
||||
RE.setHeading = function(heading) {
|
||||
document.execCommand('formatBlock', false, '<h'+heading+'>');
|
||||
RE.sendElementNameToNative()
|
||||
}
|
||||
|
||||
RE.setIndent = function() {
|
||||
@ -190,6 +196,9 @@ RE.setJustifyRight = function() {
|
||||
|
||||
RE.setBlockquote = function() {
|
||||
document.execCommand('formatBlock', false, '<blockquote>');
|
||||
// var blockId = window.getSelection().focusNode.parentNode;
|
||||
// $(blockId).addClass("haloBlock")
|
||||
RE.sendElementNameToNative()
|
||||
}
|
||||
|
||||
RE.insertImage = function(url) {
|
||||
@ -197,19 +206,17 @@ RE.insertImage = function(url) {
|
||||
RE.insertHTML(html);
|
||||
}
|
||||
|
||||
//RE.lazyLoad = function() {
|
||||
// var myLazyLoad = new LazyLoad({
|
||||
// elements_selector: ".lazy"
|
||||
// })
|
||||
//}
|
||||
|
||||
// 替换成缩略图
|
||||
RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
var index = 0
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
// console.log(imageClassName)
|
||||
if (imageClassName == "image-link") continue;
|
||||
if(img.src.indexOf("?") > 0) continue;
|
||||
|
||||
// console.log(i)
|
||||
var tbImg
|
||||
if(img.src.indexOf(".gif") > 0) {
|
||||
tbImg = img.src + gifRuleFlag
|
||||
@ -220,7 +227,7 @@ RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) {
|
||||
img.style.cssText = "max-width: 60%; display:block; margin:15px auto; height: auto;"
|
||||
img.src = tbImg;
|
||||
|
||||
if (i == 0) {
|
||||
if (index == 0) {
|
||||
var bigImg = document.createElement('img');
|
||||
bigImg.src = "file:///android_asset/web_load_dfimg_icon.png";
|
||||
bigImg.style.cssText = "max-width: 20%; margin:15px 0 0 0; height: auto;"
|
||||
@ -236,6 +243,7 @@ RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) {
|
||||
}
|
||||
|
||||
}
|
||||
index ++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,6 +252,8 @@ RE.replaceAllDfImage = function(imgRuleFlag, gifRuleFlag) {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link") continue;
|
||||
if(img.src.indexOf("web_load_dfimg_icon") > 0) {
|
||||
img.parentNode.removeChild(img.parentNode.childNodes[0]);
|
||||
i--;
|
||||
@ -268,6 +278,8 @@ RE.hideShowBigPic = function() {
|
||||
var j = 0;
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link") continue;
|
||||
if(img.src.indexOf(",thumbnail") > 0 && img.src.indexOf(".gif") == -1) {
|
||||
j++;
|
||||
}
|
||||
@ -277,6 +289,8 @@ RE.hideShowBigPic = function() {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link") continue;
|
||||
if(img.src.indexOf("web_load_dfimg_icon") > 0) {
|
||||
img.parentNode.removeChild(img.parentNode.childNodes[0]);
|
||||
break;
|
||||
@ -289,6 +303,8 @@ RE.replaceDfImageByUrl = function(imgUrl, imgRuleFlag, gifRuleFlag) {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link") 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) {
|
||||
@ -305,6 +321,8 @@ RE.ImageClickListener = function() {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link") continue;
|
||||
window.imagelistener.imageArr(img.src);
|
||||
img.onclick = function() {
|
||||
window.imagelistener.imageClick(this.src);
|
||||
@ -357,12 +375,16 @@ RE.backuprange = function(){
|
||||
}
|
||||
|
||||
RE.restorerange = function(){
|
||||
var selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
var range = document.createRange();
|
||||
range.setStart(RE.currentSelection.startContainer, RE.currentSelection.startOffset);
|
||||
range.setEnd(RE.currentSelection.endContainer, RE.currentSelection.endOffset);
|
||||
selection.addRange(range);
|
||||
try {
|
||||
var selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
var range = document.createRange();
|
||||
range.setStart(RE.currentSelection.startContainer, RE.currentSelection.startOffset);
|
||||
range.setEnd(RE.currentSelection.endContainer, RE.currentSelection.endOffset);
|
||||
selection.addRange(range);
|
||||
} catch(error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RE.enabledEditingItems = function(e) {
|
||||
@ -432,12 +454,145 @@ RE.removeFormat = function() {
|
||||
document.execCommand('removeFormat', false, null);
|
||||
}
|
||||
|
||||
RE.insertCustomStyleLink = function(data) {
|
||||
var entity = JSON.parse(data)
|
||||
var html = "<br/><div class='"+ entity.type +"-container'>\n" +
|
||||
" <a class='"+ entity.type +"' href=\"javascript:void(0);\" contenteditable=\"false\" onclick=\"customLinkgo(this)\" data-datas='"+ data +"'>\n" +
|
||||
" <div class='flex-container'>\n" +
|
||||
" <div class='gh-internal-content img-left'>\n" +
|
||||
" <img class = \"image-link\" src='"+ entity.icon +"' />\n" +
|
||||
" </div>\n" +
|
||||
" <div class='gh-internal-content content-right'>\n" +
|
||||
" <p class='content-title'>"+ entity.title +"</p>\n" +
|
||||
" <p class='contents'>"+ entity.brief +"</p>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </a>\n" +
|
||||
" </div><br/>"
|
||||
var tags = "", gameHtml = ""
|
||||
if (entity.tags != null) {
|
||||
for (var i = 0; i < entity.tags.length; i++) {
|
||||
tags += "<label>"+ entity.tags[i]+"</label>"
|
||||
}
|
||||
|
||||
gameHtml = "<br/><div class='"+ entity.type +"-container'>\n" +
|
||||
" <a class='"+ entity.type +"' href=\"javascript:void(0);\" contenteditable=\"false\" onclick=\"customLinkgo(this)\" data-datas='"+ data +"'>\n" +
|
||||
" <div class='flex-container'>\n" +
|
||||
" <div class='gh-internal-content img-left'>\n" +
|
||||
" <img class='image-link' src='"+ entity.icon +"' />\n" +
|
||||
" </div>\n" +
|
||||
" <div class='gh-internal-content content-right'>\n" +
|
||||
" <p class='content-title'>"+ entity.title +"</p>\n" +
|
||||
" <p class='tags'>"+ tags +"</p>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </a></div><br/>"
|
||||
}
|
||||
|
||||
switch(entity.type) {
|
||||
case "answer":
|
||||
document.execCommand("insertHTML",false, html);
|
||||
break
|
||||
case "community_article":
|
||||
document.execCommand("insertHTML",false, html);
|
||||
break
|
||||
case "game":
|
||||
document.execCommand("insertHTML",false, gameHtml);
|
||||
break
|
||||
}
|
||||
RE.callback();
|
||||
}
|
||||
|
||||
RE.showLinkStyle = function() {
|
||||
var answerElement = document.getElementsByClassName("answer-container");
|
||||
for (var i=0;i<answerElement.length;i+=1){
|
||||
answerElement[i].style.display = 'inline';
|
||||
}
|
||||
var articleElement = document.getElementsByClassName("community_article-container");
|
||||
for (var i=0;i<articleElement.length;i+=1){
|
||||
articleElement[i].style.display = 'inline';
|
||||
}
|
||||
var gameElement = document.getElementsByClassName("game-container");
|
||||
for (var i=0;i<gameElement.length;i+=1){
|
||||
gameElement[i].style.display = 'inline';
|
||||
}
|
||||
}
|
||||
|
||||
RE.hideLinkStyle = function() {
|
||||
var answerElement = document.getElementsByClassName("answer-container");
|
||||
for (var i=0;i<answerElement.length;i+=1){
|
||||
answerElement[i].style.display = 'none';
|
||||
}
|
||||
var articleElement = document.getElementsByClassName("community_article-container");
|
||||
for (var i=0;i<articleElement.length;i+=1){
|
||||
articleElement[i].style.display = 'none';
|
||||
}
|
||||
var gameElement = document.getElementsByClassName("game-container");
|
||||
for (var i=0;i<gameElement.length;i+=1){
|
||||
gameElement[i].style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Event Listeners
|
||||
RE.editor.addEventListener("input", RE.callback);
|
||||
|
||||
RE.editor.addEventListener("keyup", function(e) {
|
||||
var KEY_LEFT = 37, KEY_RIGHT = 39;
|
||||
if (e.which == KEY_LEFT || e.which == KEY_RIGHT) {
|
||||
RE.enabledEditingItems(e);
|
||||
}
|
||||
RE.sendElementNameToNative()
|
||||
});
|
||||
RE.editor.addEventListener("click", RE.enabledEditingItems);
|
||||
|
||||
RE.editor.addEventListener("click", function(e) {
|
||||
RE.enabledEditingItems
|
||||
RE.sendElementNameToNative()
|
||||
var s = document.getSelection()
|
||||
var isNeedRemoveR = RE.recursion(e.target)
|
||||
if (isNeedRemoveR && s.rangeCount) {
|
||||
s.removeAllRanges()
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("selectionchange", function(e) {
|
||||
RE.sendElementNameToNative()
|
||||
});
|
||||
|
||||
RE.recursion = function(dom) {
|
||||
var parenDom = dom.parentElement
|
||||
if (parenDom && parenDom instanceof Element &&
|
||||
typeClassList.indexOf(parenDom.className) > -1) {
|
||||
return parenDom
|
||||
} else if(parenDom && parenDom instanceof Element &&
|
||||
typeClassList.indexOf(parenDom.className) === -1 && parenDom.nodeName !== 'BODY') {
|
||||
return RE.recursion(parenDom)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// 返回组件标签 多个标签以"空格"划分
|
||||
RE.sendElementNameToNative = function() {
|
||||
if (window.getSelection) {
|
||||
var selection = window.getSelection()
|
||||
if (selection.rangeCount > 0) {
|
||||
var range = selection.getRangeAt(0);
|
||||
var container = range.startContainer;
|
||||
var elements = " " + container.localName + " ";
|
||||
var parentElement;
|
||||
while(true) {
|
||||
if(parentElement != null) {
|
||||
parentElement = parentElement.parentElement
|
||||
} else {
|
||||
parentElement = container.parentElement
|
||||
}
|
||||
if (parentElement == null || parentElement.localName == null) {
|
||||
break;
|
||||
}
|
||||
elements = elements + " " + parentElement.localName + " "
|
||||
}
|
||||
// console.log(elements)
|
||||
window.OnCursorChangeListener.onElements(elements);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ public class AppUncaughtHandler implements UncaughtExceptionHandler {
|
||||
// 保存log到本地
|
||||
public static void saveLocalLog(Context context, Throwable ex) {
|
||||
String errorMsg = Log.getStackTraceString(ex);
|
||||
Config.setExceptionMsg(context, errorMsg);
|
||||
Config.setExceptionMsg(errorMsg);
|
||||
|
||||
// 保存到本地
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault());
|
||||
|
||||
239
app/src/main/java/com/gh/base/BaseRichEditorActivity.kt
Normal file
239
app/src/main/java/com/gh/base/BaseRichEditorActivity.kt
Normal file
@ -0,0 +1,239 @@
|
||||
package com.gh.base
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.webkit.JavascriptInterface
|
||||
import butterknife.OnClick
|
||||
import com.gh.common.view.RichEditor
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.qa.editor.GameActivity
|
||||
import com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity
|
||||
import com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.ArticleEntity
|
||||
import com.gh.gamecenter.qa.entity.EditorInsertEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import com.lightgame.view.CheckableImageView
|
||||
import kotterknife.bindView
|
||||
|
||||
abstract class BaseRichEditorActivity : BaseActivity() {
|
||||
|
||||
val mRichEditor by bindView<RichEditor>(R.id.rich_editor)
|
||||
|
||||
private val mEditorFont by bindView<CheckableImageView>(R.id.editor_font)
|
||||
private val mEditorLink by bindView<CheckableImageView>(R.id.editor_link)
|
||||
private val mEditorParagraph by bindView<CheckableImageView>(R.id.editor_paragraph)
|
||||
private val mEditorFontBold by bindView<CheckableImageView>(R.id.editor_font_bold)
|
||||
private val mEditorFontItalic by bindView<CheckableImageView>(R.id.editor_font_italic)
|
||||
private val mEditorFontStrikeThrough by bindView<CheckableImageView>(R.id.editor_font_strikethrough)
|
||||
private val mEditorParagraphH1 by bindView<CheckableImageView>(R.id.editor_paragraph_h1)
|
||||
private val mEditorParagraphH2 by bindView<CheckableImageView>(R.id.editor_paragraph_h2)
|
||||
private val mEditorParagraphH3 by bindView<CheckableImageView>(R.id.editor_paragraph_h3)
|
||||
private val mEditorParagraphH4 by bindView<CheckableImageView>(R.id.editor_paragraph_h4)
|
||||
private val mEditorParagraphQuote by bindView<CheckableImageView>(R.id.editor_paragraph_quote)
|
||||
private val mEditorFontContainer by bindView<View>(R.id.editor_font_container)
|
||||
private val mEditorParagraphContainer by bindView<View>(R.id.editor_paragraph_container)
|
||||
private val mEditorLinkContainer by bindView<View>(R.id.editor_link_container)
|
||||
private val mEditorInsertDetail by bindView<View>(R.id.editor_insert_detail)
|
||||
|
||||
private var mCurrentParagraphStyle = ""
|
||||
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (resultCode != Activity.RESULT_OK) return
|
||||
var insertData: EditorInsertEntity? = null
|
||||
when (requestCode) {
|
||||
INSERT_ANSWER_CODE -> {
|
||||
val answer = data?.getParcelableExtra<AnswerEntity>(AnswerEntity::class.java.simpleName)
|
||||
if (answer != null) insertData = EditorInsertEntity.transform(answer)
|
||||
}
|
||||
INSERT_ARTICLE_CODE -> {
|
||||
val article = data?.getParcelableExtra<ArticleEntity>(ArticleEntity::class.java.simpleName)
|
||||
if (article != null) insertData = EditorInsertEntity.transform(article)
|
||||
}
|
||||
INSERT_GAME_CODE -> {
|
||||
val game = data?.getParcelableExtra<GameEntity>(GameEntity::class.java.simpleName)
|
||||
if (game != null) insertData = EditorInsertEntity.transform(game)
|
||||
}
|
||||
}
|
||||
if (mCurrentParagraphStyle == ELEMENT_PARAGRAPH_QUOTE || mCurrentParagraphStyle == ELEMENT_PARAGRAPH_P) {
|
||||
mRichEditor.insertHtml(" ")
|
||||
if (mCurrentParagraphStyle == ELEMENT_PARAGRAPH_QUOTE) mRichEditor.formatBlock()
|
||||
}
|
||||
|
||||
mRichEditor.insertCustomStyleLink(insertData)
|
||||
}
|
||||
|
||||
@SuppressLint("AddJavascriptInterface")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
mRichEditor.setPadding(20, 15, 20, 15)
|
||||
// 防止个别手机在Js里无法获取粘贴内容
|
||||
mRichEditor.addJavascriptInterface(OnPasteListener(), "onPasteListener")
|
||||
mRichEditor.addJavascriptInterface(OnCursorChangeListener(), "OnCursorChangeListener")
|
||||
}
|
||||
|
||||
@OnClick(R.id.editor_image, R.id.editor_font, R.id.editor_link, R.id.editor_paragraph,
|
||||
R.id.editor_font_bold, R.id.editor_font_italic, R.id.editor_font_strikethrough,
|
||||
R.id.editor_paragraph_h1, R.id.editor_paragraph_h2, R.id.editor_paragraph_h3,
|
||||
R.id.editor_paragraph_h4, R.id.editor_font_container, R.id.editor_paragraph_container,
|
||||
R.id.editor_paragraph_quote, R.id.editor_link_answer, R.id.editor_link_article,
|
||||
R.id.editor_link_game)
|
||||
fun onRichClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.editor_font -> {
|
||||
mEditorFont.isChecked = !mEditorFont.isChecked
|
||||
mEditorParagraph.isChecked = false
|
||||
mEditorLink.isChecked = false
|
||||
mEditorFontContainer.visibility = if (mEditorFont.isChecked) View.VISIBLE else View.GONE
|
||||
mEditorParagraphContainer.visibility = if (!mEditorFont.isChecked) View.VISIBLE else View.GONE
|
||||
mEditorLinkContainer.visibility = if (!mEditorFont.isChecked) View.VISIBLE else View.GONE
|
||||
mEditorInsertDetail.visibility = mEditorFontContainer.visibility
|
||||
}
|
||||
R.id.editor_paragraph -> {
|
||||
mEditorParagraph.isChecked = !mEditorParagraph.isChecked
|
||||
mEditorFont.isChecked = false
|
||||
mEditorLink.isChecked = false
|
||||
mEditorParagraphContainer.visibility = if (mEditorParagraph.isChecked) View.VISIBLE else View.GONE
|
||||
mEditorFontContainer.visibility = if (!mEditorParagraph.isChecked) View.VISIBLE else View.GONE
|
||||
mEditorLinkContainer.visibility = if (!mEditorParagraph.isChecked) View.VISIBLE else View.GONE
|
||||
mEditorInsertDetail.visibility = mEditorParagraphContainer.visibility
|
||||
}
|
||||
R.id.editor_link -> {
|
||||
mEditorLink.isChecked = !mEditorLink.isChecked
|
||||
mEditorFont.isChecked = false
|
||||
mEditorParagraph.isChecked = false
|
||||
mEditorLinkContainer.visibility = if (mEditorLink.isChecked) View.VISIBLE else View.GONE
|
||||
mEditorParagraphContainer.visibility = if (!mEditorLink.isChecked) View.VISIBLE else View.GONE
|
||||
mEditorFontContainer.visibility = if (!mEditorLink.isChecked) View.VISIBLE else View.GONE
|
||||
mEditorInsertDetail.visibility = mEditorLinkContainer.visibility
|
||||
}
|
||||
R.id.editor_font_bold -> {
|
||||
mEditorFontBold.isChecked = !mEditorFontBold.isChecked
|
||||
mRichEditor.setBold()
|
||||
}
|
||||
R.id.editor_font_italic -> {
|
||||
mEditorFontItalic.isChecked = !mEditorFontItalic.isChecked
|
||||
mRichEditor.setItalic()
|
||||
}
|
||||
R.id.editor_font_strikethrough -> {
|
||||
mEditorFontStrikeThrough.isChecked = !mEditorFontStrikeThrough.isChecked
|
||||
mRichEditor.setStrikeThrough()
|
||||
}
|
||||
R.id.editor_paragraph_h1 -> {
|
||||
if (mEditorParagraphH1.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
mRichEditor.setHeading(1)
|
||||
}
|
||||
mEditorParagraphH1.isChecked = !mEditorParagraphH1.isChecked
|
||||
}
|
||||
R.id.editor_paragraph_h2 -> {
|
||||
if (mEditorParagraphH2.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
mRichEditor.setHeading(2)
|
||||
}
|
||||
mEditorParagraphH2.isChecked = !mEditorParagraphH2.isChecked
|
||||
}
|
||||
R.id.editor_paragraph_h3 -> {
|
||||
if (mEditorParagraphH3.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
mRichEditor.setHeading(3)
|
||||
}
|
||||
mEditorParagraphH3.isChecked = !mEditorParagraphH3.isChecked
|
||||
}
|
||||
R.id.editor_paragraph_h4 -> {
|
||||
if (mEditorParagraphH4.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
mRichEditor.setHeading(4)
|
||||
}
|
||||
mEditorParagraphH4.isChecked = !mEditorParagraphH4.isChecked
|
||||
}
|
||||
R.id.editor_paragraph_quote -> {
|
||||
if (mEditorParagraphQuote.isChecked) {
|
||||
mRichEditor.formatBlock()
|
||||
} else {
|
||||
mRichEditor.setBlockquote()
|
||||
}
|
||||
mEditorParagraphQuote.isChecked = !mEditorParagraphQuote.isChecked
|
||||
}
|
||||
R.id.editor_link_answer -> {
|
||||
startActivityForResult(InsertAnswerWrapperActivity.getIntent(this), INSERT_ANSWER_CODE)
|
||||
}
|
||||
R.id.editor_link_article -> {
|
||||
startActivityForResult(InsertArticleWrapperActivity.getIntent(this), INSERT_ARTICLE_CODE)
|
||||
}
|
||||
R.id.editor_link_game -> {
|
||||
startActivityForResult(GameActivity.getIntent(this), INSERT_GAME_CODE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class OnCursorChangeListener {
|
||||
@JavascriptInterface
|
||||
fun onElements(elements: String) {
|
||||
Utils.log("-----------------------")
|
||||
Utils.log(elements)
|
||||
Utils.log(mRichEditor.html)
|
||||
Utils.log("-----------------------")
|
||||
|
||||
mCurrentParagraphStyle = when {
|
||||
elements.contains(ELEMENT_PARAGRAPH_QUOTE) -> ELEMENT_PARAGRAPH_QUOTE
|
||||
elements.contains(ELEMENT_PARAGRAPH_P) -> ELEMENT_PARAGRAPH_P
|
||||
else -> ""
|
||||
}
|
||||
|
||||
mBaseHandler.post {
|
||||
mEditorFontBold.isChecked = elements.contains(ELEMENT_NAME_BOLD)
|
||||
mEditorFontItalic.isChecked = elements.contains(ELEMENT_NAME_ITALIC)
|
||||
mEditorFontStrikeThrough.isChecked = elements.contains(ELEMENT_NAME_STRIKE)
|
||||
mEditorParagraphH1.isChecked = elements.contains(ELEMENT_PARAGRAPH_H1)
|
||||
mEditorParagraphH2.isChecked = elements.contains(ELEMENT_PARAGRAPH_H2)
|
||||
mEditorParagraphH3.isChecked = elements.contains(ELEMENT_PARAGRAPH_H3)
|
||||
mEditorParagraphH4.isChecked = elements.contains(ELEMENT_PARAGRAPH_H4)
|
||||
mEditorParagraphQuote.isChecked = elements.contains(ELEMENT_PARAGRAPH_QUOTE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class OnPasteListener {
|
||||
@JavascriptInterface
|
||||
fun onPaste() {
|
||||
val clipboard =
|
||||
HaloApp.getInstance().application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clipText = clipboard.text.toString()
|
||||
if (!TextUtils.isEmpty(clipText)) {
|
||||
// 替换换行符号否则 插入失败
|
||||
val text = clipText.replace("[ ]".toRegex(), " ").replace("[\r\n]".toRegex(), "<br/>")
|
||||
mBaseHandler.post { mRichEditor.insertHtml(text) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ELEMENT_NAME_BOLD = " b "
|
||||
const val ELEMENT_NAME_ITALIC = " i "
|
||||
const val ELEMENT_NAME_STRIKE = " strike "
|
||||
const val ELEMENT_PARAGRAPH_H1 = " h1 "
|
||||
const val ELEMENT_PARAGRAPH_H2 = " h2 "
|
||||
const val ELEMENT_PARAGRAPH_H3 = " h3 "
|
||||
const val ELEMENT_PARAGRAPH_H4 = " h4 "
|
||||
const val ELEMENT_PARAGRAPH_P = " p "
|
||||
const val ELEMENT_PARAGRAPH_QUOTE = " blockquote "
|
||||
const val INSERT_ANSWER_CODE = 411
|
||||
const val INSERT_ARTICLE_CODE = 412
|
||||
const val INSERT_GAME_CODE = 413
|
||||
}
|
||||
}
|
||||
@ -101,6 +101,12 @@ public abstract class BaseToolBarActivity extends BaseAppCompatActivity implemen
|
||||
return mToolbar.getMenu().findItem(res);
|
||||
}
|
||||
|
||||
public void clearMenu() {
|
||||
if (mToolbar != null) {
|
||||
mToolbar.getMenu().clear();
|
||||
}
|
||||
}
|
||||
|
||||
public Menu getMenu() {
|
||||
return mToolbar.getMenu();
|
||||
}
|
||||
|
||||
@ -15,9 +15,8 @@ import android.view.View
|
||||
import com.gh.common.notifier.Notifier
|
||||
import com.gh.common.util.DataUtils
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.common.util.PackageUtils
|
||||
import com.gh.common.util.StringUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.PushEntity
|
||||
import com.gh.gamecenter.entity.PushMessageEntity
|
||||
@ -32,7 +31,6 @@ import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_REMOVE
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.google.gson.Gson
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.umeng.message.UmengMessageService
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
@ -48,22 +46,16 @@ class GHUmengNotificationService : UmengMessageService() {
|
||||
|
||||
companion object {
|
||||
const val ACTION_UMENG = "com.gh.gamecenter.UMENG"
|
||||
|
||||
const val MESSAGE_FROM_SYSTEM = "message_from_system"
|
||||
|
||||
const val HALO_MESSAGE_DIALOG = "HALO_MESSAGE_DIALOG"
|
||||
|
||||
const val HALO_MESSAGE_CENTER = "HALO_MESSAGE_CENTER"
|
||||
|
||||
const val ANSWER = "answer"
|
||||
|
||||
const val FOLLOW_QUESTION = "follow_question"
|
||||
|
||||
const val NOTIFICATION_ID = 2015
|
||||
|
||||
const val DISPLAY_TYPE_NOTIFICATION = "notification"
|
||||
|
||||
const val DISPLAY_TYPE_CUSTOM = "custom"
|
||||
const val MESSAGE_ID = "message_id"
|
||||
const val PUSH_ID = "push_id"
|
||||
}
|
||||
|
||||
val notificationTags = arrayOf("GH_UMENG_TAG_1", "GH_UMENG_TAG_2", "GH_UMENG_TAG_3")
|
||||
@ -74,7 +66,7 @@ class GHUmengNotificationService : UmengMessageService() {
|
||||
val isMessageFromSystem = intent.getBooleanExtra(MESSAGE_FROM_SYSTEM, false)
|
||||
|
||||
try {
|
||||
val pushData = gson.fromJson(message, PushEntity::class.java)
|
||||
val pushData = message.toObject<PushEntity>()
|
||||
pushData?.let { handlePushData(context, it, message, isMessageFromSystem) }
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -87,10 +79,10 @@ class GHUmengNotificationService : UmengMessageService() {
|
||||
if (pushData.displayType == DISPLAY_TYPE_NOTIFICATION) {
|
||||
// 其它类型的透传信息
|
||||
// 显示到通知栏
|
||||
val msg = gson.fromJson(message, PushNotificationEntity::class.java)
|
||||
val msg = message.toObject<PushNotificationEntity>()
|
||||
val data = msg?.extra?.data
|
||||
|
||||
// 系统推送,直接处理跳转
|
||||
// 系统推送(非自定义信息),直接处理跳转
|
||||
if (isMessageFromSystem) {
|
||||
val intent = Intent()
|
||||
intent.setClass(context, UmengMessageReceiver::class.java)
|
||||
@ -101,45 +93,52 @@ class GHUmengNotificationService : UmengMessageService() {
|
||||
return
|
||||
}
|
||||
|
||||
// 判断是否过滤该消息
|
||||
if (validatePush(data?.condition)) {
|
||||
val clickIntent = Intent()
|
||||
val removeIntent = Intent()
|
||||
|
||||
clickIntent.setClass(context, UmengMessageReceiver::class.java)
|
||||
clickIntent.putExtra(EntranceUtils.KEY_DATA, data?.link)
|
||||
clickIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
clickIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_CLICK)
|
||||
|
||||
removeIntent.setClass(context, UmengMessageReceiver::class.java)
|
||||
removeIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_REMOVE)
|
||||
removeIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
|
||||
val clickPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(),
|
||||
clickIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
val deletePendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt() + 1,
|
||||
removeIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel("Halo_Push", "Halo_Push", NotificationManager.IMPORTANCE_DEFAULT)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
val notification = NotificationCompat.Builder(context, "Halo_Push")
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setTicker(pushData.body?.ticker)
|
||||
.setContentTitle(pushData.body?.title)
|
||||
.setContentText(pushData.body?.text)
|
||||
.setContentIntent(clickPendingIntent)
|
||||
.setDeleteIntent(deletePendingIntent)
|
||||
.build()
|
||||
notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL
|
||||
|
||||
notificationManager.notify(getNotificationTag(context), NOTIFICATION_ID, notification)
|
||||
// 用户未登录的情况下不生成消息中心通知,避免用户掉登录了还收到跳转至消息中心的通知
|
||||
if (data != null
|
||||
&& data.link?.target == "system"
|
||||
&& !UserManager.getInstance().isLoggedIn) {
|
||||
return
|
||||
}
|
||||
|
||||
val clickIntent = Intent()
|
||||
val removeIntent = Intent()
|
||||
|
||||
clickIntent.setClass(context, UmengMessageReceiver::class.java)
|
||||
clickIntent.putExtra(EntranceUtils.KEY_DATA, data?.link)
|
||||
clickIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
clickIntent.putExtra(MESSAGE_ID, msg?.msgId)
|
||||
clickIntent.putExtra(PUSH_ID, data?.pushId)
|
||||
clickIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_CLICK)
|
||||
|
||||
removeIntent.setClass(context, UmengMessageReceiver::class.java)
|
||||
removeIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_REMOVE)
|
||||
removeIntent.putExtra(EntranceUtils.KEY_MESSAGE, message)
|
||||
|
||||
val clickPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(),
|
||||
clickIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
val deletePendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt() + 1,
|
||||
removeIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel("Halo_Push", "Halo_Push", NotificationManager.IMPORTANCE_DEFAULT)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
val notification = NotificationCompat.Builder(context, "Halo_Push")
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setTicker(pushData.body?.ticker)
|
||||
.setContentTitle(pushData.body?.title)
|
||||
.setContentText(pushData.body?.text)
|
||||
.setContentIntent(clickPendingIntent)
|
||||
.setDeleteIntent(deletePendingIntent)
|
||||
.build()
|
||||
notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL
|
||||
|
||||
notificationManager.notify(getNotificationTag(context), NOTIFICATION_ID, notification)
|
||||
} else {
|
||||
if (HALO_MESSAGE_DIALOG == pushData.body?.custom) {
|
||||
if (UserManager.getInstance().isLoggedIn
|
||||
&& HALO_MESSAGE_DIALOG == pushData.body?.custom) {
|
||||
// 回答了问题或者关注了问题的消息
|
||||
val msg = gson.fromJson(message, PushMessageEntity::class.java)
|
||||
val data = msg?.extra?.data
|
||||
@ -166,8 +165,7 @@ class GHUmengNotificationService : UmengMessageService() {
|
||||
bundle.putString(EntranceUtils.KEY_TO, AnswerDetailActivity::class.java.name)
|
||||
EntranceUtils.jumpActivity(context, bundle)
|
||||
|
||||
DataUtils.onMtaEvent(context, "消息弹窗",
|
||||
type, "Does not contains any parameter.")
|
||||
DataUtils.onMtaEvent(context, "消息弹窗", type, "Does not contains any parameter.")
|
||||
|
||||
// 标记已读
|
||||
val jsonObject = JSONObject()
|
||||
@ -201,37 +199,6 @@ class GHUmengNotificationService : UmengMessageService() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun validatePush(condition: PushNotificationEntity.Data.Condition?): Boolean {
|
||||
if (condition == null) return true
|
||||
|
||||
// 校验渠道是否匹配
|
||||
condition.ghzs?.channel?.let {
|
||||
if (it.isNotEmpty() && it != HaloApp.getInstance().channel) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 校验光环版本版本是否匹配
|
||||
condition.ghzs?.version?.let {
|
||||
if (it.isNotEmpty() && !BuildConfig.VERSION_NAME.contains(it)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 校验已安装的应用里是否存在条件的包名
|
||||
if (condition.packageName.isNotEmpty()) {
|
||||
val installedPackageList = PackageUtils.getAllPackageName(HaloApp.getInstance().application)
|
||||
for (packageName in installedPackageList) {
|
||||
if (condition.packageName == packageName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则:最多三条消息,以旧换新
|
||||
*
|
||||
|
||||
@ -22,4 +22,12 @@ object AppExecutor {
|
||||
mainThreadHandler.postDelayed(command, delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun runOnIoThread(f: () -> Unit) {
|
||||
AppExecutor.ioExecutor.execute(f)
|
||||
}
|
||||
|
||||
fun runOnUiThread(f: () -> Unit) {
|
||||
AppExecutor.uiExecutor.execute(f)
|
||||
}
|
||||
@ -1,14 +1,16 @@
|
||||
package com.gh.common
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.preference.PreferenceManager
|
||||
import com.gh.base.GHUmengNotificationService
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.common.exposure.meta.MetaUtil
|
||||
import com.gh.common.util.edit
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.entity.AliasEntity
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.google.gson.Gson
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import com.umeng.commonsdk.UMConfigure
|
||||
@ -24,7 +26,6 @@ import org.json.JSONObject
|
||||
|
||||
object PushManager {
|
||||
|
||||
var gson = Gson()
|
||||
var deviceToken: String? = ""
|
||||
var previousAlias: AliasEntity? = null
|
||||
var application = HaloApp.getInstance().application
|
||||
@ -52,7 +53,7 @@ object PushManager {
|
||||
registerDevice()
|
||||
|
||||
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(application).getString(SP_PUSH_ALIAS, "")
|
||||
previousAlias = gson.fromJson(aliasInSp, AliasEntity::class.java)
|
||||
previousAlias = aliasInSp.toObject()
|
||||
|
||||
if (previousAlias == null) {
|
||||
getAndSetAlias()
|
||||
@ -77,6 +78,7 @@ object PushManager {
|
||||
})
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun getAndSetAlias() {
|
||||
if (deviceToken.isNullOrEmpty()) {
|
||||
@ -112,7 +114,7 @@ object PushManager {
|
||||
|
||||
previousAlias = alias
|
||||
PreferenceManager.getDefaultSharedPreferences(application).edit {
|
||||
putString(SP_PUSH_ALIAS, gson.toJson(previousAlias))
|
||||
putString(SP_PUSH_ALIAS, previousAlias?.toJson())
|
||||
}
|
||||
|
||||
pushAgent.setAlias(alias.alias, alias.aliasType) { b, s ->
|
||||
|
||||
@ -13,6 +13,8 @@ import java.util.concurrent.Executors
|
||||
*/
|
||||
class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) {
|
||||
|
||||
constructor() : this(null, null)
|
||||
|
||||
constructor(fragment: Fragment) : this(fragment, null)
|
||||
|
||||
constructor(activity: Activity) : this(null, activity)
|
||||
@ -79,7 +81,7 @@ class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) {
|
||||
}, false)
|
||||
}
|
||||
|
||||
private fun resumeCounting() {
|
||||
fun resumeCounting() {
|
||||
isWorking = true
|
||||
TimeElapsedThreadHolder.threadService.execute {
|
||||
while (isWorking) {
|
||||
@ -100,7 +102,11 @@ class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun pauseCounting() {
|
||||
fun resetCounting() {
|
||||
elapsedTime = 0
|
||||
}
|
||||
|
||||
fun pauseCounting() {
|
||||
isWorking = false
|
||||
}
|
||||
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
package com.gh.common.constant;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.PackageHelper;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.NewsEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
@ -50,9 +52,14 @@ public class Config {
|
||||
|
||||
private static SettingsEntity mSettingsEntity;
|
||||
|
||||
public static final String FIX_DOWNLOAD_KEY = "isFixDownload";
|
||||
public static final String FIX_PLUGIN_KEY = "isFixPlugin";
|
||||
public static final String FIX_ARTICLE_KEY = "isFixArticle";
|
||||
public static final String FIX_COMMUNITY_KEY = "isFixCommunity";
|
||||
|
||||
|
||||
public static boolean isShow() {
|
||||
if (PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication())
|
||||
.getBoolean("isFixDownload", false)) return true;
|
||||
if (getPreferences().getBoolean(FIX_DOWNLOAD_KEY, false)) return true;
|
||||
|
||||
if (!isExistDownloadFilter()) return false;
|
||||
|
||||
@ -63,23 +70,20 @@ public class Config {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String getExceptionMsg(Context context) {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
return sp.getString("errMsg", null);
|
||||
public static String getExceptionMsg() {
|
||||
return getPreferences().getString("errMsg", null);
|
||||
}
|
||||
|
||||
public static void setExceptionMsg(Context context, String errMsg) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().putString("errMsg", errMsg).apply();
|
||||
public static void setExceptionMsg(String errMsg) {
|
||||
SPUtils.setString(getPreferences(), "errMsg", errMsg); //先用apply(),保存不了再用commit() 9.0机型保存不了信息
|
||||
}
|
||||
|
||||
public static boolean isShowDownload(String gameId) {
|
||||
|
||||
if (PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication())
|
||||
.getBoolean("isFixDownload", false)) return true;
|
||||
if (getPreferences().getBoolean(FIX_DOWNLOAD_KEY, false)) return true;
|
||||
|
||||
if (TextUtils.isEmpty(gameId) || !isExistDownloadFilter())
|
||||
return false;
|
||||
@ -103,6 +107,10 @@ public class Config {
|
||||
|
||||
|
||||
public static boolean isShowPlugin(String gameId) {
|
||||
SharedPreferences preferences = getPreferences();
|
||||
boolean isFixPlugin = preferences.getBoolean(FIX_PLUGIN_KEY, false);
|
||||
if (isFixPlugin) return true;
|
||||
|
||||
if (TextUtils.isEmpty(gameId) || !isExistDownloadFilter())
|
||||
return false;
|
||||
|
||||
@ -113,8 +121,11 @@ public class Config {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if ("all".equals(entity.getGame())) {
|
||||
}
|
||||
|
||||
if ("all".equals(entity.getGame())) {
|
||||
if (entity.getPluginfy() && filterTime(entity.getTime())) {
|
||||
preferences.edit().putBoolean(FIX_PLUGIN_KEY, true).apply();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -124,12 +135,17 @@ public class Config {
|
||||
}
|
||||
|
||||
public static boolean isShowPlugin() {
|
||||
SharedPreferences preferences = getPreferences();
|
||||
boolean isFixPlugin = preferences.getBoolean(FIX_PLUGIN_KEY, false);
|
||||
if (isFixPlugin) return true;
|
||||
|
||||
if (!isExistDownloadFilter())
|
||||
return false;
|
||||
|
||||
for (SettingsEntity.Download entity : getSettings().getDownload()) {
|
||||
if ("all".equals(entity.getGame())) {
|
||||
if (entity.getPluginfy() && filterTime(entity.getTime())) {
|
||||
preferences.edit().putBoolean(FIX_PLUGIN_KEY, true).apply();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -151,19 +167,20 @@ public class Config {
|
||||
}
|
||||
|
||||
public static void setSettings(SettingsEntity settingsEntity) {
|
||||
SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit();
|
||||
edit.putString(SETTINGS_KEY, GsonUtils.getInstance().toJson(settingsEntity)).apply();
|
||||
|
||||
getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply();
|
||||
mSettingsEntity = settingsEntity;
|
||||
|
||||
// 加载完设置后刷新下
|
||||
PackageHelper.initList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SettingsEntity getSettings() {
|
||||
if (mSettingsEntity == null) {
|
||||
try {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
|
||||
String json = sp.getString(SETTINGS_KEY, null);
|
||||
String json = getPreferences().getString(SETTINGS_KEY, null);
|
||||
if (!TextUtils.isEmpty(json)) {
|
||||
mSettingsEntity = GsonUtils.getInstance().fromJsonBean(json, SettingsEntity.class);
|
||||
mSettingsEntity = GsonUtils.fromJson(json, SettingsEntity.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@ -193,4 +210,27 @@ public class Config {
|
||||
}
|
||||
}
|
||||
|
||||
public static SharedPreferences getPreferences() {
|
||||
return PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
|
||||
}
|
||||
|
||||
public static boolean isExistHideFunction() {
|
||||
SharedPreferences preferences = getPreferences();
|
||||
if (!preferences.getBoolean(FIX_DOWNLOAD_KEY, false)) return true;
|
||||
if (!preferences.getBoolean(FIX_PLUGIN_KEY, false)) return true;
|
||||
if (!preferences.getBoolean(FIX_COMMUNITY_KEY, false)) return true;
|
||||
if (!preferences.getBoolean(FIX_ARTICLE_KEY, false)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void fixHideFunction() {
|
||||
SharedPreferences preferences = PreferenceManager.
|
||||
getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putBoolean(Config.FIX_DOWNLOAD_KEY, true);
|
||||
editor.putBoolean(Config.FIX_ARTICLE_KEY, true);
|
||||
editor.putBoolean(Config.FIX_COMMUNITY_KEY, true);
|
||||
editor.putBoolean(Config.FIX_PLUGIN_KEY, true);
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,4 +47,5 @@ public class Constants {
|
||||
//评论 cd间隔
|
||||
public static final int COMMENT_CD = 60 * 1000;
|
||||
|
||||
public static final String[] REPORT_LIST = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息", "违法有害信息", "其它"};
|
||||
}
|
||||
|
||||
@ -33,7 +33,6 @@ public class ItemViewType {
|
||||
*/
|
||||
public static final int ITEM_BODY = 100;
|
||||
public static final int ITEM_FOOTER = 101;
|
||||
public static final int ITEM_TOP = 102;
|
||||
|
||||
public static final int ITEM_HEADER = 102;
|
||||
|
||||
}
|
||||
|
||||
@ -23,7 +23,6 @@ import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.GameUtils;
|
||||
import com.gh.common.util.GameViewUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.KaiFuUtils;
|
||||
import com.gh.common.util.NewsUtils;
|
||||
import com.gh.common.util.NumberUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
@ -64,12 +63,16 @@ public class BindingAdapters {
|
||||
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({"addDetailKaiFuView", "addDetailKaiFuViewListener", "isReadyPatch"})
|
||||
public static void addDetailKaiFuView(LinearLayout view, List<KaiFuCalendarEntity> list
|
||||
, OnViewClickListener listener, Boolean isReadyPatch) {
|
||||
@ -457,8 +460,8 @@ public class BindingAdapters {
|
||||
View testView = LayoutInflater.from(layout.getContext()).inflate(R.layout.game_test_label, null);
|
||||
TextView testType = testView.findViewById(R.id.test_type);
|
||||
TextView testTime = testView.findViewById(R.id.test_time);
|
||||
String type = gameEntity.getTest().getType();
|
||||
KaiFuUtils.setKaiFuType(testType, type);
|
||||
testType.setText(gameEntity.getTest().getType());
|
||||
testType.setBackgroundColor(ContextCompat.getColor(layout.getContext(), R.color.tag_yellow));
|
||||
|
||||
if (gameEntity.getTest().getStart() == 0) {
|
||||
testTime.setVisibility(View.GONE);
|
||||
|
||||
@ -3,7 +3,6 @@ package com.gh.common.exposure
|
||||
import android.arch.persistence.room.TypeConverter
|
||||
import com.gh.common.exposure.meta.Meta
|
||||
import com.gh.common.util.GsonUtils
|
||||
import com.google.gson.Gson
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
@ -11,32 +10,32 @@ class ExposureConverters {
|
||||
|
||||
@TypeConverter
|
||||
fun convertPayload2String(any: ExposureEntity): String {
|
||||
return GsonUtils.getInstance().mGson.toJson(any)
|
||||
return GsonUtils.toJson(any)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun convertString2Payload(string: String): ExposureEntity {
|
||||
return GsonUtils.getInstance().mGson.fromJson(string, ExposureEntity::class.java)
|
||||
return GsonUtils.fromJson(string, ExposureEntity::class.java)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun convertSource2String(sourceList: List<ExposureSource>): String {
|
||||
return GsonUtils.getInstance().mGson.toJson(sourceList)
|
||||
return GsonUtils.toJson(sourceList)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun convertString2Source(sourceList: String): List<ExposureSource> {
|
||||
return ArrayList(Arrays.asList(GsonUtils.getInstance().mGson.fromJson(sourceList, Array<ExposureSource>::class.java))) as List<ExposureSource>
|
||||
return ArrayList(Arrays.asList(GsonUtils.fromJson(sourceList, Array<ExposureSource>::class.java))) as List<ExposureSource>
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun convertETrace2String(sourceList: List<ExposureEvent>?): String {
|
||||
return GsonUtils.getInstance().mGson.toJson(sourceList)
|
||||
return GsonUtils.toJson(sourceList)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun convertStringToETrace(sourceList: String): List<ExposureEvent> {
|
||||
return ArrayList(Arrays.asList(Gson().fromJson(sourceList, Array<ExposureEvent>::class.java))) as List<ExposureEvent>
|
||||
return ArrayList(Arrays.asList(GsonUtils.fromJson(sourceList, Array<ExposureEvent>::class.java))) as List<ExposureEvent>
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
@ -51,12 +50,12 @@ class ExposureConverters {
|
||||
|
||||
@TypeConverter
|
||||
fun convertMeta2String(any: Meta): String {
|
||||
return GsonUtils.getInstance().mGson.toJson(any)
|
||||
return GsonUtils.toJson(any)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun convertString2Meta(string: String): Meta {
|
||||
return GsonUtils.getInstance().mGson.fromJson(string, Meta::class.java)
|
||||
return GsonUtils.fromJson(string, Meta::class.java)
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,7 +15,7 @@ import java.util.*
|
||||
@Parcelize
|
||||
@Entity(tableName = "exposureEvent")
|
||||
data class ExposureEvent(
|
||||
val payload: ExposureEntity,
|
||||
var payload: ExposureEntity,
|
||||
val source: List<ExposureSource>,
|
||||
var eTrace: List<ExposureEvent>? = arrayListOf(),
|
||||
val event: ExposureType,
|
||||
@ -26,7 +26,7 @@ data class ExposureEvent(
|
||||
companion object {
|
||||
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>?, event: ExposureType): ExposureEvent {
|
||||
return ExposureEvent(
|
||||
ExposureEntity(gameId = gameEntity?.id,
|
||||
payload = ExposureEntity(gameId = gameEntity?.id,
|
||||
gameName = gameEntity?.name,
|
||||
sequence = gameEntity?.sequence,
|
||||
platform = gameEntity?.platform,
|
||||
|
||||
@ -2,10 +2,10 @@ package com.gh.common.exposure
|
||||
|
||||
import com.aliyun.sls.android.sdk.model.LogGroup
|
||||
import com.gh.common.exposure.time.TimeUtil
|
||||
import com.gh.common.util.toJson
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.loghub.LgLOG
|
||||
import com.gh.loghub.LoghubHelper
|
||||
import com.google.gson.Gson
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import java.util.concurrent.Executors
|
||||
@ -30,8 +30,6 @@ object ExposureManager {
|
||||
|
||||
private val loghubHelper = LoghubHelper.getInstance()
|
||||
|
||||
private val gson = Gson()
|
||||
|
||||
// exposureCache 用来过滤掉具有相同 id 的曝光事件,避免重复发送事件
|
||||
private val exposureCache = FixedSizeLinkedHashSet<String>(100)
|
||||
private val exposureSet = hashSetOf<ExposureEvent>()
|
||||
@ -127,11 +125,13 @@ object ExposureManager {
|
||||
val log = LgLOG(TimeUtil.currentTime())
|
||||
|
||||
log.PutContent("id", event.id)
|
||||
log.PutContent("payload", gson.toJson(event.payload))
|
||||
log.PutContent("payload", event.payload.toJson())
|
||||
log.PutContent("event", event.event.toString())
|
||||
log.PutContent("source", eliminateMultipleBrackets(gson.toJson(event.source)))
|
||||
log.PutContent("meta", gson.toJson(event.meta))
|
||||
log.PutContent("e-traces", if (event.eTrace != null) eliminateMultipleBrackets(gson.toJson(event.eTrace)) else "")
|
||||
log.PutContent("source", eliminateMultipleBrackets(event.source.toJson()))
|
||||
log.PutContent("meta", event.meta.toJson())
|
||||
log.PutContent("e-traces", if (event.eTrace != null) {
|
||||
eliminateMultipleBrackets(event.eTrace?.toJson() ?: "")
|
||||
} else "")
|
||||
log.PutTime(event.time)
|
||||
|
||||
return log
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import com.gh.common.util.fromObject
|
||||
import com.gh.common.util.toObject
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import java.util.*
|
||||
|
||||
@ -30,7 +30,7 @@ object ExposureUtils {
|
||||
val gameEntity = entity.clone()
|
||||
gameEntity.platform = platform
|
||||
gameEntity.downloadCompleteType = downloadType.toString()
|
||||
val traceEvent = trace?.fromObject<ExposureEvent>()
|
||||
val traceEvent = trace?.toObject<ExposureEvent>()
|
||||
val exposureEvent = ExposureEvent.createEvent(gameEntity = gameEntity,
|
||||
source = traceEvent?.source ?: ArrayList(),
|
||||
eTrace = ExposureTraceUtils.appendTrace(traceEvent),
|
||||
|
||||
@ -20,5 +20,6 @@ data class Meta(
|
||||
val channel: String? = "",
|
||||
val appVersion: String? = "",
|
||||
val userId: String? = "",
|
||||
val exposureVersion: String? = ""
|
||||
val exposureVersion: String? = "",
|
||||
val rom: String? = ""
|
||||
) : Parcelable
|
||||
@ -14,6 +14,7 @@ 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
|
||||
import java.io.File
|
||||
|
||||
object MetaUtil {
|
||||
@ -37,7 +38,8 @@ object MetaUtil {
|
||||
channel = getChannel(),
|
||||
appVersion = BuildConfig.VERSION_NAME,
|
||||
userId = UserManager.getInstance().userId,
|
||||
exposureVersion = BuildConfig.EXPOSURE_VERSION)
|
||||
exposureVersion = BuildConfig.EXPOSURE_VERSION,
|
||||
rom = RomIdentifier.getRom().name + "" + RomIdentifier.getRom().versionName)
|
||||
}
|
||||
|
||||
fun getMeta(): Meta {
|
||||
|
||||
43
app/src/main/java/com/gh/common/history/HistoryDatabase.kt
Normal file
43
app/src/main/java/com/gh/common/history/HistoryDatabase.kt
Normal file
@ -0,0 +1,43 @@
|
||||
package com.gh.common.history
|
||||
|
||||
import android.arch.persistence.room.Database
|
||||
import android.arch.persistence.room.Room
|
||||
import android.arch.persistence.room.RoomDatabase
|
||||
import android.arch.persistence.room.TypeConverters
|
||||
import com.gh.gamecenter.entity.HistoryGameEntity
|
||||
import com.gh.gamecenter.entity.NewsEntity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.ArticleEntity
|
||||
import com.gh.gamecenter.room.converter.*
|
||||
import com.gh.gamecenter.room.dao.AnswerHistoryDao
|
||||
import com.gh.gamecenter.room.dao.ArticleHistoryDao
|
||||
import com.gh.gamecenter.room.dao.GameDao
|
||||
import com.gh.gamecenter.room.dao.NewsHistoryDao
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class], version = 2, exportSchema = false)
|
||||
@TypeConverters(*[
|
||||
CountConverter::class,
|
||||
CommunityConverter::class,
|
||||
TimeConverter::class,
|
||||
AnswerUserConverter::class,
|
||||
ThumbnailConverter::class,
|
||||
TagStyleListConverter::class,
|
||||
StringArrayListConverter::class])
|
||||
|
||||
abstract class HistoryDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun answerDao(): AnswerHistoryDao
|
||||
abstract fun articleDao(): ArticleHistoryDao
|
||||
abstract fun newsDao(): NewsHistoryDao
|
||||
abstract fun gameDao(): GameDao
|
||||
|
||||
companion object {
|
||||
val instance by lazy {
|
||||
Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE")
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
107
app/src/main/java/com/gh/common/history/HistoryHelper.kt
Normal file
107
app/src/main/java/com/gh/common/history/HistoryHelper.kt
Normal file
@ -0,0 +1,107 @@
|
||||
package com.gh.common.history
|
||||
|
||||
import com.gh.common.runOnIoThread
|
||||
import com.gh.common.util.clearHtmlFormatCompletely
|
||||
import com.gh.common.util.removeInsertedContent
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.HistoryGameEntity
|
||||
import com.gh.gamecenter.entity.NewsEntity
|
||||
import com.gh.gamecenter.qa.entity.AnswerDetailEntity
|
||||
import com.gh.gamecenter.qa.entity.AnswerEntity
|
||||
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
|
||||
import com.gh.gamecenter.qa.entity.ArticleEntity
|
||||
|
||||
object HistoryHelper {
|
||||
|
||||
fun insertAnswerEntity(answerDetailEntity: AnswerDetailEntity) {
|
||||
val answerEntity = convertAnswerDetailToAnswer(answerDetailEntity)
|
||||
runOnIoThread { HistoryDatabase.instance.answerDao().addAnswer(answerEntity) }
|
||||
}
|
||||
|
||||
fun insertArticleEntity(articleDetailEntity: ArticleDetailEntity) {
|
||||
val articleEntity = convertArticleDetailToArticle(articleDetailEntity)
|
||||
runOnIoThread { HistoryDatabase.instance.articleDao().addArticle(articleEntity) }
|
||||
}
|
||||
|
||||
fun insertGameEntity(gameEntity: GameEntity) {
|
||||
val historyGameEntity = convertGameEntityToHistoryGameEntity(gameEntity)
|
||||
runOnIoThread { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) }
|
||||
}
|
||||
|
||||
private fun convertGameEntityToHistoryGameEntity(gameEntity: GameEntity): HistoryGameEntity {
|
||||
val historyGame = HistoryGameEntity()
|
||||
|
||||
historyGame.orderTag = System.currentTimeMillis()
|
||||
historyGame.id = gameEntity.id
|
||||
historyGame.brief = gameEntity.brief
|
||||
historyGame.des = gameEntity.des
|
||||
historyGame.icon = gameEntity.icon
|
||||
historyGame.name = gameEntity.name
|
||||
historyGame.tagStyle = gameEntity.tagStyle
|
||||
historyGame.tag = gameEntity.getTag()
|
||||
return historyGame
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun insertNewsEntity(newsEntity: NewsEntity) {
|
||||
newsEntity.orderTag = System.currentTimeMillis()
|
||||
runOnIoThread { HistoryDatabase.instance.newsDao().addNews(newsEntity) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun deleteNewsEntity(newsId: String) {
|
||||
runOnIoThread { HistoryDatabase.instance.newsDao().deleteNews(NewsEntity().apply { id = newsId }) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun deleteGameEntity(gameId: String) {
|
||||
runOnIoThread { HistoryDatabase.instance.gameDao().deleteGame(HistoryGameEntity(id = gameId)) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun deleteArticleEntity(articleId: String) {
|
||||
runOnIoThread { HistoryDatabase.instance.articleDao().deleteArticle(ArticleEntity(id = articleId)) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun deleteAnswerEntity(answerId: String) {
|
||||
runOnIoThread { HistoryDatabase.instance.answerDao().deleteAnswer(AnswerEntity().apply { primaryKey = answerId }) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun emptyDatabase() {
|
||||
runOnIoThread { HistoryDatabase.instance.clearAllTables() }
|
||||
}
|
||||
|
||||
private fun convertArticleDetailToArticle(articleDetailEntity: ArticleDetailEntity): ArticleEntity {
|
||||
val articleEntity = ArticleEntity()
|
||||
|
||||
articleEntity.id = articleDetailEntity.id
|
||||
articleEntity.brief = articleDetailEntity.content.removeInsertedContent().clearHtmlFormatCompletely().replace(" +".toRegex()," ")
|
||||
articleEntity.count = articleDetailEntity.count
|
||||
articleEntity.community = articleDetailEntity.community
|
||||
articleEntity.time = articleDetailEntity.time
|
||||
articleEntity.title = articleDetailEntity.title
|
||||
articleEntity.user = articleDetailEntity.user
|
||||
articleEntity.orderTag = System.currentTimeMillis()
|
||||
|
||||
return articleEntity
|
||||
}
|
||||
|
||||
private fun convertAnswerDetailToAnswer(answerDetailEntity: AnswerDetailEntity): AnswerEntity {
|
||||
val answerEntity = AnswerEntity()
|
||||
|
||||
answerEntity.id = answerDetailEntity.id
|
||||
answerEntity.primaryKey = answerDetailEntity.id
|
||||
answerEntity.commentCount = answerDetailEntity.commentCount
|
||||
answerEntity.questions = answerDetailEntity.question
|
||||
answerEntity.vote = answerDetailEntity.vote
|
||||
answerEntity.user = answerDetailEntity.user
|
||||
answerEntity.orderTag = System.currentTimeMillis()
|
||||
answerEntity.brief = answerDetailEntity.content.removeInsertedContent().clearHtmlFormatCompletely().replace(" +".toRegex(), " ")
|
||||
answerEntity.time = answerDetailEntity.time
|
||||
|
||||
return answerEntity
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,16 +5,19 @@ import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.MainActivity
|
||||
import com.gh.gamecenter.MessageActivity
|
||||
import com.gh.gamecenter.SuggestSelectActivity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.m7.imkfsdk.KfStartHelper
|
||||
import com.m7.imkfsdk.utils.Utils
|
||||
import com.moor.imkf.ChatListener
|
||||
import com.moor.imkf.IMChat
|
||||
import com.moor.imkf.IMChatManager
|
||||
import com.moor.imkf.IMMessage
|
||||
import com.moor.imkf.utils.MoorUtils
|
||||
|
||||
object ImManager {
|
||||
|
||||
@ -25,10 +28,17 @@ object ImManager {
|
||||
var shouldShowFloatingWindow = false
|
||||
var shouldShowFloatingWindowDot = false
|
||||
|
||||
// 记录当前用户 ID 避免重复初始化
|
||||
var currentUserId = ""
|
||||
|
||||
@JvmStatic
|
||||
fun attachIm() {
|
||||
try {
|
||||
if (UserManager.getInstance().userInfoEntity != null) {
|
||||
if (UserManager.getInstance().userInfoEntity != null &&
|
||||
currentUserId != UserManager.getInstance().userId) {
|
||||
currentUserId = UserManager.getInstance().userId
|
||||
MoorUtils.init(HaloApp.getInstance().application)
|
||||
Utils.init(HaloApp.getInstance().application)
|
||||
IMChatManager.getInstance().init(
|
||||
HaloApp.getInstance().application,
|
||||
ImReceiver.UNIQUE_BROADCAST_ACTION,
|
||||
@ -67,7 +77,8 @@ object ImManager {
|
||||
chatHelper.initSdkChat(
|
||||
ImReceiver.UNIQUE_BROADCAST_ACTION,
|
||||
IM_KEY,
|
||||
UserManager.getInstance().userInfoEntity.name + "(" + UserManager.getInstance().userId + ")",
|
||||
UserManager.getInstance().userInfoEntity.name + "(" + UserManager.getInstance().userId + ")"
|
||||
+ "[" + BuildConfig.VERSION_NAME + "]",
|
||||
UserManager.getInstance().userId)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
|
||||
@ -12,8 +12,8 @@ import android.support.v4.app.NotificationCompat
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.gamecenter.R
|
||||
import com.m7.imkfsdk.chat.ChatActivity
|
||||
import com.m7.imkfsdk.utils.Utils
|
||||
import com.moor.imkf.IMChatManager
|
||||
import com.moor.imkf.utils.Utils
|
||||
|
||||
class ImReceiver : BroadcastReceiver() {
|
||||
|
||||
|
||||
@ -28,6 +28,8 @@ object RemenkapaiRepository {
|
||||
* 选择随机数量的热门卡牌
|
||||
*/
|
||||
private fun pickRandomSizeEntity(size: Int): List<GameEntity> {
|
||||
if (size > remenkapaiList.size) return remenkapaiList
|
||||
|
||||
val randomGameList = arrayListOf<GameEntity>()
|
||||
val randomArray = RandomUtils.getRandomArray(size, remenkapaiList.size)
|
||||
for (i in randomArray) {
|
||||
|
||||
@ -18,6 +18,7 @@ package com.gh.common.util
|
||||
|
||||
import android.animation.Animator
|
||||
import android.support.annotation.RequiresApi
|
||||
import android.view.ViewPropertyAnimator
|
||||
|
||||
/**
|
||||
* Since [Android KTX] has not release a stable build yet,
|
||||
@ -125,4 +126,26 @@ fun Animator.addPauseListener(
|
||||
}
|
||||
addPauseListener(listener)
|
||||
return listener
|
||||
}
|
||||
|
||||
fun ViewPropertyAnimator.doOnEnd(onEnd: ((animator: Animator?) -> Unit)? = null): ViewPropertyAnimator {
|
||||
val listener = object : Animator.AnimatorListener {
|
||||
override fun onAnimationRepeat(animation: Animator?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
onEnd?.invoke(animation)
|
||||
}
|
||||
|
||||
override fun onAnimationCancel(animation: Animator?) {
|
||||
|
||||
}
|
||||
|
||||
override fun onAnimationStart(animation: Animator?) {
|
||||
|
||||
}
|
||||
}
|
||||
this.setListener(listener)
|
||||
return this
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import retrofit2.HttpException;
|
||||
|
||||
/**
|
||||
* Created by khy on 28/12/17.
|
||||
*/
|
||||
|
||||
public class AskErrorResponseUtils {
|
||||
|
||||
public static void errorResponseControl(Context context, HttpException e) {
|
||||
if (e == null) return;
|
||||
int code = e.code();
|
||||
try {
|
||||
if (code == 403 || code == 401) {
|
||||
JSONObject object = new JSONObject(e.response().errorBody().string());
|
||||
errorResponseControl(context, object);
|
||||
} else {
|
||||
Utils.toast(context, "网络错误");
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void errorResponseControl(Context context, JSONObject jsonObject) {
|
||||
int errorCode = 0;
|
||||
try {
|
||||
errorCode = jsonObject.getInt("code");
|
||||
switch (errorCode) {
|
||||
case 403001:
|
||||
Utils.toast(context, "标签名称太长了");
|
||||
break;
|
||||
case 403002:
|
||||
Utils.toast(context, "已经被邀请了");
|
||||
break;
|
||||
case 403003:
|
||||
Utils.toast(context, "每天最多可以邀请10次");
|
||||
break;
|
||||
case 403004:
|
||||
Utils.toast(context, "客户端提供的ID无效(空/无效ID)");
|
||||
break;
|
||||
case 403005:
|
||||
Utils.toast(context, "已经回答过了(限制频率)");
|
||||
break;
|
||||
case 403006:
|
||||
Utils.toast(context, "图片数量达到限制点");
|
||||
break;
|
||||
case 403007:
|
||||
Utils.toast(context, "不合法的用户");
|
||||
break;
|
||||
case 403008:
|
||||
Utils.toast(context, "已投票");
|
||||
break;
|
||||
case 403009:
|
||||
Utils.toast(context, "已经收藏过了");
|
||||
break;
|
||||
case 403010:
|
||||
Utils.toast(context, "无效的标签栏");
|
||||
break;
|
||||
case 403011:
|
||||
Utils.toast(context, "标题内容过长");
|
||||
break;
|
||||
case 403012:
|
||||
Utils.toast(context, "描述内容过长");
|
||||
break;
|
||||
case 403013:
|
||||
Utils.toast(context, "无效的标签");
|
||||
break;
|
||||
case 403014:
|
||||
Utils.toast(context, "标签数量太多了");
|
||||
break;
|
||||
case 403015:
|
||||
Utils.toast(context, "已经关注过了");
|
||||
break;
|
||||
case 404001:
|
||||
Utils.toast(context, "请求的资源不存在");
|
||||
break;
|
||||
default:
|
||||
Utils.toast(context, "网络错误");
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,9 @@ import android.graphics.Matrix;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.ExifInterface;
|
||||
import android.os.Build;
|
||||
|
||||
import com.halo.assistant.HaloApp;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@ -186,15 +189,30 @@ public class BitmapUtils {
|
||||
|
||||
/**
|
||||
* Drawable转Bitmap
|
||||
* @param isSquare 是否是正方形
|
||||
*/
|
||||
public static Bitmap drawableToBitmap(Drawable drawable) {
|
||||
public static Bitmap drawableToBitmap(Drawable drawable, boolean isSquare) {
|
||||
if (drawable == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int w,h;
|
||||
|
||||
// 取 drawable 的长宽
|
||||
int w = drawable.getIntrinsicWidth();
|
||||
int h = drawable.getIntrinsicHeight();
|
||||
w = drawable.getIntrinsicWidth();
|
||||
h = drawable.getIntrinsicHeight();
|
||||
|
||||
// 在低于 5.1 和运行内存小于 2G 的设备上减小图片大小,避免 OOM,128 * 128 又不是不能看
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
|
||||
|| DeviceUtils.getTotalRamSizeOfDevice(HaloApp.getInstance().getApplication()) < 2000) {
|
||||
if (isSquare) {
|
||||
w = w > 128 ? 128 : w;
|
||||
h = h > 128 ? 128 : h;
|
||||
} else {
|
||||
w = w > 128 ? w / 2 : w;
|
||||
h = h > 128 ? h / 2 : h;
|
||||
}
|
||||
}
|
||||
// 取 drawable 的颜色格式
|
||||
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
|
||||
: Bitmap.Config.RGB_565;
|
||||
|
||||
@ -15,14 +15,16 @@ import com.lightgame.utils.Utils;
|
||||
public class CheckLoginUtils {
|
||||
|
||||
public static void checkLogin(final Context context, String entrance, OnLoginListener listener) {
|
||||
if (TextUtils.isEmpty(UserManager.getInstance().getToken())) {
|
||||
if (!isLogin()) {
|
||||
if (listener != null) Utils.toast(context, "需要登录");
|
||||
LogUtils.login("dialog", null, entrance);
|
||||
LogUtils.login("activity", null, entrance);
|
||||
Intent intent = LoginActivity.getIntent(context, entrance);
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
listener.onLogin();
|
||||
if (listener != null) {
|
||||
listener.onLogin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ object CollectionUtils {
|
||||
try {
|
||||
val string = e.response()?.errorBody()?.string()
|
||||
val errorBody = JSONObject(string)
|
||||
if (errorBody.getInt("detail") == 403009) {
|
||||
if (errorBody.getInt("code") == 403009) {
|
||||
listener.onSuccess()
|
||||
return
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import com.gh.gamecenter.MessageDetailActivity
|
||||
import com.gh.gamecenter.adapter.OnCommentCallBackListener
|
||||
import com.gh.gamecenter.entity.CommentEntity
|
||||
import com.gh.gamecenter.entity.MeEntity
|
||||
import com.gh.gamecenter.entity.Permissions
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.lightgame.utils.Utils
|
||||
@ -21,78 +22,41 @@ import retrofit2.HttpException
|
||||
|
||||
object CommentHelper {
|
||||
|
||||
// TODO 合并这两个方法的共同部分
|
||||
@JvmStatic
|
||||
fun showCommunityArticleCommentOptions(
|
||||
context: Context,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
articleId: String,
|
||||
communityId: String,
|
||||
listener: OnCommentCallBackListener?) {
|
||||
val dialogOptions = ArrayList<String>()
|
||||
|
||||
if (commentEntity.me == null || !commentEntity.me?.isAnswerCommented!!) {
|
||||
dialogOptions.add("回复")
|
||||
}
|
||||
|
||||
dialogOptions.add("复制")
|
||||
dialogOptions.add("举报")
|
||||
|
||||
if (commentEntity.parentUser != null && showConversation) {
|
||||
dialogOptions.add("查看对话")
|
||||
}
|
||||
|
||||
DialogUtils.showListDialog(context, dialogOptions, null) {
|
||||
when (it) {
|
||||
"回复" -> {
|
||||
context.ifLogin("社区文章详情-评论-回复") {
|
||||
if (listener != null) {
|
||||
listener.onCommentCallback(commentEntity)
|
||||
} else if (!TextUtils.isEmpty(commentEntity.id)) {
|
||||
context.startActivity(MessageDetailActivity.getMessageDetailIntent(context, commentEntity, commentEntity.id))
|
||||
} else {
|
||||
Utils.toast(context, "缺少关键属性")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"复制" -> copyText(commentEntity.content, context)
|
||||
|
||||
"举报" -> context.ifLogin("社区文章详情-评论-举报") {
|
||||
showReportTypeDialog(context) { reportType ->
|
||||
PostCommentUtils.reportCommunityArticleComment(context, communityId, articleId, commentEntity.id, reportType,
|
||||
object : PostCommentUtils.PostCommentListener {
|
||||
override fun postSuccess(response: JSONObject?) {
|
||||
Utils.toast(context, "感谢您的举报")
|
||||
}
|
||||
|
||||
override fun postFailed(error: Throwable?) {
|
||||
if (error == null) {
|
||||
Utils.toast(context, "举报失败,请稍后重试")
|
||||
} else {
|
||||
Utils.toast(context, "举报失败,${error.message}")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
"查看对话" -> {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getCommunityArticleCommentIntent(context, articleId, commentEntity.id, communityId, null))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun showCommunityArticleCommentOptions(context: Context,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
articleId: String,
|
||||
communityId: String,
|
||||
listener: OnCommentCallBackListener?) {
|
||||
showCommentOptions(context = context,
|
||||
commentEntity = commentEntity,
|
||||
showConversation = showConversation,
|
||||
articleId = articleId,
|
||||
communityId = communityId,
|
||||
listener = listener)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showAnswerCommentOptions(
|
||||
context: Context,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
answerId: String,
|
||||
listener: OnCommentCallBackListener?) {
|
||||
fun showAnswerCommentOptions(context: Context,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
answerId: String,
|
||||
listener: OnCommentCallBackListener?) {
|
||||
showCommentOptions(context = context,
|
||||
commentEntity = commentEntity,
|
||||
showConversation = showConversation,
|
||||
answerId = answerId,
|
||||
listener = listener)
|
||||
}
|
||||
|
||||
private fun showCommentOptions(context: Context,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
articleId: String? = null,
|
||||
communityId: String? = null,
|
||||
answerId: String? = null,
|
||||
listener: OnCommentCallBackListener? = null) {
|
||||
val dialogOptions = ArrayList<String>()
|
||||
|
||||
if (commentEntity.me == null || !commentEntity.me?.isAnswerCommented!!) {
|
||||
@ -103,9 +67,10 @@ object CommentHelper {
|
||||
dialogOptions.add("举报")
|
||||
|
||||
commentEntity.me?.let {
|
||||
if (it.isModerator && (
|
||||
it.moderatorPermissions.contains(MeEntity.HIDE_ANSWER_COMMENT)
|
||||
|| it.moderatorPermissions.contains(MeEntity.TOP_ANSWER_COMMENT))) {
|
||||
if (it.isModerator || (it.moderatorPermissions.hideAnswerComment > Permissions.GUEST
|
||||
|| it.moderatorPermissions.topAnswerComment > Permissions.GUEST
|
||||
|| it.moderatorPermissions.hideCommunityArticleComment > Permissions.GUEST
|
||||
|| it.moderatorPermissions.topCommunityArticleComment > Permissions.GUEST)) {
|
||||
dialogOptions.add("管理")
|
||||
}
|
||||
}
|
||||
@ -116,7 +81,7 @@ object CommentHelper {
|
||||
|
||||
DialogUtils.showListDialog(context, dialogOptions, null) {
|
||||
when (it) {
|
||||
"管理" -> showControlDialog(context, answerId, commentEntity, commentEntity.me!!)
|
||||
"管理" -> showControlDialog(context, answerId, articleId, communityId, commentEntity, commentEntity.me!!)
|
||||
|
||||
"回复" -> {
|
||||
context.ifLogin("回答详情-评论-回复") {
|
||||
@ -132,56 +97,95 @@ object CommentHelper {
|
||||
|
||||
"复制" -> copyText(commentEntity.content, context)
|
||||
|
||||
"举报" -> context.ifLogin("回答详情-评论-举报") {
|
||||
showReportTypeDialog(context) { reportType ->
|
||||
PostCommentUtils.postAnswerReportData(context, commentEntity.id, answerId, reportType,
|
||||
object : PostCommentUtils.PostCommentListener {
|
||||
override fun postSuccess(response: JSONObject?) {
|
||||
Utils.toast(context, "感谢您的举报")
|
||||
}
|
||||
"举报" -> {
|
||||
context.ifLogin("回答详情-评论-举报") {
|
||||
showReportTypeDialog(context) { reportType ->
|
||||
|
||||
override fun postFailed(error: Throwable?) {
|
||||
if (error == null) {
|
||||
Utils.toast(context, "举报失败,请稍后重试")
|
||||
} else {
|
||||
Utils.toast(context, "举报失败,${error.message}")
|
||||
}
|
||||
val commentListener = object : PostCommentUtils.PostCommentListener {
|
||||
override fun postSuccess(response: JSONObject?) {
|
||||
Utils.toast(context, "感谢您的举报")
|
||||
}
|
||||
|
||||
override fun postFailed(error: Throwable?) {
|
||||
if (error == null) {
|
||||
Utils.toast(context, "举报失败,请稍后重试")
|
||||
} else {
|
||||
Utils.toast(context, "举报失败,${error.message}")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (answerId != null) {
|
||||
PostCommentUtils.postAnswerReportData(context, commentEntity.id, answerId, reportType, commentListener)
|
||||
} else {
|
||||
PostCommentUtils.reportCommunityArticleComment(context, communityId, articleId, commentEntity.id, reportType, commentListener)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"查看对话" -> {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getAnswerCommentIntent(context, commentEntity.id, answerId, null))
|
||||
if (answerId != null) {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getAnswerCommentIntent(context, commentEntity.id, answerId, null))
|
||||
} else {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getCommunityArticleCommentIntent(context, articleId, commentEntity.id, communityId, null))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showControlDialog(context: Context, answerId: String, comment: CommentEntity, me: MeEntity) {
|
||||
private fun showControlDialog(context: Context,
|
||||
answerId: String? = null,
|
||||
articleId: String? = null,
|
||||
communityId: String? = null,
|
||||
comment: CommentEntity,
|
||||
me: MeEntity) {
|
||||
val dialogOptions = arrayListOf<String>()
|
||||
val highlight = "置顶评论"
|
||||
val hide = "隐藏评论"
|
||||
|
||||
if (me.moderatorPermissions.contains(MeEntity.TOP_ANSWER_COMMENT)) {
|
||||
var canHighlightCommentDirectly = false
|
||||
var canHideCommentDirectly = false
|
||||
|
||||
if (me.moderatorPermissions.topAnswerComment > Permissions.GUEST
|
||||
|| me.moderatorPermissions.topCommunityArticleComment > Permissions.GUEST) {
|
||||
dialogOptions.add(highlight)
|
||||
if (me.moderatorPermissions.topAnswerComment > Permissions.REPORTER
|
||||
|| me.moderatorPermissions.topCommunityArticleComment > Permissions.REPORTER ) {
|
||||
canHighlightCommentDirectly = true
|
||||
}
|
||||
}
|
||||
|
||||
if (me.moderatorPermissions.contains(MeEntity.HIDE_ANSWER_COMMENT)) {
|
||||
if (me.moderatorPermissions.hideAnswerComment > Permissions.GUEST
|
||||
|| me.moderatorPermissions.hideCommunityArticleComment > Permissions.GUEST) {
|
||||
dialogOptions.add(hide)
|
||||
if (me.moderatorPermissions.hideAnswerComment > Permissions.REPORTER
|
||||
|| me.moderatorPermissions.hideCommunityArticleComment > Permissions.REPORTER ) {
|
||||
canHideCommentDirectly = true
|
||||
}
|
||||
}
|
||||
|
||||
val content = if (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
|
||||
"你的操作将提交给小编审核,确定提交吗?"
|
||||
} else {
|
||||
val highlightDialogHintContent = if (canHighlightCommentDirectly) {
|
||||
"你的操作将立即生效,确定提交吗?(你的管理权限为:高级)"
|
||||
} else {
|
||||
"你的操作将提交给小编审核,确定提交吗?"
|
||||
}
|
||||
|
||||
val hideDialogHintContent = if (canHideCommentDirectly) {
|
||||
"你的操作将立即生效,确定提交吗?(你的管理权限为:高级)"
|
||||
} else {
|
||||
"你的操作将提交给小编审核,确定提交吗?"
|
||||
}
|
||||
|
||||
val disabledOptions = arrayListOf<String>()
|
||||
|
||||
if (comment.priority != 0) {
|
||||
disabledOptions.add(highlight)
|
||||
}
|
||||
|
||||
comment.me?.let {
|
||||
if (it.isAnswerCommented) {
|
||||
disabledOptions.add(highlight)
|
||||
@ -191,7 +195,6 @@ object CommentHelper {
|
||||
DialogUtils.showListDialog(context, dialogOptions, disabledOptions) {
|
||||
when (it) {
|
||||
highlight -> {
|
||||
|
||||
if (comment.priority != 0) {
|
||||
Utils.toast(context, "评论已经置顶")
|
||||
return@showListDialog
|
||||
@ -204,77 +207,101 @@ object CommentHelper {
|
||||
}
|
||||
}
|
||||
|
||||
DialogUtils.showAlertDialog(context, highlight, content,
|
||||
"确定", "取消",
|
||||
{
|
||||
RetrofitManager.getInstance(context).api
|
||||
.highlightAnswerComment(answerId, comment.id)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
if (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
|
||||
Utils.toast(context, "提交成功")
|
||||
} else {
|
||||
Utils.toast(context, "置顶成功,请刷新列表")
|
||||
}
|
||||
}
|
||||
val highlightObserver = object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
if (canHighlightCommentDirectly) {
|
||||
Utils.toast(context, "置顶成功,请刷新列表")
|
||||
} else {
|
||||
Utils.toast(context, "提交成功")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
e?.let { httpException ->
|
||||
if (httpException.code() == 403) {
|
||||
val string = e.response().errorBody()?.string()
|
||||
val errorJson = JSONObject(string)
|
||||
val errorCode = errorJson.getInt("code")
|
||||
if (errorCode == 403059) {
|
||||
Utils.toast(getApplication(), "权限错误,请刷新后重试")
|
||||
return
|
||||
} else {
|
||||
Utils.toast(getApplication(), e.message())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}, null)
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
e?.let { httpException ->
|
||||
if (httpException.code() == 403) {
|
||||
val string = e.response().errorBody()?.string()
|
||||
val errorJson = JSONObject(string)
|
||||
val errorCode = errorJson.getInt("code")
|
||||
if (errorCode == 403059) {
|
||||
Utils.toast(getApplication(), "权限错误,请刷新后重试")
|
||||
return
|
||||
} else {
|
||||
Utils.toast(getApplication(), e.message())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (answerId != null) {
|
||||
DialogUtils.showAlertDialog(context, highlight, highlightDialogHintContent,
|
||||
"确定", "取消", {
|
||||
RetrofitManager.getInstance(context).api
|
||||
.highlightAnswerComment(answerId, comment.id)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(highlightObserver)
|
||||
}, null)
|
||||
} else {
|
||||
DialogUtils.showAlertDialog(context, highlight, highlightDialogHintContent,
|
||||
"确定", "取消", {
|
||||
RetrofitManager.getInstance(context).api
|
||||
.highlightCommunityArticleComment(communityId, articleId, comment.id)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(highlightObserver)
|
||||
}, null)
|
||||
}
|
||||
}
|
||||
|
||||
hide -> {
|
||||
DialogUtils.showAlertDialog(context, hide, content,
|
||||
"确定", "取消",
|
||||
{
|
||||
RetrofitManager.getInstance(context).api
|
||||
.hideAnswerComment(answerId, comment.id)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
if (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
|
||||
Utils.toast(context, "提交成功")
|
||||
} else {
|
||||
Utils.toast(context, "隐藏成功,请刷新列表")
|
||||
}
|
||||
}
|
||||
val hideObserver = object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
if (canHideCommentDirectly) {
|
||||
Utils.toast(context, "隐藏成功,请刷新列表")
|
||||
} else {
|
||||
Utils.toast(context, "提交成功")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
e?.let { httpException ->
|
||||
if (httpException.code() == 403) {
|
||||
val string = e.response().errorBody()?.string()
|
||||
val errorJson = JSONObject(string)
|
||||
val errorCode = errorJson.getInt("code")
|
||||
if (errorCode == 403059) {
|
||||
Utils.toast(getApplication(), "权限错误,请刷新后重试")
|
||||
return
|
||||
} else {
|
||||
Utils.toast(getApplication(), e.message())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}, null)
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
e?.let { httpException ->
|
||||
if (httpException.code() == 403) {
|
||||
val string = e.response().errorBody()?.string()
|
||||
val errorJson = JSONObject(string)
|
||||
val errorCode = errorJson.getInt("code")
|
||||
if (errorCode == 403059) {
|
||||
Utils.toast(getApplication(), "权限错误,请刷新后重试")
|
||||
return
|
||||
} else {
|
||||
Utils.toast(getApplication(), e.message())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (answerId != null) {
|
||||
DialogUtils.showAlertDialog(context, hide, hideDialogHintContent,
|
||||
"确定", "取消", {
|
||||
RetrofitManager.getInstance(context).api
|
||||
.hideAnswerComment(answerId, comment.id)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(hideObserver)
|
||||
}, null)
|
||||
} else {
|
||||
DialogUtils.showAlertDialog(context, hide, hideDialogHintContent,
|
||||
"确定", "取消", {
|
||||
RetrofitManager.getInstance(context).api
|
||||
.hideCommunityArticleComment(communityId, articleId, comment.id)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(hideObserver)
|
||||
}, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import android.app.Dialog;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
@ -20,11 +19,8 @@ import com.gh.gamecenter.adapter.OnCommentCallBackListener;
|
||||
import com.gh.gamecenter.adapter.viewholder.CommentViewHolder;
|
||||
import com.gh.gamecenter.entity.CommentEntity;
|
||||
import com.gh.gamecenter.entity.MeEntity;
|
||||
import com.gh.gamecenter.entity.RatingComment;
|
||||
import com.gh.gamecenter.entity.UserInfoEntity;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONException;
|
||||
@ -37,11 +33,6 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.HttpException;
|
||||
|
||||
/**
|
||||
@ -80,111 +71,6 @@ public class CommentUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void showGameCommentOptions(final Context context,
|
||||
final RatingComment comment,
|
||||
final String gameId,
|
||||
final String entrance) {
|
||||
|
||||
final Dialog dialog = new Dialog(context);
|
||||
|
||||
LinearLayout container = new LinearLayout(context);
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
container.setBackgroundColor(Color.WHITE);
|
||||
container.setPadding(0, DisplayUtils.dip2px(context, 12), 0, DisplayUtils.dip2px(context, 12));
|
||||
|
||||
List<String> dialogType = new ArrayList<>();
|
||||
|
||||
dialogType.add("复制");
|
||||
dialogType.add("举报");
|
||||
|
||||
|
||||
for (String s : dialogType) {
|
||||
final TextView reportTv = new TextView(context);
|
||||
reportTv.setText(s);
|
||||
reportTv.setTextSize(17);
|
||||
reportTv.setTextColor(ContextCompat.getColor(context, R.color.title));
|
||||
reportTv.setBackgroundResource(R.drawable.textview_white_style);
|
||||
int widthPixels = context.getResources().getDisplayMetrics().widthPixels;
|
||||
reportTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
reportTv.setPadding(DisplayUtils.dip2px(context, 20), DisplayUtils.dip2px(context, 12),
|
||||
0, DisplayUtils.dip2px(context, 12));
|
||||
container.addView(reportTv);
|
||||
|
||||
reportTv.setOnClickListener(v -> {
|
||||
dialog.cancel();
|
||||
switch (reportTv.getText().toString()) {
|
||||
case "复制":
|
||||
copyText(comment.getContent(), context);
|
||||
break;
|
||||
case "举报":
|
||||
CheckLoginUtils.checkLogin(context, entrance, () -> showGameCommentReportDialog(gameId, comment, context));
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(container);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private static void showGameCommentReportDialog(final String gameId, final RatingComment comment, final Context context) {
|
||||
final String[] arrReportType = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息",
|
||||
"违法有害信息", "其它"};
|
||||
int widthPixels = context.getResources().getDisplayMetrics().widthPixels;
|
||||
|
||||
final Dialog reportTypeDialog = new Dialog(context);
|
||||
LinearLayout container = new LinearLayout(context);
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
container.setPadding(0, DisplayUtils.dip2px(context, 12), 0, DisplayUtils.dip2px(context, 12));
|
||||
container.setBackgroundColor(Color.WHITE);
|
||||
|
||||
for (final String s : arrReportType) {
|
||||
TextView reportTypeTv = new TextView(context);
|
||||
reportTypeTv.setText(s);
|
||||
reportTypeTv.setTextSize(17);
|
||||
reportTypeTv.setTextColor(ContextCompat.getColor(context, R.color.title));
|
||||
reportTypeTv.setBackgroundResource(R.drawable.textview_white_style);
|
||||
reportTypeTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
reportTypeTv.setPadding(DisplayUtils.dip2px(context, 20), DisplayUtils.dip2px(context, 12),
|
||||
0, DisplayUtils.dip2px(context, 12));
|
||||
container.addView(reportTypeTv);
|
||||
|
||||
reportTypeTv.setOnClickListener(v -> {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
try {
|
||||
jsonObject.put("reason", s);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
RequestBody body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString());
|
||||
RetrofitManager.getInstance(context).getApi()
|
||||
.reportGameComment(gameId, comment.getId(), body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(@Nullable ResponseBody response) {
|
||||
Utils.toast(context, "感谢您的举报");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@Nullable HttpException e) {
|
||||
Utils.toast(context, "举报失败,请先检查网络设置");
|
||||
}
|
||||
});
|
||||
|
||||
reportTypeDialog.cancel();
|
||||
});
|
||||
}
|
||||
|
||||
reportTypeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
reportTypeDialog.setContentView(container);
|
||||
reportTypeDialog.show();
|
||||
}
|
||||
|
||||
|
||||
public static void showReportDialog(final CommentEntity commentEntity,
|
||||
final Context context,
|
||||
@ -263,135 +149,6 @@ public class CommentUtils {
|
||||
|
||||
}
|
||||
|
||||
// public static void showAnswerCommentOptions(final CommentEntity commentEntity, final Context context,
|
||||
// final OnCommentCallBackListener listener, final String id,
|
||||
// boolean showConversation, String answerId, String articleId, String articleCommunityId) {
|
||||
//
|
||||
// final Dialog dialog = new Dialog(context);
|
||||
//
|
||||
// LinearLayout container = new LinearLayout(context);
|
||||
// container.setOrientation(LinearLayout.VERTICAL);
|
||||
// container.setBackgroundColor(Color.WHITE);
|
||||
// container.setPadding(0, DisplayUtils.dip2px(context, 12), 0, DisplayUtils.dip2px(context, 12));
|
||||
//
|
||||
// List<String> dialogType = new ArrayList<>();
|
||||
//
|
||||
// if (commentEntity.getMe() == null || !commentEntity.getMe().isAnswerCommented()) {
|
||||
// dialogType.add("回复");
|
||||
// }
|
||||
//
|
||||
// dialogType.add("复制");
|
||||
// dialogType.add("举报");
|
||||
//
|
||||
// if (commentEntity.getParentUser() != null && showConversation) {
|
||||
// dialogType.add("查看对话");
|
||||
// }
|
||||
//
|
||||
// for (String s : dialogType) {
|
||||
// final TextView reportTv = new TextView(context);
|
||||
// reportTv.setText(s);
|
||||
// reportTv.setTextSize(17);
|
||||
// reportTv.setTextColor(ContextCompat.getColor(context, R.color.title));
|
||||
// reportTv.setBackgroundResource(R.drawable.textview_white_style);
|
||||
// int widthPixels = context.getResources().getDisplayMetrics().widthPixels;
|
||||
// reportTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
|
||||
// LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
// reportTv.setPadding(DisplayUtils.dip2px(context, 20), DisplayUtils.dip2px(context, 12),
|
||||
// 0, DisplayUtils.dip2px(context, 12));
|
||||
// container.addView(reportTv);
|
||||
//
|
||||
// reportTv.setOnClickListener(v -> {
|
||||
// dialog.cancel();
|
||||
// switch (reportTv.getText().toString()) {
|
||||
// case "回复":
|
||||
// CheckLoginUtils.checkLogin(context, () -> {
|
||||
// if (listener != null) {
|
||||
// listener.onCommentCallback(commentEntity);
|
||||
// } else if (!TextUtils.isEmpty(id)) {
|
||||
// context.startActivity(MessageDetailActivity.getMessageDetailIntent(context, commentEntity, id));
|
||||
// } else {
|
||||
// Utils.toast(context, "缺少关键属性");
|
||||
// }
|
||||
// });
|
||||
// break;
|
||||
// case "复制":
|
||||
// copyText(commentEntity.getContent(), context);
|
||||
// break;
|
||||
// case "举报":
|
||||
// CheckLoginUtils.checkLogin(context, () -> showAnswerReportDialog(answerId, commentEntity, context));
|
||||
// break;
|
||||
// case "查看对话":
|
||||
// if (TextUtils.isEmpty(articleId)) {
|
||||
// context.startActivity(CommentDetailActivity.getAnswerCommentIntent(context, commentEntity.getId(), answerId, null));
|
||||
// } else {
|
||||
// context.startActivity(CommentDetailActivity.getCommunityArticleCommentIntent(context, articleId, commentEntity.getId(), articleCommunityId, null));
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
// dialog.setContentView(container);
|
||||
// dialog.show();
|
||||
// }
|
||||
|
||||
// private static void showAnswerReportDialog(final String answerId, final CommentEntity commentEntity, final Context context) {
|
||||
// final String[] arrReportType = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息",
|
||||
// "违法有害信息", "其它"};
|
||||
// int widthPixels = context.getResources().getDisplayMetrics().widthPixels;
|
||||
//
|
||||
// final Dialog reportTypeDialog = new Dialog(context);
|
||||
// LinearLayout container = new LinearLayout(context);
|
||||
// container.setOrientation(LinearLayout.VERTICAL);
|
||||
// container.setPadding(0, DisplayUtils.dip2px(context, 12), 0, DisplayUtils.dip2px(context, 12));
|
||||
// container.setBackgroundColor(Color.WHITE);
|
||||
//
|
||||
// for (final String s : arrReportType) {
|
||||
// TextView reportTypeTv = new TextView(context);
|
||||
// reportTypeTv.setText(s);
|
||||
// reportTypeTv.setTextSize(17);
|
||||
// reportTypeTv.setTextColor(ContextCompat.getColor(context, R.color.title));
|
||||
// reportTypeTv.setBackgroundResource(R.drawable.textview_white_style);
|
||||
// reportTypeTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
|
||||
// LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
// reportTypeTv.setPadding(DisplayUtils.dip2px(context, 20), DisplayUtils.dip2px(context, 12),
|
||||
// 0, DisplayUtils.dip2px(context, 12));
|
||||
// container.addView(reportTypeTv);
|
||||
//
|
||||
// reportTypeTv.setOnClickListener(v -> {
|
||||
// JSONObject jsonObject = new JSONObject();
|
||||
// try {
|
||||
// jsonObject.put("reason", s);
|
||||
// } catch (JSONException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// PostCommentUtils.postAnswerReportData(context, commentEntity.getId(), answerId, jsonObject.toString(),
|
||||
// new PostCommentUtils.PostCommentListener() {
|
||||
// @Override
|
||||
// public void postSuccess(JSONObject response) {
|
||||
// Utils.toast(context, "感谢您的举报");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void postFailed(Throwable error) {
|
||||
// if (error != null) {
|
||||
// Utils.toast(context, "举报失败" + error.getMessage());
|
||||
// } else {
|
||||
// Utils.toast(context, "举报失败,请稍候重试");
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// reportTypeDialog.cancel();
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// reportTypeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
// reportTypeDialog.setContentView(container);
|
||||
// reportTypeDialog.show();
|
||||
// }
|
||||
|
||||
private static void showReportTypeDialog(final CommentEntity commentEntity, final Context context) {
|
||||
final String[] arrReportType = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息",
|
||||
"违法有害信息", "其它"};
|
||||
@ -458,7 +215,7 @@ public class CommentUtils {
|
||||
commentEntity.setVote(commentEntity.getVote() + 1);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.theme));
|
||||
commentLikeIv.setImageResource(R.drawable.vote_icon_select);
|
||||
commentLikeCountTv.setText(String.valueOf(commentEntity.getVote()));
|
||||
commentLikeCountTv.setText(NumberUtils.transSimpleCount(commentEntity.getVote()));
|
||||
commentLikeCountTv.setVisibility(View.VISIBLE);
|
||||
|
||||
PostCommentUtils.addCommentVote(context, commentEntity.getId(),
|
||||
@ -476,7 +233,7 @@ public class CommentUtils {
|
||||
commentEntity.setVote(commentEntity.getVote() - 1);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.hint));
|
||||
commentLikeIv.setImageResource(R.drawable.vote_icon_unselect);
|
||||
commentLikeCountTv.setText(String.valueOf(commentEntity.getVote()));
|
||||
commentLikeCountTv.setText(NumberUtils.transSimpleCount(commentEntity.getVote()));
|
||||
if (commentEntity.getVote() == 0) {
|
||||
commentLikeCountTv.setVisibility(View.GONE);
|
||||
} else {
|
||||
@ -518,7 +275,7 @@ public class CommentUtils {
|
||||
commentEntity.setVote(commentEntity.getVote() + 1);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.theme));
|
||||
commentLikeIv.setImageResource(R.drawable.vote_icon_select);
|
||||
commentLikeCountTv.setText(String.valueOf(commentEntity.getVote()));
|
||||
commentLikeCountTv.setText(NumberUtils.transSimpleCount(commentEntity.getVote()));
|
||||
commentLikeCountTv.setVisibility(View.VISIBLE);
|
||||
|
||||
PostCommentUtils.voteAnswerComment(context, answerId, articleId, articleCommunityId, commentEntity.getId(),
|
||||
@ -536,7 +293,7 @@ public class CommentUtils {
|
||||
commentEntity.setVote(commentEntity.getVote() - 1);
|
||||
commentLikeCountTv.setTextColor(ContextCompat.getColor(context, R.color.hint));
|
||||
commentLikeIv.setImageResource(R.drawable.vote_icon_unselect);
|
||||
commentLikeCountTv.setText(String.valueOf(commentEntity.getVote()));
|
||||
commentLikeCountTv.setText(NumberUtils.transSimpleCount(commentEntity.getVote()));
|
||||
if (commentEntity.getVote() == 0) {
|
||||
commentLikeCountTv.setVisibility(View.GONE);
|
||||
} else {
|
||||
|
||||
@ -1,45 +1,47 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.gh.gamecenter.packagehelper.PackageRepository
|
||||
import com.gh.gamecenter.qa.entity.AskGameSelectEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
/**
|
||||
* 用于判断社区跳转前社区是否可用
|
||||
*/
|
||||
object CommunityHelper {
|
||||
|
||||
private var availableCommunityList = listOf<AskGameSelectEntity>()
|
||||
/**
|
||||
* 为已开通的社区排序
|
||||
* 排序规则为将本地存在已安装游戏或已关联游戏的社区置顶
|
||||
*/
|
||||
fun sortOpenedCommunity(rawList: List<AskGameSelectEntity>?): ArrayList<AskGameSelectEntity> {
|
||||
val sortedList = ArrayList<AskGameSelectEntity>()
|
||||
rawList?.let {
|
||||
for (game in rawList) {
|
||||
var thisGameIsInstalled = false
|
||||
for (installGame in PackageRepository.gameInstalled) {
|
||||
if (PackageHelper.downloadPackageNameBlackList.contains(installGame.packageName)) {
|
||||
continue
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getAvailableCommunityList() {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
.getAskGameSelect(HaloApp.getInstance().channel
|
||||
, UrlFilterUtils.getFilterQuery("status", "opened"), 1, 100)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Response<List<AskGameSelectEntity>>() {
|
||||
override fun onResponse(response: List<AskGameSelectEntity>?) {
|
||||
if (response != null && response.isNotEmpty()) {
|
||||
availableCommunityList = response
|
||||
// 判断是否已安装
|
||||
if (installGame.id == game.game.id) {
|
||||
thisGameIsInstalled = true
|
||||
break
|
||||
}
|
||||
|
||||
// 判断是否关联了别游戏
|
||||
for (relatedGameId in game.game.relation) {
|
||||
if (installGame.id == relatedGameId) {
|
||||
thisGameIsInstalled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isCommunityAvailable(communityId: String?): Boolean {
|
||||
communityId?.let {
|
||||
if (availableCommunityList.isEmpty()) return true
|
||||
for (entity in availableCommunityList) {
|
||||
if (communityId == entity.id) {
|
||||
return true
|
||||
// 将已安装的置顶
|
||||
if (thisGameIsInstalled) {
|
||||
sortedList.add(0, game)
|
||||
} else {
|
||||
sortedList.add(game)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return sortedList
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,6 @@ package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.facebook.drawee.drawable.ScalingUtils;
|
||||
@ -93,12 +92,9 @@ public class ConcernContentUtils {
|
||||
ScalingUtils.ScaleType.CENTER_CROP, list.get(position));
|
||||
break;
|
||||
}
|
||||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent checkIntent = ViewImageActivity.getViewImageIntent(context, (ArrayList<String>) list, position, entrance);
|
||||
context.startActivity(checkIntent);
|
||||
}
|
||||
imageView.setOnClickListener(v -> {
|
||||
Intent checkIntent = ViewImageActivity.getViewImageIntent(context, (ArrayList<String>) list, position, entrance);
|
||||
context.startActivity(checkIntent);
|
||||
});
|
||||
return imageView;
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.eventbus.EBConcernChanged
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
@ -20,9 +21,17 @@ import retrofit2.HttpException
|
||||
*/
|
||||
object ConcernUtils {
|
||||
|
||||
fun postConcernGameId(context: Context, gameId: String, listener: onConcernListener?) {
|
||||
RetrofitManager.getInstance(context).getApi()
|
||||
.postConcern(UserManager.getInstance().userId, gameId)
|
||||
/**
|
||||
* autoConcern:是否自动关注'关联关注'
|
||||
*/
|
||||
fun postConcernGameId(context: Context, gameId: String, listener: onConcernListener?, autoConcern: Boolean = false) {
|
||||
val mode = if (autoConcern) "auto" else "manual"
|
||||
|
||||
val userId = UserManager.getInstance().userId
|
||||
if (TextUtils.isEmpty(userId)) return
|
||||
|
||||
RetrofitManager.getInstance(context).api
|
||||
.postConcern(UserManager.getInstance().userId, gameId, mode)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
@ -40,7 +49,7 @@ object ConcernUtils {
|
||||
}
|
||||
|
||||
fun deleteConcernData(context: Context, gameId: String, listener: onConcernListener?) {
|
||||
RetrofitManager.getInstance(context).getApi()
|
||||
RetrofitManager.getInstance(context).api
|
||||
.deleteConcern(UserManager.getInstance().userId, gameId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -61,7 +70,7 @@ object ConcernUtils {
|
||||
fun updateConcernData(context: Context, data: JSONArray) {
|
||||
val body = RequestBody.create(MediaType.parse("application/json"),
|
||||
data.toString())
|
||||
RetrofitManager.getInstance(context).getApi()
|
||||
RetrofitManager.getInstance(context).api
|
||||
.putConcern(UserManager.getInstance().userId, body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
@ -73,7 +82,7 @@ object ConcernUtils {
|
||||
}
|
||||
|
||||
fun deleteConcernQuestions(context: Context, questionsId: String, listener: onConcernListener?) {
|
||||
RetrofitManager.getInstance(context).getApi()
|
||||
RetrofitManager.getInstance(context).api
|
||||
.deleteConcernQuestions(UserManager.getInstance().userId, questionsId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -86,13 +95,19 @@ object ConcernUtils {
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
listener?.onError()
|
||||
AskErrorResponseUtils.errorResponseControl(context, e)
|
||||
var errorString: String? = null
|
||||
try {
|
||||
errorString = e?.response()?.errorBody()?.string()
|
||||
} catch (e1: Exception) {
|
||||
e1.printStackTrace()
|
||||
}
|
||||
ErrorHelper.handleError(context, errorString, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun postConcernQuestions(context: Context, questionsId: String, listener: onConcernListener?) {
|
||||
RetrofitManager.getInstance(context).getApi()
|
||||
RetrofitManager.getInstance(context).api
|
||||
.postConcernQuestions(UserManager.getInstance().userId, questionsId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -105,7 +120,13 @@ object ConcernUtils {
|
||||
override fun onFailure(e: HttpException?) {
|
||||
super.onFailure(e)
|
||||
listener?.onError()
|
||||
AskErrorResponseUtils.errorResponseControl(context, e)
|
||||
var errorString: String? = null
|
||||
try {
|
||||
errorString = e?.response()?.errorBody()?.string()
|
||||
} catch (e1: Exception) {
|
||||
e1.printStackTrace()
|
||||
}
|
||||
ErrorHelper.handleError(context, errorString, false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -72,6 +72,7 @@ public class DetailDownloadUtils {
|
||||
switch (downloadEntity.getStatus()) {
|
||||
case downloading:
|
||||
case pause:
|
||||
case overflow:
|
||||
viewHolder.mDownloadPb.setText(R.string.downloading);
|
||||
if (downloadEntity.isPluggable() && PackagesManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.DOWNLOADING_PLUGIN);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
@ -128,6 +129,20 @@ public class DeviceUtils {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static String getUserAgent() {
|
||||
String userAgent = "";
|
||||
userAgent = System.getProperty("http.agent");
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i = 0, length = userAgent.length(); i < length; i++) {
|
||||
char c = userAgent.charAt(i);
|
||||
if (c <= '\u001f' || c >= '\u007f') {
|
||||
sb.append(String.format("\\u%04x", (int) c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String getIPAddress(Context context) {
|
||||
NetworkInfo info = ((ConnectivityManager) context
|
||||
@ -224,7 +239,6 @@ public class DeviceUtils {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
// ping domain
|
||||
public static String ping(String domain) {
|
||||
try {
|
||||
@ -243,5 +257,13 @@ public class DeviceUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static long getTotalRamSizeOfDevice(Context context) {
|
||||
ActivityManager actManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
|
||||
if (actManager != null) {
|
||||
actManager.getMemoryInfo(memInfo);
|
||||
}
|
||||
return memInfo.totalMem / (1024 * 1024);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Baidu, Inc. All Rights Reserved.
|
||||
*/
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Created by sunpengfei on 15/11/4.
|
||||
*/
|
||||
public class DexUtils {
|
||||
|
||||
private static final int BUF_SIZE = 2048;
|
||||
|
||||
public static boolean prepareAssetsDex(Context context, File dexInternalStoragePath, String dex_file) {
|
||||
BufferedInputStream bis = null;
|
||||
OutputStream dexWriter = null;
|
||||
|
||||
try {
|
||||
bis = new BufferedInputStream(context.getAssets().open(dex_file));
|
||||
dexWriter = new BufferedOutputStream(new FileOutputStream(dexInternalStoragePath));
|
||||
byte[] buf = new byte[BUF_SIZE];
|
||||
int len;
|
||||
while ((len = bis.read(buf, 0, BUF_SIZE)) > 0) {
|
||||
dexWriter.write(buf, 0, len);
|
||||
}
|
||||
dexWriter.close();
|
||||
bis.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
if (dexWriter != null) {
|
||||
try {
|
||||
dexWriter.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (bis != null) {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean prepareDex(File dexInternalStoragePath, File dex_file) {
|
||||
BufferedInputStream bis = null;
|
||||
OutputStream dexWriter = null;
|
||||
|
||||
try {
|
||||
bis = new BufferedInputStream(new FileInputStream(dex_file));
|
||||
dexWriter = new BufferedOutputStream(new FileOutputStream(dexInternalStoragePath));
|
||||
byte[] buf = new byte[BUF_SIZE];
|
||||
int len;
|
||||
while ((len = bis.read(buf, 0, BUF_SIZE)) > 0) {
|
||||
dexWriter.write(buf, 0, len);
|
||||
}
|
||||
dexWriter.close();
|
||||
bis.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
if (dexWriter != null) {
|
||||
try {
|
||||
dexWriter.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (bis != null) {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -130,7 +130,7 @@ public class DialogUtils {
|
||||
ApplicationInfo appInfo = info.applicationInfo;
|
||||
appInfo.sourceDir = apkPath;
|
||||
appInfo.publicSourceDir = apkPath;
|
||||
Bitmap bitmap = BitmapUtils.drawableToBitmap(appInfo.loadIcon(pm));
|
||||
Bitmap bitmap = BitmapUtils.drawableToBitmap(appInfo.loadIcon(pm), true);
|
||||
|
||||
ImageView imageView = new ImageView(activity);
|
||||
imageView.setLayoutParams(new LinearLayout.LayoutParams(DisplayUtils.dip2px(activity, 25)
|
||||
@ -360,9 +360,16 @@ public class DialogUtils {
|
||||
} else if (NetworkUtils.isWifiConnected(context) || filter4GorSize(context, size)) {
|
||||
callBack.onResponse(false);
|
||||
} else {
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "出现弹窗提示");
|
||||
showDownloadDialog(context,
|
||||
() -> callBack.onResponse(false),
|
||||
() -> callBack.onResponse(true));
|
||||
() -> {
|
||||
callBack.onResponse(false);
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "立即下载");
|
||||
},
|
||||
() -> {
|
||||
callBack.onResponse(true);
|
||||
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "连上WiFi后自动下载");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -445,7 +452,53 @@ public class DialogUtils {
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
if (message.toString().contains("红包奖励")) {//将红包奖励四个字标红
|
||||
String str = message.toString().substring(0, message.toString().indexOf("红包奖励")) + "<font color='#FF0000'>红包奖励</font>";
|
||||
contentTv.setText(Html.fromHtml(str));
|
||||
} else {
|
||||
contentTv.setText(message);
|
||||
}
|
||||
titleTv.setText(title);
|
||||
negativeTv.setText(negative);
|
||||
positiveTv.setText(positive);
|
||||
|
||||
negativeTv.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (clListener != null) {
|
||||
clListener.onCancel();
|
||||
}
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
positiveTv.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (cmListener != null) {
|
||||
cmListener.onConfirm();
|
||||
}
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
public static Dialog showAlertDialog(Context context, String title, Spanned message
|
||||
, String positive, String negative, final ConfirmListener cmListener, final CancelListener clListener) {
|
||||
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_alert, null);
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
|
||||
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
|
||||
contentTv.setText(message);
|
||||
titleTv.setText(title);
|
||||
negativeTv.setText(negative);
|
||||
@ -795,7 +848,7 @@ public class DialogUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param options 供以显示的选项
|
||||
* @param options 供以显示的选项
|
||||
* @param disabledOptions 显示为灰色的选项(是 options 的子集)
|
||||
*/
|
||||
public static void showListDialog(Context context,
|
||||
|
||||
@ -86,7 +86,7 @@ object DirectUtils {
|
||||
|
||||
"community_article" -> context.startActivity(ArticleDetailActivity.getIntent(context, linkEntity.community!!, linkEntity.link!!, entrance, path))
|
||||
|
||||
"community_column" -> context.startActivity(CommunitySubjectActivity.getIntent(context, linkEntity.community!!, linkEntity.link, entrance))
|
||||
"community_column" -> context.startActivity(CommunitySubjectActivity.getIntent(context, linkEntity.community!!, linkEntity.link, entrance, path))
|
||||
|
||||
"community_special_column" -> context.startActivity(AskColumnDetailActivity.getIntentByColumnId(context, linkEntity.link, linkEntity.community!!, entrance, path))
|
||||
|
||||
@ -99,7 +99,7 @@ object DirectUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到文章详情
|
||||
* 跳转到新闻详情
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToArticle(context: Context, id: String, entrance: String? = null) {
|
||||
|
||||
@ -69,7 +69,7 @@ public class DownloadItemUtils {
|
||||
// adapter.notifyItemChanged(index);
|
||||
// }
|
||||
} else {
|
||||
if (!queue.contains(platform)) {
|
||||
if (!queue.contains(platform) && !TextUtils.isEmpty(platform)) {
|
||||
queue.offer(platform);
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(DownloadItemUtils.class, queue.size(), gameEntity.getBrief(), downloadEntity.getPlatform(), index);
|
||||
@ -83,7 +83,7 @@ public class DownloadItemUtils {
|
||||
DownloadManager.getInstance(context).sendMessageDelayed(msg, 3000);
|
||||
}
|
||||
}
|
||||
if (platform.equals(queue.peek())) {
|
||||
if (platform != null && platform.equals(queue.peek())) {
|
||||
if (entryMap == null) {
|
||||
entryMap = new ArrayMap<>();
|
||||
gameEntity.setEntryMap(entryMap);
|
||||
@ -96,6 +96,13 @@ public class DownloadItemUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// 下载按钮显示为查看,并且不提供下载功能
|
||||
public static void updateItemWithViewOnlyStyle(GameViewHolder holder) {
|
||||
holder.gameDownloadBtn.setVisibility(View.VISIBLE);
|
||||
holder.gameDownloadBtn.setText("查看");
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
}
|
||||
|
||||
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
|
||||
boolean isShowPlatform) {
|
||||
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game);
|
||||
@ -159,6 +166,7 @@ public class DownloadItemUtils {
|
||||
// 更新插件的条目,有多个apk包
|
||||
private static void updatePluginItem(Context context, GameViewHolder holder, GameEntity gameEntity,
|
||||
boolean isShowPlatform, PluginLocation pluginLocation) {
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, holder.gameDownloadBtn, pluginLocation);
|
||||
|
||||
ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
|
||||
if (entryMap != null && !entryMap.isEmpty()) {
|
||||
@ -177,8 +185,6 @@ public class DownloadItemUtils {
|
||||
}
|
||||
}
|
||||
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, holder.gameDownloadBtn, pluginLocation);
|
||||
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
@ -230,7 +236,8 @@ public class DownloadItemUtils {
|
||||
} else if (status.equals(DownloadStatus.pause)
|
||||
|| status.equals(DownloadStatus.timeout)
|
||||
|| status.equals(DownloadStatus.neterror)
|
||||
|| status.equals(DownloadStatus.subscribe)) {
|
||||
|| status.equals(DownloadStatus.subscribe)
|
||||
|| status.equals(DownloadStatus.overflow)) {
|
||||
holder.gameProgressbar.setProgress((int) (downloadEntity.getPercent() * 10));
|
||||
if (isShowPlatform && platform != null) {
|
||||
holder.gameDownloadSpeed.setText(String.format("%s - 暂停", platform));
|
||||
@ -240,10 +247,10 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadPercentage.setText(downloadEntity.getPercent() + "%");
|
||||
|
||||
if (isNormal) {
|
||||
if (status.equals(DownloadStatus.pause)) {
|
||||
holder.gameDownloadBtn.setText(R.string.downloading);
|
||||
} else {
|
||||
if (status.equals(DownloadStatus.waiting)) {
|
||||
holder.gameDownloadBtn.setText(R.string.waiting);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setText(R.string.downloading);
|
||||
}
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
|
||||
|
||||
@ -25,7 +25,7 @@ public class EntranceUtils {
|
||||
public static final String KEY_URL = "url";
|
||||
public static final String KEY_GAMENAME = "gameName";
|
||||
public static final String HOST_ARTICLE = "article";
|
||||
public static final String HOST_COMMUNITY_ARTICLE = "community.article";
|
||||
public static final String HOST_COMMUNITY_ARTICLE = "community_article";
|
||||
public static final String HOST_GAME = "game";
|
||||
public static final String HOST_GAME_DOWNLOAD = "game_download";
|
||||
public static final String HOST_COLUMN = "column";
|
||||
@ -98,7 +98,6 @@ public class EntranceUtils {
|
||||
public static final String KEY_COMMUNITY_DATA = "communityData";
|
||||
public static final String KEY_TRACE_EVENT = "trace_event";
|
||||
public static final String KEY_SUBJECT_DATA = "subjectData";
|
||||
public static final String KEY_SHOW_SELECT_COMMUNITY = "show_select_community";
|
||||
public static final String KEY_USER_ID = "user_id";
|
||||
public static final String KEY_QUESTION_TAG = "question_tag";
|
||||
public static final String KEY_COLUMN_ID = "column_id";
|
||||
@ -111,6 +110,8 @@ public class EntranceUtils {
|
||||
public static final String KEY_RATING_STAR_COUNT = "ratingStarCount";
|
||||
public static final String KEY_QUESTION_MODERATOR_PATCH = "questionModeratorPatch";
|
||||
public static final String KEY_SKIP_GAME_COMMENT = "skipGameComment";
|
||||
public static final String KEY_OPEN_PLATFORM_WINDOW = "openPlatformWindow";
|
||||
public static final String KEY_OPEN_KEYBOARD = "openKeyboard";
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
|
||||
|
||||
@ -10,6 +10,54 @@ import com.lightgame.utils.Utils
|
||||
*/
|
||||
object ErrorHelper {
|
||||
|
||||
/**
|
||||
* 手动匹配处理特定错误码
|
||||
* [showHighPriorityHint] 用来标识有同样错误码可以触发两种处理时,为 true 时选择重要的
|
||||
* [customizedHandler] 返回 true 为已处理该错误码,false 则交由 [handleError] 处理
|
||||
*/
|
||||
fun handleErrorWithCustomizedHandler(context: Context,
|
||||
errorString: String?,
|
||||
showHighPriorityHint: Boolean = false,
|
||||
customizedHandler: (code: Int) -> Boolean) {
|
||||
val errorEntity = errorString?.toObject<ErrorEntity>()
|
||||
|
||||
if (errorEntity == null) {
|
||||
Utils.toast(context, R.string.post_failure_hint)
|
||||
return
|
||||
}
|
||||
|
||||
if (!errorEntity.toast.isNullOrEmpty()) {
|
||||
Utils.toast(context, errorEntity.toast)
|
||||
return
|
||||
}
|
||||
|
||||
if (customizedHandler(errorEntity.code ?: 0)) {
|
||||
return
|
||||
} else {
|
||||
handleError(context, showHighPriorityHint, errorEntity)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [showHighPriorityHint] 用来标识有同样错误码可以触发两种处理时,为 true 时选择重要的
|
||||
*/
|
||||
@JvmStatic
|
||||
fun handleError(context: Context, errorString: String?, showHighPriorityHint: Boolean = false) {
|
||||
val errorEntity = errorString?.toObject<ErrorEntity>()
|
||||
|
||||
if (errorEntity == null) {
|
||||
Utils.toast(context, R.string.post_failure_hint)
|
||||
return
|
||||
}
|
||||
|
||||
if (!errorEntity.toast.isNullOrEmpty()) {
|
||||
Utils.toast(context, errorEntity.toast)
|
||||
return
|
||||
}
|
||||
|
||||
handleError(context, showHighPriorityHint, errorEntity)
|
||||
}
|
||||
|
||||
/***
|
||||
* 禁言错误,
|
||||
*403050: 评论回答
|
||||
@ -24,23 +72,7 @@ object ErrorHelper {
|
||||
*403054: 更新社区文章
|
||||
*403047: 回答点赞
|
||||
*/
|
||||
|
||||
/**
|
||||
* [important] 用来标识有同样错误码可以触发两种处理时,为 true 时选择重要的
|
||||
*/
|
||||
fun handleError(context: Context, errorString: String?, important: Boolean? = false) {
|
||||
val errorEntity = errorString?.fromObject<ErrorEntity>()
|
||||
|
||||
if (errorEntity == null) {
|
||||
Utils.toast(context, R.string.post_failure_hint)
|
||||
return
|
||||
}
|
||||
|
||||
if (!errorEntity.toast.isNullOrEmpty()) {
|
||||
Utils.toast(context, errorEntity.toast)
|
||||
return
|
||||
}
|
||||
|
||||
private fun handleError(context: Context, showHighPriorityHint: Boolean = false, errorEntity: ErrorEntity) {
|
||||
when (errorEntity.code) {
|
||||
403050,
|
||||
403051,
|
||||
@ -70,9 +102,10 @@ object ErrorHelper {
|
||||
403014 -> Utils.toast(context, "标签数量太多了")
|
||||
403015 -> Utils.toast(context, "已经关注过了")
|
||||
404001 -> Utils.toast(context, "请求的资源不存在")
|
||||
403016 -> Utils.toast(context, "标签内容可能包含敏感信息,请修改后再提交")
|
||||
403018 -> Utils.toast(context, R.string.comment_failed_unable)
|
||||
|
||||
403020 -> if (important!!) {
|
||||
403020 -> if (showHighPriorityHint) {
|
||||
DialogUtils.showAlertDialog(context,
|
||||
"限制提醒",
|
||||
"提问过于频繁,请先休息一下哦",
|
||||
@ -83,6 +116,8 @@ object ErrorHelper {
|
||||
|
||||
403021 -> Utils.toast(context, R.string.comment_failed_illegal)
|
||||
|
||||
403059 -> Utils.toast(context, "权限错误,请刷新后重试")
|
||||
|
||||
else -> Utils.toast(context, R.string.post_failure_hint)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,24 +1,42 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.arch.lifecycle.*
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentActivity
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.text.Html
|
||||
import android.text.Spanned
|
||||
import android.view.View
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import java.net.URI
|
||||
|
||||
/**
|
||||
* 创建以 activity 为观察者上下文的 viewModel
|
||||
*/
|
||||
inline fun <reified VM : ViewModel> FragmentActivity.viewModelProvider(
|
||||
provider: ViewModelProvider.Factory
|
||||
provider: ViewModelProvider.Factory? = null
|
||||
) =
|
||||
ViewModelProviders.of(this, provider).get(VM::class.java)
|
||||
|
||||
/**
|
||||
* 创建以 activity 为观察者上下文的 viewModel
|
||||
*/
|
||||
inline fun <reified VM : ViewModel> Fragment.viewModelProviderFromParent(
|
||||
provider: ViewModelProvider.Factory? = null
|
||||
) =
|
||||
ViewModelProviders.of(requireActivity(), provider).get(VM::class.java)
|
||||
|
||||
/**
|
||||
* 创建以 fragment 为观察者上下文的 viewModel
|
||||
*/
|
||||
inline fun <reified VM : ViewModel> Fragment.viewModelProvider(
|
||||
provider: ViewModelProvider.Factory
|
||||
provider: ViewModelProvider.Factory? = null
|
||||
) =
|
||||
ViewModelProviders.of(this, provider).get(VM::class.java)
|
||||
|
||||
@ -72,9 +90,9 @@ fun Context.ifLogin(entrance: String, action: (() -> Unit)? = null) {
|
||||
/**
|
||||
* Gson related extensions.
|
||||
*/
|
||||
inline fun <reified T : Any> String.fromObject(): T? {
|
||||
inline fun <reified T : Any> String.toObject(): T? {
|
||||
return try {
|
||||
GsonUtils.getInstance().mGson.fromJson(this, T::class.java)
|
||||
GsonUtils.gson.fromJson(this, object : TypeToken<T>() {}.type)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
@ -82,14 +100,72 @@ inline fun <reified T : Any> String.fromObject(): T? {
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> T.toJson(): String {
|
||||
return GsonUtils.getInstance().mGson.toJson(this)
|
||||
return GsonUtils.toJson(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 快速点击两下
|
||||
* 在限定 interval 里只触发一次 action
|
||||
*/
|
||||
fun fastDoubleClickAction(id: Int, interval: Long = 300, action: (() -> Unit)? = null) {
|
||||
if (ClickUtils.isFastDoubleClick(id, interval)) {
|
||||
fun debounceActionWithInterval(id: Int, interval: Long = 300, action: (() -> Unit)? = null) {
|
||||
if (!ClickUtils.isFastDoubleClick(id, interval)) {
|
||||
action?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun View.debounceActionWithInterval(interval: Long = 300, action: (() -> Unit)? = null) {
|
||||
debounceActionWithInterval(this.id, interval, action)
|
||||
}
|
||||
|
||||
/**
|
||||
* 告诉需要返回 true or false 的外层这个事件已经被消费(即返回 true)
|
||||
*/
|
||||
inline fun consume(f: () -> Unit): Boolean {
|
||||
f()
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* String related
|
||||
*/
|
||||
fun String.fromHtml(): Spanned {
|
||||
return Html.fromHtml(this)
|
||||
}
|
||||
|
||||
// 去掉文章/答案的插入内容
|
||||
fun String.removeInsertedContent(): String {
|
||||
val textRegex = "(?s)<div class=\"gh-internal-content content-right\".*?</div>"
|
||||
|
||||
return this.replace(textRegex.toRegex(), "")
|
||||
}
|
||||
|
||||
// 完全地清除所有 Html 格式
|
||||
fun String.clearHtmlFormatCompletely(): String {
|
||||
return Html.fromHtml(this).toString().replace('\n', 32.toChar())
|
||||
.replace(160.toChar(), 32.toChar()).replace(65532.toChar(), 32.toChar()).trim { it <= ' ' }
|
||||
}
|
||||
|
||||
// 如果该字符串长度超过固定长度的话,从头开始截取固定长度并返回
|
||||
fun String.subStringIfPossible(length: Int): String {
|
||||
return if (this.length > length) {
|
||||
this.substring(0, length)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
fun String.copyTextAndToast(toastText: String = "复制成功") {
|
||||
val application = HaloApp.getInstance().application
|
||||
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
cmb.text = this
|
||||
Utils.toast(application, toastText)
|
||||
}
|
||||
|
||||
fun Map<String, String>.createRequestBody(): RequestBody {
|
||||
val json = GsonUtils.toJson(this)
|
||||
return RequestBody.create(MediaType.parse("application/json"), json)
|
||||
}
|
||||
|
||||
// 对在浏览器(WebView)显示的路径进行转码
|
||||
fun String.decodeURI(): String {
|
||||
return URI(null, null, this, null).rawPath
|
||||
}
|
||||
100
app/src/main/java/com/gh/common/util/GameRepositoryHelper.kt
Normal file
100
app/src/main/java/com/gh/common/util/GameRepositoryHelper.kt
Normal file
@ -0,0 +1,100 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.entity.SubjectEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
/**
|
||||
* 首页补充游戏库辅助类
|
||||
*/
|
||||
object GameRepositoryHelper {
|
||||
|
||||
private const val KEY_GAME_REPOSITORY = "game_repository"
|
||||
|
||||
var gameCollectionList: List<SubjectEntity> = arrayListOf()
|
||||
|
||||
init {
|
||||
loadSavedRepository()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取游戏补充库
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getGameRepository(context: Context) {
|
||||
|
||||
RetrofitManager.getInstance(context)
|
||||
.api
|
||||
.reserveColumns
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Response<List<SubjectEntity>>() {
|
||||
override fun onResponse(response: List<SubjectEntity>?) {
|
||||
super.onResponse(response)
|
||||
|
||||
updateGameRepository(response)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新内存中的游戏库(即从 SP 中再读一次)
|
||||
*/
|
||||
@JvmStatic
|
||||
fun refreshGameRepository() = loadSavedRepository()
|
||||
|
||||
private fun loadSavedRepository() {
|
||||
gameCollectionList = SPUtils.getString(KEY_GAME_REPOSITORY).toObject() ?: arrayListOf()
|
||||
}
|
||||
|
||||
fun updateGameRepository(subjects: List<SubjectEntity>?) {
|
||||
|
||||
if (subjects == null) return
|
||||
|
||||
SPUtils.setString(KEY_GAME_REPOSITORY, subjects.toJson())
|
||||
|
||||
gameCollectionList = subjects
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 从补充游戏库相应的专题中取出一个与其它游戏都不相同的游戏,为空时即为游戏用完或不存在该相应专题
|
||||
* @param collectionId 补充游戏库相应专题 ID
|
||||
* @param gameIdList 该专题里已经包含的游戏 ID 列表
|
||||
*/
|
||||
fun getOneUniqueGame(collectionId: String?, gameIdList: HashSet<String>): GameEntity? {
|
||||
collectionId?.let {
|
||||
val collection = gameCollectionList.find { it.id == collectionId }
|
||||
collection?.let {
|
||||
val game = collection.data?.find { game -> isThisGameUnique(game, gameIdList) }
|
||||
game?.let {
|
||||
collection.data?.remove(game)
|
||||
// 产品说要记录补充专题的曝光数,所以这个游戏附带了所在专题的名字
|
||||
game.subjectName = collection.name
|
||||
return game
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun isThisGameUnique(game: GameEntity, gameIdList: HashSet<String>): Boolean {
|
||||
// 若该补充游戏已经存在关联关系,判定为非唯一
|
||||
for (relatedId in game.relatedGameIds!!) {
|
||||
gameIdList.contains(relatedId)
|
||||
return false
|
||||
}
|
||||
for (apk in game.getApk()) {
|
||||
// 检查本地是否已安装该游戏,已过滤那部分框架服务的包名
|
||||
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return !gameIdList.contains(game.id) && !TextUtils.isEmpty(game.id)
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,13 +6,14 @@ import android.support.v4.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameCollectionEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.download.DownloadStatus;
|
||||
@ -71,15 +72,18 @@ public class GameUtils {
|
||||
int installCount = 0; // 已安装数量
|
||||
DownloadEntity downloadEntity;
|
||||
Object gh_id;
|
||||
apkFor:
|
||||
for (ApkEntity apkEntity : gameEntity.getApk()) {
|
||||
|
||||
// 去除下载合集判断
|
||||
boolean isCollection = false;
|
||||
for (GameCollectionEntity collectionEntity : gameEntity.getCollection()) {
|
||||
if (collectionEntity.getPackage().contains(apkEntity.getPackageName()))
|
||||
isCollection = true;
|
||||
// filter by packageName
|
||||
SettingsEntity settings = Config.getSettings();
|
||||
if (settings != null && gameEntity.getApk().size() > 1) {
|
||||
for (String pkgName : settings.getGameDownloadBlackList()) {
|
||||
if (pkgName.equals(apkEntity.getPackageName())) {
|
||||
continue apkFor;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isCollection) continue;
|
||||
|
||||
downloadEntity = DownloadManager.getInstance(context).getDownloadEntityByUrl(apkEntity.getUrl());
|
||||
if (downloadEntity != null) {
|
||||
|
||||
@ -21,7 +21,7 @@ object GdtHelper {
|
||||
const val PLATFORM = "PLATFORM"
|
||||
|
||||
fun init(application: Application) {
|
||||
GDTAction.init(application, "1107958753", "dff25cc0dcb4a3b9f881a5fd7eec7e8a")
|
||||
GDTAction.init(application, "1108222478", "0b2bb2b971c8221be45a8454f05a0b1f")
|
||||
}
|
||||
|
||||
fun logAction(type: String) {
|
||||
|
||||
@ -16,9 +16,9 @@ import com.sina.weibo.sdk.auth.Oauth2AccessToken;
|
||||
import com.sina.weibo.sdk.auth.WbAuthListener;
|
||||
import com.sina.weibo.sdk.auth.WbConnectErrorMessage;
|
||||
import com.sina.weibo.sdk.auth.sso.SsoHandler;
|
||||
import com.tencent.mm.sdk.openapi.IWXAPI;
|
||||
import com.tencent.mm.sdk.openapi.SendAuth;
|
||||
import com.tencent.mm.sdk.openapi.WXAPIFactory;
|
||||
import com.tencent.mm.opensdk.modelmsg.SendAuth;
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI;
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
|
||||
import com.tencent.tauth.IUiListener;
|
||||
import com.tencent.tauth.Tencent;
|
||||
import com.tencent.tauth.UiError;
|
||||
@ -56,7 +56,7 @@ public class GetLoginDataUtils {
|
||||
+ "follow_app_official_microblog," + "invitation_write"; // weiboCode
|
||||
|
||||
private GetLoginDataUtils(Context context) {
|
||||
mContext = context.getApplicationContext();
|
||||
mContext = context;
|
||||
mTencent = Tencent.createInstance(Config.TENCENT_APPID, mContext); //初始化QQ分享
|
||||
|
||||
mIWXAPI = WXAPIFactory.createWXAPI(mContext, Config.WECHAT_APPID, true); //初始化微信分享
|
||||
@ -68,7 +68,7 @@ public class GetLoginDataUtils {
|
||||
|
||||
public static GetLoginDataUtils getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
instance = new GetLoginDataUtils(context);
|
||||
instance = new GetLoginDataUtils(context.getApplicationContext());
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
@ -172,7 +172,7 @@ public class GetLoginDataUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public void WCLofinCallBack(JSONObject content) {
|
||||
public void WCLoginCallBack(JSONObject content) {
|
||||
if (mLoginListener != null) {
|
||||
mLoginListener.OnLoginData(content, LoginTag.wechat);
|
||||
}
|
||||
|
||||
20
app/src/main/java/com/gh/common/util/GhMatisseFilter.kt
Normal file
20
app/src/main/java/com/gh/common/util/GhMatisseFilter.kt
Normal file
@ -0,0 +1,20 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import com.zhihu.matisse.MimeType
|
||||
import com.zhihu.matisse.filter.Filter
|
||||
import com.zhihu.matisse.internal.entity.IncapableCause
|
||||
import com.zhihu.matisse.internal.entity.Item
|
||||
|
||||
class GhMatisseFilter : Filter() {
|
||||
|
||||
override fun constraintTypes(): MutableSet<MimeType> {
|
||||
return MimeType.ofVideo()
|
||||
}
|
||||
|
||||
override fun filter(context: Context?, item: Item?): IncapableCause? {
|
||||
if (!needFiltering(context, item)) return null
|
||||
return IncapableCause(IncapableCause.TOAST, "暂不支持视频")
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,36 +1,27 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
||||
|
||||
/**
|
||||
* Created by khy on 11/10/17.
|
||||
*/
|
||||
class GsonUtils private constructor() {
|
||||
val mGson: Gson = Gson()
|
||||
object GsonUtils {
|
||||
val gson: Gson = Gson()
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun getInstance(): GsonUtils {
|
||||
return Inner.anotherSingle
|
||||
}
|
||||
|
||||
private object Inner {
|
||||
val anotherSingle = GsonUtils()
|
||||
}
|
||||
@JvmStatic
|
||||
fun <T> fromJson(json: String, t: Class<T>): T {
|
||||
return gson.fromJson(json, t)
|
||||
}
|
||||
|
||||
fun <T> fromJsonBean(json: String, t: Class<T>): T {
|
||||
return mGson.fromJson(json, t)
|
||||
}
|
||||
// @JvmStatic
|
||||
// fun <T> fromJsonList(json: String): List<T> {
|
||||
// val type = object : TypeToken<List<T>>() {}.type
|
||||
// return gson.fromJson(json, type)
|
||||
// }
|
||||
|
||||
fun <T> fromJsonList(json: String, t: Class<T>): T {
|
||||
val type = object : TypeToken<List<T>>() {}.type
|
||||
return mGson.fromJson(json, type)
|
||||
}
|
||||
|
||||
fun toJson(any: Any): String {
|
||||
return mGson.toJson(any)
|
||||
@JvmStatic
|
||||
fun toJson(any: Any?): String {
|
||||
return gson.toJson(any)
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class HMACUtils {
|
||||
|
||||
public static String encrypt(String data, String key) {
|
||||
try {
|
||||
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA256");
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(signingKey);
|
||||
return byte2hex(mac.doFinal(data.getBytes()));
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String byte2hex(byte[] ciphertext) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
String stmp;
|
||||
for (int i = 0; ciphertext != null && i < ciphertext.length; i++) {
|
||||
stmp = Integer.toHexString(ciphertext[i] & 0XFF);
|
||||
if (stmp.length() == 1) {
|
||||
builder.append('0');
|
||||
}
|
||||
builder.append(stmp);
|
||||
}
|
||||
return builder.toString().toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,158 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Baidu, Inc. All Rights Reserved.
|
||||
*/
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import dalvik.system.DexClassLoader;
|
||||
import dalvik.system.PathClassLoader;
|
||||
|
||||
/* compiled from: ProGuard */
|
||||
public final class HotFix {
|
||||
|
||||
public static void patch(Context context, String patchDexFile, String patchClassName) {
|
||||
if (patchDexFile != null && new File(patchDexFile).exists()) {
|
||||
try {
|
||||
if (hasLexClassLoader()) {
|
||||
injectInAliyunOs(context, patchDexFile, patchClassName);
|
||||
} else if (hasDexClassLoader()) {
|
||||
injectAboveEqualApiLevel14(context, patchDexFile, patchClassName);
|
||||
} else {
|
||||
injectBelowApiLevel14(context, patchDexFile, patchClassName);
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasLexClassLoader() {
|
||||
try {
|
||||
Class.forName("dalvik.system.LexClassLoader");
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void injectInAliyunOs(Context context, String patchDexFile, String patchClassName)
|
||||
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException,
|
||||
InstantiationException, NoSuchFieldException {
|
||||
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
|
||||
String replaceAll = new File(patchDexFile).getName().replaceAll("\\.[a-zA-Z0-9]+", ".lex");
|
||||
Class cls = Class.forName("dalvik.system.LexClassLoader");
|
||||
Object newInstance =
|
||||
cls.getConstructor(new Class[]{String.class, String.class, String.class, ClassLoader.class}).newInstance(
|
||||
new Object[]{context.getDir("dex", 0).getAbsolutePath() + File.separator + replaceAll,
|
||||
context.getDir("dex", 0).getAbsolutePath(), patchDexFile, obj});
|
||||
cls.getMethod("loadClass", new Class[]{String.class}).invoke(newInstance, new Object[]{patchClassName});
|
||||
setField(obj, PathClassLoader.class, "mPaths",
|
||||
appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(newInstance, cls, "mRawDexPath")));
|
||||
setField(obj, PathClassLoader.class, "mFiles",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(newInstance, cls, "mFiles")));
|
||||
setField(obj, PathClassLoader.class, "mZips",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(newInstance, cls, "mZips")));
|
||||
setField(obj, PathClassLoader.class, "mLexs",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mLexs"), getField(newInstance, cls, "mDexs")));
|
||||
}
|
||||
|
||||
private static boolean hasDexClassLoader() {
|
||||
try {
|
||||
Class.forName("dalvik.system.BaseDexClassLoader");
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void injectAboveEqualApiLevel14(Context context, String str, String str2)
|
||||
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||
PathClassLoader pathClassLoader = (PathClassLoader) context.getClassLoader();
|
||||
Object a = combineArray(getDexElements(getPathList(pathClassLoader)),
|
||||
getDexElements(getPathList(
|
||||
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader()))));
|
||||
Object a2 = getPathList(pathClassLoader);
|
||||
setField(a2, a2.getClass(), "dexElements", a);
|
||||
pathClassLoader.loadClass(str2);
|
||||
}
|
||||
|
||||
@TargetApi(14)
|
||||
private static void injectBelowApiLevel14(Context context, String str, String str2)
|
||||
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
|
||||
DexClassLoader dexClassLoader =
|
||||
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader());
|
||||
dexClassLoader.loadClass(str2);
|
||||
setField(obj, PathClassLoader.class, "mPaths",
|
||||
appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mRawDexPath")
|
||||
));
|
||||
setField(obj, PathClassLoader.class, "mFiles",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mFiles")
|
||||
));
|
||||
setField(obj, PathClassLoader.class, "mZips",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mZips")));
|
||||
setField(obj, PathClassLoader.class, "mDexs",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mDexs"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mDexs")));
|
||||
obj.loadClass(str2);
|
||||
}
|
||||
|
||||
private static void setField(Object obj, Class cls, String str, Object obj2)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
Field declaredField = cls.getDeclaredField(str);
|
||||
declaredField.setAccessible(true);
|
||||
declaredField.set(obj, obj2);
|
||||
}
|
||||
|
||||
private static Object appendArray(Object obj, Object obj2) {
|
||||
Class componentType = obj.getClass().getComponentType();
|
||||
int length = Array.getLength(obj);
|
||||
Object newInstance = Array.newInstance(componentType, length + 1);
|
||||
Array.set(newInstance, 0, obj2);
|
||||
for (int i = 1; i < length + 1; i++) {
|
||||
Array.set(newInstance, i, Array.get(obj, i - 1));
|
||||
}
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
private static Object getField(Object obj, Class cls, String str)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
Field declaredField = cls.getDeclaredField(str);
|
||||
declaredField.setAccessible(true);
|
||||
return declaredField.get(obj);
|
||||
}
|
||||
|
||||
private static Object combineArray(Object obj, Object obj2) {
|
||||
Class componentType = obj2.getClass().getComponentType();
|
||||
int length = Array.getLength(obj2);
|
||||
int length2 = Array.getLength(obj) + length;
|
||||
Object newInstance = Array.newInstance(componentType, length2);
|
||||
for (int i = 0; i < length2; i++) {
|
||||
if (i < length) {
|
||||
Array.set(newInstance, i, Array.get(obj2, i));
|
||||
} else {
|
||||
Array.set(newInstance, i, Array.get(obj, i - length));
|
||||
}
|
||||
}
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
private static Object getDexElements(Object obj) throws NoSuchFieldException, IllegalAccessException {
|
||||
return getField(obj, obj.getClass(), "dexElements");
|
||||
}
|
||||
|
||||
private static Object getPathList(Object obj) throws ClassNotFoundException, NoSuchFieldException,
|
||||
IllegalAccessException {
|
||||
return getField(obj, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,22 +9,9 @@ import java.util.regex.Pattern;
|
||||
* Created by khy on 27/12/17.
|
||||
*/
|
||||
|
||||
public class AskUtils {
|
||||
|
||||
// public static String voteCountFormat(int voteCount) {
|
||||
// String vote;
|
||||
// if (voteCount >= 10000) {
|
||||
// DecimalFormat df = new DecimalFormat("#.0万");
|
||||
// vote = df.format(voteCount / 10000f);
|
||||
// } else {
|
||||
// vote = String.valueOf(voteCount);
|
||||
// }
|
||||
// return vote;
|
||||
// }
|
||||
public class HtmlUtils {
|
||||
|
||||
public static String stripHtml(String htmlStr) {
|
||||
|
||||
|
||||
if (TextUtils.isEmpty(htmlStr)) return "";
|
||||
|
||||
String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
|
||||
@ -45,5 +32,4 @@ public class AskUtils {
|
||||
|
||||
return htmlStr.trim(); //返回文本字符串
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,9 +2,11 @@ package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.support.annotation.DrawableRes
|
||||
import android.support.v4.content.ContextCompat
|
||||
import com.facebook.common.executors.CallerThreadExecutor
|
||||
@ -20,6 +22,7 @@ import com.facebook.imagepipeline.request.ImageRequest
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.R
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
|
||||
object ImageUtils {
|
||||
@ -231,12 +234,23 @@ object ImageUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun display(view: SimpleDraweeView?, url: String?) {
|
||||
val width = view?.layoutParams?.width
|
||||
if (width != null && width > 0) {
|
||||
view.setImageURI(getTransformLimitUrl(url, width, view.context))
|
||||
} else {
|
||||
view?.post {
|
||||
view.setImageURI(getTransformLimitUrl(url, view.width, view.context))
|
||||
url?.let {
|
||||
// 图片是以 gif 结尾的就
|
||||
if (it.endsWith(".gif")) {
|
||||
val controller = Fresco.newDraweeControllerBuilder()
|
||||
.setUri(url)
|
||||
.setAutoPlayAnimations(true)
|
||||
.build()
|
||||
view?.controller = controller
|
||||
} else {
|
||||
val width = view?.layoutParams?.width
|
||||
if (width != null && width > 0) {
|
||||
view.setImageURI(getTransformLimitUrl(url, width, view.context))
|
||||
} else {
|
||||
view?.post {
|
||||
view.setImageURI(getTransformLimitUrl(url, view.width, view.context))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -247,7 +261,10 @@ object ImageUtils {
|
||||
if (width != null && width > 0) {
|
||||
val transformUrlX2 = addLimitWidth(url, width * 2)
|
||||
val transformUrlX1 = addLimitWidth(url, width)
|
||||
if (NetworkUtils.isWifiOr4GConnected(context)) {
|
||||
// 当网络为 WIFI 或 4G, 且系统版本大于 5.0 && 手机内存大于 1G 才用高清图片
|
||||
if (NetworkUtils.isWifiOr4GConnected(context)
|
||||
&& Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP
|
||||
&& DeviceUtils.getTotalRamSizeOfDevice(context) > 1000) {
|
||||
transformUrl = transformUrlX2
|
||||
} else {
|
||||
// 检查X2大图是否被缓存
|
||||
@ -278,6 +295,24 @@ object ImageUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun bmpToByteArray(bmp: Bitmap, needRecycle: Boolean): ByteArray {
|
||||
val output = ByteArrayOutputStream()
|
||||
bmp.compress(Bitmap.CompressFormat.PNG, 100, output)
|
||||
if (needRecycle) {
|
||||
bmp.recycle()
|
||||
}
|
||||
|
||||
val result = output.toByteArray()
|
||||
try {
|
||||
output.close()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun display(draweeView: SimpleDraweeView, @DrawableRes res: Int?) {
|
||||
|
||||
@ -64,15 +64,13 @@ public class InstallUtils {
|
||||
keys.add(packageName);
|
||||
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(context).getDownloadEntityByPackageName(packageName);
|
||||
String installVersion = PackageUtils.getVersionByPackage(context, packageName);
|
||||
String installVersion = PackageUtils.getVersionByPackage(packageName);
|
||||
if (!TextUtils.isEmpty(installVersion) && downloadEntity != null &&
|
||||
installVersion.equals(downloadEntity.getVersionName())) {
|
||||
if (!downloadEntity.isPluggable() || PackageUtils.isSignature(context, packageName)) {
|
||||
EventBus.getDefault().post(new EBPackage("安装", packageName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
for (String key : keys) {
|
||||
@ -109,7 +107,7 @@ public class InstallUtils {
|
||||
if (mInstance == null) {
|
||||
synchronized (InstallUtils.class) {
|
||||
if (mInstance == null) {
|
||||
mInstance = new InstallUtils(context);
|
||||
mInstance = new InstallUtils(context.getApplicationContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
/**
|
||||
* Created by khy on 2017/3/19.
|
||||
*/
|
||||
public class KaiFuUtils {
|
||||
|
||||
public static void setKaiFuType(TextView textView, String type) {
|
||||
if (type == null) return;
|
||||
textView.setText(type);
|
||||
textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), R.color.tag_yellow));
|
||||
// switch (type) {
|
||||
// case "不删档内测":
|
||||
// textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), R.color.content));
|
||||
// break;
|
||||
// case "删档内测":
|
||||
// textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), R.color.content));
|
||||
// break;
|
||||
// case "公测":
|
||||
// textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), R.color.tag_yellow));
|
||||
// break;
|
||||
// default:
|
||||
// textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), R.color.tag_yellow));
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
}
|
||||
@ -84,7 +84,7 @@ public class LibaoUtils {
|
||||
.subscribe(new JSONObjectResponse() {
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
listener.postSucced(response);
|
||||
listener.postSucceed(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,7 +105,7 @@ public class LibaoUtils {
|
||||
.subscribe(new JSONObjectResponse() {
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
listener.postSucced(response);
|
||||
listener.postSucceed(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -123,7 +123,7 @@ public class LibaoUtils {
|
||||
.subscribe(new Response<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(ResponseBody response) {
|
||||
listener.postSucced(response);
|
||||
listener.postSucceed(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -140,7 +140,7 @@ public class LibaoUtils {
|
||||
.subscribe(new Response<List<LibaoStatusEntity>>() {
|
||||
@Override
|
||||
public void onResponse(List<LibaoStatusEntity> response) {
|
||||
listener.postSucced(response);
|
||||
listener.postSucceed(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -299,7 +299,7 @@ public class LibaoUtils {
|
||||
final Dialog loadingDialog = DialogUtils.showWaitDialog(context, "淘号中...");
|
||||
postLibaoTao(context, libaoEntity.getId(), new PostLibaoListener() {
|
||||
@Override
|
||||
public void postSucced(Object response) {
|
||||
public void postSucceed(Object response) {
|
||||
|
||||
if (loadingDialog != null) loadingDialog.dismiss();
|
||||
|
||||
@ -431,7 +431,7 @@ public class LibaoUtils {
|
||||
|
||||
postLibaoLing(context, libaoEntity.getId(), new PostLibaoListener() {
|
||||
@Override
|
||||
public void postSucced(Object response) {
|
||||
public void postSucceed(Object response) {
|
||||
if (loadingDialog != null) loadingDialog.dismiss();
|
||||
|
||||
JSONObject responseBody = (JSONObject) response;
|
||||
@ -629,7 +629,7 @@ public class LibaoUtils {
|
||||
|
||||
|
||||
public interface PostLibaoListener {
|
||||
void postSucced(Object response);
|
||||
void postSucceed(Object response);
|
||||
|
||||
void postFailed(Throwable error);
|
||||
}
|
||||
|
||||
@ -6,7 +6,9 @@ import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.CommunityEntity;
|
||||
import com.gh.gamecenter.entity.SpecialColumn;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.qa.entity.Questions;
|
||||
import com.gh.loghub.LogHubUtils;
|
||||
@ -22,8 +24,12 @@ import org.json.JSONObject;
|
||||
*/
|
||||
public class LogUtils {
|
||||
|
||||
public static void uploadCommunityArticle(String tracers, String articleId, String articleTitle,
|
||||
int readTime, CommunityEntity community) {
|
||||
public static void uploadCommunityArticle(String tracers,
|
||||
String articleId,
|
||||
String articleTitle,
|
||||
int readTime,
|
||||
CommunityEntity community,
|
||||
SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("subject", "community_article");
|
||||
@ -33,6 +39,17 @@ public class LogUtils {
|
||||
object.put("article_name", articleTitle);
|
||||
object.put("tracers", tracers);
|
||||
object.put("read", readTime);
|
||||
JSONObject columnObject = new JSONObject();
|
||||
if (specialColumn != null) {
|
||||
columnObject.put("type", specialColumn.getType());
|
||||
columnObject.put("name", specialColumn.getName());
|
||||
columnObject.put("tab", specialColumn.getTab());
|
||||
} else {
|
||||
columnObject.put("type", "");
|
||||
columnObject.put("name", "");
|
||||
columnObject.put("tab", "");
|
||||
}
|
||||
object.put("special_column", columnObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -55,17 +72,34 @@ public class LogUtils {
|
||||
upload(object);
|
||||
}
|
||||
|
||||
public static void uploadAnswerReadTime(String tracers, int readTime, String answerId, Questions questions) {
|
||||
public static void uploadAnswerReadTime(String tracers,
|
||||
int readTime,
|
||||
String answerId,
|
||||
Questions questions,
|
||||
String communityId,
|
||||
String CommunityName,
|
||||
SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("subject", "answer");
|
||||
object.put("community_id", UserManager.getInstance().getCommunity().getId());
|
||||
object.put("community_name", UserManager.getInstance().getCommunity().getName());
|
||||
object.put("community_id", communityId);
|
||||
object.put("community_name", CommunityName);
|
||||
object.put("question_id", questions.getId());
|
||||
object.put("question_name", questions.getTitle());
|
||||
object.put("tracers", tracers);
|
||||
object.put("answer_id", answerId);
|
||||
object.put("read", readTime);
|
||||
JSONObject columnObject = new JSONObject();
|
||||
if (specialColumn != null) {
|
||||
columnObject.put("type", specialColumn.getType());
|
||||
columnObject.put("name", specialColumn.getName());
|
||||
columnObject.put("tab", specialColumn.getTab());
|
||||
} else {
|
||||
columnObject.put("type", "");
|
||||
columnObject.put("name", "");
|
||||
columnObject.put("tab", "");
|
||||
}
|
||||
object.put("special_column", columnObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -73,16 +107,32 @@ public class LogUtils {
|
||||
upload(object);
|
||||
}
|
||||
|
||||
public static void uploadQuestionReadTime(String tracers, int readTime, Questions questions) {
|
||||
public static void uploadQuestionReadTime(String tracers,
|
||||
int readTime,
|
||||
Questions questions,
|
||||
String communityId,
|
||||
String communityName,
|
||||
SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
object.put("subject", "question");
|
||||
object.put("community_id", UserManager.getInstance().getCommunity().getId());
|
||||
object.put("community_name", UserManager.getInstance().getCommunity().getName());
|
||||
object.put("community_id", communityId);
|
||||
object.put("community_name", communityName);
|
||||
object.put("question_id", questions.getId());
|
||||
object.put("question_name", questions.getTitle());
|
||||
object.put("tracers", tracers);
|
||||
object.put("read", readTime);
|
||||
JSONObject columnObject = new JSONObject();
|
||||
if (specialColumn != null) {
|
||||
columnObject.put("type", specialColumn.getType());
|
||||
columnObject.put("name", specialColumn.getName());
|
||||
columnObject.put("tab", specialColumn.getTab());
|
||||
} else {
|
||||
columnObject.put("type", "");
|
||||
columnObject.put("name", "");
|
||||
columnObject.put("tab", "");
|
||||
}
|
||||
object.put("special_column", columnObject);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -137,6 +187,10 @@ public class LogUtils {
|
||||
}
|
||||
|
||||
private static void upload(JSONObject object) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->" + object.toString());
|
||||
}
|
||||
|
||||
Context context = HaloApp.getInstance().getApplication();
|
||||
try {
|
||||
object.put("version", PackageUtils.getVersionName());
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.retrofit.JSONObjectResponse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
@ -12,8 +10,6 @@ import com.lightgame.utils.Utils;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.MediaType;
|
||||
@ -106,68 +102,6 @@ public class LoginUtils {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 请用 ErrorHelper.handleError 替代本方法
|
||||
*/
|
||||
@Deprecated
|
||||
public static void userPostErrorToast(String errorString, Context context, boolean isQuestion) {
|
||||
if (TextUtils.isEmpty(errorString)) {
|
||||
Utils.toast(context, R.string.post_failure_hint);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject errorJson = new JSONObject(errorString);
|
||||
Iterator<String> iterator = errorJson.keys();
|
||||
while (iterator.hasNext()) {
|
||||
String key = iterator.next();
|
||||
if ("toast".equals(key)) {
|
||||
Utils.toast(context, errorJson.get(key).toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int errorCode = errorJson.getInt("code");
|
||||
switch (errorCode) {
|
||||
case 403018:
|
||||
Utils.toast(context, R.string.comment_failed_unable);
|
||||
case 403050:
|
||||
case 403053:
|
||||
case 403048:
|
||||
case 403049:
|
||||
case 403057:
|
||||
case 403045:
|
||||
case 403046:
|
||||
case 403054:
|
||||
Utils.toast(context, R.string.comment_failed_userbanned);
|
||||
break;
|
||||
case 403051:
|
||||
Utils.toast(context, R.string.comment_failed_userblocked);
|
||||
break;
|
||||
case 403020:
|
||||
if (isQuestion) {
|
||||
DialogUtils.showAlertDialog(context, "限制提醒"
|
||||
, "提问过于频繁,请先休息一下哦", "知道了"
|
||||
, null, null, null);
|
||||
} else {
|
||||
Utils.toast(context, R.string.comment_failed_toofrequent);
|
||||
}
|
||||
break;
|
||||
case 403021:
|
||||
Utils.toast(context, R.string.comment_failed_illegal);
|
||||
break;
|
||||
case 403047:
|
||||
Utils.toast(context, R.string.deny_vote_answer);
|
||||
break;
|
||||
default:
|
||||
Utils.toast(context, R.string.post_failure_hint);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Utils.toast(context, R.string.post_failure_hint);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void captchaErrorHint(Context context, JSONObject content) {
|
||||
try {
|
||||
@ -318,12 +252,18 @@ public class LoginUtils {
|
||||
case 403016:
|
||||
Utils.toast(context, "内容违规,请修改后再保存");
|
||||
break;
|
||||
case 403021:
|
||||
Utils.toast(context, "内容可能包含敏感信息,请修改后再提交");
|
||||
break;
|
||||
case 403801:
|
||||
Utils.toast(context, "获取验证码太频繁,请稍后再试");
|
||||
break;
|
||||
case 403204:
|
||||
Utils.toast(context, "获取验证码太频繁,请稍后再试");
|
||||
break;
|
||||
case 400212:
|
||||
Utils.toast(context, "请输入正确的手机号");
|
||||
break;
|
||||
default:
|
||||
Utils.toast(context, code + "");
|
||||
break;
|
||||
|
||||
@ -11,11 +11,11 @@ import android.graphics.Matrix;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.support.v4.content.*;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
@ -28,19 +28,17 @@ import com.gh.common.constant.Config;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.lightgame.utils.Utils;
|
||||
import com.tencent.connect.share.QQShare;
|
||||
import com.tencent.mm.sdk.openapi.IWXAPI;
|
||||
import com.tencent.mm.sdk.openapi.SendMessageToWX;
|
||||
import com.tencent.mm.sdk.openapi.WXAPIFactory;
|
||||
import com.tencent.mm.sdk.openapi.WXImageObject;
|
||||
import com.tencent.mm.sdk.openapi.WXMediaMessage;
|
||||
import com.tencent.mm.sdk.platformtools.Util;
|
||||
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
|
||||
import com.tencent.mm.opensdk.modelmsg.WXImageObject;
|
||||
import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI;
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
|
||||
import com.tencent.tauth.IUiListener;
|
||||
import com.tencent.tauth.Tencent;
|
||||
import com.tencent.tauth.UiError;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
@ -255,6 +253,11 @@ public class MessageShareUtils {
|
||||
private void wechatSahre() {
|
||||
Utils.toast(mContext, "分享跳转中...");
|
||||
|
||||
if (!PackageHelper.INSTANCE.getLocalPackageNameSet().contains("com.tencent.mm")) {
|
||||
Utils.toast(mContext, "没安装微信,分享失败");
|
||||
return;
|
||||
}
|
||||
|
||||
//官方分享
|
||||
// WXImageObject imgObj = new WXImageObject();
|
||||
// imgObj.setImagePath(mContext.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
|
||||
@ -286,6 +289,11 @@ public class MessageShareUtils {
|
||||
private void wechatMomentsSahre() {
|
||||
Utils.toast(mContext, "分享跳转中...");
|
||||
|
||||
if (!PackageHelper.INSTANCE.getLocalPackageNameSet().contains("com.tencent.mm")) {
|
||||
Utils.toast(mContext, "没安装微信,分享失败");
|
||||
return;
|
||||
}
|
||||
|
||||
WXImageObject imgObj = new WXImageObject();
|
||||
imgObj.setImagePath(mContext.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
|
||||
WXMediaMessage msg = new WXMediaMessage();
|
||||
@ -298,7 +306,7 @@ public class MessageShareUtils {
|
||||
req.scene = SendMessageToWX.Req.WXSceneTimeline;
|
||||
|
||||
Bitmap compressBp = compressBitmap(shareBm);
|
||||
msg.thumbData = Util.bmpToByteArray(compressBp, true);
|
||||
msg.thumbData = ImageUtils.bmpToByteArray(compressBp, true);
|
||||
mIWXAPI.sendReq(req);
|
||||
|
||||
if (mPopupWindow == null) return;
|
||||
@ -366,7 +374,7 @@ public class MessageShareUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
} catch (Exception e) {
|
||||
Utils.log("消息分享异常" + e.toString());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
|
||||
@ -3,6 +3,7 @@ package com.gh.common.util;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
public class NetworkUtils {
|
||||
|
||||
@ -119,4 +120,48 @@ public class NetworkUtils {
|
||||
return "NONE";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前移动网络连接的类型信息(当连接的网络是移动网络时使用)
|
||||
*
|
||||
* @param context 上下文
|
||||
* @return 当前移动网络连接的类型信息
|
||||
*/
|
||||
public static String getMobileNetworkType(Context context) {
|
||||
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
|
||||
|
||||
if (info == null) return "unknown";
|
||||
|
||||
switch (info.getType()) {
|
||||
// Unknown
|
||||
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
|
||||
return "unknown";
|
||||
// Cellular Data–2G
|
||||
case TelephonyManager.NETWORK_TYPE_EDGE:
|
||||
case TelephonyManager.NETWORK_TYPE_GPRS:
|
||||
case TelephonyManager.NETWORK_TYPE_CDMA:
|
||||
case TelephonyManager.NETWORK_TYPE_IDEN:
|
||||
case TelephonyManager.NETWORK_TYPE_1xRTT:
|
||||
return "2G";
|
||||
// Cellular Data–3G
|
||||
case TelephonyManager.NETWORK_TYPE_UMTS:
|
||||
case TelephonyManager.NETWORK_TYPE_HSDPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPAP:
|
||||
case TelephonyManager.NETWORK_TYPE_HSUPA:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_0:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_A:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_B:
|
||||
return "3G";
|
||||
// Cellular Data–4G
|
||||
case TelephonyManager.NETWORK_TYPE_LTE:
|
||||
return "4G";
|
||||
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import java.math.BigDecimal
|
||||
import java.text.DecimalFormat
|
||||
|
||||
object NumberUtils {
|
||||
|
||||
@JvmStatic
|
||||
fun transSimpleCount(count: Int): String {
|
||||
val s: String
|
||||
if (count > 10000) {
|
||||
s = if (count > 100000) {
|
||||
val number = count / 10000f
|
||||
val bd = BigDecimal(number.toDouble())
|
||||
s = bd.setScale(1, BigDecimal.ROUND_DOWN).toString() + "W"
|
||||
val fmt = DecimalFormat("#")
|
||||
fmt.format(number) + "万"
|
||||
} else {
|
||||
s = count.toString()
|
||||
count.toString()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
44
app/src/main/java/com/gh/common/util/OptionDialogHelper.kt
Normal file
44
app/src/main/java/com/gh/common/util/OptionDialogHelper.kt
Normal file
@ -0,0 +1,44 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.view.Window
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
object OptionDialogHelper {
|
||||
|
||||
fun showOptionDialog(context: Context, typeList: List<String>, callback: (String) -> Unit) {
|
||||
val dialog = Dialog(context)
|
||||
val container = LinearLayout(context)
|
||||
container.orientation = LinearLayout.VERTICAL
|
||||
container.setBackgroundColor(Color.WHITE)
|
||||
container.setPadding(0, DisplayUtils.dip2px(context, 12f), 0, DisplayUtils.dip2px(context, 12f))
|
||||
|
||||
for (type in typeList) {
|
||||
val reportTv = TextView(context)
|
||||
reportTv.text = type
|
||||
reportTv.textSize = 17f
|
||||
reportTv.setTextColor(ContextCompat.getColor(context, R.color.title))
|
||||
reportTv.setBackgroundResource(R.drawable.textview_white_style)
|
||||
val widthPixels = context.resources.displayMetrics.widthPixels
|
||||
reportTv.layoutParams = LinearLayout.LayoutParams(widthPixels * 9 / 10,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
reportTv.setPadding(DisplayUtils.dip2px(context, 20f), DisplayUtils.dip2px(context, 12f),
|
||||
0, DisplayUtils.dip2px(context, 12f))
|
||||
container.addView(reportTv)
|
||||
|
||||
reportTv.setOnClickListener {
|
||||
callback.invoke(reportTv.text.toString())
|
||||
dialog.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog.setContentView(container)
|
||||
dialog.show()
|
||||
}
|
||||
}
|
||||
@ -2,15 +2,25 @@ package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.entity.SettingsEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
object PackageHelper {
|
||||
|
||||
// 黑名单包名,用于区分像 Xposed Installer 那些工具的包名
|
||||
var excludePackageNameList = arrayListOf<String>()
|
||||
// 评论黑名单包名列表,避免用户安装了 Xposed Installer 这样的工具,也能在包含该安装包的游戏详情页评论
|
||||
var commentPackageNameBlackList = arrayListOf<String>()
|
||||
|
||||
// 关闭下载的包列表
|
||||
var downloadPackageNameBlackList = arrayListOf<String>()
|
||||
|
||||
// 本地已安装的包去掉关闭下载的包后的列表
|
||||
var validLocalPackageNameSet = hashSetOf<String>()
|
||||
|
||||
// 游戏包名匹配列表
|
||||
var relatedPackageList = arrayListOf<SettingsEntity.GameWithPackages>()
|
||||
|
||||
// 本地已安装包的列表
|
||||
var localPackageNameSet = hashSetOf<String>()
|
||||
get() {
|
||||
return if (field.isEmpty()) {
|
||||
@ -23,16 +33,28 @@ object PackageHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun refreshLocalPackageList() {
|
||||
AppExecutor.ioExecutor.execute {
|
||||
localPackageNameSet = getAllPackageName(HaloApp.getInstance().application)
|
||||
}
|
||||
localPackageNameSet = getAllPackageName(HaloApp.getInstance().application)
|
||||
updateValidPackageNameList()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun initExcludePackageName() {
|
||||
fun initList() {
|
||||
Config.getSettings()?.gameCommentBlackList?.let {
|
||||
excludePackageNameList = ArrayList(it)
|
||||
commentPackageNameBlackList = ArrayList(it)
|
||||
}
|
||||
Config.getSettings()?.gameDownloadBlackList?.let {
|
||||
downloadPackageNameBlackList = ArrayList(it)
|
||||
}
|
||||
Config.getSettings()?.gamePackageMatch?.let {
|
||||
relatedPackageList = ArrayList(it)
|
||||
}
|
||||
|
||||
Config.getSettings()?.gameDownloadBlackList
|
||||
updateValidPackageNameList()
|
||||
}
|
||||
|
||||
private fun updateValidPackageNameList() {
|
||||
validLocalPackageNameSet = localPackageNameSet.filterNot { p -> downloadPackageNameBlackList.contains(p) }.toHashSet()
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -19,6 +19,7 @@ import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@ -79,7 +80,7 @@ public class PackageUtils {
|
||||
for (ApkEntity apkEntity : gameEntity.getApkNormal()) {
|
||||
|
||||
String versionFromRequest = apkEntity.getVersion();
|
||||
String versionFromInstalledApp = getVersionByPackage(context, apkEntity.getPackageName());
|
||||
String versionFromInstalledApp = getVersionByPackage(apkEntity.getPackageName());
|
||||
|
||||
// 是否需要显示更新
|
||||
boolean shouldShouldUpdate = apkEntity.getForce();
|
||||
@ -310,9 +311,9 @@ public class PackageUtils {
|
||||
/*
|
||||
* 获取apk的版本
|
||||
*/
|
||||
public static String getVersionByPackage(Context context, String packageName) {
|
||||
public static String getVersionByPackage(String packageName) {
|
||||
try {
|
||||
return context.getApplicationContext().getPackageManager().getPackageInfo(packageName,
|
||||
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
@ -370,6 +371,25 @@ public class PackageUtils {
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
public static JSONObject getAppBasicInfoByPackageName(String packageName) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
PackageManager pm = HaloApp.getInstance().getApplication().getPackageManager();
|
||||
try {
|
||||
PackageInfo packageInfo = HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
jsonObject.put("name", pm.getApplicationLabel(packageInfo.applicationInfo).toString());
|
||||
jsonObject.put("package", packageName);
|
||||
jsonObject.put("version", packageInfo.versionName);
|
||||
}
|
||||
return jsonObject;
|
||||
} catch (JSONException | NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 启动应用
|
||||
*/
|
||||
|
||||
@ -133,7 +133,7 @@ public class PlatformUtils {
|
||||
}
|
||||
}
|
||||
|
||||
updataPlatform(platformMap, platformPicMap, platformPicUrlMap,
|
||||
updatePlatform(platformMap, platformPicMap, platformPicUrlMap,
|
||||
platformColorMap);
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ public class PlatformUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private void updataPlatform(ArrayMap<String, String> pMap,
|
||||
private void updatePlatform(ArrayMap<String, String> pMap,
|
||||
ArrayMap<String, Integer> pPMap, ArrayMap<String, String> pUMap,
|
||||
ArrayMap<String, String> pCMap) {
|
||||
platformMap = pMap;
|
||||
@ -236,7 +236,10 @@ public class PlatformUtils {
|
||||
if (TextUtils.isEmpty(platformName)) {
|
||||
getPlatform();
|
||||
}
|
||||
return platformName;
|
||||
if (!TextUtils.isEmpty(platformName)) {
|
||||
return platformName;
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
|
||||
public void getPlatform() {
|
||||
|
||||
47
app/src/main/java/com/gh/common/util/PushHelper.kt
Normal file
47
app/src/main/java/com/gh/common/util/PushHelper.kt
Normal file
@ -0,0 +1,47 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import com.gh.gamecenter.receiver.UmengMessageReceiver
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.ResponseBody
|
||||
|
||||
object PushHelper {
|
||||
|
||||
/**
|
||||
* 提交推送点击事件,会尝试从 SP 读取之前失败的一并提交
|
||||
*/
|
||||
@JvmStatic
|
||||
fun postPushClickAction(context: Context, clickEvent: UmengMessageReceiver.ClickEvent? = null) {
|
||||
val clickEventList = arrayListOf<UmengMessageReceiver.ClickEvent>()
|
||||
|
||||
clickEvent?.let { clickEventList.add(it) }
|
||||
|
||||
val failedClickEventList = SPUtils.getString(UmengMessageReceiver.SP_CLICK_EVENT)
|
||||
.toObject<ArrayList<UmengMessageReceiver.ClickEvent>>()
|
||||
|
||||
failedClickEventList?.let { clickEventList.addAll(it) }
|
||||
|
||||
// 没有要提交的事件
|
||||
if (clickEventList.size == 0) return
|
||||
|
||||
val body = RequestBody.create(MediaType.parse("application/json"), clickEventList.toJson())
|
||||
|
||||
RetrofitManager.getInstance(context)
|
||||
.api
|
||||
.postUmengReceiveInfo(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
SPUtils.setString(UmengMessageReceiver.SP_CLICK_EVENT, "")
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
SPUtils.setString(UmengMessageReceiver.SP_CLICK_EVENT, clickEventList.toJson())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -37,12 +37,11 @@ import com.sina.weibo.sdk.WbSdk;
|
||||
import com.sina.weibo.sdk.auth.AuthInfo;
|
||||
import com.tencent.connect.share.QQShare;
|
||||
import com.tencent.connect.share.QzoneShare;
|
||||
import com.tencent.mm.sdk.openapi.IWXAPI;
|
||||
import com.tencent.mm.sdk.openapi.SendMessageToWX;
|
||||
import com.tencent.mm.sdk.openapi.WXAPIFactory;
|
||||
import com.tencent.mm.sdk.openapi.WXMediaMessage;
|
||||
import com.tencent.mm.sdk.openapi.WXWebpageObject;
|
||||
import com.tencent.mm.sdk.platformtools.Util;
|
||||
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
|
||||
import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
|
||||
import com.tencent.mm.opensdk.modelmsg.WXWebpageObject;
|
||||
import com.tencent.mm.opensdk.openapi.IWXAPI;
|
||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
|
||||
import com.tencent.tauth.IUiListener;
|
||||
import com.tencent.tauth.Tencent;
|
||||
import com.tencent.tauth.UiError;
|
||||
@ -251,6 +250,12 @@ public class ShareUtils {
|
||||
//微信好友分享
|
||||
private void wechatShare() {
|
||||
Utils.toast(mContext, R.string.share_skip);
|
||||
|
||||
if (!PackageHelper.INSTANCE.getLocalPackageNameSet().contains("com.tencent.mm")) {
|
||||
Utils.toast(mContext, "没安装微信,分享失败");
|
||||
return;
|
||||
}
|
||||
|
||||
WXWebpageObject webpage = new WXWebpageObject();
|
||||
WXMediaMessage msg = new WXMediaMessage(webpage);
|
||||
webpage.webpageUrl = shareUrl;
|
||||
@ -290,10 +295,10 @@ public class ShareUtils {
|
||||
protected void onNewResultImpl(Bitmap bitmap) {
|
||||
Bitmap compressBp = compressBitmap(bitmap);
|
||||
if (mShareType == ShareType.askNormal || mShareType == ShareType.askInvite) {
|
||||
msg.thumbData = Util.bmpToByteArray(compressBp, true);
|
||||
msg.thumbData = ImageUtils.bmpToByteArray(compressBp, true);
|
||||
} else {
|
||||
Bitmap resultBp = addBackGround(compressBp);
|
||||
msg.thumbData = Util.bmpToByteArray(resultBp, true);
|
||||
msg.thumbData = ImageUtils.bmpToByteArray(resultBp, true);
|
||||
}
|
||||
mIWXAPI.sendReq(req);
|
||||
}
|
||||
@ -387,6 +392,12 @@ public class ShareUtils {
|
||||
//微信朋友圈分享
|
||||
private void wechatMomentsShare() {
|
||||
Utils.toast(mContext, R.string.share_skip);
|
||||
|
||||
if (!PackageHelper.INSTANCE.getLocalPackageNameSet().contains("com.tencent.mm")) {
|
||||
Utils.toast(mContext, "没安装微信,分享失败");
|
||||
return;
|
||||
}
|
||||
|
||||
WXWebpageObject webpage = new WXWebpageObject();
|
||||
WXMediaMessage msg = new WXMediaMessage(webpage);
|
||||
|
||||
|
||||
54
app/src/main/java/com/gh/common/util/SimpleRequestHelper.kt
Normal file
54
app/src/main/java/com/gh/common/util/SimpleRequestHelper.kt
Normal file
@ -0,0 +1,54 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.HttpException
|
||||
|
||||
/**
|
||||
* 可以在此类发送一些无关页面操作的请求
|
||||
*/
|
||||
object SimpleRequestHelper {
|
||||
private val mApi = RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
|
||||
fun reportGameComment(gameId: String, commentId: String, type: String) {
|
||||
val map = HashMap<String, String>()
|
||||
map["reason"] = type
|
||||
mApi.reportGameComment(gameId, commentId, map.createRequestBody())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
Utils.toast(HaloApp.getInstance().application, "感谢您的举报")
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
ErrorHelper.handleError(HaloApp.getInstance().application, e?.response()?.errorBody()?.string())
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
fun reportGameCommentReply(gameId: String, commentId: String, replyId: String, type: String) {
|
||||
val map = HashMap<String, String>()
|
||||
map["reason"] = type
|
||||
mApi.reportGameCommentReply(gameId, commentId, replyId, map.createRequestBody())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ResponseBody>() {
|
||||
override fun onResponse(response: ResponseBody?) {
|
||||
Utils.toast(HaloApp.getInstance().application, "感谢您的举报")
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
ErrorHelper.handleError(HaloApp.getInstance().application, e?.response()?.errorBody()?.string())
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* 用于解决因为沉浸式状态栏(自定义)时键盘不遮挡输入框
|
||||
*/
|
||||
public class SoftInputHidWidgetUtils {
|
||||
private View mChildOfContent;
|
||||
private int usableHeightPrevious;
|
||||
private FrameLayout.LayoutParams frameLayoutParams;
|
||||
private int contentHeight;
|
||||
private boolean isfirst = true;
|
||||
private int statusBarHeight;
|
||||
|
||||
public static void assistActivity(Activity activity) {
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
new SoftInputHidWidgetUtils(activity);
|
||||
}
|
||||
}
|
||||
|
||||
private SoftInputHidWidgetUtils(Activity activity) {
|
||||
statusBarHeight = getStatusBarHeight(activity);
|
||||
FrameLayout content = (FrameLayout)activity.findViewById(android.R.id.content);
|
||||
mChildOfContent = content.getChildAt(0);
|
||||
|
||||
//界面出现变动都会调用这个监听事件
|
||||
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
public void onGlobalLayout() {
|
||||
if (isfirst) {
|
||||
contentHeight = mChildOfContent.getHeight();//兼容华为等机型
|
||||
isfirst = false;
|
||||
}
|
||||
possiblyResizeChildOfContent();
|
||||
}
|
||||
});
|
||||
|
||||
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
|
||||
}
|
||||
|
||||
//重新调整跟布局的高度
|
||||
private void possiblyResizeChildOfContent() {
|
||||
|
||||
int usableHeightNow = computeUsableHeight();
|
||||
//当前可见高度和上一次可见高度不一致 布局变动
|
||||
if (usableHeightNow != usableHeightPrevious) {
|
||||
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
|
||||
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
|
||||
if (heightDifference > (usableHeightSansKeyboard / 4)) {
|
||||
// keyboard probably just became visible
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
|
||||
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference + statusBarHeight;
|
||||
} else {
|
||||
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
|
||||
}
|
||||
} else {
|
||||
frameLayoutParams.height = contentHeight;
|
||||
}
|
||||
mChildOfContent.requestLayout();
|
||||
usableHeightPrevious = usableHeightNow;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取改变之后界面的可用高度(可以为开发者显示内容的高度)
|
||||
* @return
|
||||
*/
|
||||
private int computeUsableHeight() {
|
||||
Rect r = new Rect();
|
||||
mChildOfContent.getWindowVisibleDisplayFrame(r);//获取到的rect就是界面除去标题栏、除去软键盘挡住部分,所剩下的域
|
||||
return (r.bottom - r.top);
|
||||
}
|
||||
|
||||
public static int getStatusBarHeight(Activity activity) {
|
||||
//获取状态栏的高度
|
||||
int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||
return activity.getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
}
|
||||
@ -45,6 +45,16 @@ object SPUtils {
|
||||
return sp.getInt(key, defaultValue)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getLong(key: String, defaultValue: Long): Long {
|
||||
return sp.getLong(key, defaultValue)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setLong(key: String, value: Long) {
|
||||
return sp.edit().putLong(key, value).apply()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setBoolean(key: String, value: Boolean) {
|
||||
sp.edit().putBoolean(key, value).apply()
|
||||
@ -55,6 +65,11 @@ object SPUtils {
|
||||
return sp.getBoolean(key, false)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getBoolean(key: String, defaultValue: Boolean): Boolean {
|
||||
return sp.getBoolean(key, defaultValue)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setString(sp: SharedPreferences, key: String, value: String? = null) {
|
||||
try {
|
||||
|
||||
56
app/src/main/java/com/gh/common/util/TextHelper.kt
Normal file
56
app/src/main/java/com/gh/common/util/TextHelper.kt
Normal file
@ -0,0 +1,56 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.text.Editable
|
||||
import android.text.InputFilter
|
||||
import android.text.TextWatcher
|
||||
import android.widget.EditText
|
||||
import com.gh.gamecenter.R
|
||||
|
||||
object TextHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun limitTheLengthOfEditText(editText: EditText, length: Int, exceedCallback: ExceedTextLengthLimitCallback? = null) {
|
||||
editText.addTextChangedListener(object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
val tvCount = editText.text.toString().length
|
||||
if (tvCount > length) {
|
||||
val str = editText.text.toString().substring(0, length)
|
||||
editText.setText(str)
|
||||
editText.setSelection(str.length)
|
||||
if (!ClickUtils.isFastDoubleClick(R.id.userinfo_nickname_et, 2000)) {
|
||||
exceedCallback?.onExceed()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getFilter(maxLength: Int, msg: String)//限制最大长度-Toast弹窗提示
|
||||
: InputFilter {
|
||||
return InputFilter { source, start, end, dest, dstart, dend ->
|
||||
val keep = maxLength - (dest.length - (dend - dstart))
|
||||
if (keep < end - start) {
|
||||
ToastUtils.showToast(msg)
|
||||
}
|
||||
when {
|
||||
keep <= 0 -> ""
|
||||
keep >= end - start -> null
|
||||
else -> source.subSequence(start, start + keep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ExceedTextLengthLimitCallback {
|
||||
fun onExceed()
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.gh.common.util
|
||||
|
||||
/**
|
||||
* 第三方安装包(即安装包里没有 gh-id)的辅助类
|
||||
*/
|
||||
object ThirdPartyPackageHelper {
|
||||
|
||||
private const val PREFIX = "third_party_package"
|
||||
|
||||
@JvmStatic
|
||||
fun saveGameId(packageName: String, gameId: String) {
|
||||
SPUtils.setString(PREFIX + packageName, gameId)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getGameId(packageName: String): String {
|
||||
return SPUtils.getString(PREFIX + packageName, "")!!
|
||||
}
|
||||
|
||||
}
|
||||
40
app/src/main/java/com/gh/common/util/ToastUtils.kt
Normal file
40
app/src/main/java/com/gh/common/util/ToastUtils.kt
Normal file
@ -0,0 +1,40 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.widget.Toast
|
||||
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
object ToastUtils {
|
||||
/** 之前显示的内容 */
|
||||
private var mOldMsg: String? = null
|
||||
/** Toast对象 */
|
||||
private var mToast: Toast? = null
|
||||
/** 第一次时间 */
|
||||
private var mOneTime: Long = 0
|
||||
/** 第二次时间 */
|
||||
private var mTwoTime: Long = 0
|
||||
|
||||
/**
|
||||
* 显示Toast
|
||||
* @param message
|
||||
*/
|
||||
fun showToast(message: String) {
|
||||
if (mToast == null) {
|
||||
mToast = Toast.makeText(HaloApp.getInstance().application, message, Toast.LENGTH_SHORT)
|
||||
mToast!!.show()
|
||||
mOneTime = System.currentTimeMillis()
|
||||
} else {
|
||||
mTwoTime = System.currentTimeMillis()
|
||||
if (message == mOldMsg) {
|
||||
if (mTwoTime - mOneTime > Toast.LENGTH_SHORT) {
|
||||
mToast!!.show()
|
||||
}
|
||||
} else {
|
||||
mOldMsg = message
|
||||
mToast!!.setText(message)
|
||||
mToast!!.show()
|
||||
}
|
||||
}
|
||||
mOneTime = mTwoTime
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.BitmapFactory
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.FileRequestBody
|
||||
@ -17,6 +18,8 @@ import okhttp3.MultipartBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
|
||||
object UploadImageUtils {
|
||||
|
||||
@ -27,7 +30,7 @@ object UploadImageUtils {
|
||||
icon
|
||||
}
|
||||
|
||||
// 不处理图片,只是单纯的上次
|
||||
// 不处理图片,只是单纯的上传
|
||||
fun uploadImage(type: UploadType, imgPath: String, listener: OnUploadImageListener): Disposable {
|
||||
return Single.just(imgPath)
|
||||
.subscribeOn(Schedulers.computation())
|
||||
@ -99,8 +102,10 @@ object UploadImageUtils {
|
||||
})
|
||||
}
|
||||
|
||||
fun compressAndUploadImageList(type: UploadType, imgs: List<String>, compressGif: Boolean, listener: OnUploadImageListListener) {
|
||||
val postImageList = HashMap<String, String>()
|
||||
@SuppressLint("CheckResult")
|
||||
fun compressAndUploadImageList(type: UploadType, imgs: List<String>, compressGif: Boolean, listener: OnUploadImageListListener): Disposable? {
|
||||
var subscription: Disposable? = null
|
||||
val postImageList = LinkedHashMap<String, String>()
|
||||
|
||||
Observable.create(ObservableOnSubscribe<Map<String, String>> {
|
||||
val compressList = compressImageList(imgs, compressGif)
|
||||
@ -110,9 +115,12 @@ object UploadImageUtils {
|
||||
listTotal += img.length()
|
||||
}
|
||||
for (img in compressList) {
|
||||
if (subscription?.isDisposed == true) return@ObservableOnSubscribe
|
||||
val requestBody = FileRequestBody<ResponseBody>(img, object : RetrofitCallback<ResponseBody>() {
|
||||
override fun onProgress(total: Long, progress: Long) {
|
||||
listener.onProgress(listTotal, listProgress + progress)
|
||||
if (subscription?.isDisposed != true) {
|
||||
listener.onProgress(listTotal, listProgress + progress)
|
||||
}
|
||||
}
|
||||
})
|
||||
val part = MultipartBody.Part.createFormData("Filedata", getFileName(img), requestBody)
|
||||
@ -120,11 +128,12 @@ object UploadImageUtils {
|
||||
.uploadApi.uploadImage(part, type.name)
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
if (subscription?.isDisposed == true) return
|
||||
val string = data.string()
|
||||
if (!string.isNullOrEmpty()) {
|
||||
val url = JSONObject(string).getString("url")
|
||||
if (!url.isNullOrEmpty()) {
|
||||
val map = HashMap<String, String>()
|
||||
val map = LinkedHashMap<String, String>()
|
||||
map[img.path] = url
|
||||
it.onNext(map)
|
||||
return
|
||||
@ -134,7 +143,10 @@ object UploadImageUtils {
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
it.onError(exception)
|
||||
// 若遇到错误且 subscription?.isDisposed 为 true 时会抛出 io.reactivex.exceptions.UndeliverableException 异常
|
||||
// if (subscription?.isDisposed == true) return
|
||||
// it.onError(exception) // fuck
|
||||
it.onNext(Collections.emptyMap())
|
||||
}
|
||||
})
|
||||
listProgress += img.length()
|
||||
@ -143,8 +155,9 @@ object UploadImageUtils {
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Observer<Map<String, String>> {
|
||||
.subscribe(object : Observer<Map<String, String>?> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
subscription = d
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
@ -156,12 +169,14 @@ object UploadImageUtils {
|
||||
}
|
||||
|
||||
override fun onNext(t: Map<String, String>) {
|
||||
postImageList.putAll(t)
|
||||
if (!t.isEmpty()) postImageList.putAll(t)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
})
|
||||
return subscription
|
||||
}
|
||||
|
||||
// 同步调用->避免在主线程调用以免阻塞主线程
|
||||
@ -196,7 +211,7 @@ object UploadImageUtils {
|
||||
}
|
||||
|
||||
interface OnUploadImageListListener {
|
||||
fun onSuccess(imageUrl: Map<String, String>) // key:sourceImage value:compressImage
|
||||
fun onSuccess(imageUrl: LinkedHashMap<String, String>) // key:sourceImage value:compressImage
|
||||
fun onError() // 全部上传失败时回调
|
||||
fun onProgress(total: Long, progress: Long)
|
||||
}
|
||||
|
||||
@ -1,33 +1,44 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.databinding.DataBindingUtil;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v4.view.ViewPager.OnPageChangeListener;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.util.ClickUtils;
|
||||
import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.OnCollectionCallBackListener;
|
||||
import com.gh.gamecenter.adapter.PlatformPagerAdapter;
|
||||
import com.gh.gamecenter.databinding.ImprintContentItemBinding;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.ApkLink;
|
||||
import com.gh.gamecenter.entity.GameCollectionEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.eventbus.EBPackage;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
@ -56,21 +67,35 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* @des 弹出游戏版本下载按钮,点击并添加到下载任务中
|
||||
*/
|
||||
public class DownloadDialog implements OnCollectionCallBackListener {
|
||||
|
||||
private static DownloadDialog instance;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
private boolean isShow;
|
||||
private PopupWindow popupWindow;
|
||||
private List<ApkEntity> gameApk;
|
||||
private GameEntity gameEntity;
|
||||
|
||||
private ViewPager viewPager;
|
||||
private PlatformPagerAdapter adapter;
|
||||
private ViewPager collectionViewPager;
|
||||
private LinearLayout dialog_ll_collection_hint;
|
||||
private LinearLayout dialog_ll_hint;
|
||||
private LinearLayout dialog_ll_collection;
|
||||
private ViewPager collectionViewPager;
|
||||
private View mDialogMorePlatformHint;
|
||||
|
||||
private List<ApkEntity> gameApk;
|
||||
private GameEntity gameEntity;
|
||||
|
||||
private PlatformPagerAdapter adapter;
|
||||
private PlatformPagerAdapter collectionAdapter;
|
||||
|
||||
private ExposureEvent traceEvent;
|
||||
|
||||
private static final String DOWNLOAD_PLATFORM_HINT = "download_platform_hint";
|
||||
|
||||
private String entrance;
|
||||
private String location;
|
||||
private String mAutoDownloadPlatform;
|
||||
|
||||
private final int row = 3;
|
||||
private final int column = 3;
|
||||
private boolean isLoadPlatform;
|
||||
|
||||
private DataWatcher dataWatcher = new DataWatcher() {
|
||||
@Override
|
||||
public void onDataChanged(DownloadEntity downloadEntity) {
|
||||
@ -85,25 +110,13 @@ public class DownloadDialog implements OnCollectionCallBackListener {
|
||||
}
|
||||
}
|
||||
};
|
||||
private LinearLayout dialog_ll_collection_hint;
|
||||
private String entrance;
|
||||
private String location;
|
||||
private ExposureEvent traceEvent;
|
||||
private String mAutoDownloadPlatform;
|
||||
private final int row = 3;
|
||||
private final int column = 3;
|
||||
private boolean isLoadPlatform;
|
||||
|
||||
private DownloadDialog() {
|
||||
isShow = false;
|
||||
private DownloadDialog(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public static DownloadDialog getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
instance = new DownloadDialog();
|
||||
}
|
||||
instance.mContext = context; // 每次创建context重新赋值, Dialog持有context问题
|
||||
return instance;
|
||||
return new DownloadDialog(context);
|
||||
}
|
||||
|
||||
// 自动下载并翻到相应页面
|
||||
@ -119,13 +132,9 @@ public class DownloadDialog implements OnCollectionCallBackListener {
|
||||
|
||||
public void showPopupWindow(View view, GameEntity gameEntity, String entrance, String location,
|
||||
@Nullable ExposureEvent traceEvent) {
|
||||
if (isShow && (popupWindow == null || !popupWindow.isShowing())) {
|
||||
isShow = false;
|
||||
}
|
||||
if (isShow) {
|
||||
if (ClickUtils.isFastDoubleClick()) {
|
||||
return;
|
||||
}
|
||||
isShow = true;
|
||||
|
||||
this.gameEntity = gameEntity;
|
||||
this.entrance = entrance;
|
||||
@ -146,14 +155,39 @@ public class DownloadDialog implements OnCollectionCallBackListener {
|
||||
// 一个自定义的布局,作为显示的内容
|
||||
View contentView = View.inflate(mContext, R.layout.game_download_dialog, null);
|
||||
|
||||
TextView title = (TextView) contentView.findViewById(R.id.dialog_title);
|
||||
TextView title = contentView.findViewById(R.id.dialog_title);
|
||||
title.setText(gameEntity.getName());
|
||||
|
||||
viewPager = (ViewPager) contentView.findViewById(R.id.dialog_viewPager);
|
||||
dialog_ll_hint = (LinearLayout) contentView.findViewById(R.id.dialog_ll_hint);
|
||||
dialog_ll_collection = (LinearLayout) contentView.findViewById(R.id.dialog_ll_collection);
|
||||
dialog_ll_collection_hint = (LinearLayout) contentView.findViewById(R.id.dialog_ll_collection_hint);
|
||||
collectionViewPager = (ViewPager) contentView.findViewById(R.id.dialog_collection_viewPager);
|
||||
viewPager = contentView.findViewById(R.id.dialog_viewPager);
|
||||
dialog_ll_hint = contentView.findViewById(R.id.dialog_ll_hint);
|
||||
dialog_ll_collection = contentView.findViewById(R.id.dialog_ll_collection);
|
||||
dialog_ll_collection_hint = contentView.findViewById(R.id.dialog_ll_collection_hint);
|
||||
collectionViewPager = contentView.findViewById(R.id.dialog_collection_viewPager);
|
||||
mDialogMorePlatformHint = contentView.findViewById(R.id.dialog_more_platform_hit);
|
||||
TextView dialogAd = contentView.findViewById(R.id.dialog_ad);
|
||||
TextView dialogAdMirror = contentView.findViewById(R.id.dialog_ad_mirror);
|
||||
mDialogMorePlatformHint.setOnClickListener(v -> {
|
||||
mDialogMorePlatformHint.setVisibility(View.GONE);
|
||||
SPUtils.setBoolean(DOWNLOAD_PLATFORM_HINT, false);
|
||||
});
|
||||
|
||||
LinkEntity downloadAd = gameEntity.getDownloadAd();
|
||||
if (downloadAd != null) {
|
||||
dialogAd.setVisibility(View.VISIBLE);
|
||||
dialogAd.setText(downloadAd.getTitle());
|
||||
dialogAdMirror.setVisibility(View.INVISIBLE);
|
||||
dialogAdMirror.setText(downloadAd.getTitle());
|
||||
dialogAd.setOnClickListener(v -> {
|
||||
if ("imprint".equals(downloadAd.getType())) {
|
||||
showImprintDialog(downloadAd.getTitle());
|
||||
} else {
|
||||
DirectUtils.directToLinkPage(
|
||||
mContext,
|
||||
downloadAd,
|
||||
entrance, "下载多平台弹窗");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isLoadPlatform = false;
|
||||
|
||||
@ -164,32 +198,20 @@ public class DownloadDialog implements OnCollectionCallBackListener {
|
||||
popupWindow = new PopupWindow(contentView, LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.MATCH_PARENT, true);
|
||||
|
||||
contentView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
popupWindow.dismiss();
|
||||
}
|
||||
});
|
||||
contentView.setOnClickListener(v -> popupWindow.dismiss());
|
||||
contentView.setFocusable(true);
|
||||
contentView.setFocusableInTouchMode(true);
|
||||
contentView.setOnKeyListener(new View.OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0
|
||||
&& popupWindow != null && popupWindow.isShowing()) {
|
||||
popupWindow.dismiss();
|
||||
}
|
||||
return false;
|
||||
contentView.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0
|
||||
&& popupWindow != null && popupWindow.isShowing()) {
|
||||
popupWindow.dismiss();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss() {
|
||||
isShow = false;
|
||||
EventBus.getDefault().unregister(DownloadDialog.this);
|
||||
DownloadManager.getInstance(mContext).removeObserver(dataWatcher);
|
||||
}
|
||||
popupWindow.setOnDismissListener(() -> {
|
||||
EventBus.getDefault().unregister(DownloadDialog.this);
|
||||
DownloadManager.getInstance(mContext).removeObserver(dataWatcher);
|
||||
});
|
||||
|
||||
popupWindow.setTouchable(true);
|
||||
@ -208,6 +230,51 @@ public class DownloadDialog implements OnCollectionCallBackListener {
|
||||
DownloadManager.getInstance(mContext).addObserver(dataWatcher);
|
||||
}
|
||||
|
||||
private void showImprintDialog(String titleName) {
|
||||
Dialog dialog = new Dialog(mContext, R.style.full_dialog);
|
||||
View inflate = LayoutInflater.from(mContext).inflate(R.layout.imprint_dialog, null);
|
||||
dialog.setContentView(inflate);
|
||||
dialog.show();
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
WindowManager.LayoutParams params;
|
||||
if (window != null) {
|
||||
params = window.getAttributes();
|
||||
params.width = (int) (mContext.getResources().getDisplayMetrics().widthPixels * 0.9);
|
||||
window.setAttributes(params);
|
||||
window.setBackgroundDrawableResource(R.drawable.full_dialog_background);
|
||||
}
|
||||
|
||||
inflate.findViewById(R.id.imprint_close).setOnClickListener(v -> dialog.dismiss());
|
||||
LinearLayout content = inflate.findViewById(R.id.imprint_content);
|
||||
((TextView) inflate.findViewById(R.id.imprint_title)).setText(titleName);
|
||||
View head = LayoutInflater.from(mContext).inflate(R.layout.imprint_content_item, null);
|
||||
content.addView(head, LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(30));
|
||||
LimitHeightLinearLayout imprintContainer = inflate.findViewById(R.id.imprint_container);
|
||||
imprintContainer.setLimitHeight((int) (mContext.getResources().getDisplayMetrics().heightPixels * 0.8));
|
||||
|
||||
ArrayList<ApkEntity> list = gameEntity.getApk();
|
||||
SettingsEntity settings = Config.getSettings();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ApkEntity apk = gameEntity.getApk().get(i);
|
||||
if (settings != null && settings.getGameDownloadBlackList().contains(apk.getPackageName())) {
|
||||
continue;
|
||||
}
|
||||
View item = LayoutInflater.from(mContext).inflate(R.layout.imprint_content_item, null);
|
||||
ImprintContentItemBinding bind = DataBindingUtil.bind(item);
|
||||
bind.setApk(apk);
|
||||
bind.setPlatformName(PlatformUtils.getInstance(mContext).getPlatformName(apk.getPlatform()));
|
||||
content.addView(item, LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(40));
|
||||
}
|
||||
|
||||
|
||||
// close line
|
||||
View view = new View(mContext);
|
||||
view.setBackgroundColor(mContext.getResources().getColor(R.color.text_5d5d5d));
|
||||
view.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(1)));
|
||||
content.addView(view);
|
||||
}
|
||||
|
||||
private void sortApk() {
|
||||
for (ApkEntity apkEntity : gameApk) {
|
||||
GameCollectionEntity apkCollection = apkEntity.getApkCollection();
|
||||
@ -388,6 +455,13 @@ public class DownloadDialog implements OnCollectionCallBackListener {
|
||||
int size = (int) Math.ceil(apkList.size() / (double) (row * column));
|
||||
addHintPoint(dialog_ll_hint, size);
|
||||
|
||||
if (size >= 2) {
|
||||
boolean isShowPlatformHint = SPUtils.getBoolean(DOWNLOAD_PLATFORM_HINT, true);
|
||||
if (isShowPlatformHint) {
|
||||
mDialogMorePlatformHint.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
int count = apkList.size();
|
||||
int vpHeight;
|
||||
if (count <= 3) {
|
||||
|
||||
@ -8,9 +8,11 @@ import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ProgressBar;
|
||||
@ -37,6 +39,8 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
|
||||
private PorterDuffXfermode mDuffXFerMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
|
||||
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
// 仅用于测量文字是否超出范围,不用于画文字
|
||||
private TextPaint mFakeTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
private DownloadType mDownloadType;
|
||||
|
||||
@ -46,6 +50,8 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
private int mDefaultColor;
|
||||
private int mTextSize;
|
||||
|
||||
private Rect mTextBound = new Rect();
|
||||
|
||||
public DownloadProgressBar(Context context) {
|
||||
super(context);
|
||||
}
|
||||
@ -79,6 +85,9 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
|
||||
mPaint.setColor(mDefaultColor == 0 ? ContextCompat.getColor(getContext(), R.color.theme) : mDefaultColor); // 初始化颜色
|
||||
mPaint.setTextSize(mTextSize);
|
||||
mFakeTextPaint.setTextSize(mTextSize);
|
||||
mFakeTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
mFakeTextPaint.setTextAlign(Paint.Align.CENTER);
|
||||
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
mPaint.setXfermode(null);
|
||||
create();
|
||||
@ -87,9 +96,13 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
int baseline = (getHeight() - fontMetrics.bottom - fontMetrics.top) / 2;
|
||||
|
||||
mPaint.setTextAlign(Paint.Align.CENTER);
|
||||
srcCanvas.drawText(mText, getWidth() / 2, baseline, mPaint);
|
||||
|
||||
canvas.getClipBounds(mTextBound); //The dimensions of your canvas
|
||||
int width = mTextBound.width() - 20; //10 to keep some space on the right for the "..."
|
||||
String txt = TextUtils.ellipsize(mText, mFakeTextPaint, width, TextUtils.TruncateAt.END).toString();
|
||||
srcCanvas.drawText(txt, getWidth() / 2, baseline, mPaint);
|
||||
mPaint.setXfermode(mDuffXFerMode);
|
||||
if (getProgress() != 0 && getProgress() != MAX_LENGTH) {
|
||||
if (getProgress() != 0) {
|
||||
mPaint.setColor(DOWNLOAD_IMAGE_STYLE == mDownloadStyle ? Color.BLACK : Color.WHITE); // 反向颜色
|
||||
}
|
||||
|
||||
@ -108,7 +121,6 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
|
||||
public void setText(@StringRes int res) {
|
||||
setText(getResources().getString(res));
|
||||
invalidate(); // 文字绘制没有同步 就重绘多几遍吧 虽然不知到有没有用
|
||||
}
|
||||
|
||||
public void setDownloadType(DownloadType downloadType) {
|
||||
|
||||
@ -10,8 +10,13 @@ object DrawableView {
|
||||
|
||||
@JvmStatic
|
||||
fun getServerDrawable(colorCode: String): Drawable {
|
||||
return getServerDrawable(Color.parseColor(colorCode))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getServerDrawable(colorCode: Int): Drawable {
|
||||
val drawable = GradientDrawable()
|
||||
drawable.setColor(Color.parseColor(colorCode))
|
||||
drawable.setColor(colorCode)
|
||||
drawable.cornerRadius = DisplayUtils.dip2px(2F).toFloat()
|
||||
return drawable
|
||||
}
|
||||
|
||||
@ -89,7 +89,9 @@ public class ExpendTextView extends android.support.v7.widget.AppCompatTextView
|
||||
}
|
||||
SpannableStringBuilder msp = new SpannableStringBuilder(content);
|
||||
int length = msp.length();
|
||||
msp.replace(length - mExpendText.length(), length, mExpendText);
|
||||
int startPosition = length - mExpendText.length();
|
||||
startPosition = startPosition < 0 ? 0 : startPosition;
|
||||
msp.replace(startPosition, length, mExpendText);
|
||||
msp.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(TextPaint ds) {
|
||||
@ -108,12 +110,18 @@ public class ExpendTextView extends android.support.v7.widget.AppCompatTextView
|
||||
mExpandCallback.onExpand();
|
||||
}
|
||||
}
|
||||
}, length - mExpendText.length(), length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}, startPosition, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
setText(msp);
|
||||
setMovementMethod(CustomLinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
|
||||
public void setExpendMaxLines(int maxLines) {
|
||||
mMaxLines = maxLines;
|
||||
setMaxLines(maxLines);
|
||||
}
|
||||
|
||||
public interface ExpandCallback {
|
||||
void onExpand();
|
||||
}
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
/**
|
||||
* Created by khy on 2/04/18.
|
||||
*/
|
||||
|
||||
public class LimitHeightLinearLayout extends LinearLayout {
|
||||
|
||||
private int mLimitHeight;
|
||||
|
||||
public LimitHeightLinearLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LimitHeightLinearLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
if (attrs != null) {
|
||||
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LimitHeightScrollView);
|
||||
mLimitHeight = ta.getDimensionPixelSize(R.styleable.LimitHeightScrollView_maxHeight, DisplayUtils.dip2px(getContext(), 240));
|
||||
ta.recycle();
|
||||
} else {
|
||||
mLimitHeight = DisplayUtils.dip2px(getContext(), 240);
|
||||
}
|
||||
}
|
||||
|
||||
public LimitHeightLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
if (heightMode == MeasureSpec.EXACTLY
|
||||
|| heightMode == MeasureSpec.AT_MOST
|
||||
|| heightMode == MeasureSpec.UNSPECIFIED) {
|
||||
heightSize = heightSize <= mLimitHeight ? heightSize
|
||||
: mLimitHeight;
|
||||
}
|
||||
int maxHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize,
|
||||
heightMode);
|
||||
super.onMeasure(widthMeasureSpec, maxHeightMeasureSpec);
|
||||
}
|
||||
|
||||
public void setLimitHeight(int limitHeight) {
|
||||
mLimitHeight = limitHeight;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
//package com.gh.common.view;
|
||||
//
|
||||
//import android.content.Context;
|
||||
//import android.support.v7.widget.LinearLayoutManager;
|
||||
//import android.support.v7.widget.RecyclerView;
|
||||
//import android.view.View;
|
||||
//import android.view.ViewGroup;
|
||||
//
|
||||
///**
|
||||
// * Created by khy on 2017/3/30.
|
||||
// */
|
||||
//public class MeasureLinearLayoutManager extends LinearLayoutManager {
|
||||
// int height;
|
||||
// private int[] mMeasuredDimension = new int[1];
|
||||
//
|
||||
// public MeasureLinearLayoutManager(Context context) {
|
||||
// super(context);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
|
||||
// int widthSpec, int heightSpec) {
|
||||
// super.onMeasure(recycler, state, widthSpec, heightSpec);
|
||||
// height = 0;
|
||||
//
|
||||
// try {
|
||||
// for (int i = 0; i < getItemCount(); i++) {
|
||||
// measureScrapChild(recycler, i,
|
||||
// View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
|
||||
// View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
|
||||
// mMeasuredDimension);
|
||||
// height = height + mMeasuredDimension[0];
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
|
||||
// int heightSpec, int[] measuredDimension) throws Exception {
|
||||
// View view = recycler.getViewForPosition(position);
|
||||
// if (view.getVisibility() == View.GONE) {
|
||||
// measuredDimension[0] = 0;
|
||||
// return;
|
||||
// }
|
||||
// super.measureChildWithMargins(view, 0, 0);
|
||||
// RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
|
||||
// int childHeightSpec = ViewGroup.getChildMeasureSpec(
|
||||
// heightSpec,
|
||||
// getPaddingTop() + getPaddingBottom() + getDecoratedTop(view) + getDecoratedBottom(view),
|
||||
// p.height);
|
||||
//
|
||||
// view.measure(0, childHeightSpec);
|
||||
// measuredDimension[0] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin;
|
||||
// recycler.recycleView(view);
|
||||
// }
|
||||
//
|
||||
// public int getRvHeight() {
|
||||
// return height;
|
||||
// }
|
||||
//}
|
||||
@ -0,0 +1,134 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class MessageSpannableTextView extends android.support.v7.widget.AppCompatTextView {
|
||||
|
||||
private OnSpannableClickListener mSpannableClickListener;
|
||||
|
||||
private final String mStartMarkKey = "{{";
|
||||
private final String mEndMarkKey = "}}";
|
||||
|
||||
private List<MarkData> mMarkList;
|
||||
|
||||
public MessageSpannableTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public MessageSpannableTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mMarkList = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
if (TextUtils.isEmpty(text) ||
|
||||
!text.toString().contains(mStartMarkKey) && !text.toString().contains(mEndMarkKey)) {
|
||||
super.setText(text, type);
|
||||
return;
|
||||
}
|
||||
|
||||
mMarkList.clear();
|
||||
String sText = text.toString();
|
||||
String[] split = sText.split("\\}\\}");
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
String s = split[i];
|
||||
int p = s.lastIndexOf(mStartMarkKey);
|
||||
if (p != -1) {
|
||||
MarkData markData = new MarkData();
|
||||
String substring = s.substring(p);
|
||||
String content = s.replace(substring, "");
|
||||
builder.append(content);
|
||||
markData.setStart(builder.length() + 1);
|
||||
|
||||
String key = substring.replace(mStartMarkKey, " ") + " ";
|
||||
builder.append(key);
|
||||
markData.setEnd(builder.length() - 1);
|
||||
markData.setKey(key);
|
||||
|
||||
mMarkList.add(markData);
|
||||
} else {
|
||||
builder.append(s);
|
||||
if (i != split.length - 1 || sText.substring(sText.length() - 2, sText.length()).equals("}}")) {
|
||||
builder.append("}}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpannableStringBuilder msp = new SpannableStringBuilder(builder);
|
||||
for (MarkData markData : mMarkList) {
|
||||
msp.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setColor(getContext().getResources().getColor(R.color.tag_orange));
|
||||
ds.setUnderlineText(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
if (mSpannableClickListener != null) {
|
||||
mSpannableClickListener.onClick(markData.getKey().trim());
|
||||
}
|
||||
}
|
||||
}, markData.getStart(), markData.getEnd(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
}
|
||||
|
||||
setMovementMethod(CustomLinkMovementMethod.getInstance());
|
||||
super.setText(msp, type);
|
||||
}
|
||||
|
||||
public void setOnSpannableClickListener(OnSpannableClickListener spannableClickListener) {
|
||||
this.mSpannableClickListener = spannableClickListener;
|
||||
}
|
||||
|
||||
|
||||
public interface OnSpannableClickListener {
|
||||
void onClick(String spannableText);
|
||||
}
|
||||
|
||||
class MarkData {
|
||||
private int start;
|
||||
private int end;
|
||||
private String key;
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public int getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(int end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,18 +3,13 @@ package com.gh.common.view
|
||||
import android.content.Context
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
import android.media.AudioManager
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import cn.jzvd.JZDataSource
|
||||
import cn.jzvd.JZUtils
|
||||
import cn.jzvd.Jzvd
|
||||
import cn.jzvd.JzvdStd
|
||||
import cn.jzvd.*
|
||||
import com.gh.common.observer.MuteCallback
|
||||
import com.gh.common.observer.VolumeObserver
|
||||
import com.gh.common.util.DialogUtils
|
||||
@ -60,12 +55,12 @@ class PlayerView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
if (v.id == R.id.start || v.id == R.id.thumb) {
|
||||
if (Jzvd.CURRENT_STATE_PLAYING != currentState) {
|
||||
if ((currentScreen == SCREEN_WINDOW_NORMAL || currentScreen == SCREEN_WINDOW_LIST)) {
|
||||
MtaHelper.onEvent("游戏详情", "视频_点击播放", gameName)
|
||||
MtaHelper.onEvent("游戏详情_新", "视频_点击播放", gameName)
|
||||
} else {
|
||||
MtaHelper.onEvent("游戏详情", "视频全屏_点击播放", gameName)
|
||||
MtaHelper.onEvent("游戏详情_新", "视频全屏_点击播放", gameName)
|
||||
}
|
||||
} else {
|
||||
MtaHelper.onEvent("游戏详情", "视频_点击暂停", gameName)
|
||||
MtaHelper.onEvent("游戏详情_新", "视频_点击暂停", gameName)
|
||||
}
|
||||
|
||||
if (showAlertDialogForTheFistTime
|
||||
@ -86,7 +81,7 @@ class PlayerView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
Jzvd.FULLSCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
JZUtils.setRequestedOrientation(context, Jzvd.FULLSCREEN_ORIENTATION)
|
||||
}
|
||||
MtaHelper.onEvent("游戏详情", "视频全屏_点击旋转", gameName)
|
||||
MtaHelper.onEvent("游戏详情_新", "视频全屏_点击旋转", gameName)
|
||||
}
|
||||
R.id.mute -> {
|
||||
toggleMute()
|
||||
@ -101,6 +96,10 @@ class PlayerView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
|
||||
private fun toggleMute() {
|
||||
HaloApp.getInstance().isMute = !HaloApp.getInstance().isMute
|
||||
updateMuteStatus()
|
||||
}
|
||||
|
||||
private fun updateMuteStatus() {
|
||||
if (HaloApp.getInstance().isMute) {
|
||||
mute()
|
||||
} else {
|
||||
@ -124,26 +123,22 @@ class PlayerView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
|
||||
private fun mute() {
|
||||
muteIv.setImageResource(R.drawable.ic_volume_off)
|
||||
// 安卓 6.0 以上 toggle 静音接口,以下将声音置为 0% 或 60%
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
mAudioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_MUTE, 0)
|
||||
} else {
|
||||
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0)
|
||||
try {
|
||||
JZMediaManager.instance()?.jzMediaInterface?.setVolume(0f, 0f)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
MtaHelper.onEvent("游戏详情", "视频_点击静音", gameName)
|
||||
MtaHelper.onEvent("游戏详情_新", "视频_点击静音", gameName)
|
||||
}
|
||||
|
||||
private fun unmute() {
|
||||
muteIv.setImageResource(R.drawable.ic_volume_on)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
mAudioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_UNMUTE, 0)
|
||||
} else {
|
||||
mAudioManager.setStreamVolume(
|
||||
AudioManager.STREAM_MUSIC,
|
||||
60 * mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
|
||||
0)
|
||||
try {
|
||||
JZMediaManager.instance()?.jzMediaInterface?.setVolume(1.0f, 1.0f)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
MtaHelper.onEvent("游戏详情", "视频_解除静音", gameName)
|
||||
MtaHelper.onEvent("游戏详情_新", "视频_解除静音", gameName)
|
||||
}
|
||||
|
||||
override fun onStatePlaying() {
|
||||
@ -154,6 +149,11 @@ class PlayerView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStatePrepared() {
|
||||
super.onStatePrepared()
|
||||
updateMuteStatus()
|
||||
}
|
||||
|
||||
override fun onClickUiToggle() {
|
||||
// 仅在全屏状态下才会 toggle 播放信息
|
||||
if (currentScreen == Jzvd.SCREEN_WINDOW_FULLSCREEN) {
|
||||
@ -204,11 +204,7 @@ class PlayerView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
rotateIv.visibility = View.GONE
|
||||
|
||||
// 将右下角的按钮变成静音与否
|
||||
if (HaloApp.getInstance().isMute) {
|
||||
mute()
|
||||
} else {
|
||||
unmute()
|
||||
}
|
||||
updateMuteStatus()
|
||||
} else {
|
||||
progressBar.visibility = View.VISIBLE
|
||||
totalTimeTextView.visibility = View.VISIBLE
|
||||
@ -257,7 +253,7 @@ class PlayerView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
if (currentScreen == SCREEN_WINDOW_NORMAL || currentScreen == SCREEN_WINDOW_LIST) {
|
||||
progressBar.visibility = View.INVISIBLE
|
||||
totalTimeTextView.visibility = View.INVISIBLE
|
||||
MtaHelper.onEvent("游戏详情", "视频全屏_点击后退", gameName)
|
||||
MtaHelper.onEvent("游戏详情_新", "视频全屏_点击后退", gameName)
|
||||
} else {
|
||||
progressBar.visibility = View.VISIBLE
|
||||
totalTimeTextView.visibility = View.VISIBLE
|
||||
@ -267,7 +263,7 @@ class PlayerView @JvmOverloads constructor(context: Context, attrs: AttributeSet
|
||||
override fun startWindowFullscreen() {
|
||||
super.startWindowFullscreen()
|
||||
unmute()
|
||||
MtaHelper.onEvent("游戏详情", "视频_点击进入全屏", gameName)
|
||||
MtaHelper.onEvent("游戏详情_新", "视频_点击进入全屏", gameName)
|
||||
}
|
||||
|
||||
override fun startDismissControlViewTimer() {
|
||||
|
||||
@ -13,12 +13,14 @@ import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import com.gh.common.util.AskUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.HtmlUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.RichEditorUtils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.qa.entity.EditorInsertEntity;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
@ -90,6 +92,7 @@ public class RichEditor extends WebView {
|
||||
private static final String SETUP_HTML = "file:///android_asset/editor.html";
|
||||
private static final String CALLBACK_SCHEME = "re-callback://";
|
||||
private static final String STATE_SCHEME = "re-state://";
|
||||
|
||||
private boolean isReady = false;
|
||||
private String mContents;
|
||||
private OnTextChangeListener mTextChangeListener;
|
||||
@ -122,11 +125,12 @@ public class RichEditor extends WebView {
|
||||
getSettings().setJavaScriptEnabled(true);
|
||||
setWebChromeClient(new WebChromeClient()); // 不要重写这个方法否则无法加载
|
||||
setWebViewClient(createWebViewClient());
|
||||
// 临时开启让 H5 同事调试
|
||||
if (BuildConfig.DEBUG && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
|
||||
setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
loadUrl(SETUP_HTML);
|
||||
|
||||
loadUrl(SETUP_HTML);
|
||||
applyAttributes(context, attrs);
|
||||
}
|
||||
|
||||
@ -213,7 +217,6 @@ public class RichEditor extends WebView {
|
||||
}
|
||||
// getSettings().setBlockNetworkImage(true); // 先不加载网络图片,因为后面有资源替换操作防止流量无故丢失
|
||||
|
||||
// contents = contents.replace("src=", "class=\"lazy\" data-src=");
|
||||
try {
|
||||
exec("javascript:RE.setHtml('" + URLEncoder.encode(contents, "UTF-8") + "');");
|
||||
|
||||
@ -226,7 +229,6 @@ public class RichEditor extends WebView {
|
||||
replaceAllDfImageExcludeGif();
|
||||
}
|
||||
exec("javascript:RE.ImageClickListener()");
|
||||
// exec("javascript:RE.lazyLoad()");
|
||||
}
|
||||
|
||||
callback(contents);
|
||||
@ -234,6 +236,8 @@ public class RichEditor extends WebView {
|
||||
// No handling
|
||||
}
|
||||
mContents = contents;
|
||||
|
||||
showLinkStyle(); // 显示隐藏样式
|
||||
// getSettings().setBlockNetworkImage(false); // 重新加载图片
|
||||
}
|
||||
|
||||
@ -241,9 +245,26 @@ public class RichEditor extends WebView {
|
||||
return TextUtils.isEmpty(mContents) ? "" : mContents;
|
||||
}
|
||||
|
||||
public void setEditorFontColor(int color) {
|
||||
String hex = convertHexColorString(color);
|
||||
exec("javascript:RE.setBaseTextColor('" + hex + "');");
|
||||
public void insertCustomStyleLink(EditorInsertEntity entity) {
|
||||
if (entity == null) return;
|
||||
// 转译
|
||||
String brief = entity.getBrief();
|
||||
String title = entity.getTitle();
|
||||
brief = TextUtils.isEmpty(brief) ? "" : brief.replaceAll("[\\x00-\\x1F\\x7F]", "");
|
||||
title = TextUtils.isEmpty(title) ? "" : title.replaceAll("[\\x00-\\x1F\\x7F]", "");
|
||||
|
||||
entity.setBrief(TextUtils.htmlEncode(brief));
|
||||
entity.setTitle(TextUtils.htmlEncode(title));
|
||||
entity.setIcon(TextUtils.htmlEncode(entity.getIcon()));
|
||||
exec("javascript:RE.insertCustomStyleLink('" + GsonUtils.toJson(entity) + "');");
|
||||
}
|
||||
|
||||
public void hideLinkStyle() {
|
||||
exec("javascript:RE.hideLinkStyle();");
|
||||
}
|
||||
|
||||
public void showLinkStyle() {
|
||||
exec("javascript:RE.showLinkStyle();");
|
||||
}
|
||||
|
||||
public void setEditorFontSize(int px) {
|
||||
@ -290,6 +311,58 @@ public class RichEditor extends WebView {
|
||||
exec("javascript:RE.setBackgroundImage('url(data:image/png;base64," + base64 + ")');");
|
||||
}
|
||||
|
||||
public void replaceAllDfImageExcludeGif() {
|
||||
exec("javascript:RE.replaceAllDfImage('" +
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + IMAGE_FLAG_DEFAULT + "','" +
|
||||
ImageUtils.getWatermarkWidthGifRule(mThumbnailImageWidth) + IMAGE_FLAG_THUMBNAIL + "')");
|
||||
}
|
||||
|
||||
|
||||
public void replaceAllDfImage() {
|
||||
exec("javascript:RE.replaceAllDfImage('" +
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + IMAGE_FLAG_DEFAULT + "','" +
|
||||
ImageUtils.getDefaultGifRule() + IMAGE_FLAG_DEFAULT + "')");
|
||||
}
|
||||
|
||||
public void replaceDfImageByUrl(String imgUrl) {
|
||||
exec("javascript:RE.replaceDfImageByUrl('" + imgUrl + "','" +
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + IMAGE_FLAG_DEFAULT + "','" +
|
||||
ImageUtils.getDefaultGifRule() + IMAGE_FLAG_DEFAULT + "');");
|
||||
}
|
||||
|
||||
public void loadCSS(String cssFile) {
|
||||
String jsCSSImport = "(function() {" +
|
||||
" var head = document.getElementsByTagName(\"head\")[0];" +
|
||||
" var link = document.createElement(\"link\");" +
|
||||
" link.rel = \"stylesheet\";" +
|
||||
" link.type = \"text/css\";" +
|
||||
" link.href = \"" + cssFile + "\";" +
|
||||
" link.media = \"all\";" +
|
||||
" head.appendChild(link);" +
|
||||
"}) ();";
|
||||
exec("javascript:" + jsCSSImport + "");
|
||||
}
|
||||
|
||||
public void insertImage(String url) {
|
||||
exec("javascript:RE.prepareInsert();");
|
||||
exec("javascript:RE.insertImage('" + url + "');");
|
||||
}
|
||||
|
||||
public void insertHtml(String html) {
|
||||
exec("javascript:RE.prepareInsert();");
|
||||
exec("javascript:RE.insertHTML('" + html + "');");
|
||||
}
|
||||
|
||||
public void focusEditor() {
|
||||
requestFocus();
|
||||
exec("javascript:RE.focus();");
|
||||
}
|
||||
|
||||
public void insertLink(String href, String title) {
|
||||
exec("javascript:RE.prepareInsert();");
|
||||
exec("javascript:RE.insertLink('" + href + "', '" + title + "');");
|
||||
}
|
||||
|
||||
public void setBackground(String url) {
|
||||
exec("javascript:RE.setBackgroundImage('url(" + url + ")');");
|
||||
}
|
||||
@ -314,68 +387,90 @@ public class RichEditor extends WebView {
|
||||
exec("javascript:RE.setInputEnabled(" + inputEnabled + ")");
|
||||
}
|
||||
|
||||
public void replaceAllDfImageExcludeGif() {
|
||||
exec("javascript:RE.replaceAllDfImage('" +
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + IMAGE_FLAG_DEFAULT + "','" +
|
||||
ImageUtils.getWatermarkWidthGifRule(mThumbnailImageWidth) + IMAGE_FLAG_THUMBNAIL + "')");
|
||||
}
|
||||
|
||||
|
||||
public void replaceAllDfImage() {
|
||||
exec("javascript:RE.replaceAllDfImage('" +
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + IMAGE_FLAG_DEFAULT + "','" +
|
||||
ImageUtils.getDefaultGifRule() + IMAGE_FLAG_DEFAULT + "')");
|
||||
}
|
||||
|
||||
public void setFocusByEnd() {
|
||||
exec("javascript:RE.setFocusByEnd()");
|
||||
}
|
||||
|
||||
public void replaceDfImageByUrl(String imgUrl) {
|
||||
exec("javascript:RE.replaceDfImageByUrl('" + imgUrl + "','" +
|
||||
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + IMAGE_FLAG_DEFAULT + "','" +
|
||||
ImageUtils.getDefaultGifRule() + IMAGE_FLAG_DEFAULT + "');");
|
||||
}
|
||||
|
||||
public void loadCSS(String cssFile) {
|
||||
String jsCSSImport = "(function() {" +
|
||||
" var head = document.getElementsByTagName(\"head\")[0];" +
|
||||
" var link = document.createElement(\"link\");" +
|
||||
" link.rel = \"stylesheet\";" +
|
||||
" link.type = \"text/css\";" +
|
||||
" link.href = \"" + cssFile + "\";" +
|
||||
" link.media = \"all\";" +
|
||||
" head.appendChild(link);" +
|
||||
"}) ();";
|
||||
exec("javascript:" + jsCSSImport + "");
|
||||
}
|
||||
|
||||
|
||||
public void setTextColor(int color) {
|
||||
exec("javascript:RE.prepareInsert();");
|
||||
|
||||
String hex = convertHexColorString(color);
|
||||
exec("javascript:RE.prepareInsert();");
|
||||
exec("javascript:RE.setTextColor('" + hex + "');");
|
||||
}
|
||||
|
||||
public void insertImage(String url) {
|
||||
exec("javascript:RE.prepareInsert();");
|
||||
exec("javascript:RE.insertImage('" + url + "');");
|
||||
public void removeFormat() {
|
||||
exec("javascript:RE.removeFormat();");
|
||||
}
|
||||
|
||||
public void insertHtml(String html) {
|
||||
exec("javascript:RE.prepareInsert();");
|
||||
exec("javascript:RE.insertHTML('" + html + "');");
|
||||
public void setHeading(int heading) {
|
||||
exec("javascript:RE.setHeading('" + heading + "');");
|
||||
}
|
||||
|
||||
public void focusEditor() {
|
||||
requestFocus();
|
||||
exec("javascript:RE.focus();");
|
||||
public void setIndent() {
|
||||
exec("javascript:RE.setIndent();");
|
||||
}
|
||||
|
||||
public void setOutdent() {
|
||||
exec("javascript:RE.setOutdent();");
|
||||
}
|
||||
|
||||
public void setAlignLeft() {
|
||||
exec("javascript:RE.setJustifyLeft();");
|
||||
}
|
||||
|
||||
public void setAlignCenter() {
|
||||
exec("javascript:RE.setJustifyCenter();");
|
||||
}
|
||||
|
||||
public void setAlignRight() {
|
||||
exec("javascript:RE.setJustifyRight();");
|
||||
}
|
||||
|
||||
public void setBlockquote() {
|
||||
exec("javascript:RE.setBlockquote();");
|
||||
}
|
||||
|
||||
public void setBullets() {
|
||||
exec("javascript:RE.setBullets();");
|
||||
}
|
||||
|
||||
public void setNumbers() {
|
||||
exec("javascript:RE.setNumbers();");
|
||||
}
|
||||
|
||||
public void undo() {
|
||||
exec("javascript:RE.undo();");
|
||||
}
|
||||
|
||||
public void redo() {
|
||||
exec("javascript:RE.redo();");
|
||||
}
|
||||
|
||||
public void setBold() {
|
||||
exec("javascript:RE.setBold();");
|
||||
}
|
||||
|
||||
public void setItalic() {
|
||||
exec("javascript:RE.setItalic();");
|
||||
}
|
||||
|
||||
public void setSubscript() {
|
||||
exec("javascript:RE.setSubscript();");
|
||||
}
|
||||
|
||||
public void setSuperscript() {
|
||||
exec("javascript:RE.setSuperscript();");
|
||||
}
|
||||
|
||||
public void setStrikeThrough() {
|
||||
exec("javascript:RE.setStrikeThrough();");
|
||||
}
|
||||
|
||||
public void setUnderline() {
|
||||
exec("javascript:RE.setUnderline();");
|
||||
}
|
||||
|
||||
public void formatBlock() {
|
||||
exec("javascript:RE.formatBlock();");
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return AskUtils.stripHtml(mContents);
|
||||
return HtmlUtils.stripHtml(mContents);
|
||||
}
|
||||
|
||||
|
||||
@ -398,7 +493,11 @@ public class RichEditor extends WebView {
|
||||
|
||||
private void load(String trigger) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
evaluateJavascript(trigger, null);
|
||||
try {
|
||||
evaluateJavascript(trigger, null);
|
||||
} catch (IllegalStateException ignore) {
|
||||
loadUrl(trigger);
|
||||
}
|
||||
} else {
|
||||
loadUrl(trigger);
|
||||
}
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.graphics.Rect
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.View
|
||||
|
||||
class SpacingItemDecoration(
|
||||
var onlyDecorateTheFirstItem: Boolean = false,
|
||||
var notDecorateTheFirstItem: Boolean = false,
|
||||
var notDecorateTheLastItem: Boolean = false,
|
||||
var left: Int = 0,
|
||||
var top: Int = 0,
|
||||
var right: Int = 0,
|
||||
var bottom: Int = 0)
|
||||
: RecyclerView.ItemDecoration() {
|
||||
|
||||
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) {
|
||||
if (onlyDecorateTheFirstItem) {
|
||||
if (parent.getChildAdapterPosition(view) == 0) outRect.set(left, top, right, bottom)
|
||||
} else {
|
||||
if (parent.getChildAdapterPosition(view) == 0 && notDecorateTheFirstItem) {
|
||||
outRect.set(0, 0, 0, 0)
|
||||
} else if (parent.getChildAdapterPosition(view) == parent.adapter.itemCount - 1 && notDecorateTheLastItem) {
|
||||
outRect.set(0, 0, 0, 0)
|
||||
} else {
|
||||
outRect.set(left, top, right, bottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
app/src/main/java/com/gh/common/view/VerticalViewPager.kt
Normal file
64
app/src/main/java/com/gh/common/view/VerticalViewPager.kt
Normal file
@ -0,0 +1,64 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
|
||||
class VerticalViewPager @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
|
||||
: ViewPager(context, attrs) {
|
||||
|
||||
init {
|
||||
// The majority of the magic happens here
|
||||
setPageTransformer(true, VerticalPageTransformer())
|
||||
// The easiest way to get rid of the overscroll drawing that happens on the left and right
|
||||
overScrollMode = View.OVER_SCROLL_NEVER
|
||||
}
|
||||
|
||||
private inner class VerticalPageTransformer : ViewPager.PageTransformer {
|
||||
override fun transformPage(view: View, position: Float) {
|
||||
if (position < -1) { // [-Infinity,-1)
|
||||
// This page is way off-screen to the left.
|
||||
view.alpha = 0F
|
||||
|
||||
} else if (position <= 1) { // [-1,1]
|
||||
view.alpha = 1F
|
||||
|
||||
// Counteract the default slide transition
|
||||
view.translationX = view.width * -position
|
||||
|
||||
//set Y position to swipe in from top
|
||||
val yPosition = position * view.height
|
||||
view.translationY = yPosition
|
||||
|
||||
} else { // (1,+Infinity]
|
||||
// This page is way off-screen to the right.
|
||||
view.alpha = 0F
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps the X and Y coordinates of your touch event.
|
||||
*/
|
||||
private fun swapXY(ev: MotionEvent): MotionEvent {
|
||||
val width = width.toFloat()
|
||||
val height = height.toFloat()
|
||||
|
||||
val newX = ev.y / height * width
|
||||
val newY = ev.x / width * height
|
||||
|
||||
ev.setLocation(newX, newY)
|
||||
|
||||
return ev
|
||||
}
|
||||
|
||||
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
|
||||
// val intercepted = super.onInterceptTouchEvent(swapXY(ev))
|
||||
// return touch coordinates to original reference frame for any child views
|
||||
// swapXY(ev)
|
||||
// we do not need it view pager to intercept touch event
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,7 @@ import com.gh.common.util.DataCollectionUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.GdtHelper;
|
||||
import com.gh.common.util.MD5Utils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
@ -92,8 +93,13 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
|
||||
@Override
|
||||
public void onTaskError(DownloadEntity entity) {
|
||||
DownloadNotification.showDownloadingNotification(mContext);
|
||||
downloadingMap.remove(entity.getUrl());
|
||||
// 下载进度超出是任务出错,但不需要去掉状态栏通知 https://gitlab.ghzs.com/pm/halo-app-issues/issues/496
|
||||
if (entity.getStatus() == DownloadStatus.overflow) {
|
||||
MtaHelper.onEventWithBasicDeviceInfo("下载无法完成", "游戏", entity.getName());
|
||||
} else {
|
||||
DownloadNotification.showDownloadingNotification(mContext);
|
||||
downloadingMap.remove(entity.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -29,7 +29,7 @@ public class DownloadNotification {
|
||||
|
||||
public static final String ACTION_INSTALL = "com.gh.gamecenter.INSTALL";
|
||||
public static final String ACTION_DOWNLOAD = "com.gh.gamecenter.DOWNLOAD";
|
||||
public static final int ICON = R.drawable.logo;
|
||||
public static final int ICON = R.mipmap.logo;
|
||||
public static final int NOTIFY_ID = 0x123;
|
||||
public static final int WAIT_NOTIFY_ID = 0x124;
|
||||
private static final String CHANNEL_ID = "Halo_Download";
|
||||
@ -69,7 +69,7 @@ public class DownloadNotification {
|
||||
}
|
||||
|
||||
final Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.logo)
|
||||
.setSmallIcon(R.mipmap.logo)
|
||||
.setTicker(title)
|
||||
.setContentTitle(text)
|
||||
.setContentText(title)
|
||||
|
||||
@ -437,7 +437,7 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
|
||||
byte[] receiveData = new byte[1024];
|
||||
byte[] sendData;
|
||||
Utils.log("=====ip::" + ipAddress);
|
||||
if (!"192.168.43.1".equals(ipAddress)) {
|
||||
if (!"logo.168.43.1".equals(ipAddress)) {
|
||||
// 连接失败,可能是连接的热点已经关闭, 关闭动画,开启扫描
|
||||
isStopScan = false;
|
||||
handler.sendEmptyMessage(0);
|
||||
|
||||
@ -39,12 +39,12 @@ public class CommentDetailActivity extends NormalActivity {
|
||||
public static Intent getCommunityArticleCommentIntent(Context context,
|
||||
String articleId,
|
||||
String articleCommentId,
|
||||
String articleCommunityId,
|
||||
String communityId,
|
||||
LinkEntity linkEntity) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(CommentActivity.ARTICLE_ID, articleId);
|
||||
args.putString(EntranceUtils.KEY_ARTICLE_COMMENT_ID, articleCommentId);
|
||||
args.putString(CommentActivity.ARTICLE_COMMUNITY_ID, articleCommunityId);
|
||||
args.putString(CommentActivity.COMMUNITY_ID, communityId);
|
||||
args.putParcelable(EntranceUtils.KEY_LINK, linkEntity);
|
||||
return getTargetIntent(context, CommentDetailActivity.class, CommentConversationFragment.class, args);
|
||||
}
|
||||
|
||||
@ -53,6 +53,18 @@ public class GameDetailActivity extends NormalActivity {
|
||||
public static void startGameDetailActivity(Context context, GameEntity gameEntity, String entrance, ExposureEvent traceEvent) {
|
||||
DataUtils.onMtaEvent(context, "详情页面", "游戏详情", gameEntity != null ? gameEntity.getName() : "");
|
||||
|
||||
if (gameEntity != null
|
||||
&& traceEvent != null
|
||||
&& gameEntity.getId() != null
|
||||
&& !gameEntity.getId().equals(traceEvent.getPayload().getGameId())) {
|
||||
// 当游戏 ID 跟曝光 traceEvent 的游戏ID 不一样的时候更新 traceEvent 的游戏ID
|
||||
ExposureEvent forNewPayload = ExposureEvent.Companion.createEvent(gameEntity,
|
||||
traceEvent.getSource(),
|
||||
ExposureTraceUtils.INSTANCE.appendTrace(traceEvent),
|
||||
ExposureType.EXPOSURE);
|
||||
traceEvent.setPayload(forNewPayload.getPayload());
|
||||
}
|
||||
|
||||
ExposureEvent clickEvent = ExposureEvent.Companion.createEvent(gameEntity, traceEvent.getSource(), ExposureTraceUtils.INSTANCE.appendTrace(traceEvent), ExposureType.CLICK);
|
||||
ExposureManager.INSTANCE.log(clickEvent);
|
||||
Bundle bundle = new Bundle();
|
||||
@ -67,6 +79,16 @@ public class GameDetailActivity extends NormalActivity {
|
||||
*/
|
||||
public static void startGameDetailActivity(Context context, String gameId, String entrance, ExposureEvent traceEvent) {
|
||||
|
||||
if (traceEvent != null
|
||||
&& !gameId.equals(traceEvent.getPayload().getGameId())) {
|
||||
// 当游戏 ID 跟曝光 traceEvent 的游戏ID 不一样的时候更新 traceEvent 的游戏ID
|
||||
ExposureEvent forNewPayload = ExposureEvent.Companion.createEvent(new GameEntity(gameId),
|
||||
traceEvent.getSource(),
|
||||
ExposureTraceUtils.INSTANCE.appendTrace(traceEvent),
|
||||
ExposureType.EXPOSURE);
|
||||
traceEvent.setPayload(forNewPayload.getPayload());
|
||||
}
|
||||
|
||||
ExposureEvent clickEvent = ExposureEvent.Companion.createEvent(new GameEntity(gameId), traceEvent.getSource(), ExposureTraceUtils.INSTANCE.appendTrace(traceEvent), ExposureType.CLICK);
|
||||
ExposureManager.INSTANCE.log(clickEvent);
|
||||
|
||||
@ -78,7 +100,7 @@ public class GameDetailActivity extends NormalActivity {
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动游戏详情页面
|
||||
* 启动游戏详情页面,自动定位到评论页面
|
||||
*/
|
||||
public static void startGameDetailCommentActivity(Context context, String gameId, String entrance) {
|
||||
Bundle bundle = new Bundle();
|
||||
@ -88,6 +110,17 @@ public class GameDetailActivity extends NormalActivity {
|
||||
context.startActivity(getTargetIntent(context, GameDetailActivity.class, GameDetailFragment.class, bundle));
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果存在多个游戏平台则打开
|
||||
*/
|
||||
public static void startGameDetailActivityByVote(Context context, String gameId, String entrance) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_GAMEID, gameId);
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
bundle.putBoolean(EntranceUtils.KEY_OPEN_PLATFORM_WINDOW, true);
|
||||
context.startActivity(getTargetIntent(context, GameDetailActivity.class, GameDetailFragment.class, bundle));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (Jzvd.backPress()) {
|
||||
|
||||
@ -13,6 +13,8 @@ import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.ethanhua.skeleton.Skeleton;
|
||||
import com.ethanhua.skeleton.ViewSkeletonScreen;
|
||||
import com.gh.base.BaseActivity;
|
||||
import com.gh.base.OnRequestCallBackListener;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
@ -38,8 +40,6 @@ import java.util.ArrayList;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
import static com.gh.gamecenter.R.id.reuse_nodata_skip_tv_btn;
|
||||
import static com.gh.gamecenter.R.id.reuse_nodata_skip_tv_hint;
|
||||
import static com.gh.gamecenter.download.FileSendFragment.KC_REQUEST;
|
||||
|
||||
/**
|
||||
@ -53,14 +53,18 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
|
||||
RecyclerView mInstallRv;
|
||||
@BindView(R.id.reuse_nodata_skip)
|
||||
LinearLayout mNoDataSkip;
|
||||
@BindView(reuse_nodata_skip_tv_hint)
|
||||
@BindView(R.id.reuse_nodata_skip_tv_hint)
|
||||
TextView mNoDataSkipHint;
|
||||
@BindView(reuse_nodata_skip_tv_btn)
|
||||
@BindView(R.id.reuse_nodata_skip_tv_btn)
|
||||
TextView mNoDataSkipBtn;
|
||||
@BindView(R.id.list_skeleton)
|
||||
View mListSkeleton;
|
||||
|
||||
private PackageViewModel mPackageViewModel;
|
||||
private InstallFragmentAdapter mAdapter;
|
||||
|
||||
private ViewSkeletonScreen mSkeleton;
|
||||
|
||||
private boolean isEverpause = false;
|
||||
|
||||
private DataWatcher dataWatcher = new DataWatcher() {
|
||||
@ -70,10 +74,12 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
|
||||
if (locationList != null && locationList.size() != 0) {
|
||||
GameEntity gameEntity;
|
||||
for (int location : locationList) {
|
||||
gameEntity = mAdapter.getGameList().get(location);
|
||||
if (gameEntity != null) {
|
||||
DownloadItemUtils.processDate(InstallActivity.this, gameEntity,
|
||||
downloadEntity, mAdapter, location);
|
||||
if (location < mAdapter.getGameList().size()) {
|
||||
gameEntity = mAdapter.getGameList().get(location);
|
||||
if (gameEntity != null) {
|
||||
DownloadItemUtils.processDate(InstallActivity.this, gameEntity,
|
||||
downloadEntity, mAdapter, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,6 +107,7 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
|
||||
super.onCreate(savedInstanceState);
|
||||
setNavigationTitle(getString(R.string.personale_mygame));
|
||||
mNoDataSkip.setVisibility(View.GONE);
|
||||
mSkeleton = Skeleton.bind(mListSkeleton).shimmer(false).load(R.layout.activity_install_skeleton).show();
|
||||
mNoDataSkipHint.setText("暂无游戏");
|
||||
mNoDataSkipBtn.setText("查看精品推荐");
|
||||
mNoDataSkipBtn.setOnClickListener(v -> {
|
||||
@ -111,12 +118,12 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
|
||||
mInstallRv.setLayoutManager(new LinearLayoutManager(this));
|
||||
((DefaultItemAnimator) mInstallRv.getItemAnimator()).setSupportsChangeAnimations(false);
|
||||
mAdapter = new InstallFragmentAdapter(this);
|
||||
mInstallRv.addItemDecoration(new VerticalItemDecoration(this, true));
|
||||
mInstallRv.addItemDecoration(new VerticalItemDecoration(this, 8, true));
|
||||
mInstallRv.setAdapter(mAdapter);
|
||||
|
||||
mPackageViewModel = ViewModelProviders.of(this, new PackageViewModel.Factory()).get(PackageViewModel.class);
|
||||
mPackageViewModel.getGameInstalledLiveData().observe(this,
|
||||
gameInstalls -> mAdapter.initData(PackagesManager.filterSameApk(gameInstalls)));
|
||||
gameInstalls -> mAdapter.initData(PackagesManager.filterSameApk(PackagesManager.filterDownloadBlackPackage(gameInstalls))));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -146,7 +153,7 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
|
||||
|
||||
@Override
|
||||
public void loadDone() {
|
||||
|
||||
mSkeleton.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -161,6 +168,7 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
|
||||
|
||||
@Override
|
||||
public void loadEmpty() {
|
||||
mSkeleton.hide();
|
||||
mInstallRv.setVisibility(View.GONE);
|
||||
mNoDataSkip.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@ -13,6 +13,8 @@ import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.ethanhua.skeleton.Skeleton;
|
||||
import com.ethanhua.skeleton.ViewSkeletonScreen;
|
||||
import com.gh.base.BaseActivity;
|
||||
import com.gh.base.OnRequestCallBackListener;
|
||||
import com.gh.common.util.ApkActiveUtils;
|
||||
@ -33,6 +35,7 @@ import com.gh.gamecenter.entity.MeEntity;
|
||||
import com.gh.gamecenter.entity.UserDataLibaoEntity;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.eventbus.EBPackage;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.eventbus.EBUISwitch;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
@ -56,6 +59,7 @@ import io.reactivex.schedulers.Schedulers;
|
||||
import retrofit2.HttpException;
|
||||
|
||||
import static com.gh.gamecenter.R.id.reuse_tv_none_data;
|
||||
import static com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG;
|
||||
|
||||
/**
|
||||
* Created by khy on 2016/12/13.
|
||||
@ -75,6 +79,10 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
|
||||
LinearLayout mNoneData;
|
||||
@BindView(R.id.detail_progressbar)
|
||||
DownloadProgressBar mDownloadPb;
|
||||
@BindView(R.id.list_skeleton)
|
||||
View mListSkeleton;
|
||||
|
||||
private ViewSkeletonScreen mSkeleton;
|
||||
|
||||
private LibaoDetailAdapter mAdapter;
|
||||
|
||||
@ -174,6 +182,7 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
|
||||
|
||||
mIsScroll = true;
|
||||
|
||||
mSkeleton = Skeleton.bind(mListSkeleton).shimmer(false).load(R.layout.activity_libaodetail_skeleton).show();
|
||||
mAdapter = new LibaoDetailAdapter(this, this, this, mLibaoEntity, mDownloadPb, mEntrance);
|
||||
mLibaoDetailRv.setLayoutManager(new LinearLayoutManager(this) {
|
||||
@Override
|
||||
@ -184,13 +193,11 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
|
||||
mLibaoDetailRv.addItemDecoration(new VerticalItemDecoration(this, 8, true));
|
||||
mLibaoDetailRv.setAdapter(mAdapter);
|
||||
|
||||
mNoConnection.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mNoConnection.setVisibility(View.GONE);
|
||||
mLlLoading.setVisibility(View.VISIBLE);
|
||||
mBaseHandler.postDelayed(() -> getGameDigest(), 1000);
|
||||
}
|
||||
mNoConnection.setOnClickListener(v -> {
|
||||
mSkeleton.show();
|
||||
mNoConnection.setVisibility(View.GONE);
|
||||
mLlLoading.setVisibility(View.VISIBLE);
|
||||
mBaseHandler.postDelayed(() -> getGameDigest(), 1000);
|
||||
});
|
||||
|
||||
if (mLibaoEntity == null) {
|
||||
@ -307,8 +314,12 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
|
||||
.subscribe(new Response<LibaoEntity>() {
|
||||
@Override
|
||||
public void onResponse(LibaoEntity response) {
|
||||
mLibaoEntity = response;
|
||||
mLibaoEntity.setActive(true); // addLibaoDetail设置userData
|
||||
response.setActive(true); // addLibaoDetail设置userData
|
||||
if (mLibaoEntity != null) {
|
||||
mLibaoEntity.resetLibaoEntity(response);
|
||||
} else {
|
||||
mLibaoEntity = response;
|
||||
}
|
||||
mAdapter.setLibaoEntity(mLibaoEntity);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
getGameDigest();
|
||||
@ -321,7 +332,7 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
|
||||
private void getLibaoStatus(String libaoId) {
|
||||
LibaoUtils.getLibaoStatus(this, libaoId, new LibaoUtils.PostLibaoListener() {
|
||||
@Override
|
||||
public void postSucced(Object response) {
|
||||
public void postSucceed(Object response) {
|
||||
List<LibaoStatusEntity> statusList = (List<LibaoStatusEntity>) response;
|
||||
|
||||
LibaoUtils.initLiBaoEntity(statusList.get(0), mLibaoEntity);
|
||||
@ -411,6 +422,8 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
|
||||
|
||||
checkLibaoStatus();
|
||||
}
|
||||
|
||||
mSkeleton.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -428,6 +441,8 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
|
||||
mLlLoading.setVisibility(View.GONE);
|
||||
mLibaoDetailRv.setPadding(0, 0, 0, 0);
|
||||
mNoConnection.setVisibility(View.VISIBLE);
|
||||
|
||||
mSkeleton.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -442,6 +457,8 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
|
||||
} else {
|
||||
mNoneDataTv.setText("天了噜~页面不见了");
|
||||
}
|
||||
|
||||
mSkeleton.hide();
|
||||
}
|
||||
|
||||
// 领取/淘号失败,根据返回的时间重新倒数
|
||||
@ -479,4 +496,11 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBReuse reuse) {
|
||||
if (reuse.getType().equals(LOGIN_TAG) && mLibaoEntity != null) { // 登入
|
||||
getLibaoDigest(mLibaoEntity.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.gamecenter;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.app.NotificationManager;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
@ -27,12 +28,12 @@ import android.widget.TextView;
|
||||
import com.gh.base.AppUncaughtHandler;
|
||||
import com.gh.base.BaseActivity;
|
||||
import com.gh.base.fragment.BaseFragment_ViewPager;
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.common.im.ImManager;
|
||||
import com.gh.common.util.ClassUtils;
|
||||
import com.gh.common.util.CommunityHelper;
|
||||
import com.gh.common.util.ConcernUtils;
|
||||
import com.gh.common.util.DataCollectionUtils;
|
||||
import com.gh.common.util.DataLogUtils;
|
||||
@ -44,10 +45,13 @@ import com.gh.common.util.DirectUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.GsonUtils;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.LunchType;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.PushHelper;
|
||||
import com.gh.common.util.ThirdPartyPackageHelper;
|
||||
import com.gh.common.util.UrlFilterUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.DownloadNotification;
|
||||
@ -69,6 +73,7 @@ import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.normal.NormalFragment;
|
||||
import com.gh.gamecenter.packagehelper.PackageViewModel;
|
||||
import com.gh.gamecenter.qa.AskFragment;
|
||||
import com.gh.gamecenter.retrofit.BiResponse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.gh.gamecenter.suggest.SuggestType;
|
||||
@ -89,6 +94,7 @@ import com.tencent.bugly.crashreport.CrashReport;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@ -135,7 +141,6 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
private boolean isSkipped = false;
|
||||
public static boolean isNewFirstLaunch;
|
||||
public static boolean openCommunityWithDefaultIdForTheFirsTime; // 是否根据 META-INFO 里的 JSON 自动选择默认的社区 ID
|
||||
|
||||
private Handler handler = new Handler();
|
||||
// 黄壮华 添加观察者 修改2015/8/15
|
||||
@ -259,8 +264,15 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
isNewFirstLaunch = mSp.getBoolean("isNewFirstLaunchV" + PackageUtils.getVersionName(), true);
|
||||
if (isNewFirstLaunch) {
|
||||
LogUtils.uploadDevice(DeviceTokenUtils.getLaunchType());
|
||||
final LunchType lunchType = DeviceTokenUtils.getLaunchType();
|
||||
// 延时两秒提交 APP 启动日志的,避免提交时还没获取到 GID
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
if (!this.isFinishing()) {
|
||||
LogUtils.uploadDevice(lunchType);
|
||||
}
|
||||
}, 2000L);
|
||||
getPluginUpdate();
|
||||
sendActivationInfo();
|
||||
mSp.edit().putBoolean("isNewFirstLaunchV" + PackageUtils.getVersionName(), false).apply();
|
||||
|
||||
checkDevice(); // 根据设备信息判断用户是否是新用户
|
||||
@ -277,9 +289,9 @@ public class MainActivity extends BaseActivity {
|
||||
|
||||
mPackageViewModel = ViewModelProviders.of(this, new PackageViewModel.Factory()).get(PackageViewModel.class);
|
||||
|
||||
final String message = Config.getExceptionMsg(this);
|
||||
final String message = Config.getExceptionMsg();
|
||||
if (!TextUtils.isEmpty(message)) {
|
||||
Config.setExceptionMsg(this, null);
|
||||
Config.setExceptionMsg(null);
|
||||
AppUncaughtHandler.reportException(this, new Throwable(message));
|
||||
DialogUtils.showWarningDialog(this, "发生闪退", "光环助手刚刚发生了闪退,马上反馈以帮助我们更好地修复问题?(只需简单描述你刚才的操作)"
|
||||
, "暂不", "马上反馈",
|
||||
@ -294,7 +306,7 @@ public class MainActivity extends BaseActivity {
|
||||
"玩家操作", "点击关闭"));
|
||||
}
|
||||
|
||||
checkTinkerPath();
|
||||
// checkTinkerPath(); // todo 看情况是否需要显示弹窗
|
||||
|
||||
checkRetryDownload();
|
||||
|
||||
@ -304,9 +316,6 @@ public class MainActivity extends BaseActivity {
|
||||
handler.postDelayed(ImManager::attachIm, 1000);
|
||||
}
|
||||
|
||||
// 获取可用(没有被隐藏的)的社区列表
|
||||
CommunityHelper.getAvailableCommunityList();
|
||||
|
||||
if (getIntent().getBooleanExtra(SWITCH_TO_COMMUNITY, false)) {
|
||||
handler.postDelayed(this::switchToCommunityTabAndRefresh, 800);
|
||||
}
|
||||
@ -315,6 +324,10 @@ public class MainActivity extends BaseActivity {
|
||||
if (getIntent() != null && getIntent().getExtras() != null && !isSkipped) {
|
||||
doSkip();
|
||||
}
|
||||
|
||||
handler.postDelayed(() -> {
|
||||
PushHelper.postPushClickAction(this.getApplicationContext(), null);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -332,6 +345,13 @@ public class MainActivity extends BaseActivity {
|
||||
return intent;
|
||||
}
|
||||
|
||||
private void sendActivationInfo() {
|
||||
RetrofitManager.getInstance(this)
|
||||
.getApi().postActivationInfo()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(new Response<>());
|
||||
}
|
||||
|
||||
private void doSkip() {
|
||||
handler.postDelayed(() -> {
|
||||
isSkipped = true;
|
||||
@ -420,7 +440,11 @@ public class MainActivity extends BaseActivity {
|
||||
"网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
}
|
||||
|
||||
ExposureUtils.logADownloadCompleteExposureEvent(new GameEntity(downloadEntity.getGameId()), downloadEntity.getPlatform(), downloadEntity.getExposureTrace(), type);
|
||||
ExposureUtils.logADownloadCompleteExposureEvent(
|
||||
new GameEntity(downloadEntity.getGameId(), downloadEntity.getName()),
|
||||
downloadEntity.getPlatform(),
|
||||
downloadEntity.getExposureTrace(),
|
||||
type);
|
||||
|
||||
DataCollectionUtils.uploadDownload(this, downloadEntity, "完成");
|
||||
}
|
||||
@ -537,11 +561,11 @@ public class MainActivity extends BaseActivity {
|
||||
// 意见反馈
|
||||
SharedPreferences.Editor edit = mSp.edit();
|
||||
edit.putString(SuggestionActivity.SUGGESTION_HINT_TYPE,
|
||||
GsonUtils.Companion.getInstance().toJson(response.getSuggestion()));
|
||||
GsonUtils.toJson(response.getSuggestion()));
|
||||
edit.apply();
|
||||
|
||||
if (!mSp.getBoolean("isFixDownload", false) && Config.isShow()) {
|
||||
mSp.edit().putBoolean("isFixDownload", true).apply();
|
||||
if (!mSp.getBoolean(Config.FIX_DOWNLOAD_KEY, false) && Config.isShow()) {
|
||||
mSp.edit().putBoolean(Config.FIX_DOWNLOAD_KEY, true).apply();
|
||||
}
|
||||
|
||||
EventBus.getDefault().post(new EBReuse("Refresh"));
|
||||
@ -694,7 +718,6 @@ public class MainActivity extends BaseActivity {
|
||||
InnerMetaInfoEntity info = gson.fromJson(reader, InnerMetaInfoEntity.class);
|
||||
if (info != null) {
|
||||
if (EntranceUtils.HOST_COMMUNITY.equals(info.getType())) {
|
||||
openCommunityWithDefaultIdForTheFirsTime = true;
|
||||
UserManager.getInstance().setCommunityData(new CommunityEntity(info.getLink(), info.getText()));
|
||||
runOnUiThread(() -> mMainWrapperFragment.setCurrentItem(MainWrapperFragment.INDEX_ASK));
|
||||
} else {
|
||||
@ -769,6 +792,12 @@ public class MainActivity extends BaseActivity {
|
||||
"操作", "安装完成",
|
||||
"网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
}
|
||||
|
||||
// 没有光环 ID 的都记录一下游戏 ID,供'我的游戏'区分同包名不同插件用
|
||||
Object gh_id = PackageUtils.getMetaData(this, mDownloadEntity.getPackageName(), "gh_id");
|
||||
if (gh_id == null) {
|
||||
ThirdPartyPackageHelper.saveGameId(mDownloadEntity.getPackageName(), mDownloadEntity.getGameId());
|
||||
}
|
||||
DownloadManager.getInstance(getApplicationContext()).cancel(
|
||||
mDownloadEntity.getUrl(), false); // 默认不删除安装包 mSp.getBoolean("autodelete", true)
|
||||
}
|
||||
@ -786,21 +815,15 @@ public class MainActivity extends BaseActivity {
|
||||
for (GameDigestEntity gameDigestEntity : response) {
|
||||
if (!TextUtils.isEmpty(gameDigestEntity.getId())) { // 关注游戏
|
||||
if (finalDownloadEntity != null && gameDigestEntity.getId().equals(finalDownloadEntity.getGameId())) {
|
||||
ConcernUtils.INSTANCE.postConcernGameId(MainActivity.this, gameDigestEntity.getId(), null);
|
||||
ConcernUtils.INSTANCE.postConcernGameId(MainActivity.this, gameDigestEntity.getId(), null, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新已安装游戏
|
||||
RetrofitManager.getInstance(MainActivity.this).getApi()
|
||||
.postPackage(UserManager.getInstance().getUserId(), packageName)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new Response<>());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
postNewlyInstalledApp(packageName);
|
||||
}
|
||||
if ("卸载".equals(busFour.getType())) {
|
||||
mPackageViewModel.addUninstalledGame(packageName);
|
||||
@ -821,16 +844,58 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
// 更新已安装游戏
|
||||
RetrofitManager.getInstance(this).getApi()
|
||||
.deletePackage(UserManager.getInstance().getUserId(), packageName)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new Response<>());
|
||||
deleteInstalledPackage(packageName);
|
||||
}
|
||||
|
||||
DataCollectionUtils.uploadInorunstall(this, busFour.getType(), busFour.getPackageName());
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void postNewlyInstalledApp(String packageName) {
|
||||
|
||||
JSONObject packageObject = PackageUtils.getAppBasicInfoByPackageName(packageName);
|
||||
|
||||
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"),
|
||||
packageObject.toString());
|
||||
|
||||
// 更新已安装游戏
|
||||
RetrofitManager.getInstance(MainActivity.this).getApi()
|
||||
.postNewlyInstalledApp(HaloApp.getInstance().getGid(), requestBody)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new BiResponse<ResponseBody>() {
|
||||
@Override
|
||||
public void onSuccess(ResponseBody data) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private void deleteInstalledPackage(String packageName) {
|
||||
// 删除已安装游戏
|
||||
RetrofitManager.getInstance(MainActivity.this).getApi()
|
||||
.deleteInstalledApp(HaloApp.getInstance().getGid(), packageName)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new BiResponse<ResponseBody>() {
|
||||
@Override
|
||||
public void onSuccess(ResponseBody data) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 接收登录和登出更新事件统计的 Meta
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBReuse reuse) {
|
||||
|
||||
@ -24,6 +24,7 @@ import android.widget.TextView;
|
||||
|
||||
import com.gh.base.BaseActivity;
|
||||
import com.gh.base.OnRequestCallBackListener;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
import com.gh.common.util.ApkActiveUtils;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.ClickUtils;
|
||||
@ -46,6 +47,7 @@ import com.gh.gamecenter.eventbus.EBConcernChanged;
|
||||
import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.eventbus.EBNetworkState;
|
||||
import com.gh.gamecenter.eventbus.EBPackage;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.newsdetail.NewsDetailAdapter;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
@ -66,6 +68,8 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import retrofit2.HttpException;
|
||||
|
||||
import static com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG;
|
||||
|
||||
|
||||
/**
|
||||
* 文章详情页面 要启动该页面 需要传入一下参数 放入 EssayEntity中传过来 文章 id 文章标题 title 文章发表时间 time
|
||||
@ -258,6 +262,8 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
|
||||
if (mNewsEntity.getType() != null) {
|
||||
setNavigationTitle(mNewsEntity.getType());
|
||||
}
|
||||
|
||||
HistoryHelper.insertNewsEntity(mNewsEntity);
|
||||
adapter.setId(mNewsEntity.getId());
|
||||
adapter.setType(mNewsEntity.getType());
|
||||
adapter.setTitle(mNewsEntity.getTitle());
|
||||
@ -418,9 +424,7 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (gameEntity != null
|
||||
&& gameEntity.getApk() != null
|
||||
&& gameEntity.getApk().size() == 1) {
|
||||
if (gameEntity != null && gameEntity.getApk().size() == 1) {
|
||||
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), true);
|
||||
}
|
||||
DownloadManager.getInstance(this).addObserver(dataWatcher);
|
||||
@ -487,6 +491,8 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
|
||||
|
||||
mNewsShare.setVisible(true);
|
||||
|
||||
HistoryHelper.insertNewsEntity(mNewsEntity);
|
||||
|
||||
DataUtils.onMtaEvent(NewsDetailActivity.this, "详情页面", "文章详情", response.getTitle());
|
||||
}
|
||||
|
||||
@ -650,10 +656,7 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
|
||||
// 接收下载被删除消息
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEvent(EBDownloadStatus status) {
|
||||
if ("delete".equals(status.getStatus())
|
||||
&& gameEntity != null
|
||||
&& gameEntity.getApk() != null
|
||||
&& gameEntity.getApk().size() == 1) {
|
||||
if ("delete".equals(status.getStatus()) && gameEntity != null && gameEntity.getApk().size() == 1) {
|
||||
String url = gameEntity.getApk().get(0).getUrl();
|
||||
if (url.equals(status.getUrl())) {
|
||||
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), false);
|
||||
@ -664,9 +667,7 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
|
||||
// 接受安装、卸载消息
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBPackage busFour) {
|
||||
if (gameEntity != null
|
||||
&& gameEntity.getApk() != null
|
||||
&& gameEntity.getApk().size() == 1) {
|
||||
if (gameEntity != null && gameEntity.getApk().size() == 1) {
|
||||
String packageName = gameEntity.getApk().get(0).getPackageName();
|
||||
if (packageName.equals(busFour.getPackageName())) {
|
||||
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), false);
|
||||
@ -674,4 +675,11 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBReuse reuse) {
|
||||
if (reuse.getType().equals(LOGIN_TAG) && adapter != null) { // 登入
|
||||
adapter.getNewsDetail();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.View
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.common.util.DataUtils
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.common.util.StringUtils
|
||||
@ -139,12 +140,12 @@ class PersonalHomeActivity : ListActivity<PersonalHistoryEntity, PersonalHomeVie
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun startTargetActivity(context: Context, userId: String?, entrance: String, path: String?) {
|
||||
fun startTargetActivity(context: Context, userId: String?, entrance: String?, path: String?) {
|
||||
if (!userId.isNullOrEmpty()) {
|
||||
val intent = Intent(context, PersonalHomeActivity::class.java)
|
||||
intent.putExtra(EntranceUtils.KEY_USER_ID, userId)
|
||||
intent.putExtra(EntranceUtils.KEY_PATH, path)
|
||||
intent.putExtra(EntranceUtils.KEY_ENTRANCE, "$entrance+($path)")
|
||||
intent.putExtra(EntranceUtils.KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user