Compare commits

..

152 Commits

Author SHA1 Message Date
28440d97de 删除无用代码 2019-04-08 18:00:21 +08:00
2b2b71fe01 资讯文章超链接支持跳转到社区文章 2019-04-04 16:21:50 +08:00
f5a9e7b487 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-04-03 17:56:56 +08:00
d43842a0e6 社区搜索新增页面增加关键字统计和点击跳转时增加到历史搜索 2019-04-03 17:56:42 +08:00
a557962f17 微调UI 2019-04-02 18:32:49 +08:00
560c682157 完成光环助手V3.6.3 RELEASE(20190402-1130)测试问题汇总(6,7,8) 2019-04-02 17:41:48 +08:00
a0ae36f511 修复问题编辑图片数量的显示错误问题 2019-04-02 15:57:21 +08:00
bdee17ffc4 修复社区选择排序问题 2019-04-02 09:59:12 +08:00
5829f09f8c 调整文案 2019-04-01 20:18:00 +08:00
bc6fa5e7db 更换编辑框图标 2019-04-01 18:07:06 +08:00
1607cea9ce Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-04-01 17:58:33 +08:00
426019ea7c 光环助手V3.6.3 RELEASE(20190331-1830)测试问题汇总(前端)(1.3.4.10) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/483 2019-04-01 17:57:08 +08:00
1b878a50c4 调整关闭评论点击的 toast 文案 2019-04-01 17:13:43 +08:00
97525189b7 调整反馈文案 2019-04-01 16:59:38 +08:00
999947751a 修复回答浮窗在用户退出登录后也有可能显示的问题 2019-04-01 16:40:56 +08:00
2def61ab43 修复光环助手V3.6.3 RELEASE(20190331-1830)测试问题汇总(6,7,8,9) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/483 2019-04-01 16:28:17 +08:00
5e07ef488c 整理重复定义的权限 2019-04-01 11:10:40 +08:00
7af47c0caf 调整资源位置 2019-04-01 11:10:12 +08:00
1a5ed3c05f 调整代码 2019-03-31 17:05:47 +08:00
9cc9b09861 光环助手V3.6.3 RELEASE(20190328-1930)测试问题汇总(前端)(5.6.7.8.13) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/480 2019-03-31 15:21:12 +08:00
cef4432d97 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-31 14:17:02 +08:00
18be6acc34 光环助手V3.6.3 RELEASE(20190329-1930)测试问题汇总(前端)(1.2.3.8.9) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/482 2019-03-31 14:16:27 +08:00
27d0dd40d0 修复了版主不能修改问题图片数量的问题 2019-03-30 17:13:33 +08:00
b05fa626f6 处理一些内存泄漏问题 2019-03-30 14:41:31 +08:00
f1fc84ea5f 修复答案被隐藏时的闪退问题 2019-03-30 14:40:55 +08:00
3942154c05 修复缺少路径引起的闪退问题 2019-03-30 14:23:52 +08:00
ff182ee3c7 修复了光环助手V3.6.3 RELEASE(20190328-1930)测试问题汇总的(1,2,9,10,11) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/480 2019-03-30 10:38:01 +08:00
10cc275970 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/qa/AskFragment.kt
2019-03-29 17:03:41 +08:00
21821d584e 光环助手V3.6.3 DEV(20190328-1830)测试问题汇总(前端)(1.6.7.13.14.15) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/479 2019-03-29 17:01:43 +08:00
6b8716eff8 补充社区搜索事件 MTA https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/478 2019-03-29 15:58:28 +08:00
47434e2943 处理了环助手V3.6.3 DEV(20190328-1830)测试问题汇总的(3,4,5,8,10,12) 2019-03-29 15:05:29 +08:00
4c3b327cff 完成数据统计需求 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/477 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/478 2019-03-29 11:00:37 +08:00
3454d13e48 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-28 20:55:58 +08:00
0aad7c59ee 源码引入matisse库 2019-03-28 20:55:49 +08:00
ee8e4e0338 修复社区文章无法置顶的问题 2019-03-28 18:29:50 +08:00
a430c51c97 让测试社区隐藏了也能点击进入 2019-03-28 18:20:53 +08:00
b59508e9e5 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-28 16:58:36 +08:00
08deac1dea 光环助手V3.6.3 DEV(20190327-1830)测试问题汇总(前端)(6.8.13.14.15) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/476 2019-03-28 16:58:28 +08:00
a2dc3f3d5b 修复了部分 光环助手V3.6.3 DEV(20190327-1830)测试问题 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/476 2019-03-28 16:25:42 +08:00
679cfab088 社区搜索历史页面间距微调 2019-03-28 10:11:22 +08:00
9144595aaf 修复打包错误问题 2019-03-27 18:44:36 +08:00
8a545180a2 文章详情-评论详情UI微调 2019-03-27 17:37:56 +08:00
17c5793558 增加关闭评论确定弹窗 2019-03-27 16:15:05 +08:00
8afc346a2c 添加测试用的推送点击 toast 2019-03-27 15:49:35 +08:00
026bb7f67b 添加 CSS 和 JS 的外联依赖 2019-03-27 15:48:39 +08:00
b971e7dbf6 添加敏感词错误码 2019-03-27 15:48:00 +08:00
ec39ef16e4 优化社区搜索历史数据库操作 2019-03-27 11:14:51 +08:00
ae07bacbb7 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-27 10:41:44 +08:00
0f0d8da6cd merge 2019-03-27 10:41:37 +08:00
2a1c99efac 社区搜索热门增加置顶功能 2019-03-27 10:40:01 +08:00
caa89d3f4c 修复了回答详情列表较长上下滑动时会存在偏移的问题 2019-03-27 10:26:24 +08:00
1602816d08 调整回答详情上下滑动动画距离 2019-03-26 19:58:50 +08:00
1062cf5924 处理一些内存泄漏问题 2019-03-26 19:45:46 +08:00
f6e5cd3fd7 更新微信分享、登录SDK 2019-03-26 18:14:06 +08:00
c675196cb2 修复一些闪退问题 2019-03-26 16:35:21 +08:00
8b9c2668d1 完成3月第4周需求汇总 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/475 2019-03-26 15:54:43 +08:00
c1a927ed88 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-26 15:09:56 +08:00
4d4416c1df 社区搜索增加文章和用户模块 2019-03-26 15:09:46 +08:00
f4833983c0 完成3月第3周需求汇总 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/473 2019-03-26 11:24:05 +08:00
89eb99d813 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-25 18:28:00 +08:00
683a68d179 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt
#	app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
2019-03-25 18:26:13 +08:00
598af67338 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/qa/answer/detail/AnswerDetailFragment.kt
#	app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
2019-03-25 18:25:41 +08:00
d9d0ffc3b9 基本完成社区前端优化需求汇总 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/470 2019-03-25 18:16:18 +08:00
4d8e04580e 1.问答模块增加提问悬浮按钮
2.问答搜索增加默认搜索文案
3.问答搜索增加热门搜索区域
2019-03-25 18:15:17 +08:00
cfaddf2f22 基本完成社区版主权限强化需求 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/471 2019-03-25 16:45:42 +08:00
c72b194107 优化问答模块社区隐藏的交互 2019-03-25 14:27:09 +08:00
d7f33ff8b1 修复编译问题 2019-03-23 17:33:31 +08:00
91e491b66a 基本完成回答详情与社区文章详情优化 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/463 2019-03-23 17:26:16 +08:00
31b7e40ab0 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-22 18:58:53 +08:00
f2b094fff0 统一内容数值显示规则 完成 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/468 2019-03-22 18:54:55 +08:00
185ee7f0f4 调整选择游戏社区的排序,已安装相应游戏的放到最前 2019-03-22 18:25:14 +08:00
f446b15f7a Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-22 18:01:03 +08:00
52a833f18b 社区文章/回答 富文本编辑框统一插入样式 2019-03-22 18:00:51 +08:00
37fc68977c 根据接口调整回答详情的可拖动切换设定 2019-03-22 15:50:11 +08:00
96ee71a594 Merge remote-tracking branch 'origin/dev' into dev 2019-03-22 10:55:35 +08:00
1c2dda9353 基本完成提问与问题详情优化需求 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/464 2019-03-22 10:55:07 +08:00
96a9fd0ad7 富文本编辑框增加引用样式 2019-03-22 10:51:37 +08:00
c53c27e350 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-21 15:25:39 +08:00
fd4f32bb3c 回答编辑框增加各种内容样式 2019-03-21 15:25:31 +08:00
cbd2d8ed6c 修复图片上传闪退BUG 2019-03-20 18:32:11 +08:00
3dd06bc620 简单处理问题页面多张图片上传 2019-03-20 18:28:17 +08:00
3a829e1cfd 重构回答编辑 2019-03-20 15:40:48 +08:00
183e1a85c3 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-20 10:55:09 +08:00
6b696234ab 回答编辑支持批量插入图片 2019-03-20 10:54:58 +08:00
21ac1d1f17 基本完成答案详情上下滑动功能,待接口数据再调试 2019-03-20 10:23:33 +08:00
4163b81f70 Merge head 2019-03-19 18:10:34 +08:00
6c3268ce72 简单包裹答案详情页面以实现上下拖拽切换回答 2019-03-19 18:08:06 +08:00
4d87f86fcd Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-19 14:40:20 +08:00
4a37401dc2 RichEditor增加元件样式回调 2019-03-19 14:40:06 +08:00
8cf90193fc 修复一个数组越界造成的闪退问题 2019-03-18 16:12:27 +08:00
9942a51cad Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-11 18:24:47 +08:00
4980d96c8c 修复当后台返回错误的游戏标签时会闪退的问题 2019-03-11 18:24:37 +08:00
f32c8748ed Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-03-11 18:10:26 +08:00
7b886679e1 修改礼包图标大小 2019-03-11 18:08:52 +08:00
2620c04b09 捕抓闪退异常 (ObservableUtil 这个地方贡献了得有40%的闪退量) 2019-03-10 10:07:03 +08:00
c22157f2f5 修复了关注页面被销毁网络回调回来会导致闪退的问题 2019-03-08 09:44:54 +08:00
09f02bc225 修复插件化隐藏后无法一键修复问题 2019-03-07 15:57:38 +08:00
9fc9549a28 光环前端需求汇总(2019年3月第1周)(1.4.6.7.8)https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/461 2019-03-07 14:55:35 +08:00
0099afad09 update changelog 2019-03-04 10:00:08 +08:00
3e512634c6 tinkerBase:3.6.2 2019-03-04 09:51:55 +08:00
7045354808 修复推送系统通道内容乱码问题 2019-02-28 23:25:22 +08:00
dbcc97a250 修复版本说明弹窗圆角 2019-02-28 19:28:20 +08:00
050081b7b1 修复版本说明弹窗大小 修改求版本文案 2019-02-28 18:04:57 +08:00
993d1e7635 UI调整 2019-02-28 10:07:48 +08:00
a86a3c1f71 修复了游戏详情下载按钮文字过多导致超出可是范围的问题 2019-02-27 17:54:41 +08:00
b0a192ad9a 修复了未登录时游戏动态的热门推荐区域不显示的问题 2019-02-27 17:31:51 +08:00
ea7b478c6b Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-02-27 16:23:01 +08:00
b673383f59 修复文章详情引用评论隐藏后没有显示"该内容已被隐藏"问题 2019-02-27 16:22:27 +08:00
06ae366b74 修复隐藏入口后一键修复无法即时更新页面问题 2019-02-27 16:20:57 +08:00
6b9cf7094e 修复关注页面刷新不及时的问题 2019-02-27 15:45:38 +08:00
5ae22bd2bc 修复了用户没有登录也能看到消息中心推送的问题 2019-02-27 10:40:46 +08:00
e951551531 修复了答案详情点击更多会闪退的问题 2019-02-27 10:39:50 +08:00
272e5fb6cc 调整专栏阅读日志的默认值 2019-02-26 14:49:42 +08:00
7dc17d09c1 记录专栏的阅读位置信息 2019-02-26 14:29:39 +08:00
cfacbe739d 修复一些空指针异常 2019-02-26 10:10:29 +08:00
0a72226ba5 下载平台面板增加翻页提示 2019-02-25 10:56:25 +08:00
5f22a14643 整理部分代码 2019-02-24 15:14:42 +08:00
5562e38c2f Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-02-24 11:16:58 +08:00
f9027f7a61 消息中心样式修改 2019-02-24 11:16:46 +08:00
6d0e437ad4 完成 MTA 统计需求 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/456 2019-02-23 11:40:19 +08:00
3abc53d3b3 完成首页游戏替换功能 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/447 2019-02-23 10:33:55 +08:00
d0e4c2c3ab 补充注释 2019-02-22 15:39:09 +08:00
5be50c1638 修复数据统计缺失社区ID的问题 2019-02-22 15:38:31 +08:00
7c525aec79 推送功能优化 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/451 2019-02-22 15:35:11 +08:00
63d5edf892 光环前端需求汇总(2019年2月第4周)(2.3.6.7)https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/452 2019-02-22 15:32:34 +08:00
c9f2cf178a 去掉推送通知的本地过滤 2019-02-22 10:14:37 +08:00
fc98de3bc0 更换广点通接入帐号 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/454 2019-02-22 09:59:36 +08:00
dd8360f5e8 游戏下载面板增加公告(补充) 2019-02-21 11:13:06 +08:00
bc9b815b47 DownloadDialog 去除单例 2019-02-20 14:41:15 +08:00
2a93995221 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-02-20 10:32:15 +08:00
0e93f6521c 版本升为3.6.2 2019-02-20 10:32:09 +08:00
b3a6d0ce94 修复横排专题的曝光出现内容错乱的问题 2019-02-19 18:11:38 +08:00
de60d05190 插件游戏求版本功能完善 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/450#note_17274 2019-02-19 15:42:22 +08:00
2a2ce9a490 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-02-19 11:32:42 +08:00
639644e3c3 游戏下载面板增加公告功能 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/449#note_17186 2019-02-19 11:30:52 +08:00
2378e6e94e 基本完成首页游戏替换功能(本地测试通过,暂未与后台调试) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/447 2019-02-18 15:33:12 +08:00
87d9feae70 修改 Gson 的对象化实现,避免类型擦除 2019-02-18 15:27:49 +08:00
4a93d129bb 游戏下载面板增加公告 2019-02-16 15:46:15 +08:00
39e5e2e9f9 渠道包功能开关控制规则优化(未测试) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/448 2019-02-15 16:07:30 +08:00
8a5f777c65 社区和文章评论被删除的默认文案颜色修改 2019-02-14 10:48:53 +08:00
22c693e042 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-02-13 18:25:13 +08:00
36d04f5841 意见反馈修改 光环前端需求汇总(2019年2月第3周)(8.9.10.11) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/445#note_17027 2019-02-13 18:25:05 +08:00
409123337d 统一游戏动态和我的关注页面的游戏推荐样式 2019-02-13 17:32:06 +08:00
b180a210cb Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-02-13 15:38:40 +08:00
32dfdc4d08 更改草稿刷新逻辑 光环前端需求汇总(2019年2月第3周)(3) 2019-02-13 15:38:35 +08:00
4d46888995 修复更新非活跃状态的页面造成的闪退问题 2019-02-13 14:27:31 +08:00
69db836231 修复问题详情和答案详情页面会丢失部分阅读时长统计的问题 2019-02-12 17:46:54 +08:00
f82b9ad308 修复进入有视频的游戏详情时会造成手机被静音的问题 2019-02-12 15:14:46 +08:00
3ac91b1216 修复重复初始化七陌客服SDK造成后台产生空的聊天条目的问题 2019-02-11 15:36:05 +08:00
8d4b3e0851 修复更新非活跃状态的页面造成的闪退问题 2019-02-11 10:39:11 +08:00
67d8f46217 反馈图标大小自适应 2019-01-30 17:18:57 +08:00
f357136936 update CHANGELOG
3.6.1 Tinker Base
2019-01-30 15:48:00 +08:00
389 changed files with 14547 additions and 4726 deletions

View File

@ -30,4 +30,16 @@
- 删除TINKER_VERISON_NAME
- tinker打包方式变更(以小版本作为Base包,防止与数据后台小版本更新发生冲突)
* 社区增加版主功能(版主可以对存在的相关内容进行修改/隐藏操作,内容包括问题/回答/回答评论)
* 社区互动引导优化(问答推荐增加`推荐关注`,回答详情增加一些交互动效)
* 社区互动引导优化(问答推荐增加`推荐关注`,回答详情增加一些交互动效)
### Ver 3.6.1
* 可以后台控制关闭资讯功能
* 版块、分类、专题详情、游戏详情、礼包详情增加预览骨架
* 下载按钮状态可以通过接口屏蔽相应的包
### Ver 3.6.2
* 资讯/问答入口和插件功能线上控制(不可逆)
* 首页不显示已安装的游戏
* 插件求版本功能增加内部跳转
* 下载面板增加公告和版本说明功能
* 接入腾讯`广点通`(广告)

View File

@ -273,6 +273,7 @@ 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 project(':libraries:gid')
implementation project(':libraries:LGLibrary')
@ -280,9 +281,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()) {

View File

@ -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
@ -398,6 +393,15 @@
</intent-filter >
</activity >
<activity
android:name="${applicationId}.wxapi.WXEntryActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:exported="true"
android:launchMode="singleTop"
android:screenOrientation = "portrait" >
</activity>
<provider
android:name = "android.support.v4.content.FileProvider"
android:authorities = "${applicationId}"

View File

@ -4,12 +4,14 @@
<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 type="text/javascript" src="https://resource.ghzs.com/js/halo_app.js"></script>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/10.15.0/lazyload.min.js"></script>-->
</body>
</html>

View File

@ -14,6 +14,17 @@
* limitations under the License.
*/
// alert("")
// link block
// var html = "<div style = \"background:#f5f5f5;padding:10px;\", contenteditable=\"false\", spellcheck=\"false\" >\n" +
// "<font style = \"display: inline-block;white-space: nowrap;max-width: 100%;overflow: hidden; text-overflow:ellipsis;\" size = \"4\" >In HTML and XHTML, the blockquote element defines</font>\n" +
// "<br>\n" +
// "<font style = \"display: inline-block;white-space: nowrap;max-width: 100%;overflow: hidden; text-overflow:ellipsis;\", size = \"3\" >In HTML and XHTML, the blockquote element defines</font>\n" +
// "</div>" +
// "<br>\n"
// document.execCommand('insertHTML', false, html);
var RE = {};
RE.currentSelection = {
@ -94,16 +105,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 +169,7 @@ RE.setFontSize = function(fontSize){
RE.setHeading = function(heading) {
document.execCommand('formatBlock', false, '<h'+heading+'>');
RE.sendElementNameToNative()
}
RE.setIndent = function() {
@ -190,6 +194,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,12 +204,6 @@ 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");
@ -439,5 +440,34 @@ RE.editor.addEventListener("keyup", function(e) {
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()
});
// 返回组件标签 多个标签以"空格"划分
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 + " "
}
window.OnCursorChangeListener.onElements(elements);
}
}
}

View File

@ -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());

View File

@ -0,0 +1,181 @@
package com.gh.base
import android.annotation.SuppressLint
import android.content.ClipboardManager
import android.content.Context
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.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)
@SuppressLint("AddJavascriptInterface")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 防止个别手机在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)
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
}
}
}
private inner class OnCursorChangeListener {
@JavascriptInterface
fun onElements(elements: String) {
Utils.log("-----------------------")
Utils.log(elements)
Utils.log(mRichEditor.html)
Utils.log("-----------------------")
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(), "&nbsp;").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_QUOTE = " blockquote "
}
}

View File

@ -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();
}

View File

@ -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
}
/**
* 规则:最多三条消息,以旧换新
*

View File

@ -1,5 +1,6 @@
package com.gh.common
import android.annotation.SuppressLint
import android.preference.PreferenceManager
import com.gh.base.GHUmengNotificationService
import com.gh.common.constant.Config
@ -77,6 +78,7 @@ object PushManager {
})
}
@SuppressLint("CheckResult")
@JvmStatic
fun getAndSetAlias() {
if (deviceToken.isNullOrEmpty()) {

View File

@ -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
}

View File

@ -1,6 +1,5 @@
package com.gh.common.constant;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
@ -8,6 +7,7 @@ import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.gh.common.util.GsonUtils;
import com.gh.common.util.PackageHelper;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.entity.NewsEntity;
import com.gh.gamecenter.entity.SettingsEntity;
@ -51,9 +51,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;
@ -64,23 +69,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) {
getPreferences().edit().putString("errMsg", errMsg).apply();
}
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;
@ -104,6 +106,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;
@ -114,8 +120,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;
}
}
@ -125,6 +134,10 @@ 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;
@ -152,20 +165,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();
@ -195,4 +208,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();
}
}

View File

@ -11,27 +11,27 @@ 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
@ -51,12 +51,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)
}
}

View File

@ -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,

View File

@ -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),

View File

@ -5,6 +5,7 @@ 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
@ -27,10 +28,15 @@ 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(
@ -71,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()

View File

@ -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) {

View File

@ -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
}

View File

@ -21,78 +21,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 +66,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.contains(MeEntity.HIDE_ANSWER_COMMENT)
|| it.moderatorPermissions.contains(MeEntity.TOP_ANSWER_COMMENT)
|| it.moderatorPermissions.contains(MeEntity.HIDE_COMMUNITY_ARTICLE)
|| it.moderatorPermissions.contains(MeEntity.TOP_COMMUNITY_ARTICLE_COMMENT))) {
dialogOptions.add("管理")
}
}
@ -116,7 +80,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,43 +96,63 @@ 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)) {
if (me.moderatorPermissions.contains(MeEntity.TOP_ANSWER_COMMENT)
|| me.moderatorPermissions.contains(MeEntity.TOP_COMMUNITY_ARTICLE_COMMENT)) {
dialogOptions.add(highlight)
}
if (me.moderatorPermissions.contains(MeEntity.HIDE_ANSWER_COMMENT)) {
if (me.moderatorPermissions.contains(MeEntity.HIDE_ANSWER_COMMENT)
|| me.moderatorPermissions.contains(MeEntity.HIDE_COMMUNITY_ARTICLE_COMMENT)) {
dialogOptions.add(hide)
}
@ -179,9 +163,11 @@ object CommentHelper {
}
val disabledOptions = arrayListOf<String>()
if (comment.priority != 0) {
disabledOptions.add(highlight)
}
comment.me?.let {
if (it.isAnswerCommented) {
disabledOptions.add(highlight)
@ -191,7 +177,6 @@ object CommentHelper {
DialogUtils.showListDialog(context, dialogOptions, disabledOptions) {
when (it) {
highlight -> {
if (comment.priority != 0) {
Utils.toast(context, "评论已经置顶")
return@showListDialog
@ -204,77 +189,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 (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
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, content,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.highlightAnswerComment(answerId, comment.id)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(highlightObserver)
}, null)
} else {
DialogUtils.showAlertDialog(context, highlight, content,
"确定", "取消", {
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 (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
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, content,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.hideAnswerComment(answerId, comment.id)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(hideObserver)
}, null)
} else {
DialogUtils.showAlertDialog(context, hide, content,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.hideCommunityArticleComment(communityId, articleId, comment.id)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(hideObserver)
}, null)
}
}
}
}

View File

@ -458,7 +458,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 +476,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 +518,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 +536,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 {

View File

@ -1,45 +0,0 @@
package com.gh.common.util
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>()
@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
}
}
})
}
@JvmStatic
fun isCommunityAvailable(communityId: String?): Boolean {
communityId?.let {
if (availableCommunityList.isEmpty()) return true
for (entity in availableCommunityList) {
if (communityId == entity.id) {
return true
}
}
}
return false
}
}

View File

@ -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;
@ -238,7 +239,6 @@ public class DeviceUtils {
return "";
}
// ping domain
public static String ping(String domain) {
try {
@ -257,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);
}
}

View File

@ -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))

View File

@ -111,6 +111,7 @@ 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 void jumpActivity(Context context, Bundle bundle) {

View File

@ -29,7 +29,7 @@ object ErrorHelper {
* [important] 用来标识有同样错误码可以触发两种处理时,为 true 时选择重要的
*/
fun handleError(context: Context, errorString: String?, important: Boolean = false) {
val errorEntity = errorString?.fromObject<ErrorEntity>()
val errorEntity = errorString?.toObject<ErrorEntity>()
if (errorEntity == null) {
Utils.toast(context, R.string.post_failure_hint)

View File

@ -6,6 +6,7 @@ import android.support.v4.app.Fragment
import android.support.v4.app.FragmentActivity
import android.support.v4.view.ViewPager
import android.view.View
import com.google.gson.reflect.TypeToken
/**
* 创建以 activity 为观察者上下文的 viewModel
@ -73,9 +74,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
@ -83,18 +84,18 @@ 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.fastDoubleClickAction(interval: Long, action: (() -> Unit)? = null) {
fastDoubleClickAction(id, interval, action)
fun View.debounceActionWithInterval(interval: Long = 300, action: (() -> Unit)? = null) {
debounceActionWithInterval(this.id, interval, action)
}

View File

@ -0,0 +1,95 @@
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: List<String>): GameEntity? {
collectionId?.let {
val collection = gameCollectionList.find { it.id == collectionId }
collection?.let {
val game = collection.data?.find { game -> findUniqueGame(game, gameIdList) }
game?.let {
collection.data?.remove(game)
// 产品说要记录补充专题的曝光数,所以这个游戏附带了所在专题的名字
game.subjectName = collection.name
return game
}
}
}
return null
}
private fun findUniqueGame(game: GameEntity, gameIdList: List<String>): Boolean {
for (apk in game.getApk()) {
// 检查本地是否已安装该游戏,已过滤那部分框架服务的包名
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
return false
}
}
return !gameIdList.contains(game.id) && !TextUtils.isEmpty(game.id)
}
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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)
}
}

View File

@ -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 {
@ -258,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大图是否被缓存
@ -289,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?) {

View File

@ -70,9 +70,7 @@ public class InstallUtils {
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());
}
}
}

View File

@ -8,6 +8,7 @@ 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;
@ -23,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");
@ -34,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();
}
@ -56,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();
}
@ -74,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();
}

View File

@ -318,6 +318,9 @@ public class LoginUtils {
case 403016:
Utils.toast(context, "内容违规,请修改后再保存");
break;
case 403021:
Utils.toast(context, "内容可能包含敏感信息,请修改后再提交");
break;
case 403801:
Utils.toast(context, "获取验证码太频繁,请稍后再试");
break;

View File

@ -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;
@ -308,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;
@ -376,7 +374,7 @@ public class MessageShareUtils {
}
}
}
} catch (FileNotFoundException e) {
} catch (Exception e) {
Utils.log("消息分享异常" + e.toString());
e.printStackTrace();
} finally {

View File

@ -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
}

View File

@ -3,13 +3,24 @@ package com.gh.common.util
import android.content.Context
import android.content.pm.ApplicationInfo
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,13 +34,27 @@ object PackageHelper {
@JvmStatic
fun refreshLocalPackageList() {
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()
}
/*

View File

@ -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() {

View File

@ -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;
@ -296,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);
}

View File

@ -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);
}
}

View File

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

View File

@ -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
@ -18,6 +19,7 @@ import okhttp3.ResponseBody
import org.json.JSONObject
import java.io.File
object UploadImageUtils {
enum class UploadType {
@ -27,7 +29,7 @@ object UploadImageUtils {
icon
}
// 不处理图片,只是单纯的上
// 不处理图片,只是单纯的上
fun uploadImage(type: UploadType, imgPath: String, listener: OnUploadImageListener): Disposable {
return Single.just(imgPath)
.subscribeOn(Schedulers.computation())
@ -99,7 +101,9 @@ object UploadImageUtils {
})
}
fun compressAndUploadImageList(type: UploadType, imgs: List<String>, compressGif: Boolean, listener: OnUploadImageListListener) {
@SuppressLint("CheckResult")
fun compressAndUploadImageList(type: UploadType, imgs: List<String>, compressGif: Boolean, listener: OnUploadImageListListener): Disposable? {
var subscription: Disposable? = null
val postImageList = HashMap<String, String>()
Observable.create(ObservableOnSubscribe<Map<String, String>> {
@ -110,9 +114,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,6 +127,7 @@ 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")
@ -134,6 +142,7 @@ object UploadImageUtils {
}
override fun onFailure(exception: Exception) {
if (subscription?.isDisposed == true) return
it.onError(exception)
}
})
@ -145,6 +154,7 @@ object UploadImageUtils {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<Map<String, String>> {
override fun onSubscribe(d: Disposable) {
subscription = d
}
override fun onComplete() {
@ -162,6 +172,7 @@ object UploadImageUtils {
override fun onError(e: Throwable) {
}
})
return subscription
}
// 同步调用->避免在主线程调用以免阻塞主线程

View File

@ -1,32 +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.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;
@ -55,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) {
@ -84,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);
}
// 自动下载并翻到相应页面
@ -118,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;
@ -153,6 +163,31 @@ public class DownloadDialog implements OnCollectionCallBackListener {
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;
@ -175,7 +210,6 @@ public class DownloadDialog implements OnCollectionCallBackListener {
});
popupWindow.setOnDismissListener(() -> {
isShow = false;
EventBus.getDefault().unregister(DownloadDialog.this);
DownloadManager.getInstance(mContext).removeObserver(dataWatcher);
});
@ -196,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();
@ -376,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) {

View File

@ -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,7 +96,11 @@ 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) {
mPaint.setColor(DOWNLOAD_IMAGE_STYLE == mDownloadStyle ? Color.BLACK : Color.WHITE); // 反向颜色

View File

@ -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();
}
}

View File

@ -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;
// }
//}

View File

@ -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
@ -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,24 +123,20 @@ 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)
}
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)
}
@ -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

View File

@ -327,10 +327,6 @@ public class RichEditor extends WebView {
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 + "','" +
@ -373,6 +369,86 @@ public class RichEditor extends WebView {
exec("javascript:RE.focus();");
}
public void insertLink(String href, String title) {
exec("javascript:RE.prepareInsert();");
exec("javascript:RE.insertLink('" + href + "', '" + title + "');");
}
public void removeFormat() {
exec("javascript:RE.removeFormat();");
}
public void setHeading(int heading) {
exec("javascript:RE.setHeading('" + heading + "');");
}
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);

View File

@ -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)
}
}
}
}

View File

@ -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);
}

View File

@ -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);
@ -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()) {

View File

@ -27,12 +27,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;
@ -136,7 +136,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
@ -260,7 +259,12 @@ public class MainActivity extends BaseActivity {
isNewFirstLaunch = mSp.getBoolean("isNewFirstLaunchV" + PackageUtils.getVersionName(), true);
if (isNewFirstLaunch) {
LogUtils.uploadDevice(DeviceTokenUtils.getLaunchType());
// 延时两秒提交 APP 启动日志的,避免提交时还没获取到 GID
AppExecutor.getUiExecutor().executeWithDelay(() -> {
if (!this.isFinishing()) {
LogUtils.uploadDevice(DeviceTokenUtils.getLaunchType());
}
}, 2000L);
getPluginUpdate();
sendActivationInfo();
mSp.edit().putBoolean("isNewFirstLaunchV" + PackageUtils.getVersionName(), false).apply();
@ -279,9 +283,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, "发生闪退", "光环助手刚刚发生了闪退,马上反馈以帮助我们更好地修复问题?(只需简单描述你刚才的操作)"
, "暂不", "马上反馈",
@ -306,9 +310,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);
}
@ -550,11 +551,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"));
@ -707,7 +708,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 {

View File

@ -72,7 +72,7 @@ public class SkipActivity extends BaseActivity {
case HOST_SUGGESTION:
String platform = uri.getQueryParameter(KEY_PLATFORM);
String platformName = PlatformUtils.getInstance(this).getPlatformName(platform);
String content = String.format("%s-%s-V%s",
String content = String.format("%s-%s-V%s",
uri.getQueryParameter(KEY_GAME_NAME),
TextUtils.isEmpty(platformName) ? platform : platformName,
uri.getQueryParameter(KEY_VERSION));

View File

@ -25,6 +25,7 @@ import com.gh.common.exposure.meta.MetaUtil;
import com.gh.common.util.DeviceTokenUtils;
import com.gh.common.util.DeviceUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.GameRepositoryHelper;
import com.gh.common.util.GdtHelper;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.PlatformUtils;
@ -210,6 +211,8 @@ public class SplashScreenActivity extends BaseActivity {
if (hasFocus && isFirst) {
isFirst = false;
GameRepositoryHelper.getGameRepository(this);
HaloApp.getInstance().getMainExecutor().execute(() -> {
// 第一次启动把package.txt文件内容加载进数据库
FilterManager filterManager = new FilterManager(getApplicationContext());

View File

@ -38,10 +38,13 @@ import com.gh.common.util.DialogUtils;
import com.gh.common.util.DirectUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.GsonUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.UploadImageUtils;
import com.gh.gamecenter.entity.ErrorEntity;
import com.gh.gamecenter.entity.InstallGameEntity;
import com.gh.gamecenter.entity.SettingsEntity;
import com.gh.gamecenter.entity.SuggestionTypeEntity;
@ -128,6 +131,12 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
TextView mEmailName;
@BindView(R.id.tv_ad)
TextView mAdTv;
@BindView(R.id.suggest_platform_container)
View mPlatformContainer;
@BindView(R.id.suggest_platform_et)
TextView mPlatformEt;
@BindView(R.id.suggest_platform_title)
TextView mPlatformTitle;
public static final int MEDIA_STORE_REQUEST = 1;
public static final String SUGGESTION_HINT_TYPE = "SUGGESTION_HINT_TYPE";
@ -146,6 +155,7 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
private String mGameInfo;
private String mHideHint;
private String mSuggestContent;
private String mSuggestHintType;
private boolean mAgreePostPic;
@ -226,7 +236,7 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
mSuggestType = SuggestType.normal;
}
mSuggestContent = extras.getString(EntranceUtils.KEY_CONTENT);
String suggestHintType = extras.getString(EntranceUtils.KEY_SUGGEST_HINT_TYPE);
mSuggestHintType = extras.getString(EntranceUtils.KEY_SUGGEST_HINT_TYPE);
mHideHint = extras.getString(EntranceUtils.KEY_HIDE_SUGGEST_HINT, "");
mFunctionTypeName = getResources().getStringArray(R.array.suggest_function_type);
@ -238,10 +248,11 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
mAdTv.setVisibility(View.VISIBLE);
mAdTv.setText(ad.getTitle());
mAdTv.setOnClickListener(v -> {
MtaHelper.onEvent("广告位统计", "意见反馈_功能收录", ad.getTitle());
DirectUtils.directToLinkPage(this,
ad.toLinkEntity(),
"意见反馈",
"意见反馈" + mSuggestType.getType());
"(意见反馈)",
"意见反馈-功能收录-广告位");
});
}
@ -258,19 +269,26 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
mSuggestPicRv.setAdapter(mAdapter);
if (!TextUtils.isEmpty(mSuggestContent)) {
mSuggestContentEt.setText(mSuggestContent);
if (mSuggestType == SuggestType.gameQuestion && "game".equals(mSuggestHintType)) {
mSuggestContentEt.setText("问题反馈:");
mSuggestSelectGame.setVisibility(View.GONE);
mSuggestGameName.setVisibility(View.VISIBLE);
mSuggestGameName.setText(mSuggestContent);
} else {
mSuggestContentEt.setText(mSuggestContent);
}
mSuggestContentEt.setSelection(mSuggestContentEt.getText().length());
}
initSuggest(mSuggestType);
String suggestionType = sp.getString(SUGGESTION_HINT_TYPE, null);
if (!TextUtils.isEmpty(suggestHintType) && !TextUtils.isEmpty(suggestionType)) {
if (!TextUtils.isEmpty(mSuggestHintType) && !TextUtils.isEmpty(suggestionType)) {
Gson gson = new Gson();
SuggestionTypeEntity typeEntity = gson.fromJson(suggestionType, SuggestionTypeEntity.class);
if (typeEntity != null) {
switch (suggestHintType) {
case "plugin":
switch (mSuggestHintType) {
case EntranceUtils.KEY_PLUGIN:
List<String> plugin = typeEntity.getPlugin();
if (plugin != null && plugin.size() > 0) {
showHintDialog(plugin);
@ -335,9 +353,18 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
mSuggestTypeContainer.setVisibility(View.GONE);
mSuggestGameLl.setVisibility(View.GONE);
} else if (type == SuggestType.gameQuestion) {
mSuggestContentEt.setHint("请写上游戏名字,以及具体遇到的问题... \n ↓↓你还可以上传截图");
mSuggestTypeContainer.setVisibility(View.GONE);
mSuggestGameLl.setVisibility(View.GONE);
if (!EntranceUtils.KEY_PLUGIN.equals(mSuggestHintType)) {
mSuggestContentEt.setHint("请描述具体遇到的问题... \n ↓↓你还可以上传截图");
mSuggestGameLl.setVisibility(View.VISIBLE);
mPlatformContainer.setVisibility(View.VISIBLE);
mGameNameTitle.setText(Html.fromHtml(getString(R.string.suggestion_game_name)));
mPlatformTitle.setText(Html.fromHtml(getString(R.string.suggestion_platform_name)));
} else {
mSuggestContentEt.setHint("请写上游戏名字,以及具体遇到的问题... \n ↓↓你还可以上传截图");
mSuggestGameLl.setVisibility(View.GONE);
mPlatformContainer.setVisibility(View.GONE);
}
} else if (type == SuggestType.gameCollect) {
mSuggestGameLl.setVisibility(View.VISIBLE);
mGameNameTitle.setText(Html.fromHtml(getString(R.string.suggestion_game_name)));
@ -456,6 +483,12 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
}
}
if (mPlatformContainer.getVisibility() == View.VISIBLE &&
TextUtils.isEmpty(mPlatformEt.getText().toString())) {
toast("请填写版本");
return;
}
String entrance = "我的光环-反馈-[提交]";
if (!TextUtils.isEmpty(mSuggestContent)) {
switch (mSuggestContent) {
@ -470,25 +503,14 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
break;
}
}
CheckLoginUtils.checkLogin(this, entrance, () -> {
if (TextUtils.isEmpty(email)) {
if (mSuggestType == SuggestType.functionSuggest || mSuggestType == SuggestType.gameCollect) {
toast("请填写联系方式");
} else {
showConfirmDialog(email);
}
} else {
postDialog = WaitingDialogFragment.newInstance(getString(R.string.dialog_feedback_doing));
postDialog.show(getSupportFragmentManager(), null);
List<String> fileList = mAdapter.getFileList();
if (fileList != null && fileList.size() > 0) {
postPic(email);
} else {
initPostData(email, null);
}
}
});
// 闪退反馈不需要反馈(由闪退提示框跳转)
if (mSuggestType == SuggestType.crash && !mHideHint.isEmpty()) {
postSuggestion(email);
} else {
CheckLoginUtils.checkLogin(this, entrance, () -> {
postSuggestion(email);
});
}
break;
case R.id.suggest_game_container:
showSelectDialog();
@ -528,6 +550,26 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
}
}
private void postSuggestion(String email) {
if (TextUtils.isEmpty(email)) {
if (mSuggestType == SuggestType.functionSuggest || mSuggestType == SuggestType.gameCollect) {
toast("请填写联系方式");
} else {
showConfirmDialog(email);
}
} else {
postDialog = WaitingDialogFragment.newInstance(getString(R.string.dialog_feedback_doing));
postDialog.show(getSupportFragmentManager(), null);
List<String> fileList = mAdapter.getFileList();
if (fileList != null && fileList.size() > 0) {
postPic(email);
} else {
initPostData(email, null);
}
}
}
// 弹出确认对话框
private void showConfirmDialog(final String email) {
@ -598,8 +640,9 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
params.put("suggestion_type", mSuggestType.getType());
String message;
String content = mSuggestContentEt.getText().toString().trim();
if (mSuggestType == SuggestType.gameCollect) {
message = mGameInfo + "" + mSuggestContentEt.getText().toString().trim();
message = mGameInfo + "" + content;
} else if (mSuggestType == SuggestType.functionSuggest) {
String typeName;
if (mFunctionType == 3) {
@ -607,9 +650,15 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
} else {
typeName = mFunctionTypeName[mFunctionType];
}
message = mGameInfo + "" + typeName + "" + mSuggestContentEt.getText().toString().trim();
message = mGameInfo + "" + typeName + "" + content;
} else if (mSuggestType == SuggestType.gameQuestion) {
if (EntranceUtils.KEY_PLUGIN.equals(mSuggestHintType)) {
message = "【插件问题】" + content;
} else {
message = mSuggestGameName.getText() + "-" + mPlatformEt.getText() + "" + content;
}
} else {
message = mSuggestContentEt.getText().toString().trim();
message = content;
if (mSuggestType == SuggestType.crash) {
params.put("log", readFromFile());
}
@ -627,18 +676,19 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
}
}
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
jsonObject.toString());
sendSuggestion(jsonObject);
sendSuggestion(body);
// 创建一条信息至七陌客服
String feedbackType = "意见反馈-" + mSuggestType.getType();
ImManager.sendFeedbackMessage(feedbackType + ": " + message);
if (CheckLoginUtils.isLogin()) {
// 创建一条信息至七陌客服
String feedbackType = "意见反馈-" + mSuggestType.getType();
ImManager.sendFeedbackMessage(feedbackType + ": " + message);
}
}
private void sendSuggestion(final RequestBody body) {
private void sendSuggestion(JSONObject jsonObject) {
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
jsonObject.toString());
RetrofitManager.getInstance(this).getApi().postSuggestion(body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@ -669,15 +719,31 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
try {
if (e != null && e.code() == 403) {
String string = e.response().errorBody().string();
JSONObject object = new JSONObject(string);
int code = object.getInt("code");
if (code == 403052) {
ErrorEntity error = GsonUtils.fromJson(string, ErrorEntity.class);
if (error.getCode() == 403052) {
DialogUtils.showAlertDialog(SuggestionActivity.this, "提醒", "你已经提交过相同的反馈了"
, "关闭提交", "返回修改", () -> {
setResult(SUGGEST_TYPE_REQUEST);
finish();
}, null);
return;
} else if (error.getCode() == 403062) {
DialogUtils.showAlertDialog(SuggestionActivity.this,
"提示", "光环助手已收录游戏:" + error.getData().getGameName(),
"查看游戏", "仍然提交", () -> {
GameDetailActivity.startGameDetailActivity(SuggestionActivity.this,
error.getData().getGameId(), "(意见反馈-游戏收录-存在相同游戏)");
}, () -> {
try {
jsonObject.put("again", true);
} catch (Exception e1) {
e1.printStackTrace();
}
postDialog = WaitingDialogFragment.newInstance(getString(R.string.dialog_feedback_doing));
postDialog.show(getSupportFragmentManager(), null);
sendSuggestion(jsonObject);
});
return;
}
}
} catch (Exception e1) {

View File

@ -4,10 +4,14 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -15,9 +19,12 @@ import com.gc.materialdesign.views.ProgressBarCircularIndeterminate;
import com.gh.base.BaseActivity;
import com.gh.base.OnRequestCallBackListener;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.TextHelper;
import com.gh.common.view.VerticalItemDecoration;
import com.gh.gamecenter.adapter.ToolBoxRvAdapter;
import com.gh.gamecenter.suggest.SuggestType;
import com.lightgame.utils.Util_System_Keyboard;
import com.lightgame.utils.Utils;
import butterknife.BindView;
import butterknife.OnClick;
@ -27,8 +34,16 @@ import butterknife.OnClick;
*/
public class ToolBoxActivity extends BaseActivity implements SwipeRefreshLayout.OnRefreshListener,
ToolBoxRvAdapter.OnSearchCallBackListener, OnRequestCallBackListener {
OnRequestCallBackListener {
@BindView(R.id.et_search)
public EditText searchEt;
@BindView(R.id.tv_search)
public TextView searchTv;
@BindView(R.id.tv_back)
public TextView backTv;
@BindView(R.id.toolbox_appbar)
AppBarLayout mAppBar;
@BindView(R.id.toolbox_rv)
RecyclerView mToolboxRv;
@BindView(R.id.reuse_none_data)
@ -46,16 +61,10 @@ public class ToolBoxActivity extends BaseActivity implements SwipeRefreshLayout.
private ToolBoxRvAdapter mRvAdapter;
private ToolBoxRvAdapter mNormalRvAdapter;
private boolean mIsSearch; // 记录页面状态 搜索页面/普通页面
private String mSearchKey; // 记录搜索关键字
Runnable runnable = new Runnable() {
@Override
public void run() {
changeAdapter(true);
}
};
Runnable runnable = () -> changeAdapter(true);
@NonNull
public static Intent getIntent(Context context, String entrance) {
@ -64,7 +73,6 @@ public class ToolBoxActivity extends BaseActivity implements SwipeRefreshLayout.
return intent;
}
@Override
protected int getLayoutId() {
return R.layout.activity_toolbox;
@ -81,7 +89,7 @@ public class ToolBoxActivity extends BaseActivity implements SwipeRefreshLayout.
mLayoutManager = new LinearLayoutManager(this);
mToolboxRv.setLayoutManager(mLayoutManager);
mRvAdapter = new ToolBoxRvAdapter(this, this, ToolBoxActivity.this, mIsSearch, mSearchKey);
mRvAdapter = new ToolBoxRvAdapter(this, this, mIsSearch, mSearchKey);
mToolboxRv.addItemDecoration(new VerticalItemDecoration(this, 8, false));
mToolboxRv.setAdapter(mRvAdapter);
@ -99,8 +107,52 @@ public class ToolBoxActivity extends BaseActivity implements SwipeRefreshLayout.
}
}
});
mAppBar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
if (verticalOffset == 0) {
mRefresh.setEnabled(true);
} else {
mRefresh.setEnabled(false);
}
int totalScrollRange = appBarLayout.getTotalScrollRange();
if (totalScrollRange == -verticalOffset) {
Util_System_Keyboard.hideSoftKeyboard(this);
}
});
initSearch();
}
private void initSearch() {
backTv.setOnClickListener(v -> search(false, searchEt.getText().toString()));
TextHelper.limitTheLengthOfEditText(searchEt, 20, () -> {
Utils.toast(this, "最多输入20字");
});
searchTv.setOnClickListener(v -> {
if (TextUtils.isEmpty(searchEt.getText().toString())) {
Utils.toast(this, R.string.search_hint);
return;
}
search(true, searchEt.getText().toString());
});
searchEt.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
Util_System_Keyboard.hideSoftKeyboard(this, searchEt);
}
});
searchEt.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
searchTv.performClick();
}
return false;
});
}
@OnClick({R.id.reuse_no_connection, R.id.reuse_none_data})
public void onClick(View view) {
if (view.getId() == R.id.reuse_no_connection) {
@ -113,7 +165,6 @@ public class ToolBoxActivity extends BaseActivity implements SwipeRefreshLayout.
SuggestionActivity.startSuggestionActivity(this, SuggestType.functionSuggest, null, null);
}
}
}
@Override
@ -122,7 +173,6 @@ public class ToolBoxActivity extends BaseActivity implements SwipeRefreshLayout.
mNoneData.setVisibility(View.GONE);
mNoConnection.setVisibility(View.GONE);
mLoading.setVisibility(View.GONE);
}
@Override
@ -156,7 +206,6 @@ public class ToolBoxActivity extends BaseActivity implements SwipeRefreshLayout.
mRefresh.postDelayed(runnable, 1000);
}
@Override
public void search(boolean isSearch, String searchKey) {
if (mNoneData.getVisibility() == View.VISIBLE) {
mNoneData.setVisibility(View.GONE);
@ -171,15 +220,26 @@ public class ToolBoxActivity extends BaseActivity implements SwipeRefreshLayout.
private void changeAdapter(boolean isRefresh) {
if (mIsSearch) {
mRvAdapter = new ToolBoxRvAdapter(this, this, this, mIsSearch, mSearchKey);
mRvAdapter = new ToolBoxRvAdapter(this, this, mIsSearch, mSearchKey);
} else {
if (mNormalRvAdapter != null && !isRefresh) {
mRvAdapter = mNormalRvAdapter;
} else {
mRvAdapter = new ToolBoxRvAdapter(this, this, this, mIsSearch, null);
mRvAdapter = new ToolBoxRvAdapter(this, this, mIsSearch, null);
mNormalRvAdapter = mRvAdapter;
}
}
mToolboxRv.setAdapter(mRvAdapter);
if (mSearchKey != null) {
searchEt.setText(mSearchKey);
searchEt.setSelection(searchEt.getText().length());
}
if (mIsSearch) {
backTv.setVisibility(View.VISIBLE);
} else {
backTv.setVisibility(View.GONE);
}
}
}

View File

@ -17,7 +17,7 @@ public class UserInfoEditActivity extends NormalActivity {
@NonNull
public static Intent getIntent(Context context, String editType) {
Bundle args = new Bundle();
args.putString(UserViewModel.KEY_EDITTYPE, editType);
args.putString(UserViewModel.KEY_EDIT_TYPE, editType);
return getTargetIntent(context, UserInfoEditActivity.class, UserInfoEditFragment.class, args);
}

View File

@ -338,7 +338,10 @@ public class ViewImageActivity extends BaseActivity implements OnPageChangeListe
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(container1);
dialog.show();
if (!isFinishing()) {
dialog.show();
}
reportTv.setOnClickListener(v -> {
findImageBM();

View File

@ -161,8 +161,10 @@ public class CommentDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
String content;
if (parent.getActive()) {
content = parent.getComment();
holder.quoteContentTv.setTextColor(mContext.getResources().getColor(R.color.text_5d5d5d));
} else {
content = mContext.getString(R.string.comment_hide_hint);
holder.quoteContentTv.setTextColor(mContext.getResources().getColor(R.color.text_d5d5d5));
}
holder.quoteContentTv.setText(content);
} else {

View File

@ -75,17 +75,21 @@ public class ImagePagerAdapter extends RecyclingPagerAdapter {
view.setOnClickListener(v -> {
int size = mSlideEntityList.size();
if (size == 0) return;
// 首页轮播图数据统计
DataLogUtils.uploadLunbotuLog(mContext, slideEntity.getType(),
slideEntity.getText(), String.valueOf(getPosition(position) % mSlideEntityList.size() + 1));
slideEntity.getText(), String.valueOf(getPosition(position) % size + 1));
String entrance = StringUtils.buildString("(游戏-专题:滚动图["
, slideEntity.getText()
, "=", slideEntity.getType()
, "=", String.valueOf(getPosition(position) + 1)
, "=", String.valueOf(size + 1)
, "])");
DataUtils.onMtaEvent(mContext, "轮播图", mSource, String.valueOf(getPosition(position) % mSlideEntityList.size() + 1));
DataUtils.onMtaEvent(mContext, "轮播图", mSource, String.valueOf(getPosition(position) % size + 1));
DirectUtils.directToLinkPage(mContext, slideEntity, entrance, "首页游戏");

View File

@ -20,6 +20,7 @@ import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.NewsUtils;
import com.gh.common.util.NumberUtils;
import com.gh.common.util.StringUtils;
import com.gh.common.util.TimestampUtils;
import com.gh.gamecenter.NewsDetailActivity;
@ -247,14 +248,10 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
private void initNewsDigestViewHolder(final NewsDigestViewHolder viewHolder) {
if (mConcernEntity.getViews() != 0) {
viewHolder.readNum.setText(String.valueOf(mConcernEntity.getViews()));
viewHolder.readNum.setText(NumberUtils.transSimpleCount(mConcernEntity.getViews()));
}
if (mConcernEntity.getCommentnum() > 999) {
viewHolder.commentnum.setText(R.string.thousand);
} else {
viewHolder.commentnum.setText(String.valueOf(mConcernEntity.getCommentnum()));
}
viewHolder.commentnum.setText(NumberUtils.transSimpleCount(mConcernEntity.getCommentnum()));
if (mConcernEntity.getBrief() != null) {
viewHolder.content.setText(Html.fromHtml(mConcernEntity.getBrief()));
@ -368,8 +365,10 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
String content;
if (parent.getActive()) {
content = parent.getComment();
holder.quoteContentTv.setTextColor(mContext.getResources().getColor(R.color.text_5d5d5d));
} else {
content = mContext.getString(R.string.comment_hide_hint);
holder.quoteContentTv.setTextColor(mContext.getResources().getColor(R.color.text_d5d5d5));
}
holder.quoteContentTv.setText(content);
} else {

View File

@ -3,12 +3,8 @@ package com.gh.gamecenter.adapter;
import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import com.gh.base.OnRequestCallBackListener;
import com.gh.common.util.ImageUtils;
@ -19,16 +15,12 @@ import com.gh.gamecenter.SuggestionActivity;
import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder;
import com.gh.gamecenter.adapter.viewholder.ReuseViewHolder;
import com.gh.gamecenter.adapter.viewholder.SearchViewHolder;
import com.gh.gamecenter.adapter.viewholder.ToolBoxViewHolder;
import com.gh.gamecenter.entity.ToolBoxEntity;
import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.gh.gamecenter.suggest.SuggestType;
import com.lightgame.adapter.BaseRecyclerAdapter;
import com.lightgame.utils.Util_System_Keyboard;
import com.lightgame.utils.Utils;
import java.util.ArrayList;
import java.util.List;
@ -47,29 +39,23 @@ import static com.gh.gamecenter.R.string.loading;
public class ToolBoxRvAdapter extends BaseRecyclerAdapter {
private OnRequestCallBackListener mCallBackListener;
private OnSearchCallBackListener mSearchListener;
private List<ToolBoxEntity> mEntityList;
private String mSearchKey;
private String mToken;
// private boolean mLoadConcernDataOver;
private boolean mIsSearch;
private boolean mIsLoading;
private boolean mIsOver;
private boolean mIsNetworkError;
private int mPage;
public ToolBoxRvAdapter(Context context, OnRequestCallBackListener listener, OnSearchCallBackListener searchListener,
boolean isSearch, String key) {
public ToolBoxRvAdapter(Context context, OnRequestCallBackListener listener, boolean isSearch, String key) {
super(context);
this.mIsSearch = isSearch;
this.mSearchKey = key;
mPage = 1;
mToken = UserManager.getInstance().getToken();
mSearchListener = searchListener;
mCallBackListener = listener;
mEntityList = new ArrayList<>();
loadData();
@ -121,31 +107,9 @@ public class ToolBoxRvAdapter extends BaseRecyclerAdapter {
});
}
// 去除重复数据(普通列表排除关注数据)
private static List<ToolBoxEntity> removeDuplicateData(List<ToolBoxEntity> sourceList, List<ToolBoxEntity> rawList) {
if (sourceList == null || sourceList.isEmpty()
|| rawList == null || rawList.isEmpty()) {
return rawList;
}
String id;
for (int i = 0; i < rawList.size(); i++) {
id = rawList.get(i).getId();
for (ToolBoxEntity toolBoxEntity : sourceList) {
if (id.equals(toolBoxEntity.getId())) {
rawList.remove(i);
i--;
break;
}
}
}
return rawList;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return 0;
} else if (position == 1) {
return 1;
} else if (position == getItemCount() - 1) {
return 2;
@ -156,10 +120,7 @@ public class ToolBoxRvAdapter extends BaseRecyclerAdapter {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == 0) {
View view = mLayoutInflater.inflate(R.layout.layout_search_bar, parent, false);
return new SearchViewHolder(view);
} else if (viewType == 2) {
if (viewType == 2) {
View view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false);
return new FooterViewHolder(view);
} else if (viewType == 1) {
@ -176,83 +137,26 @@ public class ToolBoxRvAdapter extends BaseRecyclerAdapter {
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof ToolBoxViewHolder) {
ToolBoxViewHolder viewHolder = (ToolBoxViewHolder) holder;
ToolBoxEntity toolBoxEntity = mEntityList.get(position - 2);
ToolBoxEntity toolBoxEntity = mEntityList.get(position - 1);
initToolBoxViewHolder(viewHolder, toolBoxEntity);
} else if (holder instanceof FooterViewHolder) {
FooterViewHolder viewHolder = (FooterViewHolder) holder;
initFooterViewHolder(viewHolder);
} else if (holder instanceof SearchViewHolder) {
SearchViewHolder viewHolder = (SearchViewHolder) holder;
initSearchViewHolder(viewHolder);
} else if (holder instanceof ReuseViewHolder) {
holder.itemView.setOnClickListener(v -> SuggestionActivity.startSuggestionActivity(mContext, SuggestType.functionSuggest, null, null));
holder.itemView.setOnClickListener(v -> SuggestionActivity.startSuggestionActivity(mContext, SuggestType.normal, null, null));
}
}
@Override
public int getItemCount() {
if (mEntityList.size() > 0) {
return mEntityList.size() + 3;
return mEntityList.size() + 2;
} else {
return 1;
return 0;
}
}
private void initSearchViewHolder(final SearchViewHolder viewHolder) {
if (mSearchKey != null) {
viewHolder.searchEt.setText(mSearchKey);
}
if (mIsSearch) {
viewHolder.backTv.setVisibility(View.VISIBLE);
} else {
viewHolder.backTv.setVisibility(View.GONE);
}
viewHolder.backTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSearchListener.search(false, viewHolder.searchEt.getText().toString());
}
});
viewHolder.searchTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (TextUtils.isEmpty(viewHolder.searchEt.getText().toString())) {
Utils.toast(mContext, R.string.search_hint);
return;
}
mSearchListener.search(true, viewHolder.searchEt.getText().toString());
}
});
viewHolder.searchEt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
Util_System_Keyboard.hideSoftKeyboard(mContext, viewHolder.searchEt);
}
}
});
viewHolder.searchEt.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
viewHolder.searchTv.performClick();
}
return false;
}
});
}
private void initFooterViewHolder(FooterViewHolder viewHolder) {
viewHolder.initItemPadding();
if (mIsNetworkError) {
@ -261,12 +165,7 @@ public class ToolBoxRvAdapter extends BaseRecyclerAdapter {
viewHolder.loading.setVisibility(View.GONE);
viewHolder.hint.setText(R.string.loading_failed_retry);
viewHolder.itemView.setClickable(true);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
loadData();
}
});
viewHolder.itemView.setOnClickListener(v -> loadData());
} else if (mIsOver) {
viewHolder.lineLeft.setVisibility(View.VISIBLE);
viewHolder.lineRight.setVisibility(View.VISIBLE);
@ -287,26 +186,19 @@ public class ToolBoxRvAdapter extends BaseRecyclerAdapter {
viewHolder.mTitle.setText(toolBoxEntity.getName());
ImageUtils.display(viewHolder.mGameThumb, toolBoxEntity.getIcon());
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String url = toolBoxEntity.getUrl();
viewHolder.itemView.setOnClickListener(v -> {
String url = toolBoxEntity.getUrl();
// http://www.ghzs666.com/article/59291e7ce9a64a496cfd6897.html
if (url != null && url.contains(URL_ARTICLE)) {
String newsId = url.substring(url.lastIndexOf("/") + 1, url.length() - 5); // 5: ".html"
Intent intent = NewsDetailActivity.getIntentById(mContext, newsId, "工具箱列表");
mContext.startActivity(intent);
} else {
mContext.startActivity(WebActivity.getWebByCollectionTools(mContext, toolBoxEntity, false));
}
if (url != null && url.contains(URL_ARTICLE)) {
String newsId = url.substring(url.lastIndexOf("/") + 1, url.length() - 5); // 5: ".html"
Intent intent = NewsDetailActivity.getIntentById(mContext, newsId, "工具箱列表");
mContext.startActivity(intent);
} else {
mContext.startActivity(WebActivity.getWebByCollectionTools(mContext, toolBoxEntity, false));
}
});
}
public int dataSize() {
return mEntityList.size();
}
public boolean isOver() {
return mIsOver;
}
@ -318,8 +210,4 @@ public class ToolBoxRvAdapter extends BaseRecyclerAdapter {
public boolean isNetworkError() {
return mIsNetworkError;
}
public interface OnSearchCallBackListener {
void search(boolean isSearch, String searchKey);
}
}

View File

@ -11,11 +11,16 @@ import android.view.View;
import android.view.ViewGroup;
import com.gh.base.OnRequestCallBackListener;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.gamecenter.GameDetailActivity;
import com.gh.gamecenter.NewsDetailActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder;
import com.gh.gamecenter.adapter.viewholder.VoteViewHolder;
import com.gh.gamecenter.baselist.ListAdapter;
import com.gh.gamecenter.entity.LinkEntity;
import com.gh.gamecenter.entity.MeEntity;
import com.gh.gamecenter.entity.VersionVoteEntity;
@ -62,19 +67,32 @@ public class VoteAdapter extends ListAdapter<VersionVoteEntity> {
if (holder instanceof VoteViewHolder) {
final VoteViewHolder viewHolder = (VoteViewHolder) holder;
VersionVoteEntity versionVoteEntity = mEntityList.get(position);
MeEntity userData = versionVoteEntity.getMe();
if (userData != null && userData.isVersionRequested()) {
viewHolder.voteBtn.setBackgroundResource(R.drawable.border_suggest_bg);
viewHolder.voteBtn.setTextColor(ContextCompat.getColor(mContext, R.color.content));
viewHolder.voteBtn.setText(R.string.voted);
viewHolder.voteBtn.setEnabled(false);
if (versionVoteEntity.getOpen()) {
MeEntity userData = versionVoteEntity.getMe();
if (userData != null && userData.isVersionRequested()) {
viewHolder.voteBtn.setBackgroundResource(R.drawable.border_suggest_bg);
viewHolder.voteBtn.setTextColor(ContextCompat.getColor(mContext, R.color.content));
viewHolder.voteBtn.setText(R.string.voted);
viewHolder.voteBtn.setEnabled(false);
} else {
viewHolder.voteBtn.setBackgroundResource(R.drawable.button_normal_style);
viewHolder.voteBtn.setTextColor(Color.WHITE);
viewHolder.voteBtn.setText(R.string.vote);
viewHolder.voteBtn.setEnabled(true);
}
} else {
LinkEntity link = versionVoteEntity.getLink();
if (EntranceUtils.HOST_GAME.equals(link.getType())) {
viewHolder.voteBtn.setText(R.string.download);
} else {
viewHolder.voteBtn.setText(R.string.libao_check);
}
viewHolder.voteBtn.setBackgroundResource(R.drawable.button_normal_style);
viewHolder.voteBtn.setTextColor(Color.WHITE);
viewHolder.voteBtn.setText(R.string.vote);
viewHolder.voteBtn.setEnabled(true);
}
View progressbar = viewHolder.progressbar;
ViewGroup.LayoutParams layoutParams = progressbar.getLayoutParams();
if (position > 0) {
@ -99,7 +117,25 @@ public class VoteAdapter extends ListAdapter<VersionVoteEntity> {
viewHolder.count.setText(mContext.getString(R.string.vote_count, versionVoteEntity.getNum()));
progressbar.setLayoutParams(layoutParams);
viewHolder.voteBtn.setOnClickListener(v -> mCallBackListener.loadDone(versionVoteEntity.getId()));
viewHolder.voteBtn.setOnClickListener(v -> {
if (versionVoteEntity.getOpen()) {
mCallBackListener.loadDone(versionVoteEntity.getId());
} else {
LinkEntity link = versionVoteEntity.getLink();
String entrance = "(游戏求版本)";
switch (link.getType() == null ? "" : link.getType()) {
case EntranceUtils.HOST_GAME:
GameDetailActivity.startGameDetailActivityByVote(mContext, link.getLink(), entrance);
break;
case EntranceUtils.HOST_ARTICLE:
mContext.startActivity(NewsDetailActivity.getIntentById(mContext, link.getLink(), entrance));
break;
default:
DialogUtils.showLowVersionDialog(mContext);
break;
}
}
});
} else if (holder instanceof FooterViewHolder) {
initFooterViewHolder((FooterViewHolder) holder);
}

View File

@ -32,7 +32,7 @@ import io.reactivex.Observable;
public abstract class ListFragment<T, VM extends BaseListViewModel /* 该泛型位置对应getViewModelClass */> extends NormalFragment implements
Observer<List<T>>,
SwipeRefreshLayout.OnRefreshListener,
OnDataObservable {
OnDataObservable<T> {
@BindView(R.id.list_rv)
protected RecyclerView mListRv;

View File

@ -15,6 +15,7 @@ import io.reactivex.Observable;
public class NormalListViewModel<T> extends ListViewModel<T, T> {
// TODO 作为构造函数从外部传入会引起内存泄漏,当 View 被销毁时,这个类的实例还会持有原有 View 的引用
private OnDataObservable mDataObservable;
public NormalListViewModel(@NonNull Application application, OnDataObservable dataObservable) {

View File

@ -16,6 +16,7 @@ import com.gh.common.constant.ItemViewType;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.NewsUtils;
import com.gh.common.util.NumberUtils;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder;
import com.gh.gamecenter.adapter.viewholder.NewsImage1ViewHolder;
@ -145,7 +146,7 @@ public class ArticleAdapter extends ListAdapter<NewsEntity> {
viewHolder.read.setVisibility(View.GONE);
} else {
viewHolder.read.setVisibility(View.VISIBLE);
viewHolder.read.setText(String.format(Locale.getDefault(), "阅读 %d", views));
viewHolder.read.setText(String.format(Locale.getDefault(), "阅读 %s", NumberUtils.transSimpleCount(views)));
}
NewsUtils.setNewsType(viewHolder.type, newsEntity.getType(), newsEntity.getPriority(), position);
}
@ -187,7 +188,7 @@ public class ArticleAdapter extends ListAdapter<NewsEntity> {
viewHolder.read.setVisibility(View.GONE);
} else {
viewHolder.read.setVisibility(View.VISIBLE);
viewHolder.read.setText(String.format(Locale.getDefault(), "阅读 %d", views));
viewHolder.read.setText(String.format(Locale.getDefault(), "阅读 %s", NumberUtils.transSimpleCount(views)));
}
NewsUtils.setNewsType(viewHolder.type, newsEntity.getType(), newsEntity.getPriority(), position);
}
@ -211,7 +212,7 @@ public class ArticleAdapter extends ListAdapter<NewsEntity> {
viewHolder.read.setVisibility(View.GONE);
} else {
viewHolder.read.setVisibility(View.VISIBLE);
viewHolder.read.setText(String.format(Locale.getDefault(), "阅读 %d", views));
viewHolder.read.setText(String.format(Locale.getDefault(), "阅读 %s", NumberUtils.transSimpleCount(views)));
}
NewsUtils.setNewsType(viewHolder.type, newsEntity.getType(), newsEntity.getPriority(), position);
}

View File

@ -1,12 +1,12 @@
package com.gh.gamecenter.db;
import android.content.Context;
import android.text.TextUtils;
import com.gh.gamecenter.db.info.AskSearchHistoryInfo;
import com.j256.ormlite.dao.CloseableIterator;
import com.j256.ormlite.dao.Dao;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -20,36 +20,45 @@ public class AskSearchHistoryDao {
try {
helper = DatabaseHelper.getHelper(context);
dao = helper.getDao(AskSearchHistoryInfo.class);
} catch (SQLException e) {
} catch (Exception e) {
e.printStackTrace();
}
}
public void add(String item) {
public void add(String key, String communityId) {
try {
dao.createOrUpdate(new AskSearchHistoryInfo(item));
} catch (SQLException e) {
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(communityId)) {
dao.createOrUpdate(createInfo(key, communityId));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void delete(String item) {
private AskSearchHistoryInfo createInfo(String key, String communityId) {
try {
dao.deleteById(item);
} catch (SQLException e) {
List<AskSearchHistoryInfo> his = dao.queryBuilder().
orderBy("time", false).
where().eq("communityId", communityId).
query();
for (AskSearchHistoryInfo next : his) {
String dbKey = next.getKey();
if (dbKey != null && dbKey.equals(key)) dao.delete(next);
}
} catch (Exception e) {
e.printStackTrace();
}
return new AskSearchHistoryInfo(key, communityId);
}
public void deleteAll() {
CloseableIterator<AskSearchHistoryInfo> iterator = dao.iterator();
while (iterator.hasNext()) {
try {
dao.delete(iterator.next());
} catch (SQLException e) {
} catch (Exception e) {
e.printStackTrace();
}
@ -57,16 +66,19 @@ public class AskSearchHistoryDao {
return;
}
public List<String> getAll() {
public List<String> getAll(String communityId) {
List<String> history = new ArrayList<String>();
try {
List<AskSearchHistoryInfo> his = dao.queryBuilder().orderBy("time", false).query();
List<AskSearchHistoryInfo> his = dao.queryBuilder().
orderBy("time", false).
where().eq("communityId", communityId).
query();
Iterator<AskSearchHistoryInfo> hisIterator = his.iterator();
while (hisIterator.hasNext()) {
history.add(hisIterator.next().getItem());
history.add(hisIterator.next().getKey());
}
} catch (SQLException e) {
} catch (Exception e) {
e.printStackTrace();
}

View File

@ -21,7 +21,7 @@ import java.sql.SQLException;
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "gh_assist.db";
private static final int DATABASE_VERSION = 12;
private static final int DATABASE_VERSION = 13;
private static DatabaseHelper instance;
private ArrayMap<String, Dao> daos = new ArrayMap<>();

View File

@ -16,27 +16,46 @@ public class AskSearchHistoryInfo implements Serializable {
*/
private static final long serialVersionUID = 1L;
@DatabaseField(id = true, columnName = "item")
private String item;
@DatabaseField(id = true, columnName = "id")
private String id;
@DatabaseField(useGetSet = true, columnName = "time")
@DatabaseField(columnName = "key")
private String key;
@DatabaseField(columnName = "time")
private String time;
@DatabaseField(columnName = "communityId")
private String communityId;
public AskSearchHistoryInfo() {
}
public AskSearchHistoryInfo(String item) {
this.item = item;
public AskSearchHistoryInfo(String key, String communityId) {
this.key = key;
this.communityId = communityId;
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
Locale.getDefault());
this.time = format.format(date);
this.id = String.valueOf(date.getTime());
}
public AskSearchHistoryInfo(String item, String time) {
this.item = item;
this.time = time;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getTime() {
@ -47,13 +66,20 @@ public class AskSearchHistoryInfo implements Serializable {
this.time = time;
}
public String getItem() {
return item;
public String getCommunityId() {
return communityId;
}
public void setCommunityId(String communityId) {
this.communityId = communityId;
}
@Override
public String toString() {
return "SearchHistoryEntity [item=" + item + ", time=" + time + "]";
return "AskSearchHistoryInfo{" +
"key='" + key + '\'' +
", time='" + time + '\'' +
", communityId='" + communityId + '\'' +
'}';
}
}

View File

@ -78,7 +78,8 @@ class DiscoverFragment : BaseFragment<Any>() {
discoverAdView.setOnClickListener {
MtaHelper.onEvent("发现", "广告-${ad.title}")
DirectUtils.directToLinkPage(requireContext(), ad.toLinkEntity(), "(首页)", "(首页:发现)")
MtaHelper.onEvent("广告位统计", "发现_功能列表", ad.title)
DirectUtils.directToLinkPage(requireContext(), ad.toLinkEntity(), "(首页:发现)", "发现-广告位")
}
mDiscoverContainer.addView(discoverAdView)
}
@ -165,11 +166,15 @@ class DiscoverFragment : BaseFragment<Any>() {
}
private fun checkArticleStatus() {
val showArticleEntrance = Config.getSettings()?.showArticleEntrance
if (showArticleEntrance == "off") {
val showArticleEntrance = Config.getSettings()?.showArticleEntrance()
if (showArticleEntrance == false) {
mDiscoverGameTrends.visibility = View.GONE
mDiscoverInfo.visibility = View.GONE
mDiscoverLibaoLine.visibility = View.GONE
} else {
mDiscoverGameTrends.visibility = View.VISIBLE
mDiscoverInfo.visibility = View.VISIBLE
mDiscoverLibaoLine.visibility = View.VISIBLE
}
}

View File

@ -149,11 +149,12 @@ class DownloadFragment : BaseFragment_TabLayout() {
if (view != null) {
view!!.postDelayed({
mViewPager.currentItem = skip.currentItem
if (skip.currentItem == DownloadManagerActivity.INDEX_DOWNLOAD) {
if (isAdded && skip.currentItem == DownloadManagerActivity.INDEX_DOWNLOAD) {
val fragments = childFragmentManager.fragments
if (fragments != null) {
for (fragment in fragments) {
if (fragment is GameDownloadFragment) {
if (fragment.isAdded
&& fragment is GameDownloadFragment) {
fragment.onResume() // auto refresh list
}
}

View File

@ -132,7 +132,7 @@ public class GameDownloadFragment extends BaseFragment implements View.OnClickLi
}
}
adapter.getUrlMap().put(PackageUtils.getPackageNameByPath(getActivity(),
adapter.getUrlMap().put(PackageUtils.getPackageNameByPath(HaloApp.getInstance().getApplication(),
downloadEntity.getPath()), downloadEntity.getUrl());
} else if (DownloadStatus.cancel.equals(downloadEntity.getStatus())) { // 有可能由于网络劫持造成的
adapter.initMap();

View File

@ -475,7 +475,7 @@ class GameUpdateFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
null,
ExposureUtils.DownloadType.UPDATE);
downloadEntity.setExposureTrace(GsonUtils.Companion.getInstance().toJson(event));
downloadEntity.setExposureTrace(GsonUtils.toJson(event));
String platform = PlatformUtils.getInstance(mContext)
.getPlatformName(updateEntity.getPlatform());

View File

@ -21,7 +21,8 @@ data class ApkEntity(@SerializedName("package")
var isActive: Boolean = true,
var force: Boolean = false,
var apkLink: ApkLink? = null,
var plugin: String? = ""/*控制是否显示插件化 默认open取值有open/only_index/only_game/close*/) : Parcelable {
var plugin: String? = "",/*控制是否显示插件化 默认open取值有open/only_index/only_game/close*/
var time: Long? = null) : Parcelable {
fun getPlatform(): String? {
if (TextUtils.isEmpty(platform)) {
return "官方版"

View File

@ -1,10 +1,13 @@
package com.gh.gamecenter.entity
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize
@Parcelize
data class Auth(
val text: String = "",
val color: String = "",
val icon: String = "") : Parcelable
val icon: String = "",
@SerializedName("article_id")
val articleId: String? = null) : Parcelable

View File

@ -7,5 +7,9 @@ data class ErrorEntity(var code: Int? = 0,
var toast: String? = "",
var data: Data? = null) {
data class Data(@SerializedName("always_block")
var alwaysBlock: Boolean? = false)
var alwaysBlock: Boolean? = false,
@SerializedName("game_id")
var gameId: String = "",
@SerializedName("game_name")
var gameName: String = "")
}

View File

@ -69,7 +69,11 @@ data class GameEntity(
// 用于开服表标记是否为置顶项目
@SerializedName("is_fixed_top")
var fixedTop: Boolean? = false,
var fixedTopHint: Boolean? = false) : Parcelable {
var fixedTopHint: Boolean? = false,
@SerializedName("download_notice")
val downloadAd: LinkEntity? = null,
// 社区名字,用于首页替换游戏曝光时使用
var subjectName: String? = null) : Parcelable {
@IgnoredOnParcel
private var entryMap: ArrayMap<String, DownloadEntity>? = ArrayMap()

View File

@ -90,15 +90,24 @@ class MeEntity(@SerializedName("is_community_voted")
const val MODERATOR_LEVEL_SUPPER = "super"
// moderator permissions
// 问题权限
const val PATCH_QUESTION_TAG = "update-question-tag" // 修改问题标签:只修改标签
const val PATCH_QUESTION = "update-question" // 修改问题:除标签以外的字段
const val HIDE_QUESTION = "hide-question" // 隐藏问题
const val GET_MODIFIED_VERSIONS = "get-modified-versions" // 查看问题的修改历史
// 回答权限
const val CHOICENESS_ANSWER = "choiceness-answer" // 将回答加入精选列表
const val FOLD_ANSWER = "fold-answer" // 折叠回答
const val HIDE_ANSWER = "hide-answer" // 隐藏回答
const val TOP_ANSWER_COMMENT = "top-answer-comment" // 置顶回答的评论
const val HIDE_ANSWER_COMMENT = "hide-answer-comment" // 隐藏回答的评论
// 文章权限
const val UPDATE_COMMUNITY_ARTICLE = "update-community-article" // 修改文章
const val CHOICENESS_COMMUNITY_ARTICLE = "choiceness-community-article" // 加精文章
const val HIDE_COMMUNITY_ARTICLE = "hide-community-article" // 隐藏文章
const val TOP_COMMUNITY_ARTICLE_COMMENT = "top-community-article-comment" // 置顶文章评论
const val HIDE_COMMUNITY_ARTICLE_COMMENT = "hide-community-article-comment" // 隐藏文章评论
}
}

View File

@ -8,7 +8,7 @@ data class PersonalHistoryEntity(
val type: String = "",
val question: Question = Question(),
val brief: String = "",
val count: Count = Count(),
var count: Count = Count(),
val time: Long = 0,
val title: String = "",
val community: CommunityEntity,
@ -23,7 +23,7 @@ data class PersonalHistoryEntity(
val title: String = "")
data class Count(
val comment: Int = -1,
var comment: Int = -1,
val vote: Int = -1,
val answer: Int = -1)

View File

@ -30,8 +30,11 @@ data class PushNotificationEntity(
data class Extra(var data: Data? = null)
data class Data(var condition: Condition? = null,
var link: Link? = null) {
data class Data(
@SerializedName("push_id")
var pushId: String? = "",
var condition: Condition? = null,
var link: Link? = null) {
@Parcelize
data class Link(var type: String? = "", var target: String? = "") : Parcelable

View File

@ -0,0 +1,5 @@
package com.gh.gamecenter.entity
import android.content.Intent
class ResultEntity(val requestCode: Int, val resultCode: Int, val data: Intent?)

View File

@ -1,6 +1,9 @@
package com.gh.gamecenter.entity
import android.preference.PreferenceManager
import com.gh.common.constant.Config
import com.google.gson.annotations.SerializedName
import com.halo.assistant.HaloApp
data class SettingsEntity(
var download: List<Download>? = listOf(),
@ -10,15 +13,54 @@ data class SettingsEntity(
var image: Image? = null,
var support: Support? = null,
@SerializedName("community_entrance")
var communityEntrance: String? = "",
private var communityEntrance: String? = "",
@SerializedName("game_comment_blacklist")
var gameCommentBlackList: List<String>? = listOf(),
@SerializedName("game_download_blacklist")
var gameDownloadBlackList: List<String> = listOf(),
@SerializedName("game_package_match")
var gamePackageMatch: List<GameWithPackages>? = listOf(),
@SerializedName("ad")
var adList: List<AD>? = listOf(),
@SerializedName("article_entrance")
var showArticleEntrance: String = "on") {
private var articleEntrance: String = "") {
fun setCommunityEntrance(communityEntrance: String) {
this.communityEntrance = communityEntrance
}
fun showCommunityEntrance(): Boolean {
val preferences =
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().application)
val isFixCommunity =
preferences.getBoolean(Config.FIX_COMMUNITY_KEY, false)
if (isFixCommunity) return true
if ("on" == communityEntrance) {
preferences.edit().putBoolean(Config.FIX_COMMUNITY_KEY, true).apply()
return true
}
return false
}
fun setArticleEntrance(articleEntrance: String) {
this.articleEntrance = articleEntrance
}
fun showArticleEntrance(): Boolean {
val preferences =
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().application)
val isFixArticle =
preferences.getBoolean(Config.FIX_ARTICLE_KEY, false)
if (isFixArticle) return true
if ("on" == articleEntrance) {
preferences.edit().putBoolean(Config.FIX_ARTICLE_KEY, true).apply()
return true
}
return false
}
data class Support(
@SerializedName("qq-group")
@ -80,4 +122,10 @@ data class SettingsEntity(
}
}
data class GameWithPackages(
@SerializedName("game_id")
var gameId: String? = "",
var packages: List<String>? = listOf()
)
}

View File

@ -0,0 +1,11 @@
package com.gh.gamecenter.entity
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
@Parcelize
data class SpecialColumn(
var type: String? = "",
var name: String? = "",
var tab: String? = ""
) : Parcelable

View File

@ -19,4 +19,6 @@ data class SubjectEntity(@SerializedName("_id")
var sort: Int = 0,
var data: MutableList<GameEntity>? = null,
var type: String? = null,
var des: String? = null) : Parcelable
var des: String? = null,
@SerializedName("relation_column_id")
var relatedColumnId: String ?= null) : Parcelable

View File

@ -19,4 +19,8 @@ class VersionVoteEntity {
var me: MeEntity? = null
var reply: String? = null
var open : Boolean = true
var link: LinkEntity = LinkEntity()
}

View File

@ -203,7 +203,7 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable {
}
} else if ("Refresh".equals(reuse.getType())) {
SettingsEntity settings = Config.getSettings();
if (settings != null && "off".equals(settings.getCommunityEntrance())) {
if (settings != null && !settings.showCommunityEntrance()) {
mTabCommunity.setVisibility(View.GONE);
} else {
mTabCommunity.setVisibility(View.VISIBLE);

View File

@ -21,6 +21,7 @@ import com.gh.common.util.DataCollectionUtils;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.MtaHelper;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.ConcernActivity;
import com.gh.gamecenter.DownloadManagerActivity;
@ -30,8 +31,8 @@ import com.gh.gamecenter.entity.GameUpdateEntity;
import com.gh.gamecenter.entity.PluginLocation;
import com.gh.gamecenter.eventbus.EBDownloadStatus;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.packagehelper.PackageViewModel;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.gamecenter.packagehelper.PackageViewModel;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@ -220,13 +221,13 @@ public class SearchToolbarFragment extends BaseFragment implements View.OnClickL
switch (id) {
case R.id.actionbar_rl_download:
DataUtils.onEvent(getActivity(), "主页", "下载图标");
MtaHelper.onEvent("首页_点击", "顶栏", "下载管理");
DataCollectionUtils.uploadClick(getActivity(), "下载图标", "主页");
startActivity(DownloadManagerActivity.getDownloadMangerIntent(getContext(), null, "(工具栏)"));
break;
case R.id.actionbar_iv_search:
DataUtils.onEvent(getActivity(), "主页", "搜索图标");
MtaHelper.onEvent("首页_点击", "顶栏", "搜索");
DataCollectionUtils.uploadClick(getActivity(), "搜索图标", "主页");
intent = SearchActivity.getIntent(getContext(), true, mSearchHintTv.getHint().toString(), "(工具栏)");
@ -235,6 +236,7 @@ public class SearchToolbarFragment extends BaseFragment implements View.OnClickL
case R.id.actionbar_search_input:
case R.id.actionbar_search_rl:
DataUtils.onEvent(getActivity(), "主页", "搜索框");
MtaHelper.onEvent("首页_点击", "顶栏", "搜索");
DataCollectionUtils.uploadClick(getActivity(), "搜索框", "主页");
intent = SearchActivity.getIntent(getContext(), false, mSearchHintTv.getHint().toString(), "(工具栏)");
@ -242,6 +244,7 @@ public class SearchToolbarFragment extends BaseFragment implements View.OnClickL
break;
case R.id.actionbar_notification:
DataUtils.onEvent(getActivity(), "主页", "关注图标");
MtaHelper.onEvent("首页_点击", "顶栏", "我的关注");
DataCollectionUtils.uploadClick(getActivity(), "关注图标", "主页");
intent = ConcernActivity.getIntent(getContext(), "(工具栏)");

View File

@ -155,7 +155,6 @@ class GameFragment : NormalFragment() {
mSkeleton = Skeleton.bind(mBinding?.gameSkeletonContainer).shimmer(false).load(R.layout.fragment_game_skeleton).show()
}
override fun onPause() {
super.onPause()
DownloadManager.getInstance(context).removeObserver(dataWatcher)

View File

@ -14,6 +14,7 @@ import android.widget.LinearLayout
import com.facebook.drawee.controller.BaseControllerListener
import com.facebook.imagepipeline.image.ImageInfo
import com.gh.base.OnViewClickListener
import com.gh.common.AppExecutor
import com.gh.common.constant.Config
import com.gh.common.constant.ItemViewType
import com.gh.common.exposure.ExposureEvent
@ -42,7 +43,8 @@ import com.lightgame.download.DownloadEntity
import java.util.*
import kotlin.collections.ArrayList
class GameFragmentAdapter(context: Context, model: GameViewModel, var blockName: String) : BaseRecyclerAdapter<RecyclerView.ViewHolder>(context), IExposable {
class GameFragmentAdapter(context: Context, model: GameViewModel, var blockName: String)
: BaseRecyclerAdapter<RecyclerView.ViewHolder>(context), IExposable {
private val mPluginPosition = 1
@ -121,312 +123,336 @@ class GameFragmentAdapter(context: Context, model: GameViewModel, var blockName:
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is GameHeadViewHolder -> bindHeadView(holder, position)
is GamePluginViewHolder -> bindPluginView(holder, position)
is GameItemViewHolder -> bindGameItemView(holder, position)
is GameViewPagerViewHolder -> bindGameViewPagerView(holder, position)
is FooterViewHolder -> bindFooterView(holder)
is GameImageViewHolder -> bindGameImageView(holder, position)
is GameHorizontalListViewHolder -> bindGameHorizontalListView(holder, position)
}
}
if (holder is GameHeadViewHolder) {
val column = mItemDataList[position].columnHead
holder.binding.subject = column
holder.binding.headPb.visibility = View.GONE
val text = if ("change" == column?.home) "换一批" else "全部"
holder.binding.headMore.text = text
private fun bindGameHorizontalListView(holder: GameHorizontalListViewHolder, position: Int) {
val subjectEntity = mItemDataList[position].horizontalColumn
val exposureEventList = arrayListOf<ExposureEvent>()
if (text == "全部" && column != null && column.data != null && column.data!!.size >= column.more!!) {
holder.binding.headMore.visibility = View.GONE
} else {
holder.binding.headMore.visibility = View.VISIBLE
}
holder.binding.headMore.setOnClickListener {
if ("all" == column?.home) {
DataUtils.onMtaEvent(mContext, "游戏专题", "全部", column.name)
SubjectActivity.startSubjectActivity(mContext, column.id, column.name, column.isOrder, "(游戏-专题:" + column.name + "-全部)")
} else {
DataUtils.onMtaEvent(mContext, "游戏专题", "换一批", column?.name)
holder.binding.headPb.visibility = View.VISIBLE
mViewModel.changeSubjectGame(column?.id!!)
}
}
} else if (holder is GamePluginViewHolder) {
val pluginList = mItemDataList[position].pluginList
var adapter = holder.mPluginRv.adapter
if (adapter == null) {
adapter = GamePluginAdapter(mContext, pluginList)
adapter.openList(mIsOpenPluginList)
(holder.mPluginRv.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
holder.mPluginRv.layoutManager = LinearLayoutManager(mContext)
holder.mPluginRv.adapter = adapter
} else {
(adapter as GamePluginAdapter).openList(mIsOpenPluginList)
adapter.checkResetData(pluginList)
}
holder.mHeadTitle.text = String.format(Locale.getDefault(), "你有%d个游戏可以升级插件版", pluginList?.size)
holder.mPluginHead.setOnClickListener {
if (mIsOpenPluginList) {
mIsOpenPluginList = false
holder.mHeadOpen.setImageResource(R.drawable.gamedetail_open_icon)
} else {
mIsOpenPluginList = true
holder.mHeadOpen.setImageResource(R.drawable.gamedetail_colse_icon)
}
notifyItemChanged(holder.adapterPosition)
}
} else if (holder is GameItemViewHolder) {
val itemData = mItemDataList[position]
val gameEntity = itemData.game
val subjectData = gameEntity?.subjectData
if (mItemDataList[position - 1].game == null) {
holder.itemView.setPadding(DisplayUtils.dip2px(8F), DisplayUtils.dip2px(10.5F),
DisplayUtils.dip2px(20F), DisplayUtils.dip2px(6F))
} else {
holder.itemView.setPadding(DisplayUtils.dip2px(8F), DisplayUtils.dip2px(6F),
DisplayUtils.dip2px(20F), DisplayUtils.dip2px(6F))
}
holder.binding.game = gameEntity
holder.binding.subjectTag = subjectData?.tag
holder.initServerType(gameEntity!!)
holder.binding.executePendingBindings()
if (subjectData?.isOrder!!) {
holder.binding.gameOrder.visibility = View.VISIBLE
holder.binding.gameOrder.text = (subjectData.position).toString()
} else {
holder.binding.gameOrder.visibility = View.GONE
}
val binding = holder.binding
var subjectAdapter = binding.horizontalRv.adapter
if (subjectAdapter == null) {
subjectAdapter = GameHorizontalAdapter(mContext, subjectEntity!!)
(binding.horizontalRv.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
binding.horizontalRv.layoutManager = GridLayoutManager(mContext, 4)
binding.horizontalRv.adapter = subjectAdapter
} else {
(subjectAdapter as GameHorizontalAdapter).checkResetData(subjectEntity!!)
subjectAdapter.notifyItemRangeChanged(0, subjectAdapter.itemCount)
}
subjectEntity.data?.let {
val keyName = if (TextUtils.isEmpty(blockName)) "首页" else "板块"
val keyValue = if (TextUtils.isEmpty(blockName)) "" else blockName
itemData.exposureEvent = ExposureEvent.createEvent(gameEntity = gameEntity,
source = listOf(ExposureSource(keyName, keyValue), ExposureSource("专题", subjectData.name!!)),
eTrace = null,
event = ExposureType.EXPOSURE)
DownloadItemUtils.setOnClickListener(mContext, holder.binding.downloadBtn, gameEntity, position,
this@GameFragmentAdapter,
StringUtils.buildString("(游戏-专题:", subjectData.name, "-列表[", (position + 1).toString(), "])"),
StringUtils.buildString("游戏-专题-", subjectData.name, ":", gameEntity.name), itemData.exposureEvent)
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding), !gameEntity.isPluggable)
holder.itemView.setOnClickListener {
DataCollectionUtils.uploadClick(mContext, subjectData.name + "-列表", "游戏-专题", gameEntity.name)
val positionOffset = subjectAdapter.getIndex()
if (gameEntity.isPluggable) {
GameDetailActivity.startGameDetailActivity(mContext, gameEntity.id,
StringUtils.buildString("(游戏-专题:插件化-列表[", (subjectData.position).toString(), "])"), itemData.exposureEvent)
} else {
GameDetailActivity.startGameDetailActivity(mContext, gameEntity,
StringUtils.buildString("(游戏-专题:", subjectData.name, "-列表[", (subjectData.position).toString(), "])"), itemData.exposureEvent)
}
for (i in positionOffset until subjectAdapter.itemCount + positionOffset) {
it[i].sequence = i
val event = ExposureEvent.createEvent(gameEntity = it[i],
source = listOf(ExposureSource(keyName, keyValue), ExposureSource("专题", subjectEntity.name!!)),
eTrace = null,
event = ExposureType.EXPOSURE)
exposureEventList.add(event)
}
} else if (holder is GameViewPagerViewHolder) {
val subjectDigestList = mItemDataList[position].subjectRecommend
val binding = holder.binding
mItemDataList[position].exposureEventList = exposureEventList
subjectAdapter.exposureEventList = exposureEventList
}
}
binding.list = subjectDigestList
binding.clickListener = OnViewClickListener { v, data ->
if (data is Int) {
DataUtils.onMtaEvent(mContext, "推荐入口", if (TextUtils.isEmpty(blockName)) "首页" else blockName, (data + 1).toString())
if (data < subjectDigestList?.size!!) {
val entity = subjectDigestList[data]
when {
entity.type == "block" -> mContext.startActivity(BlockActivity.getIntent(mContext, entity))
entity.type == "category" -> mContext.startActivity(CategoryDirectoryActivity.getIntent(mContext, entity.link!!, entity.text!!))
entity.type == "column" -> {
SubjectActivity.startSubjectActivity(mContext, entity.link, entity.text, entity.order
, StringUtils.buildString("(游戏-专题:", entity.name, "[1-", (data + 1).toString(), "]", ")"))
DataCollectionUtils.uploadPosition(mContext, "游戏", (data + 1).toString(), entity.name)
}
entity.type == "game" -> GameDetailActivity.startGameDetailActivity(mContext, entity.link, "(推荐入口)")
entity.type == EntranceUtils.HOST_COMMUNITY -> DirectUtils.directToCommunity(mContext, CommunityEntity(entity.link!!, entity.text!!))
else -> DialogUtils.showLowVersionDialog(mContext)
private fun bindGameImageView(holder: GameImageViewHolder, position: Int) {
val entity = mItemDataList[position].image
val keyName = if (TextUtils.isEmpty(blockName)) "首页" else "板块"
val keyValue = if (TextUtils.isEmpty(blockName)) "" else blockName
entity?.let {
if (it.type == "game") {
mItemDataList[position].exposureEvent = ExposureEvent.createEvent(gameEntity = entity,
source = listOf(ExposureSource(keyName, keyValue), ExposureSource("专题", entity.subjectData?.name + "-大图")),
eTrace = null,
event = ExposureType.EXPOSURE)
}
}
holder.binding.game = entity
holder.binding.traceEvent = mItemDataList[position].exposureEvent
val name = entity?.subjectData?.name
val link = entity?.link
val width = mContext.resources.displayMetrics.widthPixels - DisplayUtils.dip2px(mContext, 16F)
ImageUtils.display(holder.binding.gameImageIcon, entity?.image, width, object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
if (imageInfo == null) return
val imageParams = holder.binding.gameImageIcon.layoutParams
val scale = imageInfo.height.toFloat() / imageInfo.width.toFloat()
imageParams?.height = (width * scale).toInt()
holder.binding.gameImageIcon.layoutParams = imageParams
holder.binding.gameContainer.layoutParams.height = (width * scale).toInt()
}
})
holder.binding.gameImageIcon.setOnClickListener {
DataCollectionUtils.uploadClick(mContext, "$name-大图", "游戏-专题")
DataUtils.onMtaEvent(mContext, "游戏专题", "大图", name + ":" + entity?.name)
val linkEntity = LinkEntity()
linkEntity.link = link
linkEntity.type = entity?.type
linkEntity.text = name
DirectUtils.directToLinkPage(mContext, linkEntity, "(游戏-专题:$name-大图)", "首页游戏")
}
}
private fun bindFooterView(holder: FooterViewHolder) {
holder.initFooterViewHolder(mLoadStatus == LoadStatus.LIST_LOADING
, mLoadStatus == LoadStatus.LIST_FAILED
, mLoadStatus == LoadStatus.LIST_OVER) {
if (mLoadStatus == LoadStatus.LIST_OVER) {
MtaHelper.onEvent("首页_点击", "底部", "点击回到顶部")
mViewModel.commandScrollTop.postValue(null)
} else {
mViewModel.getSubjectList(false)
notifyItemChanged(itemCount - 1)
}
}
}
private fun bindGameViewPagerView(holder: GameViewPagerViewHolder, position: Int) {
val subjectDigestList = mItemDataList[position].subjectRecommend
val binding = holder.binding
binding.list = subjectDigestList
binding.clickListener = OnViewClickListener { v, data ->
if (data is Int) {
DataUtils.onMtaEvent(mContext, "推荐入口", if (TextUtils.isEmpty(blockName)) "首页" else blockName, (data + 1).toString())
if (data < subjectDigestList?.size!!) {
val entity = subjectDigestList[data]
when {
entity.type == "block" -> mContext.startActivity(BlockActivity.getIntent(mContext, entity))
entity.type == "category" -> mContext.startActivity(CategoryDirectoryActivity.getIntent(mContext, entity.link!!, entity.text!!))
entity.type == "column" -> {
SubjectActivity.startSubjectActivity(mContext, entity.link, entity.text, entity.order
, StringUtils.buildString("(游戏-专题:", entity.name, "[1-", (data + 1).toString(), "]", ")"))
DataCollectionUtils.uploadPosition(mContext, "游戏", (data + 1).toString(), entity.name)
}
entity.type == "game" -> GameDetailActivity.startGameDetailActivity(mContext, entity.link, "(推荐入口)")
entity.type == EntranceUtils.HOST_COMMUNITY -> DirectUtils.directToCommunity(mContext, CommunityEntity(entity.link!!, entity.text!!))
else -> DialogUtils.showLowVersionDialog(mContext)
}
} else if (v.id == R.id.home_subject_failure) {
mViewModel.getSubjectDigest(false)
} else if (v.id == R.id.viewpager_tv_failure) {
mViewModel.getSlideData(false)
}
} else if (v.id == R.id.home_subject_failure) {
mViewModel.getSubjectDigest(false)
} else if (v.id == R.id.viewpager_tv_failure) {
mViewModel.getSlideData(false)
}
}
if (mViewModel.blockData != null) {
if (subjectDigestList != null && subjectDigestList.size >= 5) {
ImageUtils.display(binding.entranceIcon5, subjectDigestList[4].icon)
binding.entranceName5.text = if (Config.isShowPlugin()) subjectDigestList[4].name else subjectDigestList[4].nameNormal
}
} else {
ImageUtils.display(binding.entranceIcon5, R.drawable.home_entrance_kaifu)
binding.entranceName5.text = "开服表"
}
binding.entranceContainer5.setOnClickListener {
DataUtils.onMtaEvent(mContext, "推荐入口", if (TextUtils.isEmpty(blockName)) "首页" else blockName, "5")
if (mViewModel.blockData != null) {
if (subjectDigestList != null && subjectDigestList.size >= 5) {
ImageUtils.display(binding.entranceIcon5, subjectDigestList[4].icon)
binding.entranceName5.text = if (Config.isShowPlugin()) subjectDigestList[4].name else subjectDigestList[4].nameNormal
val entity = subjectDigestList[4]
when {
entity.type == "block" -> mContext.startActivity(BlockActivity.getIntent(mContext, entity))
entity.type == "category" -> mContext.startActivity(CategoryDirectoryActivity.getIntent(mContext, entity.link!!, entity.text!!))
entity.type == "column" -> {
SubjectActivity.startSubjectActivity(mContext, entity.link, entity.text, entity.order
, StringUtils.buildString("(游戏-专题:", entity.name, "[1-", (5).toString(), "]", ")"))
DataCollectionUtils.uploadPosition(mContext, "游戏", (5).toString(), entity.name)
}
entity.type == "game" -> GameDetailActivity.startGameDetailActivity(mContext, entity.link, "(推荐入口)")
entity.type == EntranceUtils.HOST_COMMUNITY -> DirectUtils.directToCommunity(mContext, CommunityEntity(entity.link!!, entity.text!!))
else -> DialogUtils.showLowVersionDialog(mContext)
}
}
} else {
ImageUtils.display(binding.entranceIcon5, R.drawable.home_entrance_kaifu)
binding.entranceName5.text = "开服表"
val intent = KaiFuActivity.getIntent(mContext, "(游戏-专题:开服表[1-4])")
mContext.startActivity(intent)
DataCollectionUtils.uploadPosition(mContext, "游戏", "4", "开服表")
}
}
binding.entranceContainer5.setOnClickListener {
DataUtils.onMtaEvent(mContext, "推荐入口", if (TextUtils.isEmpty(blockName)) "首页" else blockName, "5")
if (mViewModel.blockData != null) {
if (subjectDigestList != null && subjectDigestList.size >= 5) {
val entity = subjectDigestList[4]
when {
entity.type == "block" -> mContext.startActivity(BlockActivity.getIntent(mContext, entity))
entity.type == "category" -> mContext.startActivity(CategoryDirectoryActivity.getIntent(mContext, entity.link!!, entity.text!!))
entity.type == "column" -> {
SubjectActivity.startSubjectActivity(mContext, entity.link, entity.text, entity.order
, StringUtils.buildString("(游戏-专题:", entity.name, "[1-", (5).toString(), "]", ")"))
DataCollectionUtils.uploadPosition(mContext, "游戏", (5).toString(), entity.name)
}
entity.type == "game" -> GameDetailActivity.startGameDetailActivity(mContext, entity.link, "(推荐入口)")
entity.type == EntranceUtils.HOST_COMMUNITY -> DirectUtils.directToCommunity(mContext, CommunityEntity(entity.link!!, entity.text!!))
else -> DialogUtils.showLowVersionDialog(mContext)
}
}
val slideList = mItemDataList[position].slideList
val pagerAdapter = binding.viewPager.adapter
if (slideList != null
&& slideList.isNotEmpty()
&& (pagerAdapter == null
|| (pagerAdapter is ImagePagerAdapter && pagerAdapter.dataSize != slideList.size))) {
binding.viewpagerLlHint.removeAllViews()
val margin = DisplayUtils.dip2px(mContext, 6f)
var i = 0
val size = slideList.size
while (i < size) {
val imageView = ImageView(mContext)
val lparams = LinearLayout.LayoutParams(margin, margin)
if (i == 0) {
imageView.setImageResource(R.drawable.oval_hint_up)
} else {
val intent = KaiFuActivity.getIntent(mContext, "(游戏-专题:开服表[1-4])")
mContext.startActivity(intent)
DataCollectionUtils.uploadPosition(mContext, "游戏", "4", "开服表")
imageView.setImageResource(R.drawable.oval_hint_dn)
}
if (i != 0) {
lparams.leftMargin = margin
}
imageView.layoutParams = lparams
binding.viewpagerLlHint.addView(imageView)
i++
}
val slideList = mItemDataList[position].slideList
val pagerAdapter = binding.viewPager.adapter
if (slideList != null && slideList.isNotEmpty() &&
(pagerAdapter == null ||
pagerAdapter is ImagePagerAdapter &&
pagerAdapter.dataSize == slideList.size)) {
binding.viewpagerLlHint.removeAllViews()
val margin = DisplayUtils.dip2px(mContext, 6f)
var i = 0
val size = slideList.size
while (i < size) {
val imageView = ImageView(mContext)
val lparams = LinearLayout.LayoutParams(margin, margin)
if (i == 0) {
imageView.setImageResource(R.drawable.oval_hint_up)
binding.viewPager.adapter = ImagePagerAdapter(mContext, slideList, true, if (TextUtils.isEmpty(blockName)) "首页" else blockName)
binding.viewPager.interval = 3000
binding.viewPager.startAutoScroll()
binding.viewPager.doOnPageSelected {
var j = 0
val childCount = binding.viewpagerLlHint.childCount
while (j < childCount) {
if (j == it % childCount) {
(binding.viewpagerLlHint.getChildAt(j) as ImageView)
.setImageResource(R.drawable.oval_hint_up)
} else {
imageView.setImageResource(R.drawable.oval_hint_dn)
(binding.viewpagerLlHint.getChildAt(j) as ImageView)
.setImageResource(R.drawable.oval_hint_dn)
}
if (i != 0) {
lparams.leftMargin = margin
}
imageView.layoutParams = lparams
binding.viewpagerLlHint.addView(imageView)
i++
j++
}
binding.viewPager.adapter = ImagePagerAdapter(mContext, slideList, true, if (TextUtils.isEmpty(blockName)) "首页" else blockName)
binding.viewPager.interval = 3000
binding.viewPager.startAutoScroll()
binding.viewPager.doOnPageSelected {
var j = 0
val childCount = binding.viewpagerLlHint.childCount
while (j < childCount) {
if (j == it % childCount) {
(binding.viewpagerLlHint.getChildAt(j) as ImageView)
.setImageResource(R.drawable.oval_hint_up)
} else {
(binding.viewpagerLlHint.getChildAt(j) as ImageView)
.setImageResource(R.drawable.oval_hint_dn)
}
j++
}
}
} else if (slideList != null && slideList.isNotEmpty() && pagerAdapter != null) {
(pagerAdapter as ImagePagerAdapter).checkResetData(slideList)
} else if (slideList == null || slideList.isEmpty()) {
binding.viewPager.adapter = null
}
} else if (slideList != null && slideList.isNotEmpty() && pagerAdapter != null) {
(pagerAdapter as ImagePagerAdapter).checkResetData(slideList)
} else if (slideList == null || slideList.isEmpty()) {
binding.viewPager.adapter = null
}
if (mViewModel.blockData != null) {
binding.viewpagerContainer.visibility = if (slideList!!.isEmpty()) View.GONE else View.VISIBLE
binding.entranceContainer.visibility = if (subjectDigestList!!.isEmpty()) View.GONE else View.VISIBLE
}
if (mViewModel.blockData != null) {
binding.viewpagerContainer.visibility = if (slideList!!.isEmpty()) View.GONE else View.VISIBLE
binding.entranceContainer.visibility = if (subjectDigestList!!.isEmpty()) View.GONE else View.VISIBLE
}
if (isAutoScroll) {
binding.viewPager.startAutoScroll()
if (isAutoScroll) {
binding.viewPager.startAutoScroll()
} else {
binding.viewPager.stopAutoScroll()
}
}
private fun bindGameItemView(holder: GameItemViewHolder, position: Int) {
val itemData = mItemDataList[position]
val gameEntity = itemData.game
val subjectData = gameEntity?.subjectData
if (mItemDataList[position - 1].game == null) {
holder.itemView.setPadding(DisplayUtils.dip2px(8F), DisplayUtils.dip2px(10.5F),
DisplayUtils.dip2px(20F), DisplayUtils.dip2px(6F))
} else {
holder.itemView.setPadding(DisplayUtils.dip2px(8F), DisplayUtils.dip2px(6F),
DisplayUtils.dip2px(20F), DisplayUtils.dip2px(6F))
}
holder.binding.game = gameEntity
holder.binding.subjectTag = subjectData?.tag
holder.initServerType(gameEntity!!)
holder.binding.executePendingBindings()
if (subjectData?.isOrder!!) {
holder.binding.gameOrder.visibility = View.VISIBLE
holder.binding.gameOrder.text = (subjectData.position).toString()
} else {
holder.binding.gameOrder.visibility = View.GONE
}
val keyName = if (TextUtils.isEmpty(blockName)) "首页" else "板块"
val keyValue = if (TextUtils.isEmpty(blockName)) "" else blockName
itemData.exposureEvent = ExposureEvent.createEvent(gameEntity = gameEntity,
source = listOf(ExposureSource(keyName, keyValue), ExposureSource("专题", gameEntity.subjectName ?: subjectData.name!!)),
eTrace = null,
event = ExposureType.EXPOSURE)
DownloadItemUtils.setOnClickListener(mContext, holder.binding.downloadBtn, gameEntity, position,
this@GameFragmentAdapter,
StringUtils.buildString("(游戏-专题:", subjectData.name, "-列表[", (position + 1).toString(), "])"),
StringUtils.buildString("游戏-专题-", subjectData.name, ":", gameEntity.name), itemData.exposureEvent)
DownloadItemUtils.updateItem(mContext, gameEntity, GameViewHolder(holder.binding), !gameEntity.isPluggable)
holder.itemView.setOnClickListener {
DataCollectionUtils.uploadClick(mContext, subjectData.name + "-列表", "游戏-专题", gameEntity.name)
if (gameEntity.isPluggable) {
GameDetailActivity.startGameDetailActivity(mContext, gameEntity.id,
StringUtils.buildString("(游戏-专题:插件化-列表[", (subjectData.position).toString(), "])"), itemData.exposureEvent)
} else {
binding.viewPager.stopAutoScroll()
GameDetailActivity.startGameDetailActivity(mContext, gameEntity,
StringUtils.buildString("(游戏-专题:", subjectData.name, "-列表[", (subjectData.position).toString(), "])"), itemData.exposureEvent)
}
}
}
} else if (holder is FooterViewHolder) {
holder.initFooterViewHolder(mLoadStatus == LoadStatus.LIST_LOADING
, mLoadStatus == LoadStatus.LIST_FAILED
, mLoadStatus == LoadStatus.LIST_OVER, View.OnClickListener {
if (mLoadStatus == LoadStatus.LIST_OVER) {
mViewModel.commandScrollTop.postValue(null)
} else {
mViewModel.getSubjectList(false)
notifyItemChanged(itemCount - 1)
}
})
} else if (holder is GameImageViewHolder) {
val entity = mItemDataList[position].image
private fun bindHeadView(holder: GameHeadViewHolder, position: Int) {
val column = mItemDataList[position].columnHead
holder.binding.subject = column
holder.binding.headPb.visibility = View.GONE
val text = if ("change" == column?.home) "换一批" else "全部"
holder.binding.headMore.text = text
val keyName = if (TextUtils.isEmpty(blockName)) "首页" else "板块"
val keyValue = if (TextUtils.isEmpty(blockName)) "" else blockName
if (text == "全部" && column != null && column.data != null && column.data!!.size >= column.more!!) {
holder.binding.headMore.visibility = View.GONE
} else {
holder.binding.headMore.visibility = View.VISIBLE
}
entity?.let {
if (it.type == "game") {
mItemDataList[position].exposureEvent = ExposureEvent.createEvent(gameEntity = entity,
source = listOf(ExposureSource(keyName, keyValue), ExposureSource("专题", entity.subjectData?.name + "-大图")),
eTrace = null,
event = ExposureType.EXPOSURE)
}
}
holder.binding.game = entity
holder.binding.traceEvent = mItemDataList[position].exposureEvent
val name = entity?.subjectData?.name
val link = entity?.link
val width = mContext.resources.displayMetrics.widthPixels - DisplayUtils.dip2px(mContext, 16F)
ImageUtils.display(holder.binding.gameImageIcon, entity?.image, width, object : BaseControllerListener<ImageInfo>() {
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
if (imageInfo == null) return
val imageParams = holder.binding.gameImageIcon.layoutParams
val scale = imageInfo.height.toFloat() / imageInfo.width.toFloat()
imageParams?.height = (width * scale).toInt()
holder.binding.gameImageIcon.layoutParams = imageParams
holder.binding.gameContainer.layoutParams.height = (width * scale).toInt()
}
})
holder.binding.gameImageIcon.setOnClickListener {
DataCollectionUtils.uploadClick(mContext, "$name-大图", "游戏-专题")
DataUtils.onMtaEvent(mContext, "游戏专题", "大图", name + ":" + entity?.name)
val linkEntity = LinkEntity()
linkEntity.link = link
linkEntity.type = entity?.type
linkEntity.text = name
DirectUtils.directToLinkPage(mContext, linkEntity, "(游戏-专题:$name-大图)", "首页游戏")
}
} else if (holder is GameHorizontalListViewHolder) {
val subjectEntity = mItemDataList[position].horizontalColumn
val exposureEventList = arrayListOf<ExposureEvent>()
val binding = holder.binding
var subjectAdapter = binding.horizontalRv.adapter
if (subjectAdapter == null) {
subjectAdapter = GameHorizontalAdapter(mContext, subjectEntity!!)
(binding.horizontalRv.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
binding.horizontalRv.layoutManager = GridLayoutManager(mContext, 4)
binding.horizontalRv.adapter = subjectAdapter
holder.binding.headMore.setOnClickListener {
if ("all" == column?.home) {
DataUtils.onMtaEvent(mContext, "游戏专题", "全部", column.name)
SubjectActivity.startSubjectActivity(mContext, column.id, column.name, column.isOrder, "(游戏-专题:" + column.name + "-全部)")
} else {
(subjectAdapter as GameHorizontalAdapter).checkResetData(subjectEntity!!)
subjectAdapter.notifyItemRangeChanged(0, subjectAdapter.itemCount)
DataUtils.onMtaEvent(mContext, "游戏专题", "换一批", column?.name)
holder.binding.headPb.visibility = View.VISIBLE
mViewModel.changeSubjectGame(column?.id!!)
}
}
}
subjectEntity.data?.let {
val keyName = if (TextUtils.isEmpty(blockName)) "首页" else "板块"
val keyValue = if (TextUtils.isEmpty(blockName)) "" else blockName
private fun bindPluginView(holder: GamePluginViewHolder, position: Int) {
val pluginList = mItemDataList[position].pluginList
var adapter = holder.mPluginRv.adapter
val positionOffset = subjectAdapter.getIndex()
if (adapter == null) {
adapter = GamePluginAdapter(mContext, pluginList)
adapter.openList(mIsOpenPluginList)
(holder.mPluginRv.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
holder.mPluginRv.layoutManager = LinearLayoutManager(mContext)
holder.mPluginRv.adapter = adapter
} else {
(adapter as GamePluginAdapter).openList(mIsOpenPluginList)
adapter.checkResetData(pluginList)
}
for (i in positionOffset until subjectAdapter.itemCount + positionOffset) {
it[i].sequence = i
val event = ExposureEvent.createEvent(gameEntity = it[i],
source = listOf(ExposureSource(keyName, keyValue), ExposureSource("专题", subjectEntity.name!!)),
eTrace = null,
event = ExposureType.EXPOSURE)
exposureEventList.add(event)
}
mItemDataList[position].exposureEventList = exposureEventList
subjectAdapter.exposureEventList = exposureEventList
holder.mHeadTitle.text = String.format(Locale.getDefault(), "你有%d个游戏可以升级插件版", pluginList?.size)
holder.mPluginHead.setOnClickListener {
if (mIsOpenPluginList) {
mIsOpenPluginList = false
holder.mHeadOpen.setImageResource(R.drawable.gamedetail_open_icon)
MtaHelper.onEvent("首页_点击", "插件化区域", "收起")
} else {
mIsOpenPluginList = true
holder.mHeadOpen.setImageResource(R.drawable.gamedetail_colse_icon)
MtaHelper.onEvent("首页_点击", "插件化区域", "展开")
}
notifyItemChanged(holder.adapterPosition)
}
}
@ -442,13 +468,15 @@ class GameFragmentAdapter(context: Context, model: GameViewModel, var blockName:
entryMap[download.platform] = download
}
if (getItemViewType(gameAndPosition.position) == ItemViewType.GAME_PLUGIN) {
val adapter = mPluginViewHolder?.mPluginRv?.adapter
if (adapter is GamePluginAdapter) {
adapter.notifyItemByDownload(download)
AppExecutor.uiExecutor.execute {
if (getItemViewType(gameAndPosition.position) == ItemViewType.GAME_PLUGIN) {
val adapter = mPluginViewHolder?.mPluginRv?.adapter
if (adapter is GamePluginAdapter) {
adapter.notifyItemByDownload(download)
}
} else {
notifyItemChanged(gameAndPosition.position)
}
} else {
notifyItemChanged(gameAndPosition.position)
}
}
}
@ -477,7 +505,7 @@ class GameFragmentAdapter(context: Context, model: GameViewModel, var blockName:
}
}
} else {
if (position > mItemDataList.size) return arrayListOf()
if (position >= mItemDataList.size) return arrayListOf()
val game = mItemDataList[position].game
if (game != null) {

View File

@ -1,14 +1,14 @@
package com.gh.gamecenter.game
import android.annotation.SuppressLint
import android.app.Application
import android.arch.lifecycle.*
import android.preference.PreferenceManager
import android.support.v4.util.ArrayMap
import android.text.TextUtils
import com.gh.common.TimeElapsedHelper
import com.gh.common.constant.Constants
import com.gh.common.util.ApkActiveUtils
import com.gh.common.util.GameUtils
import com.gh.common.util.RandomUtils
import com.gh.common.util.*
import com.gh.download.DownloadManager
import com.gh.gamecenter.baselist.LoadStatus
import com.gh.gamecenter.entity.*
@ -27,52 +27,59 @@ import java.util.HashMap
import kotlin.collections.ArrayList
import kotlin.collections.set
class GameViewModel(application: Application, var blockData: SubjectRecommendEntity?)
: AndroidViewModel(application) {
class GameViewModel(application: Application, blockData: SubjectRecommendEntity?) : AndroidViewModel(application) {
private var mSlideList = ArrayList<LinkEntity>() // 轮播图
private var mPluginList: List<GameEntity>? = null // 插件化
private var mSubjectList: MutableList<SubjectEntity> = ArrayList() // 专题
private var mSubjectDigestList = ArrayList<SubjectRecommendEntity>() // 专题入口
private var mSmartSubject: SubjectEntity? = null // 插件化
var mApi = RetrofitManager.getInstance(getApplication()).api
private val mItemDataListCache: MutableList<GameItemData> = ArrayList()
private val mSubjectChangedMap: ArrayMap<String, List<GameEntity>> = ArrayMap() // 存储换一换的数据
var blockData = blockData
private var mSubjectPage = 1 // 专题分页
private var mIsLoading = false
var slideList = ArrayList<LinkEntity>() // 轮播图
var pluginList: List<GameEntity>? = null // 插件化
var subjectList: MutableList<SubjectEntity> = ArrayList() // 专题
var subjectDigestList = ArrayList<SubjectRecommendEntity>() // 专题入口
var smartSubject: SubjectEntity? = null // 插件化
private var mApi = RetrofitManager.getInstance(getApplication()).api
private var mElapsedHelper: TimeElapsedHelper? = null
private var mShouldLogReplacingGame = true
var itemDataList: MediatorLiveData<List<GameItemData>> = MediatorLiveData()
val loadStatus = MutableLiveData<LoadStatus>()
val openingDialog = MutableLiveData<WelcomeDialogEntity>()
val mSubjectChangedMap: ArrayMap<String, List<GameEntity>> = ArrayMap() //存储换一换的数据
var positionAndPackageMap = HashMap<String, Int>() // key: packageName + position, value: position
private val itemDataListCache: MutableList<GameItemData> = ArrayList()
val commandScrollTop = MutableLiveData<Any>()
private var mSubjectPage = 1 // 专分页
private var mIsLoading = false
var positionAndPackageMap = HashMap<String, Int>() // key: packageName + position, value: position
init {
if (blockData == null) {
itemDataList.addSource(PackageRepository.gameUpdateLiveData) {
initPlugin(it)
// 第一次加载开始计时,供加载成功查看加载用时
mElapsedHelper = TimeElapsedHelper()
mElapsedHelper?.resumeCounting()
}
}
initData()
}
fun initData() {
slideList.clear()
subjectList.clear()
subjectDigestList.clear()
itemDataListCache.clear()
mSlideList.clear()
mSubjectList.clear()
mSubjectDigestList.clear()
mItemDataListCache.clear()
loadStatus.postValue(LoadStatus.INIT_LOADING)
getSlideData(true)
getSmartColumn()
// 触发列表刷新行为时亦刷新内存中的备用游戏库列表
GameRepositoryHelper.refreshGameRepository()
}
private fun initPlugin(updateList: List<GameUpdateEntity>?) {
@ -87,14 +94,14 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
for (game in list) {
game.setEntryMap(DownloadManager.getInstance(getApplication()).getEntryMap(game.name))
}
pluginList = list
mPluginList = list
transformationItemData()
}
/**
* 获取启动弹窗
*/
@SuppressLint("CheckResult")
fun requestOpeningData() {
val lastId = PreferenceManager.getDefaultSharedPreferences(getApplication()).getString(Constants.SP_LAST_OPENING_ID, "")
val lastTime = PreferenceManager.getDefaultSharedPreferences(getApplication()).getLong(Constants.SP_LAST_OPENING_TIME, 0)
@ -122,7 +129,7 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<List<LinkEntity>>() {
override fun onResponse(response: List<LinkEntity>?) {
if (response != null) slideList.addAll(response)
if (response != null) mSlideList.addAll(response)
if (initData) getSubjectDigest(initData)
}
@ -138,12 +145,18 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
if (initData) getSubjectList(initData)
return
}
val observable = if (blockData == null) mApi.subjectDigest else mApi.getBlockRecommends(blockData?.link)
val observable = if (blockData == null) {
mApi.subjectDigest
} else {
mApi.getBlockRecommends(blockData?.link)
}
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<List<SubjectRecommendEntity>>() {
override fun onResponse(response: List<SubjectRecommendEntity>?) {
if (response != null) subjectDigestList.addAll(response)
if (response != null) mSubjectDigestList.addAll(response)
transformationItemData()
if (initData) {
getSubjectList(initData)
@ -169,7 +182,13 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
} else {
loadStatus.postValue(LoadStatus.LIST_LOADING)
}
val observable = if (blockData == null) mApi.getColumn(mSubjectPage) else mApi.getBlockColumns(blockData?.link, mSubjectPage)
val observable = if (blockData == null) {
mApi.getColumn(mSubjectPage)
} else {
mApi.getBlockColumns(blockData?.link, mSubjectPage)
}
observable.subscribeOn(Schedulers.io())
.map {
for (subjectEntity in it) {
@ -188,7 +207,7 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
if (response != null) {
when {
initData -> {
subjectList = response as MutableList<SubjectEntity>
mSubjectList = response as MutableList<SubjectEntity>
loadStatus.postValue(LoadStatus.INIT_LOADED)
transformationItemData()
}
@ -196,7 +215,7 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
loadStatus.postValue(LoadStatus.LIST_OVER)
}
else -> {
subjectList.addAll(response)
mSubjectList.addAll(response)
loadStatus.postValue(LoadStatus.LIST_LOADED)
transformationItemData()
}
@ -204,19 +223,39 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
}
mSubjectPage++
mIsLoading = false
logSuccess()
}
override fun onFailure(e: HttpException?) {
if (initData && slideList.isEmpty() && subjectDigestList.isEmpty()) {
if (initData && mSlideList.isEmpty() && mSubjectDigestList.isEmpty()) {
loadStatus.postValue(LoadStatus.INIT_FAILED)
} else {
loadStatus.postValue(LoadStatus.LIST_FAILED)
}
mIsLoading = false
logFailure()
}
})
}
private fun logFailure() {
mElapsedHelper?.let {
it.pauseCounting()
mElapsedHelper = null
MtaHelper.onEvent("首页_加载", "启动光环", "加载失败")
}
}
private fun logSuccess() {
mElapsedHelper?.let {
it.pauseCounting()
MtaHelper.onEventWithTime("首页_加载", it.elapsedTime, "启动光环", "加载成功")
mElapsedHelper = null
}
}
private fun getSmartColumn() {
if (blockData != null) return
mApi.smartColumn
@ -224,11 +263,7 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<SubjectEntity>() {
override fun onResponse(response: SubjectEntity?) {
smartSubject = response
}
override fun onFailure(e: HttpException?) {
mSmartSubject = response
}
})
}
@ -269,7 +304,7 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
private fun initRandomGame(subjectId: String, sourceList: List<GameEntity>?) {
var rawList: MutableList<GameEntity>? = null
for (entity in subjectList) {
for (entity in mSubjectList) {
if (entity.id == subjectId) rawList = entity.data
}
if (rawList == null) return
@ -302,46 +337,50 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
}
private fun transformationItemData() {
itemDataListCache.clear()
mItemDataListCache.clear()
positionAndPackageMap.clear()
// 插入智能推荐专题
if (smartSubject != null && subjectList.size > smartSubject!!.sort) {
subjectList.add(smartSubject!!.sort, smartSubject!!)
smartSubject = null // 防止重复插入
if (mSmartSubject != null && mSubjectList.size > mSmartSubject!!.sort) {
mSubjectList.add(mSmartSubject!!.sort, mSmartSubject!!)
mSmartSubject = null // 防止重复插入
}
// 轮播图+专题入口
if (blockData == null || blockData?.display?.recommend!! || blockData?.display?.slide!!) {
val itemDataTop = GameItemData()
itemDataTop.slideList = slideList
itemDataTop.subjectRecommend = subjectDigestList
itemDataListCache.add(itemDataTop)
itemDataTop.slideList = mSlideList
itemDataTop.subjectRecommend = mSubjectDigestList
mItemDataListCache.add(itemDataTop)
}
// 插件化
if (pluginList != null && pluginList!!.isNotEmpty()) {
if (mPluginList != null && mPluginList!!.isNotEmpty()) {
val itemDataPlugin = GameItemData()
itemDataPlugin.pluginList = pluginList
itemDataListCache.add(itemDataPlugin)
itemDataPlugin.pluginList = mPluginList
mItemDataListCache.add(itemDataPlugin)
for (entity in pluginList!!) {
for (entity in mPluginList!!) {
addGamePositionAndPackage(entity)
}
}
// 专题 "type": "image/game_vertical/game_horizontal"
for (subjectEntity in subjectList) {
for (subjectEntity in mSubjectList) {
val data = subjectEntity.data
if (data == null || data.isEmpty()) continue
subjectEntity.relatedColumnId?.let {
replaceInstalledApp(data, it)
}
if (!data[0].image.isNullOrEmpty()) {
val itemDataImage = GameItemData()
val gameEntity = data[0]
if (gameEntity.id.isNullOrEmpty()) gameEntity.id = gameEntity.link
itemDataImage.image = gameEntity
itemDataImage.image?.subjectData = GameSubjectData(name = subjectEntity.name, isOrder = false)
itemDataListCache.add(itemDataImage)
mItemDataListCache.add(itemDataImage)
if (gameEntity.type == "game") addGamePositionAndPackage(gameEntity)
if (subjectEntity.type == "image") continue
@ -349,12 +388,12 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
val itemDataHead = GameItemData()
itemDataHead.columnHead = subjectEntity
itemDataListCache.add(itemDataHead)
mItemDataListCache.add(itemDataHead)
if (subjectEntity.type == "game_horizontal") {
val itemDataSubject = GameItemData()
itemDataSubject.horizontalColumn = subjectEntity
itemDataListCache.add(itemDataSubject)
mItemDataListCache.add(itemDataSubject)
for (game in subjectEntity.data!!) {
addGamePositionAndPackage(game)
}
@ -370,12 +409,69 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
val itemDataGame = GameItemData()
game.sequence = i
itemDataGame.game = game
itemDataListCache.add(itemDataGame)
mItemDataListCache.add(itemDataGame)
addGamePositionAndPackage(game)
}
}
itemDataList.postValue(itemDataListCache)
itemDataList.postValue(mItemDataListCache)
}
private fun replaceInstalledApp(gameList: MutableList<GameEntity>, relatedCollectionId: String) {
val gameIdList = arrayListOf<String>() // 专题包含的游戏 ID 列表
val positionOfTheGameToReplaceList = arrayListOf<Int>()
// 标记需要替换的已安装游戏
for ((index, game) in gameList.withIndex()) {
gameIdList.add(game.id ?: "")
// 是大图形式的游戏时不标记替换
if ((index == 0 && !gameList[0].image.isNullOrEmpty())) {
continue
}
var isThisPositionAdded = false
// 检查是否已安装该游戏里同包名的 APK
for (apk in game.getApk()) {
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
// 将该位置的游戏标记为需要替换
positionOfTheGameToReplaceList.add(index)
isThisPositionAdded = true
break
}
}
// 若此游戏所包含的 apk 没有已安装,那么再检查是否已安装有预设相关包名
if (!isThisPositionAdded) {
var relatedPackageList = arrayListOf<String>()
for (entity in PackageHelper.relatedPackageList) {
if (entity.gameId == game.id) {
relatedPackageList = ArrayList(entity.packages)
break
}
}
for (packageName in relatedPackageList) {
if (PackageHelper.validLocalPackageNameSet.contains(packageName)) {
positionOfTheGameToReplaceList.add(index)
break
}
}
}
}
if (positionOfTheGameToReplaceList.isNotEmpty()) {
if (blockData == null && mShouldLogReplacingGame) {
mShouldLogReplacingGame = false
MtaHelper.onEvent("首页_加载", "启动光环", "替换游戏")
}
for (position in positionOfTheGameToReplaceList) {
val replacingGame = GameRepositoryHelper.getOneUniqueGame(relatedCollectionId, gameIdList)
replacingGame?.let {
gameList[position] = replacingGame
}
}
}
}
private fun addGamePositionAndPackage(game: GameEntity) {
@ -383,15 +479,12 @@ class GameViewModel(application: Application, blockData: SubjectRecommendEntity?
for (apkEntity in game.getApk()) {
packages += apkEntity.packageName
}
positionAndPackageMap[packages + (itemDataListCache.size - 1)] = itemDataListCache.size - 1
positionAndPackageMap[packages + (mItemDataListCache.size - 1)] = mItemDataListCache.size - 1
game.gameLocation = GameEntity.GameLocation.INDEX
game.setEntryMap(DownloadManager.getInstance(getApplication()).getEntryMap(game.name))
}
class Factory(val mApplication: Application, val blockData: SubjectRecommendEntity?) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return GameViewModel(mApplication, blockData) as T

View File

@ -43,7 +43,6 @@ class GameHorizontalAdapter(context: Context, subject: SubjectEntity) : BaseRecy
holder.itemView?.setOnClickListener {
GameDetailActivity.startGameDetailActivity(mContext, gameEntity,
StringUtils.buildString("(游戏-专题:", mSubjectEntity.name, "-列表[", (position + 1).toString(), "])"), exposureEventList!![position])
}
}

View File

@ -74,7 +74,7 @@ import retrofit2.HttpException;
/**
* Created by CsHeng on 19/12/2017.
* \游戏详情适配器
* 游戏详情适配器
*/
public class GameDetailFragment extends NormalFragment {
@ -152,6 +152,7 @@ public class GameDetailFragment extends NormalFragment {
private boolean mSwitchToFirstTabInStartup;
private boolean mSkipGameComment;
private boolean mIsPageChanged;
private boolean mIsOpenPlatformWindow;
private int mCurVpPosition;
private int mMaxWidth;
@ -213,6 +214,7 @@ public class GameDetailFragment extends NormalFragment {
mAutoDownload = args.getBoolean(EntranceUtils.KEY_AUTO_DOWNLOAD);
mTraceEvent = args.getParcelable(EntranceUtils.KEY_TRACE_EVENT);
mSkipGameComment = args.getBoolean(EntranceUtils.KEY_SKIP_GAME_COMMENT);
mIsOpenPlatformWindow = args.getBoolean(EntranceUtils.KEY_OPEN_PLATFORM_WINDOW);
mSkeleton = Skeleton.bind(mListSkeleton).shimmer(false).load(R.layout.fragment_gamedetail_skeleton).show();
@ -344,7 +346,7 @@ public class GameDetailFragment extends NormalFragment {
}
}
if (mAutoDownload) {
if (mAutoDownload || (mIsOpenPlatformWindow && mGameEntity.getApk().size() > 1)) {
viewHolder.mDownloadPb.performClick();
mAutoDownload = false;
}

View File

@ -106,7 +106,12 @@ public class GameDetailBasicInfoAdapter extends BaseRecyclerAdapter<RecyclerView
viewHolder.hintDv.setVisibility(View.GONE);
}
viewHolder.hintTv.setText(tagEntity.getName());
viewHolder.hintTv.setTextColor(Color.parseColor(tagEntity.getColor()));
try {
// 有可能给的颜色有问题
viewHolder.hintTv.setTextColor(Color.parseColor(tagEntity.getColor()));
} catch (Exception ignore) {
}
if (isOpen) {
viewHolder.hintContentTv.setVisibility(View.VISIBLE);
viewHolder.hintContentTv.setText(tagEntity.getDes());
@ -124,6 +129,8 @@ public class GameDetailBasicInfoAdapter extends BaseRecyclerAdapter<RecyclerView
@Override
public int getItemCount() {
if (tags == null) return 0;
if (tips.getTitle() != null) {
return tags.size() + 1;
}

View File

@ -134,7 +134,7 @@ class FuLiAdapter(context: Context,
holder.hint.setText(R.string.game_suggestion_hint)
holder.initItemPadding()
holder.itemView.setOnClickListener {
SuggestionActivity.startSuggestionActivity(mContext, SuggestType.gameQuestion, "game", mFuLiViewModel?.game?.name + ",问题反馈:")
SuggestionActivity.startSuggestionActivity(mContext, SuggestType.gameQuestion, "game", mFuLiViewModel?.game?.name)
DataUtils.onMtaEvent(mContext, "游戏详情_新", "此游戏有问题_点击反馈", mFuLiViewModel?.game?.name)
}
}

View File

@ -176,13 +176,13 @@ class FuLiViewModel(application: Application,
val itemList = ArrayList<FuLiItemData>()
var isExistServer = false
var index = 0
val showArticleEntrance = Config.getSettings()?.showArticleEntrance
if (showArticleEntrance == "on" && gameDetail.notice != null && gameDetail.notice!!.isNotEmpty()) {
val showArticleEntrance = Config.getSettings()?.showArticleEntrance()
if (showArticleEntrance == true && gameDetail.notice != null && gameDetail.notice!!.isNotEmpty()) {
val fuLiData = FuLiItemData()
fuLiData.notice = gameDetail.notice
itemList.add(fuLiData)
}
if (showArticleEntrance == "on" && mArticleList != null) {
if (showArticleEntrance == true && mArticleList != null) {
val fuLiData = FuLiItemData()
fuLiData.article = mArticleList
itemList.add(fuLiData)

View File

@ -120,7 +120,6 @@ class RatingFragment : ListFragment<RatingComment, RatingViewModel>() {
R.id.rating_score_one -> targetScore = star.one / 2
}
var f = (targetScore / star.hits.toFloat()) * 100
if (0 < f && f < 1) {
f = 1F

View File

@ -52,7 +52,7 @@ class RatingViewModel(application: Application, val game: GameEntity) : ListView
val packageName = apk.packageName
if (!TextUtils.isEmpty(packageName)
// 过滤黑名单包名
&& !PackageHelper.excludePackageNameList.contains(packageName)) {
&& !PackageHelper.commentPackageNameBlackList.contains(packageName)) {
packageNameList.add(packageName!!)
}
}

View File

@ -8,10 +8,7 @@ import android.text.TextUtils
import android.view.MenuItem
import com.gh.base.BaseActivity
import com.gh.base.fragment.WaitingDialogFragment
import com.gh.common.util.DeviceUtils
import com.gh.common.util.EntranceUtils
import com.gh.common.util.ErrorHelper
import com.gh.common.util.GdtHelper
import com.gh.common.util.*
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.ActivityRatingEditBinding
import com.gh.gamecenter.entity.GameEntity
@ -114,4 +111,16 @@ class RatingEditActivity : BaseActivity() {
return intent
}
}
override fun handleBackPressed(): Boolean {
val content = mBinding?.content?.text.toString()
if (!TextUtils.isEmpty(content)) {
DialogUtils.showAlertDialog(this, "提示",
"确定退出评论吗?已撰写的内容会丢失",
"继续撰写", "确定退出",
null, { finish() })
return true
}
return super.handleBackPressed()
}
}

View File

@ -16,6 +16,7 @@ import com.gh.common.util.DisplayUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.LibaoUtils;
import com.gh.common.util.NewsUtils;
import com.gh.common.util.NumberUtils;
import com.gh.common.util.PlatformUtils;
import com.gh.common.util.StringUtils;
import com.gh.gamecenter.R;
@ -432,15 +433,11 @@ class ConcernAdapter extends BaseRecyclerAdapter<ViewHolder> {
int views = concernEntity.getViews();
viewHolder.readIcon.setVisibility(View.VISIBLE);
viewHolder.readNum.setText(String.valueOf(views));
viewHolder.readNum.setText(NumberUtils.transSimpleCount(views));
int commentnum = concernEntity.getCommentnum();
viewHolder.commentnum.setVisibility(View.VISIBLE);
if (commentnum > 999) {
viewHolder.commentnum.setText(R.string.thousand);
} else {
viewHolder.commentnum.setText(String.valueOf(commentnum));
}
viewHolder.commentnum.setText(NumberUtils.transSimpleCount(commentnum));
}

View File

@ -4,29 +4,25 @@ import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v4.util.ArrayMap;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gc.materialdesign.views.ProgressBarCircularIndeterminate;
import com.gh.common.AppExecutor;
import com.gh.common.repository.RemenkapaiRepository;
import com.gh.base.BaseActivity;
import com.gh.base.OnRequestCallBackListener;
import com.gh.common.util.ApkActiveUtils;
import com.gh.common.util.CheckLoginUtils;
import com.gh.common.util.ConcernUtils;
import com.gh.common.util.DataCollectionUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.StringUtils;
import com.gh.common.view.Concern_LinearLayout;
import com.gh.common.view.VerticalItemDecoration;
import com.gh.gamecenter.ConcernActivity;
import com.gh.gamecenter.LibaoDetailActivity;
@ -38,7 +34,6 @@ import com.gh.gamecenter.ShareCardPicActivity;
import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.entity.ConcernEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.GameInstall;
import com.gh.gamecenter.entity.LibaoEntity;
import com.gh.gamecenter.entity.LibaoStatusEntity;
import com.gh.gamecenter.entity.MeEntity;
@ -46,27 +41,22 @@ import com.gh.gamecenter.entity.UserDataLibaoEntity;
import com.gh.gamecenter.eventbus.EBConcernChanged;
import com.gh.gamecenter.eventbus.EBNetworkState;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.normal.NormalFragment;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.halo.assistant.fragment.myconcern.MyConcernRecommendAdapter;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.OnClick;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;
import static com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG;
@ -86,23 +76,20 @@ public class ConcernFragment extends NormalFragment implements SwipeRefreshLayou
LinearLayout noConnectionLayout;
@BindView(R.id.news1_ll_empty)
LinearLayout emptyLayout;
@BindView(R.id.news1_tv_concern)
TextView concern;
@BindView(R.id.news1_ll_concern)
LinearLayout concernLayout;
@BindView(R.id.news1_ll_concern_list)
ViewGroup concernListLayout;
@BindView(R.id.news1_empty_tv)
TextView mEmptyTv;
@BindView(R.id.concern_rv_recommend)
RecyclerView mRecommendRv;
@BindView(R.id.concern_rl_title)
RelativeLayout mConcernTitleRl;
public final static int NEWS_MESSAGE_LIBAO_REQUEST = 3; // 刷新礼包状态
public final static int NEWS_MESSAGE_ARTICLE_REQUEST = 4; // 刷新文章评论数
private ConcernAdapter mAdapter;
private MyConcernRecommendAdapter mConcernRecommendAdapter;
private LinearLayoutManager layoutManager;
private List<GameEntity> recommendGameList; // 推荐关注的游戏
private List<GameEntity> installGameList; // 安装的游戏
private Map<Integer, Boolean> concernMap; // 记录选择关注
Runnable mRunnable = new Runnable() {
@Override
@ -121,15 +108,11 @@ public class ConcernFragment extends NormalFragment implements SwipeRefreshLayou
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setNavigationTitle(R.string.discover_game_trends);
initMenu(R.menu.menu_concern);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
recommendGameList = new ArrayList<>();
installGameList = new ArrayList<>();
concernMap = new ArrayMap<>();
refreshLayout.setColorSchemeResources(R.color.theme);
refreshLayout.setOnRefreshListener(this);
@ -169,11 +152,16 @@ public class ConcernFragment extends NormalFragment implements SwipeRefreshLayou
@Override
public void loadDone() { // 数据加载成功回调
refreshLayout.setEnabled(true);
refreshLayout.setRefreshing(false);
emptyLayout.setVisibility(View.GONE);
concernLayout.setVisibility(View.GONE);
mRecommendRv.setVisibility(View.GONE);
mConcernTitleRl.setVisibility(View.GONE);
loadingLayout.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
((BaseActivity) requireActivity()).clearMenu();
initMenu(R.menu.menu_concern);
}
@Override
@ -192,7 +180,7 @@ public class ConcernFragment extends NormalFragment implements SwipeRefreshLayou
emptyLayout.setVisibility(View.VISIBLE);
refreshLayout.setEnabled(false);
initInstallGame();
showRecommendGames();
if (TextUtils.isEmpty(UserManager.getInstance().getToken())) {
mEmptyTv.setText(getString(R.string.login_hint));
@ -201,202 +189,69 @@ public class ConcernFragment extends NormalFragment implements SwipeRefreshLayou
mEmptyTv.setText(getString(R.string.ask_none));
mEmptyTv.setTextColor(getResources().getColor(R.color.c7c7c7));
}
((BaseActivity) requireActivity()).clearMenu();
}
// 推荐关注改为手机安装的游戏+光环助手
private void initInstallGame() {
recommendGameList.clear();//清除上一次记录
installGameList.clear();
concernMap.clear();
concern.setEnabled(true);//防止上一次关注按钮不可以,导致重新刷新后也不可用
AppExecutor.getIoExecutor().execute(() -> {
List<GameInstall> installedList = PackagesManager.filterSameApk(PackagesManager.getInstalledList());
// 对已安装的游戏排序
Collections.sort(installedList, (lhs, rhs) -> Long.compare(lhs.getInstallTime(), rhs.getInstallTime()));
List<Observable<GameEntity>> sequences = new ArrayList<>();
List<GameEntity> gameList = new ArrayList<>();
for (int i = 0, size = installedList.size() + 1; i < size; i++) {
if (i == size - 1) {
if (getContext() != null) {
sequences.add(RetrofitManager.getInstance(getContext()).getApi().getGameDigest(getContext().getString(R.string.ghzs_id)));// 光环助手ID
}
} else {
sequences.add(RetrofitManager.getInstance(getContext()).getApi().getGameDigest(installedList.get(i).getId()));
}
}
Observable.mergeDelayError(sequences)
.map(ApkActiveUtils.filterMapper)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<GameEntity>() {
@Override
public void onFailure(@Nullable HttpException e) {
initRecommendConcern(installedList, gameList);
}
@Override
public void onComplete() {
initRecommendConcern(installedList, gameList);
}
@Override
public void onResponse(@Nullable GameEntity response) {
if (getString(R.string.ghzs_id).equals(response.getId())) {
recommendGameList.add(response);
} else {
ApkActiveUtils.filterHideApk(response);
gameList.add(response);
}
}
});
});
}
private void initRecommendConcern(List<GameInstall> list, List<GameEntity> gameList) {
for (GameInstall info : list) {
for (int i = 0; i < gameList.size(); i++) {
if (info.getId().equals(gameList.get(i).getId())) {
installGameList.add(gameList.get(i));
break;
}
}
}
RemenkapaiRepository
.getRemenkapai(4)
.map(list1 -> {
// 根据热门卡牌顺序进行排序
for (int i = 0; i < installGameList.size(); i++) {
if (recommendGameList.size() >= 4) {
break;
}
for (int j = 0; j < list1.size(); j++) {
if (list1.get(j).getId().equals(installGameList.get(i).getId())) {
recommendGameList.add(installGameList.get(i));
installGameList.remove(i);
i--;
break;
}
}
}
// 推荐关注列表不足4个时剩下的从已安装列表选取
if (recommendGameList.size() < 4) {
for (GameEntity installEntity : installGameList) {
boolean notExistInRecommendList = true;
if (recommendGameList.size() < 4) {
for (int i = 0; i < recommendGameList.size(); i++) {
GameEntity recEntity = recommendGameList.get(i);
if (recEntity.getId().equals(installEntity.getId())) {
notExistInRecommendList = false;
break;
}
}
if (notExistInRecommendList) recommendGameList.add(installEntity);
if (recommendGameList.size() == 4) break;
}
}
}
// 推荐关注列表不足4个时, 在热门卡牌补
if (recommendGameList.size() < 4) {
for (GameEntity hotEntity : list1) {
boolean notExistInRecommendList = true;
for (int i = 0; i < recommendGameList.size(); i++) {
GameEntity recEntity = recommendGameList.get(i);
if (recEntity.getId().equals(hotEntity.getId())) {
notExistInRecommendList = false;
break;
}
}
if (notExistInRecommendList) recommendGameList.add(hotEntity);
if (recommendGameList.size() == 4) break;
}
}
return "";
})
private void showRecommendGames() {
// 先请求用户已关注的游戏数据
RetrofitManager.getInstance(requireContext()).getApi()
.getConcern(UserManager.getInstance().getUserId())
.map(ApkActiveUtils.filterMapperList)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<String>() {
.subscribe(new Response<List<GameEntity>>() {
@Override
public void onResponse(String response) {
initRecommendConcernView();
public void onResponse(List<GameEntity> response) {
initRecommendAdapter(response);
}
@Override
public void onError(Throwable e) {
initRecommendAdapter(new ArrayList<>());
}
});
}
private void initRecommendConcernView() {
if (recommendGameList.isEmpty()) {
return;
}
concernLayout.setVisibility(View.VISIBLE);
concernListLayout.removeAllViews();
private void initRecommendAdapter(List<GameEntity> response) {
if (!isAdded()) return;
SimpleDraweeView icon;
TextView name;
ImageView concern;
mConcernRecommendAdapter = new MyConcernRecommendAdapter(getContext(),
new OnRequestCallBackListener() {
@Override
public void loadDone() {
mConcernTitleRl.setVisibility(View.VISIBLE);
mRecommendRv.setVisibility(View.VISIBLE);
GameEntity gameEntity;
for (int i = 0, size = recommendGameList.size(); i < size; i++) {
concernMap.put(i, true);
int size = mConcernRecommendAdapter.getItemCount();
mRecommendRv.setAdapter(mConcernRecommendAdapter);
mRecommendRv.setLayoutManager(new GridLayoutManager(getContext(), size > 4 ? 4 : size));
mConcernRecommendAdapter.notifyDataSetChanged();
}
gameEntity = recommendGameList.get(i);
@Override
public void loadDone(Object obj) {
mConcernTitleRl.setVisibility(View.VISIBLE);
mRecommendRv.setVisibility(View.VISIBLE);
View view = View.inflate(getActivity(), R.layout.concern_item, null);
int size = mConcernRecommendAdapter.getItemCount();
mRecommendRv.setAdapter(mConcernRecommendAdapter);
mRecommendRv.setLayoutManager(new GridLayoutManager(getContext(), size > 4 ? 4 : size));
mConcernRecommendAdapter.notifyDataSetChanged();
}
icon = view.findViewById(R.id.concern_item_icon);
name = view.findViewById(R.id.concern_item_name);
concern = view.findViewById(R.id.concern_item_concern_iv);
view.findViewById(R.id.concern_item_concern).setVisibility(View.GONE);
@Override
public void loadError() {
concern.setVisibility(View.VISIBLE);
ImageUtils.display(icon, gameEntity.getIcon());
name.setText(gameEntity.getName());
concern.setImageResource(R.drawable.concern_select_true);
}
final int finalI = i;
concern.setOnClickListener(v -> {
if (concernMap.get(finalI)) {
((ImageView) v).setImageResource(R.drawable.concern_select_false);
concernMap.put(finalI, false);
} else {
((ImageView) v).setImageResource(R.drawable.concern_select_true);
concernMap.put(finalI, true);
}
// 判断关注按钮是否可用
isConcernAvailable();
});
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.MATCH_PARENT);
params.weight = 1;
concernListLayout.addView(view, params);
}
concernListLayout.setVisibility(View.VISIBLE);
}
// 判断关注按钮是否可用
private void isConcernAvailable() {
// ???
boolean isEnabled = false;
for (int key : concernMap.keySet()) {
if (concernMap.get(key)) {
isEnabled = true;
break;
}
}
concern.setEnabled(isEnabled);
if (isEnabled) {
concern.setTextColor(ContextCompat.getColor(getContext(), R.color.theme));
} else {
concern.setTextColor(ContextCompat.getColor(getContext(), R.color.btn_pause));
}
@Override
public void loadEmpty() {
onRefresh();
}
},
response,
mEntrance);
}
@Override
@ -438,27 +293,7 @@ public class ConcernFragment extends NormalFragment implements SwipeRefreshLayou
mAdapter.notifyItemChanged(mAdapter.getSkipPosition());
mAdapter.setSkipPosition(-1);
break;
}
}
@OnClick(R.id.news1_tv_concern)
public void concern() { // 关注 推荐关注的游戏
CheckLoginUtils.checkLogin(getContext(), "游戏动态-推荐关注-[关注]", () -> {
ArrayList<GameEntity> list = new ArrayList<>();
for (int key : concernMap.keySet()) {
if (concernMap.get(key)) {
list.add(recommendGameList.get(key));
}
}
// 同步关注
JSONArray data = new JSONArray();
for (GameEntity gameEntity : list) {
data.put(gameEntity.getId());
}
ConcernUtils.INSTANCE.updateConcernData(getContext(), data);
});
}
// 连接上网络事件
@ -477,34 +312,46 @@ public class ConcernFragment extends NormalFragment implements SwipeRefreshLayou
@OnClick(R.id.reuse_no_connection)
public void reconnection() { // 重新连接
refresh();
}
private void refresh() {
refreshLayout.setRefreshing(true);
recyclerView.setVisibility(View.VISIBLE);
loadingLayout.setVisibility(View.VISIBLE);
noConnectionLayout.setVisibility(View.GONE);
postDelayedRunnable(mRunnable, 1000);
postRunnable(mRunnable);
}
// // Fragment界面切换事件
// @Subscribe(threadMode = ThreadMode.MAIN)
// public void onEventMainThread(EBUISwitch swith) {
// if (InfoToolWrapperFragment.EB_NEWSFRAGMENT_TAG.equals(swith.getFrom())) {
// if (swith.getPosition() == 1) {
// if (loadingLayout.getVisibility() == View.VISIBLE) {
// mAdapter.addList(0);
// }
// }
// }
// }
@OnClick(R.id.concern_rl_title)
public void onClick(View v) {
switch (v.getId()) {
case R.id.concern_rl_title:
if (mRecommendRv.getVisibility() == View.VISIBLE) {
((Concern_LinearLayout) mCachedView).hideRecyclerView();
} else {
((Concern_LinearLayout) mCachedView).showRecyclerView();
}
break;
}
}
// 关注事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBConcernChanged changed) {
emptyLayout.setVisibility(View.GONE);
refreshLayout.setEnabled(true);
refreshLayout.setRefreshing(true);
recyclerView.setVisibility(View.VISIBLE);
loadingLayout.setVisibility(View.VISIBLE);
postRunnable(mRunnable);
if (!isResumed()) {
refresh();
} else {
if (mAdapter.getItemCount() == 0) {
mEmptyTv.setText("点击刷新");
mEmptyTv.setTextColor(getResources().getColor(R.color.theme));
mEmptyTv.setOnClickListener(v -> {
refresh();
mEmptyTv.setOnClickListener(null);
});
}
}
mConcernRecommendAdapter.concernGame(changed.getGameId());
}
// 登录事件

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