Compare commits

...

190 Commits

Author SHA1 Message Date
783fbecb00 3.6.4 封包 2019-05-30 16:11:01 +08:00
de1b5ba2f3 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-30 15:49:21 +08:00
9a9e288c44 3.6.4 封包 2019-05-30 15:37:51 +08:00
424b48f631 更改远端 JS 和 CSS 至正式环境 2019-05-30 15:21:38 +08:00
86d1cd4e12 微调编译脚本 2019-05-30 15:01:02 +08:00
e700ff4744 微调编译脚本 2019-05-30 14:43:56 +08:00
34729c8c28 添加 jenkins 编译脚本 2019-05-30 14:26:54 +08:00
5a08611fdd 测试包在设置关于里显示编译时间 2019-05-30 11:51:57 +08:00
a73da1d6e4 修复游戏评论详情从弹窗回退后无法即时调起软键盘问题 2019-05-29 18:37:14 +08:00
28b8c20756 修复分类展开部分标签会丢失的问题 2019-05-29 14:41:47 +08:00
6941821b71 矫正网页资源的时间戳 2019-05-29 14:15:18 +08:00
3c2244701c 关闭 webview 调试 2019-05-29 14:07:21 +08:00
38dc873e2e Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-29 10:58:51 +08:00
c24ffb2489 修复插入数据造成浏览记录出现多个空格的问题 2019-05-29 10:58:34 +08:00
929864be30 优化游戏评论详情点赞刷新问题 2019-05-28 18:22:10 +08:00
bd87163a9b 显示/隐藏图片是无需回调(RE.callback()) 2019-05-28 17:52:23 +08:00
785c740668 修复图片名存在特殊字符无法显示的问题 2019-05-28 17:35:16 +08:00
25aa16f774 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-28 16:38:05 +08:00
9ec89c0dc1 光环助手V3.6.4测试遗留问题(2.3.5.15.16.17) https://gitlab.ghzs.com/pm/halo-app-issues/issues/536#note_22029 2019-05-28 16:37:25 +08:00
3e5bd2b087 修复我的提问、回答和文章页面分页的顺序变动问题 2019-05-28 15:31:56 +08:00
9de6cff13b 浏览记录的文章和答案过滤掉插入的内容 2019-05-27 17:53:19 +08:00
6b98bc9fca 修复了答案上下滑动可能出现页面偏移的问题 2019-05-27 17:52:39 +08:00
cdf9b0a071 去掉测试 toast 2019-05-26 15:14:49 +08:00
ff57e9c759 merge 2019-05-24 22:48:33 +08:00
b253113843 光环助手V3.6.4 RELEASE(20190524-2130)测试问题汇总(1.2.3.4.11) https://gitlab.ghzs.com/pm/halo-app-issues/issues/534 2019-05-24 22:47:32 +08:00
b7305337bf 修复浏览记录的游戏名字以及推送点击记录的问题 2019-05-24 22:10:34 +08:00
455e2ad723 处理文章隐藏时的弹两个 toast 的问题 2019-05-24 21:16:18 +08:00
8cf87b991b 推送辅助提示变更 2019-05-24 21:12:20 +08:00
ae0b289c3e 光环助手V3.6.4 RELEASE(20190524-1230)(1.2.3.4.5.6.7.8.9.10.11.12.14.15.16)测试问题汇总 https://gitlab.ghzs.com/pm/halo-app-issues/issues/533 2019-05-24 21:06:37 +08:00
9404c3349a 修复游戏评论详情重复点赞toast异常问题 2019-05-24 17:37:53 +08:00
28afbb8d35 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-24 17:16:18 +08:00
5b24443121 富文本编辑器添加样式之前将内容字符进行htmlEncode,防止JS端JSON解释失败 2019-05-24 17:15:37 +08:00
1f9aacbbbd 去掉多余的 toast 2019-05-24 16:52:32 +08:00
d194b33a5d 富文本编辑器初始化代码放置到assets目录,通过本地的rich_editor.js 访问远端的JS和CSS代码
目的:修复低版本内核浏览器的事件无法回调到原生android端问题
2019-05-24 16:02:13 +08:00
55010f0ef7 关闭rich_editor.js log 2019-05-24 14:21:10 +08:00
49fab9ed04 游戏详情判断是否安装该游戏时进行包名过滤 2019-05-24 11:44:04 +08:00
1cd1b578ec merge 2019-05-24 11:27:28 +08:00
184c56aac5 光环助手V3.6.4 DEV(20190517-1020)测试问题汇总(游戏评分)(补充) 2019-05-24 11:25:26 +08:00
7c39037472 修复记录安装新应用时记录了错误应用名的问题 2019-05-24 11:12:13 +08:00
786a803793 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-24 10:58:52 +08:00
273f0e185d 修复关闭插件功能资讯和专题相关操作失效问题
修改游戏评分引用区域样式
2019-05-24 10:58:46 +08:00
eebc2c3940 统一已开通社区的列表排序 2019-05-24 10:25:05 +08:00
3a964d629e Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-24 09:49:57 +08:00
ff041f705e 光环助手V3.6.4 DEV(20190521-1900)测试问题汇总(前端)(2.3.4.5(1).19.20.21) https://gitlab.ghzs.com/pm/halo-app-issues/issues/530#note_21778 2019-05-24 09:49:41 +08:00
af62fc9a68 替换关闭评论图标 2019-05-23 18:20:44 +08:00
6ff415cc0d 完成光环助手应用数据上报功能 https://gitlab.ghzs.com/pm/halo-app-issues/issues/531 2019-05-23 18:04:53 +08:00
41de94e6f5 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-23 16:58:36 +08:00
60d91ca04e 光环助手V3.6.4 DEV(20190521-1900)测试问题汇总(编辑器)(1.5.6.7.9.10.12.13.15.16.17.18) https://gitlab.ghzs.com/pm/halo-app-issues/issues/529 2019-05-23 16:58:29 +08:00
19004b2073 完成V3.6.4DEV(20190521-1900)测试问题汇总(6,7,8,9,10,12,14,16,17,22) https://gitlab.ghzs.com/pm/halo-app-issues/issues/530 2019-05-23 16:42:01 +08:00
70b536e6bd 修复社区编辑器插入自定义样式问题(上次兼容性修改遗留) 2019-05-23 14:36:45 +08:00
5009678587 本地JS与远程同步 2019-05-23 11:07:55 +08:00
a7a01bbe16 修复社区编辑框不兼容个别机型问题(VIVO x7 5.1.1) 2019-05-23 11:04:57 +08:00
9b2ce51c87 更换引导图 2019-05-22 16:46:36 +08:00
c735d4e717 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-22 16:26:10 +08:00
6fb4dac45d update CHANGELOG 2019-05-22 16:26:02 +08:00
3d49258b84 优化代码结构 2019-05-22 16:15:41 +08:00
c23aa12d09 优化编辑回答的接口异常处理 2019-05-22 16:08:58 +08:00
6f6ddf9fbd 更换引导图 2019-05-22 10:33:59 +08:00
63837b5c31 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-21 16:28:31 +08:00
27e245c241 我的关注不能点击关联关注进行关注操作 2019-05-21 16:28:24 +08:00
7775494ade 完成3.6.4 DEV(20190517-1020)测试问题汇总的(3,4,7,8,9,10,11,17,18) https://gitlab.ghzs.com/pm/halo-app-issues/issues/525 2019-05-21 16:12:06 +08:00
a3ce139b86 曝光增加 ROM 字段 2019-05-21 16:11:03 +08:00
ad470f10f4 光环助手V3.6.4 DEV(20190517-1020)测试问题汇总(编辑器)(1.2.3.4.5.6.8.9) https://gitlab.ghzs.com/pm/halo-app-issues/issues/527 2019-05-21 16:06:20 +08:00
302d12083b 光环助手V3.6.4 DEV(20190517-1020)测试问题汇总(游戏评分)(1.4.5.6.7.8.9.10.11) https://gitlab.ghzs.com/pm/halo-app-issues/issues/526 2019-05-21 11:17:29 +08:00
d40dd15af4 撰写回答页面添加我来回答遮罩 2019-05-20 15:28:18 +08:00
440eb8a07b 完成DEV(20190515-1900)测试问题汇总(1,2,3,16,17,18) https://gitlab.ghzs.com/pm/halo-app-issues/issues/524 2019-05-20 11:47:17 +08:00
361b861d5f 修复部分(关注/收藏)按钮,登录后不能即时刷新问题 2019-05-20 11:24:20 +08:00
b518b2961a Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-17 18:24:38 +08:00
bfae4e1501 光环助手V3.6.4 DEV(20190515-1900)测试问题汇总(前端)(10.14.15) https://gitlab.ghzs.com/pm/halo-app-issues/issues/524#note_21505 2019-05-17 18:24:32 +08:00
d3e13dd8c6 完成需求 MTA 补充需求 2019-05-17 17:27:42 +08:00
073c35ca08 浏览记录去掉游戏名称后缀 2019-05-17 17:27:19 +08:00
99b4373561 处理闪退问题 2019-05-17 17:26:51 +08:00
52dcea477e 评分相关间距调整 2019-05-17 17:03:53 +08:00
6abb8d715b Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-17 16:36:53 +08:00
51016b0704 社区编辑框插入链接样式时先将当前blockquote标签换成p标签再插入 2019-05-17 16:36:47 +08:00
d14c150070 完成需求'所有游戏名字处理成“名称+后缀”的格式的' https://gitlab.ghzs.com/pm/halo-app-issues/issues/521 2019-05-17 16:28:32 +08:00
f59f8a3e5b 完成光环前端需求汇总(2019年5月第3周)(1,3,11,12,13) https://gitlab.ghzs.com/pm/halo-app-issues/issues/522 2019-05-17 15:02:56 +08:00
965be0b5cd Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-17 14:40:46 +08:00
716900fc5d 社区编辑框增加长按选择回调 2019-05-17 14:40:31 +08:00
14280d802e 更改回答详情和文章详情底部按钮图标 2019-05-17 11:32:03 +08:00
39924857e5 我的游戏页面进行包名过滤处理 2019-05-17 10:51:47 +08:00
c88bda6615 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-16 18:37:47 +08:00
ecb80ca70d 光环助手V3.6.4 DEV(20190513-1900)编辑器相关(1.3.4.6.7.8.9.11.17) https://gitlab.ghzs.com/pm/halo-app-issues/issues/519#note_21413 2019-05-16 18:37:38 +08:00
51b03b78ce 在插入内容的 div 里添加 class 帮助后端生成摘要时去掉不需要的内容 2019-05-16 18:20:28 +08:00
a7fd029ed2 反馈提交的字段修改 2019-05-16 16:01:31 +08:00
5beb29ad09 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-16 15:03:57 +08:00
e7dc2ca810 光环前端需求汇总(2019年5月第3周)(5.6.7.9) https://gitlab.ghzs.com/pm/halo-app-issues/issues/522#note_21366 2019-05-16 15:03:45 +08:00
b5ce0db1ff 将 JS 和 CSS 的引用改为远端 2019-05-16 10:22:41 +08:00
c8b52902e9 评分相关的POST请求进行错误处理 2019-05-16 09:36:28 +08:00
dbc4e0ac26 历史搜索清空图标自适应宽高 2019-05-15 18:18:22 +08:00
a0d2860970 修改游戏搜索历史页面样式 2019-05-15 18:06:37 +08:00
77c1a05a4a 修改资讯中心标签样式 2019-05-15 17:59:23 +08:00
aeee2e049d 回答/文章 插入链接的默认图片换成网络图片 2019-05-15 17:13:21 +08:00
525b184ad4 游戏评论详情增加下载相关逻辑 2019-05-15 16:14:05 +08:00
76e0fe9f9a 光环助手V3.6.4 DEV(20190513-1900)游戏评分相关(2.4.5.6.8.9.12.13.16.18.19.20.21) https://gitlab.ghzs.com/pm/halo-app-issues/issues/520 2019-05-15 15:14:30 +08:00
06ddef114c Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-14 14:48:52 +08:00
32cdcc1304 光环助手V3.6.4 DEV(20190509-1900)测试问题汇总(前端)(3.4.5)https://gitlab.ghzs.com/pm/halo-app-issues/issues/516#note_21124 2019-05-14 14:48:40 +08:00
4a2b414b59 社区选择列表增加关联置顶 2019-05-14 11:29:04 +08:00
937497aec9 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-13 18:18:15 +08:00
38d2c189e8 游戏详情标签样式由后台控制 2019-05-13 18:18:02 +08:00
57aeacf3f5 完成光环前端需求汇总(2019年4月第3周)(1,4,5) https://gitlab.ghzs.com/pm/halo-app-issues/issues/495 2019-05-13 16:53:47 +08:00
fe4036b768 完成光环助手V3.6.4数据统计需求(光环数据后台) https://gitlab.ghzs.com/pm/halo-app-issues/issues/509 2019-05-13 15:43:41 +08:00
5dd479c492 完成光环助手V3.6.4数据统计需求(光环数据后台) https://gitlab.ghzs.com/pm/halo-app-issues/issues/509 2019-05-13 15:15:27 +08:00
5f1ff1fc6f Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-13 14:22:44 +08:00
b08fb1f170 光环前端需求汇总(2019年4月第5周)(3.6.9.10.13) https://gitlab.ghzs.com/pm/halo-app-issues/issues/512#note_21125 2019-05-13 14:20:57 +08:00
e2f6180d6d 完成光环助手V3.6.4数据统计需求(MTA) https://gitlab.ghzs.com/pm/halo-app-issues/issues/510 2019-05-13 11:00:02 +08:00
90d19ea381 补充下载进度超过 100% 的错误回调 2019-05-13 10:58:48 +08:00
13738f08eb 复用 Gson 对象 2019-05-13 10:00:08 +08:00
1b76184946 光环前端需求汇总(2019年4月第4周)(1.3.4.5.6.7.11.13) https://gitlab.ghzs.com/pm/halo-app-issues/issues/501#note_21126 2019-05-12 18:34:50 +08:00
711431f7c9 光环前端需求汇总(2019年4月第4周)(1.3.4.5.6.7.11.13) https://gitlab.ghzs.com/pm/halo-app-issues/issues/501#note_21126 2019-05-12 18:31:42 +08:00
4ea3f7ccf0 完成光环前端需求汇总(2019年4月第5周)的(2, 4, 5, 11, 12) https://gitlab.ghzs.com/pm/halo-app-issues/issues/512 2019-05-12 17:20:44 +08:00
80cd86ea29 优化游戏评论详情刷新问题 2019-05-10 17:05:56 +08:00
f87bb6cd06 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-10 16:41:10 +08:00
ea726a22bd 游戏评论相关优化 2019-05-10 16:41:02 +08:00
7e3afe7d70 Merge branch 'xiechanghong' into 'dev'
UI 变更

See merge request !5
2019-05-10 15:45:50 +08:00
8131c58fbf 规范化代码格式 2019-05-10 15:33:51 +08:00
674e32a096 优化上一版的代码问题 2019-05-10 11:52:40 +08:00
f5d42a3e01 优化上一版的代码问题 2019-05-09 20:48:05 +08:00
a079a03adc 首页猜你喜欢列表增加隐藏包过滤 2019-05-09 17:59:28 +08:00
8485f94133 优化内容:①文本输入框达到字数上限之后,继续输入内容直接出现Toast提示,不会把最后面的内容删掉,且光标停留在当前位置②如果发生闪退,再次打开光环时会提示立即反馈,这时如果玩家提交成功,会再次出现联系客服弹窗,点击"联系客服" 即直接跳转打开客服QQ对话页面 2019-05-09 17:01:59 +08:00
5d60a8f03b Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev
# Conflicts:
#	app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java
2019-05-09 16:52:16 +08:00
ec4319b74a 增加游戏评论相关的消息中心操作 2019-05-09 16:50:15 +08:00
41c3f9d073 更改游戏浏览记录的数据库结构 (从上几个测试版覆盖安装将清空所有浏览记录) 2019-05-09 14:04:05 +08:00
c27990b395 完成回答详情/社区文章详情增加反对功能 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/505 2019-05-08 18:43:10 +08:00
2e9a823ee1 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-08 17:42:01 +08:00
590afccae7 游戏详情-评论 增加小编评论 2019-05-08 17:41:53 +08:00
7a82780826 接入新的版主权限管理 2019-05-08 17:26:57 +08:00
c75e363a06 添加浏览记录图标 2019-05-08 17:12:24 +08:00
573b7b61cf Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	app/src/main/java/com/gh/common/util/Extensions.kt
2019-05-08 17:11:51 +08:00
9f9e1bc9fd 游戏评论/游戏评论详情完成'举报/复制'操作 2019-05-08 16:37:36 +08:00
34e11b1569 Merge remote-tracking branch 'origin/dev' into dev 2019-05-08 16:05:40 +08:00
cc7b77a8ad Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-08 11:50:42 +08:00
ed3a75ddc0 游戏评论详情页面用baseList实现 2019-05-08 11:50:26 +08:00
983c01df57 增加清除 HTML 标签的 extension 方法 2019-05-08 10:55:39 +08:00
9d95b7aa6b 修复首页游戏替换下拉刷新时会出现为确保页面游戏唯一而隐藏掉需要的游戏的问题 2019-05-08 10:06:19 +08:00
5319cb8679 回答详情页面增加反对功能(文章详情未完成) 2019-05-07 18:16:33 +08:00
b4b1a63c22 处理空指针异常 2019-05-07 09:52:03 +08:00
2dfd57de80 DataUtils 初始化同步执行 2019-05-06 18:22:56 +08:00
cbc8876656 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-06 15:39:46 +08:00
4e6b8bf6b3 优化游戏评论回复操作 2019-05-06 15:39:33 +08:00
da92826f6a 清理回答详情页面的无用代码 2019-05-06 11:13:44 +08:00
f1a4e429f3 修复回答详情预加载也会产生阅读时长的问题 2019-05-06 09:29:18 +08:00
3cd248a2c5 基本完成我的光环增加浏览记录需求 https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/500#note_20735 2019-05-05 17:53:22 +08:00
7f5dd97359 统一游戏评论item数据设置 2019-05-05 17:37:12 +08:00
c0ee431d1f Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-05-05 15:12:53 +08:00
f56de73eb6 完成游戏评论详情(回复)相关页面展示/分页/跳转/点赞操作 2019-05-05 15:12:36 +08:00
a0b5cd00d5 修复一个数组越界问题 2019-05-05 09:45:36 +08:00
66b5f3d896 调整回答详情页面的结构,增加回答详情的浏览记录 2019-05-04 16:48:19 +08:00
a4346a6f34 游戏评分评论详情页面(未完待续...) 2019-05-04 16:32:26 +08:00
83894f6530 修改游戏评分样式
增加游戏评分评论详情页面
2019-04-30 18:30:03 +08:00
9b776bb029 我的关注增加关联关注 2019-04-30 10:48:16 +08:00
ea72fb09e0 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-04-29 10:58:11 +08:00
b2b390cf8b community keep position when update search 2019-04-29 10:57:46 +08:00
926abe248f Merge branch '3.6.3-log-fixd' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-04-29 09:30:58 +08:00
95468cf83e 更新百度推广激活接口 2019-04-28 17:38:16 +08:00
259b93eb25 修复错误的 MTA 事件命名 2019-04-28 16:49:01 +08:00
f59646643f 修复关闭评论页面软键盘没有隐藏的问题 2019-04-28 14:32:31 +08:00
7130417e60 增加记录推送点击事件失败重试 2019-04-28 11:28:50 +08:00
458a9f2a63 更新 API 至 3.6.4 2019-04-28 11:27:03 +08:00
0f85497f75 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-04-27 17:06:56 +08:00
3c0c6afd43 整理代码 2019-04-27 17:06:45 +08:00
345cdb41bc 完成首页游戏替换功能(第二期)https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/498 2019-04-26 18:12:47 +08:00
b78fa40eff 修复在小内存设备上加载本地应用图标会内存不够然后闪退的问题 2019-04-26 16:18:44 +08:00
193831ae7e VersionName:3.6.4 VersionCode:90 2019-04-26 15:43:21 +08:00
bcb9dc3ba8 修复 loghub 启动日志都变成都变成升级安装的问题 2019-04-25 11:57:59 +08:00
7903cdc44a Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-04-23 16:55:49 +08:00
a66c1ea50b 编辑框插入链接样式对以前版本隐藏 2019-04-23 16:55:33 +08:00
978e8f160b 修复 loghub 启动日志都变成都变成升级安装的问题 2019-04-23 14:52:08 +08:00
a49351a146 更改通用库 submodule 的远程地址 2019-04-22 16:27:04 +08:00
07d9b416a3 消息中心和系统推送添加跳转类型 2019-04-22 10:49:26 +08:00
f9edb69370 编辑插入回答/文章支持分享链接插入 2019-04-19 16:47:15 +08:00
deac313ba3 文章/回答详情处理链接跳转 2019-04-19 15:01:42 +08:00
b149f9acf2 Merge branch 'dev' of gitlab.ghzhushou.com:halo/assistant-android into dev 2019-04-19 09:59:35 +08:00
7c96ba090e 编辑框增加插入链接(文章,回答,游戏) 2019-04-19 09:59:18 +08:00
11ab908848 避免上传图片时闪退 2019-04-18 14:28:24 +08:00
3d2978b2e5 增加下载失败弹窗 2019-04-18 11:01:08 +08:00
7ad3a7ae92 下载进度超过100%的情况处理 2019-04-17 18:15:41 +08:00
9042488a65 把选择社区排序的操作放回主线程避免线程冲突造成闪退 2019-04-17 09:54:30 +08:00
b08e13f05a 捕抓发起网络重试请求时的各种异常 2019-04-17 09:53:20 +08:00
6271fd4998 编辑框增加插入文章 2019-04-16 16:08:09 +08:00
4d747a3df3 Merge branch 'dev-logo' into 'dev'
logo 添加多种尺寸

See merge request !4
2019-04-15 19:10:19 +08:00
5ce057d40e logo 添加多种尺寸 2019-04-15 19:01:55 +08:00
1e2e8f932f 编辑框增加插入游戏和插入回答页面 2019-04-15 18:03:45 +08:00
5accb9c1f1 Merge branch 'answer_animation' into 'dev'
答案详情页优化变更

See merge request !3
2019-04-15 11:52:08 +08:00
5b102d65c7 完成了光环前端需求汇总(2019年4月第2周)的(4,5,6,8) https://gitlab.ghzhushou.com/pm/halo-app-issues/issues/490 2019-04-15 11:51:04 +08:00
c609ddd721 修复了图片后有文字时不能删除图片的问题 2019-04-12 14:38:39 +08:00
0c3783d127 避免重复发送答案阅读事件 2019-04-12 14:24:17 +08:00
f702ab6115 修复回答图片后有文字不能删除的问题 2019-04-11 17:54:00 +08:00
7dd760e0fb 尝试将回答详情的上下滚动改以 viewpager 实现 2019-04-09 18:08:58 +08:00
c6f3b5998c tinkerBase 3.6.3 2019-04-08 19:11:47 +08:00
337 changed files with 9460 additions and 3493 deletions

2
.gitmodules vendored
View File

@ -1,4 +1,4 @@
[submodule "libraries/LGLibrary"]
path = libraries/LGLibrary
url = git@gitlab.ghzhushou.com:client/client-common.git
url = git@gitlab.ghzhushou.com:android/common-library.git
branch = master

View File

@ -42,4 +42,25 @@
* 首页不显示已安装的游戏
* 插件求版本功能增加内部跳转
* 下载面板增加公告和版本说明功能
* 接入腾讯`广点通`(广告)
* 接入腾讯`广点通`(广告)
### ver 3.6.3
* 社区搜索修改
- 增加 `文章/用户` 模块
- 增加 `搜索置顶` 功能
* 回答详情/社区文章详情修改
- 支持文案样式(加粗/斜体/删除线)和段落样式(引用/标题)
- 支持关闭评论功能
- 回答详情新增上下切换回答
* 社区编辑框(回答/文章)修改
- 支持批量插入图片(使用知乎Matisse实现)
- 新增插入特殊样式,文案样式(加粗/斜体/删除线)和段落样式(引用/标题)
* 编辑框部分 JS/CSS 使用远程文件
### ver 3.6.4
* 增加浏览记录(回答/文章/资讯/游戏)
* 回答/社区文章 增加反对功能
* 社区编辑框增加插入文章/回答/游戏
- 低版本兼容方案: 插入的样式默认隐藏,只有在3.6.4及以上才会显示
* 游戏详情评分模块增加`小编评论`区域以及样式修改
* 游戏评分增加回复功能

View File

@ -69,6 +69,11 @@ android {
buildConfigField "String", "MTA_APPKEY", "\"${MTA_APPKEY}\""
buildConfigField "String", "TD_APPID", "\"${TD_APPID}\""
/**
* Build Time 供区分 jenkins 打包时间用
*/
buildConfigField "long", "BUILD_TIME", "0"
}
// gradle 2.2以上默认同时启用v1和v2优先用于Android N
@ -91,7 +96,7 @@ android {
signingConfig signingConfigs.debug
buildConfigField "String", "EXPOSURE_REPO", "\"test\""
buildConfigField "String", "EXPOSURE_VERSION", "\"E2\""
buildConfigField "String", "EXPOSURE_VERSION", "\"E3\""
}
release {
debuggable false
@ -101,7 +106,7 @@ android {
signingConfig signingConfigs.release
buildConfigField "String", "EXPOSURE_REPO", "\"exposure\""
buildConfigField "String", "EXPOSURE_VERSION", "\"E2\""
buildConfigField "String", "EXPOSURE_VERSION", "\"E3\""
}
}
@ -249,6 +254,7 @@ dependencies {
implementation "android.arch.lifecycle:extensions:${archLifecycleVersion}"
implementation "android.arch.persistence.room:runtime:${archRoomVersion}"
kapt "android.arch.persistence.room:compiler:${archRoomVersion}"
implementation "android.arch.persistence.room:rxjava2:${archRoomVersion}"
implementation 'com.google.android:flexbox:0.2.2'
@ -274,6 +280,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 'com.walkud.rom.checker:RomChecker:1.0.0'
implementation project(':libraries:gid')
implementation project(':libraries:LGLibrary')

View File

@ -55,7 +55,7 @@
<application
android:name = "com.halo.assistant.TinkerApp"
android:allowBackup = "true"
android:icon = "@drawable/logo"
android:icon = "@mipmap/logo"
android:label = "@string/app_name"
android:resizeableActivity = "true"
android:theme = "@style/AppCompatTheme.APP"
@ -358,8 +358,8 @@
<activity
android:name = "com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity"
android:windowSoftInputMode = "stateVisible"
android:screenOrientation = "portrait" />
android:screenOrientation = "portrait"
android:windowSoftInputMode = "stateVisible" />
<activity
android:name = "com.gh.gamecenter.qa.questions.edit.manager.HistoryDetailActivity"
@ -369,6 +369,26 @@
android:name = "com.gh.gamecenter.qa.questions.edit.manager.HistoryActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.editor.GameActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.gamedetail.rating.RatingReplyActivity"
android:screenOrientation = "portrait" />
<activity
android:name = ".history.HistoryActivity"
android:screenOrientation = "portrait" />
<activity
android:name = "com.gh.gamecenter.qa.comment.CommentActivity"
android:screenOrientation = "portrait"
@ -394,13 +414,12 @@
</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>
android:name = "${applicationId}.wxapi.WXEntryActivity"
android:exported = "true"
android:label = "@string/app_name"
android:launchMode = "singleTop"
android:screenOrientation = "portrait"
android:theme = "@android:style/Theme.Translucent.NoTitleBar" ></activity >
<provider
android:name = "android.support.v4.content.FileProvider"

View File

@ -1,28 +1,163 @@
function requestContentFocus() {
$('#editor').focus();
$("#editor").focus();
}
function setupWhenContentEditable() {
var editor = $('#editor');
if (!editor[0].hasAttribute('contenteditable')) {
return;
var editor = $("#editor");
if (!editor[0].hasAttribute("contenteditable")) {
return;
}
// paste
editor.on("paste", function(e) {
e.preventDefault();
var text = (e.originalEvent || e).clipboardData.getData("text/plain");
text = text.replace(/\n/g, "<br>");
if ("" != text) {
document.execCommand("insertHTML", false, text);
} else {
window.onPasteListener.onPaste();
}
});
// paste 回调只会获取粘贴之前的光标位置,需要自己手动加上粘贴文本的长度,并保证粘贴的是纯文本
editor.on('paste', function(e) {
e.preventDefault();
var text = (e.originalEvent || e).clipboardData.getData('text/plain');
text = text.replace(/\n/g, '<br>');
if("" != text) {
document.execCommand("insertHTML", false, text);
} else {
window.onPasteListener.onPaste();
}
});
requestContentFocus();
requestContentFocus();
}
$(document).ready(function() {
setupWhenContentEditable();
function getStyle(dom, name) {
return window.getComputedStyle(dom)[name];
}
function customLinkgo(self) {
var datas = self.dataset.datas;
console.log(datas)
window.OnLinkClickListener.onClick(datas);
}
var typeClassList = [
"community_article-container",
"answer-container",
"game-container"
];
function removeDomByParent(curDom) {
if (curDom.parentElement) {
curDom.parentElement.removeChild(curDom);
}
}
window.addEventListener("load", function() {
var EditorDom = document.querySelector("#editor");
setupWhenContentEditable();
document.addEventListener("keydown", function(e) {
var event = e || window.event;
if (event.keyCode === 8) {
var s = document.getSelection();
var r = s.getRangeAt(0);
if (r.startOffset === r.endOffset && r.endOffset === 0) {
var preDOM = s.focusNode.previousElementSibling;
if (
preDOM &&
preDOM instanceof Element &&
preDOM.nodeName === "IMG" &&
getStyle(preDOM, "display") === "block"
) {
preDOM.parentElement.removeChild(preDOM);
}
}
var customDom = s.focusNode;
if (customDom) {
if (
r.startContainer.nodeName.toLowerCase() === "blockquote" &&
r.startOffset === 0
) {
RE.formatBlock();
e.preventDefault();
} else if (
customDom.nodeName === "#text" &&
customDom.previousElementSibling &&
typeClassList.indexOf(customDom.previousElementSibling.className) >
-1 &&
r.startOffset === 1
) {
var needDeleteDom = customDom.previousElementSibling;
needDeleteDom.insertAdjacentElement(
"afterend",
document.createElement("br")
);
} else if (
customDom instanceof Element &&
customDom.childNodes[s.focusOffset] &&
customDom.childNodes[s.focusOffset].previousElementSibling &&
typeClassList.indexOf(
customDom.childNodes[s.focusOffset].previousElementSibling.className
) > -1
) {
customDom =
customDom.childNodes[s.focusOffset].previousElementSibling;
customDom.parentElement.removeChild(customDom);
}
}
}
});
document.addEventListener("keyup", function(e) {
var event = e || window.event;
if (event.keyCode === 13) {
var s = document.getSelection();
var curDom = s.focusNode;
var preDom = curDom.previousElementSibling;
if (
curDom.nodeName.toLowerCase() === "blockquote" &&
preDom.nodeName.toLowerCase() === "blockquote"
) {
if (
preDom.childNodes.length > 1 ||
(preDom.childNodes.length === 1 &&
preDom.childNodes[0].tagName !== "BR")
) {
curDom.style.marginTop = 0;
preDom.style.marginBottom = 0;
} else if (
(curDom.childNodes.length === 0 ||
(curDom.childNodes.length === 1 &&
curDom.childNodes[0].tagName === "BR")) &&
(preDom.childNodes.length === 0 ||
(preDom.childNodes.length === 1 &&
preDom.childNodes[0].tagName === "BR"))
) {
removeDomByParent(curDom);
var startQuoteDom = preDom.previousElementSibling;
startQuoteDom && startQuoteDom.nodeName.toLowerCase() === "blockquote"
? (startQuoteDom.style.marginBottom = "10px")
: null;
var range = document.createRange();
range.selectNode(preDom);
s.removeAllRanges();
s.addRange(range);
RE.formatBlock();
}
}
}
});
document.addEventListener("selectionchange", function(e) {
var event = e || window.event;
var targetDom = event.target.activeElement;
if (targetDom.id === "editor" && targetDom.lastElementChild) {
if (typeClassList.indexOf(targetDom.lastElementChild.className) > -1) {
var brDom = document.createElement("br");
EditorDom.appendChild(brDom);
}
}
});
});

View File

@ -4,14 +4,13 @@
<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">
<!--<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>-->
<!--<script type="text/javascript" src="content.js"></script>-->
<!--<script type="text/javascript" src="https://resource.ghzs.com/js/halo_app.js"></script>-->
</body>
</html>

View File

@ -16,15 +16,6 @@
// 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 = {
@ -33,6 +24,17 @@ RE.currentSelection = {
"endContainer": 0,
"endOffset": 0};
// 引用远端的JS 和 CSS
var script = document.createElement("script")
script.src = "https://resource.ghzs.com/js/halo.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
document.body.appendChild(script)
var style = document.createElement("link")
style.rel = "stylesheet"
style.type = "text/css"
style.href = "https://resource.ghzs.com/css/halo.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
document.head.appendChild(style)
RE.editor = document.getElementById('editor');
document.addEventListener("selectionchange", function() { RE.backuprange(); });
@ -207,10 +209,14 @@ RE.insertImage = function(url) {
// 替换成缩略图
RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) {
var imgs = document.getElementsByTagName("img");
var index = 0
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
var imageClassName = img.className;
// console.log(imageClassName)
if (imageClassName == "image-link") continue;
if(img.src.indexOf("?") > 0) continue;
// console.log(i)
var tbImg
if(img.src.indexOf(".gif") > 0) {
tbImg = img.src + gifRuleFlag
@ -221,7 +227,7 @@ RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) {
img.style.cssText = "max-width: 60%; display:block; margin:15px auto; height: auto;"
img.src = tbImg;
if (i == 0) {
if (index == 0) {
var bigImg = document.createElement('img');
bigImg.src = "file:///android_asset/web_load_dfimg_icon.png";
bigImg.style.cssText = "max-width: 20%; margin:15px 0 0 0; height: auto;"
@ -237,6 +243,7 @@ RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) {
}
}
index ++;
}
}
@ -245,6 +252,8 @@ RE.replaceAllDfImage = function(imgRuleFlag, gifRuleFlag) {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
var imageClassName = img.className;
if (imageClassName == "image-link") continue;
if(img.src.indexOf("web_load_dfimg_icon") > 0) {
img.parentNode.removeChild(img.parentNode.childNodes[0]);
i--;
@ -269,6 +278,8 @@ RE.hideShowBigPic = function() {
var j = 0;
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
var imageClassName = img.className;
if (imageClassName == "image-link") continue;
if(img.src.indexOf(",thumbnail") > 0 && img.src.indexOf(".gif") == -1) {
j++;
}
@ -278,6 +289,8 @@ RE.hideShowBigPic = function() {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
var imageClassName = img.className;
if (imageClassName == "image-link") continue;
if(img.src.indexOf("web_load_dfimg_icon") > 0) {
img.parentNode.removeChild(img.parentNode.childNodes[0]);
break;
@ -290,6 +303,8 @@ RE.replaceDfImageByUrl = function(imgUrl, imgRuleFlag, gifRuleFlag) {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
var imageClassName = img.className;
if (imageClassName == "image-link") continue;
if (img.src.indexOf(imgUrl) != -1) {
img.style.cssText = "max-width: 100%; display:block; margin:8px auto; height: auto;"
if(img.src.indexOf(".gif") > 0) {
@ -306,6 +321,8 @@ RE.ImageClickListener = function() {
var imgs = document.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
var imageClassName = img.className;
if (imageClassName == "image-link") continue;
window.imagelistener.imageArr(img.src);
img.onclick = function() {
window.imagelistener.imageClick(this.src);
@ -358,12 +375,16 @@ RE.backuprange = function(){
}
RE.restorerange = function(){
var selection = window.getSelection();
selection.removeAllRanges();
var range = document.createRange();
range.setStart(RE.currentSelection.startContainer, RE.currentSelection.startOffset);
range.setEnd(RE.currentSelection.endContainer, RE.currentSelection.endOffset);
selection.addRange(range);
try {
var selection = window.getSelection();
selection.removeAllRanges();
var range = document.createRange();
range.setStart(RE.currentSelection.startContainer, RE.currentSelection.startOffset);
range.setEnd(RE.currentSelection.endContainer, RE.currentSelection.endOffset);
selection.addRange(range);
} catch(error) {
}
}
RE.enabledEditingItems = function(e) {
@ -433,8 +454,88 @@ RE.removeFormat = function() {
document.execCommand('removeFormat', false, null);
}
RE.insertCustomStyleLink = function(data) {
var entity = JSON.parse(data)
var html = "<br/><div class='"+ entity.type +"-container'>\n" +
" <a class='"+ entity.type +"' href=\"javascript:void(0);\" contenteditable=\"false\" onclick=\"customLinkgo(this)\" data-datas='"+ data +"'>\n" +
" <div class='flex-container'>\n" +
" <div class='gh-internal-content img-left'>\n" +
" <img class = \"image-link\" src='"+ entity.icon +"' />\n" +
" </div>\n" +
" <div class='gh-internal-content content-right'>\n" +
" <p class='content-title'>"+ entity.title +"</p>\n" +
" <p class='contents'>"+ entity.brief +"</p>\n" +
" </div>\n" +
" </div>\n" +
" </a>\n" +
" </div><br/>"
var tags = "", gameHtml = ""
if (entity.tags != null) {
for (var i = 0; i < entity.tags.length; i++) {
tags += "<label>"+ entity.tags[i]+"</label>"
}
gameHtml = "<br/><div class='"+ entity.type +"-container'>\n" +
" <a class='"+ entity.type +"' href=\"javascript:void(0);\" contenteditable=\"false\" onclick=\"customLinkgo(this)\" data-datas='"+ data +"'>\n" +
" <div class='flex-container'>\n" +
" <div class='gh-internal-content img-left'>\n" +
" <img class='image-link' src='"+ entity.icon +"' />\n" +
" </div>\n" +
" <div class='gh-internal-content content-right'>\n" +
" <p class='content-title'>"+ entity.title +"</p>\n" +
" <p class='tags'>"+ tags +"</p>\n" +
" </div>\n" +
" </div>\n" +
" </a></div><br/>"
}
switch(entity.type) {
case "answer":
document.execCommand("insertHTML",false, html);
break
case "community_article":
document.execCommand("insertHTML",false, html);
break
case "game":
document.execCommand("insertHTML",false, gameHtml);
break
}
RE.callback();
}
RE.showLinkStyle = function() {
var answerElement = document.getElementsByClassName("answer-container");
for (var i=0;i<answerElement.length;i+=1){
answerElement[i].style.display = 'inline';
}
var articleElement = document.getElementsByClassName("community_article-container");
for (var i=0;i<articleElement.length;i+=1){
articleElement[i].style.display = 'inline';
}
var gameElement = document.getElementsByClassName("game-container");
for (var i=0;i<gameElement.length;i+=1){
gameElement[i].style.display = 'inline';
}
}
RE.hideLinkStyle = function() {
var answerElement = document.getElementsByClassName("answer-container");
for (var i=0;i<answerElement.length;i+=1){
answerElement[i].style.display = 'none';
}
var articleElement = document.getElementsByClassName("community_article-container");
for (var i=0;i<articleElement.length;i+=1){
articleElement[i].style.display = 'none';
}
var gameElement = document.getElementsByClassName("game-container");
for (var i=0;i<gameElement.length;i+=1){
gameElement[i].style.display = 'none';
}
}
// Event Listeners
RE.editor.addEventListener("input", RE.callback);
RE.editor.addEventListener("keyup", function(e) {
var KEY_LEFT = 37, KEY_RIGHT = 39;
if (e.which == KEY_LEFT || e.which == KEY_RIGHT) {
@ -442,11 +543,34 @@ RE.editor.addEventListener("keyup", function(e) {
}
RE.sendElementNameToNative()
});
RE.editor.addEventListener("click", function(e) {
RE.enabledEditingItems
RE.sendElementNameToNative()
var s = document.getSelection()
var isNeedRemoveR = RE.recursion(e.target)
if (isNeedRemoveR && s.rangeCount) {
s.removeAllRanges()
}
});
document.addEventListener("selectionchange", function(e) {
RE.sendElementNameToNative()
});
RE.recursion = function(dom) {
var parenDom = dom.parentElement
if (parenDom && parenDom instanceof Element &&
typeClassList.indexOf(parenDom.className) > -1) {
return parenDom
} else if(parenDom && parenDom instanceof Element &&
typeClassList.indexOf(parenDom.className) === -1 && parenDom.nodeName !== 'BODY') {
return RE.recursion(parenDom)
} else {
return null
}
}
// 返回组件标签 多个标签以"空格"划分
RE.sendElementNameToNative = function() {
if (window.getSelection) {
@ -467,6 +591,7 @@ RE.sendElementNameToNative = function() {
}
elements = elements + " " + parentElement.localName + " "
}
// console.log(elements)
window.OnCursorChangeListener.onElements(elements);
}
}

View File

@ -1,8 +1,10 @@
package com.gh.base
import android.annotation.SuppressLint
import android.app.Activity
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.view.View
@ -10,6 +12,13 @@ import android.webkit.JavascriptInterface
import butterknife.OnClick
import com.gh.common.view.RichEditor
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.qa.editor.GameActivity
import com.gh.gamecenter.qa.editor.InsertAnswerWrapperActivity
import com.gh.gamecenter.qa.editor.InsertArticleWrapperActivity
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.ArticleEntity
import com.gh.gamecenter.qa.entity.EditorInsertEntity
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import com.lightgame.view.CheckableImageView
@ -35,10 +44,39 @@ abstract class BaseRichEditorActivity : BaseActivity() {
private val mEditorLinkContainer by bindView<View>(R.id.editor_link_container)
private val mEditorInsertDetail by bindView<View>(R.id.editor_insert_detail)
private var mCurrentParagraphStyle = ""
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode != Activity.RESULT_OK) return
var insertData: EditorInsertEntity? = null
when (requestCode) {
INSERT_ANSWER_CODE -> {
val answer = data?.getParcelableExtra<AnswerEntity>(AnswerEntity::class.java.simpleName)
if (answer != null) insertData = EditorInsertEntity.transform(answer)
}
INSERT_ARTICLE_CODE -> {
val article = data?.getParcelableExtra<ArticleEntity>(ArticleEntity::class.java.simpleName)
if (article != null) insertData = EditorInsertEntity.transform(article)
}
INSERT_GAME_CODE -> {
val game = data?.getParcelableExtra<GameEntity>(GameEntity::class.java.simpleName)
if (game != null) insertData = EditorInsertEntity.transform(game)
}
}
if (mCurrentParagraphStyle == ELEMENT_PARAGRAPH_QUOTE || mCurrentParagraphStyle == ELEMENT_PARAGRAPH_P) {
mRichEditor.insertHtml("&nbsp")
if (mCurrentParagraphStyle == ELEMENT_PARAGRAPH_QUOTE) mRichEditor.formatBlock()
}
mRichEditor.insertCustomStyleLink(insertData)
}
@SuppressLint("AddJavascriptInterface")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mRichEditor.setPadding(20, 15, 20, 15)
// 防止个别手机在Js里无法获取粘贴内容
mRichEditor.addJavascriptInterface(OnPasteListener(), "onPasteListener")
mRichEditor.addJavascriptInterface(OnCursorChangeListener(), "OnCursorChangeListener")
@ -48,7 +86,8 @@ abstract class BaseRichEditorActivity : BaseActivity() {
R.id.editor_font_bold, R.id.editor_font_italic, R.id.editor_font_strikethrough,
R.id.editor_paragraph_h1, R.id.editor_paragraph_h2, R.id.editor_paragraph_h3,
R.id.editor_paragraph_h4, R.id.editor_font_container, R.id.editor_paragraph_container,
R.id.editor_paragraph_quote)
R.id.editor_paragraph_quote, R.id.editor_link_answer, R.id.editor_link_article,
R.id.editor_link_game)
fun onRichClick(view: View) {
when (view.id) {
R.id.editor_font -> {
@ -130,6 +169,15 @@ abstract class BaseRichEditorActivity : BaseActivity() {
}
mEditorParagraphQuote.isChecked = !mEditorParagraphQuote.isChecked
}
R.id.editor_link_answer -> {
startActivityForResult(InsertAnswerWrapperActivity.getIntent(this), INSERT_ANSWER_CODE)
}
R.id.editor_link_article -> {
startActivityForResult(InsertArticleWrapperActivity.getIntent(this), INSERT_ARTICLE_CODE)
}
R.id.editor_link_game -> {
startActivityForResult(GameActivity.getIntent(this), INSERT_GAME_CODE)
}
}
}
@ -141,6 +189,12 @@ abstract class BaseRichEditorActivity : BaseActivity() {
Utils.log(mRichEditor.html)
Utils.log("-----------------------")
mCurrentParagraphStyle = when {
elements.contains(ELEMENT_PARAGRAPH_QUOTE) -> ELEMENT_PARAGRAPH_QUOTE
elements.contains(ELEMENT_PARAGRAPH_P) -> ELEMENT_PARAGRAPH_P
else -> ""
}
mBaseHandler.post {
mEditorFontBold.isChecked = elements.contains(ELEMENT_NAME_BOLD)
mEditorFontItalic.isChecked = elements.contains(ELEMENT_NAME_ITALIC)
@ -176,6 +230,10 @@ abstract class BaseRichEditorActivity : BaseActivity() {
const val ELEMENT_PARAGRAPH_H2 = " h2 "
const val ELEMENT_PARAGRAPH_H3 = " h3 "
const val ELEMENT_PARAGRAPH_H4 = " h4 "
const val ELEMENT_PARAGRAPH_P = " p "
const val ELEMENT_PARAGRAPH_QUOTE = " blockquote "
const val INSERT_ANSWER_CODE = 411
const val INSERT_ARTICLE_CODE = 412
const val INSERT_GAME_CODE = 413
}
}

View File

@ -22,4 +22,12 @@ object AppExecutor {
mainThreadHandler.postDelayed(command, delay)
}
}
}
fun runOnIoThread(f: () -> Unit) {
AppExecutor.ioExecutor.execute(f)
}
fun runOnUiThread(f: () -> Unit) {
AppExecutor.uiExecutor.execute(f)
}

View File

@ -6,10 +6,11 @@ import com.gh.base.GHUmengNotificationService
import com.gh.common.constant.Config
import com.gh.common.exposure.meta.MetaUtil
import com.gh.common.util.edit
import com.gh.common.util.toJson
import com.gh.common.util.toObject
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.entity.AliasEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.google.gson.Gson
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import com.umeng.commonsdk.UMConfigure
@ -25,7 +26,6 @@ import org.json.JSONObject
object PushManager {
var gson = Gson()
var deviceToken: String? = ""
var previousAlias: AliasEntity? = null
var application = HaloApp.getInstance().application
@ -53,7 +53,7 @@ object PushManager {
registerDevice()
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(application).getString(SP_PUSH_ALIAS, "")
previousAlias = gson.fromJson(aliasInSp, AliasEntity::class.java)
previousAlias = aliasInSp.toObject()
if (previousAlias == null) {
getAndSetAlias()
@ -114,7 +114,7 @@ object PushManager {
previousAlias = alias
PreferenceManager.getDefaultSharedPreferences(application).edit {
putString(SP_PUSH_ALIAS, gson.toJson(previousAlias))
putString(SP_PUSH_ALIAS, previousAlias?.toJson())
}
pushAgent.setAlias(alias.alias, alias.aliasType) { b, s ->

View File

@ -8,6 +8,7 @@ import android.text.TextUtils;
import com.gh.common.util.GsonUtils;
import com.gh.common.util.PackageHelper;
import com.gh.common.util.SPUtils;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.entity.NewsEntity;
import com.gh.gamecenter.entity.SettingsEntity;
@ -77,7 +78,7 @@ public class Config {
}
public static void setExceptionMsg(String errMsg) {
getPreferences().edit().putString("errMsg", errMsg).apply();
SPUtils.setString(getPreferences(), "errMsg", errMsg); //先用apply(),保存不了再用commit() 9.0机型保存不了信息
}
public static boolean isShowDownload(String gameId) {
@ -144,6 +145,7 @@ public class Config {
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if ("all".equals(entity.getGame())) {
if (entity.getPluginfy() && filterTime(entity.getTime())) {
preferences.edit().putBoolean(FIX_PLUGIN_KEY, true).apply();
return true;
}
}

View File

@ -47,4 +47,5 @@ public class Constants {
//评论 cd间隔
public static final int COMMENT_CD = 60 * 1000;
public static final String[] REPORT_LIST = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息", "违法有害信息", "其它"};
}

View File

@ -33,7 +33,6 @@ public class ItemViewType {
*/
public static final int ITEM_BODY = 100;
public static final int ITEM_FOOTER = 101;
public static final int ITEM_TOP = 102;
public static final int ITEM_HEADER = 102;
}

View File

@ -23,7 +23,6 @@ import com.gh.common.util.DisplayUtils;
import com.gh.common.util.GameUtils;
import com.gh.common.util.GameViewUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.KaiFuUtils;
import com.gh.common.util.NewsUtils;
import com.gh.common.util.NumberUtils;
import com.gh.common.util.PackageUtils;
@ -64,12 +63,16 @@ public class BindingAdapters {
ImageUtils.displayIcon(view, imageUrl);
}
@BindingAdapter("imageUrl")
public static void loadImage(SimpleDraweeView view, String imageUrl) {
ImageUtils.display(view, imageUrl);
}
@BindingAdapter("setTextSize")
public static void setTextSize(TextView view, int number) {
view.setTextSize(number);
}
@BindingAdapter({"addDetailKaiFuView", "addDetailKaiFuViewListener", "isReadyPatch"})
public static void addDetailKaiFuView(LinearLayout view, List<KaiFuCalendarEntity> list
, OnViewClickListener listener, Boolean isReadyPatch) {
@ -457,8 +460,8 @@ public class BindingAdapters {
View testView = LayoutInflater.from(layout.getContext()).inflate(R.layout.game_test_label, null);
TextView testType = testView.findViewById(R.id.test_type);
TextView testTime = testView.findViewById(R.id.test_time);
String type = gameEntity.getTest().getType();
KaiFuUtils.setKaiFuType(testType, type);
testType.setText(gameEntity.getTest().getType());
testType.setBackgroundColor(ContextCompat.getColor(layout.getContext(), R.color.tag_yellow));
if (gameEntity.getTest().getStart() == 0) {
testTime.setVisibility(View.GONE);

View File

@ -3,7 +3,6 @@ package com.gh.common.exposure
import android.arch.persistence.room.TypeConverter
import com.gh.common.exposure.meta.Meta
import com.gh.common.util.GsonUtils
import com.google.gson.Gson
import java.util.*
import kotlin.collections.ArrayList
@ -36,7 +35,7 @@ class ExposureConverters {
@TypeConverter
fun convertStringToETrace(sourceList: String): List<ExposureEvent> {
return ArrayList(Arrays.asList(Gson().fromJson(sourceList, Array<ExposureEvent>::class.java))) as List<ExposureEvent>
return ArrayList(Arrays.asList(GsonUtils.fromJson(sourceList, Array<ExposureEvent>::class.java))) as List<ExposureEvent>
}
@TypeConverter

View File

@ -2,10 +2,10 @@ package com.gh.common.exposure
import com.aliyun.sls.android.sdk.model.LogGroup
import com.gh.common.exposure.time.TimeUtil
import com.gh.common.util.toJson
import com.gh.gamecenter.BuildConfig
import com.gh.loghub.LgLOG
import com.gh.loghub.LoghubHelper
import com.google.gson.Gson
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import java.util.concurrent.Executors
@ -30,8 +30,6 @@ object ExposureManager {
private val loghubHelper = LoghubHelper.getInstance()
private val gson = Gson()
// exposureCache 用来过滤掉具有相同 id 的曝光事件,避免重复发送事件
private val exposureCache = FixedSizeLinkedHashSet<String>(100)
private val exposureSet = hashSetOf<ExposureEvent>()
@ -127,11 +125,13 @@ object ExposureManager {
val log = LgLOG(TimeUtil.currentTime())
log.PutContent("id", event.id)
log.PutContent("payload", gson.toJson(event.payload))
log.PutContent("payload", event.payload.toJson())
log.PutContent("event", event.event.toString())
log.PutContent("source", eliminateMultipleBrackets(gson.toJson(event.source)))
log.PutContent("meta", gson.toJson(event.meta))
log.PutContent("e-traces", if (event.eTrace != null) eliminateMultipleBrackets(gson.toJson(event.eTrace)) else "")
log.PutContent("source", eliminateMultipleBrackets(event.source.toJson()))
log.PutContent("meta", event.meta.toJson())
log.PutContent("e-traces", if (event.eTrace != null) {
eliminateMultipleBrackets(event.eTrace?.toJson() ?: "")
} else "")
log.PutTime(event.time)
return log

View File

@ -20,5 +20,6 @@ data class Meta(
val channel: String? = "",
val appVersion: String? = "",
val userId: String? = "",
val exposureVersion: String? = ""
val exposureVersion: String? = "",
val rom: String? = ""
) : Parcelable

View File

@ -14,6 +14,7 @@ import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.manager.UserManager
import com.halo.assistant.HaloApp
import com.leon.channel.helper.ChannelReaderUtil
import com.walkud.rom.checker.RomIdentifier
import java.io.File
object MetaUtil {
@ -37,7 +38,8 @@ object MetaUtil {
channel = getChannel(),
appVersion = BuildConfig.VERSION_NAME,
userId = UserManager.getInstance().userId,
exposureVersion = BuildConfig.EXPOSURE_VERSION)
exposureVersion = BuildConfig.EXPOSURE_VERSION,
rom = RomIdentifier.getRom().name + "" + RomIdentifier.getRom().versionName)
}
fun getMeta(): Meta {

View File

@ -0,0 +1,43 @@
package com.gh.common.history
import android.arch.persistence.room.Database
import android.arch.persistence.room.Room
import android.arch.persistence.room.RoomDatabase
import android.arch.persistence.room.TypeConverters
import com.gh.gamecenter.entity.HistoryGameEntity
import com.gh.gamecenter.entity.NewsEntity
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.ArticleEntity
import com.gh.gamecenter.room.converter.*
import com.gh.gamecenter.room.dao.AnswerHistoryDao
import com.gh.gamecenter.room.dao.ArticleHistoryDao
import com.gh.gamecenter.room.dao.GameDao
import com.gh.gamecenter.room.dao.NewsHistoryDao
import com.halo.assistant.HaloApp
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class], version = 2, exportSchema = false)
@TypeConverters(*[
CountConverter::class,
CommunityConverter::class,
TimeConverter::class,
AnswerUserConverter::class,
ThumbnailConverter::class,
TagStyleListConverter::class,
StringArrayListConverter::class])
abstract class HistoryDatabase : RoomDatabase() {
abstract fun answerDao(): AnswerHistoryDao
abstract fun articleDao(): ArticleHistoryDao
abstract fun newsDao(): NewsHistoryDao
abstract fun gameDao(): GameDao
companion object {
val instance by lazy {
Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE")
.fallbackToDestructiveMigration()
.build()
}
}
}

View File

@ -0,0 +1,107 @@
package com.gh.common.history
import com.gh.common.runOnIoThread
import com.gh.common.util.clearHtmlFormatCompletely
import com.gh.common.util.removeInsertedContent
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.HistoryGameEntity
import com.gh.gamecenter.entity.NewsEntity
import com.gh.gamecenter.qa.entity.AnswerDetailEntity
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
import com.gh.gamecenter.qa.entity.ArticleEntity
object HistoryHelper {
fun insertAnswerEntity(answerDetailEntity: AnswerDetailEntity) {
val answerEntity = convertAnswerDetailToAnswer(answerDetailEntity)
runOnIoThread { HistoryDatabase.instance.answerDao().addAnswer(answerEntity) }
}
fun insertArticleEntity(articleDetailEntity: ArticleDetailEntity) {
val articleEntity = convertArticleDetailToArticle(articleDetailEntity)
runOnIoThread { HistoryDatabase.instance.articleDao().addArticle(articleEntity) }
}
fun insertGameEntity(gameEntity: GameEntity) {
val historyGameEntity = convertGameEntityToHistoryGameEntity(gameEntity)
runOnIoThread { HistoryDatabase.instance.gameDao().addGame(historyGameEntity) }
}
private fun convertGameEntityToHistoryGameEntity(gameEntity: GameEntity): HistoryGameEntity {
val historyGame = HistoryGameEntity()
historyGame.orderTag = System.currentTimeMillis()
historyGame.id = gameEntity.id
historyGame.brief = gameEntity.brief
historyGame.des = gameEntity.des
historyGame.icon = gameEntity.icon
historyGame.name = gameEntity.name
historyGame.tagStyle = gameEntity.tagStyle
historyGame.tag = gameEntity.getTag()
return historyGame
}
@JvmStatic
fun insertNewsEntity(newsEntity: NewsEntity) {
newsEntity.orderTag = System.currentTimeMillis()
runOnIoThread { HistoryDatabase.instance.newsDao().addNews(newsEntity) }
}
@JvmStatic
fun deleteNewsEntity(newsId: String) {
runOnIoThread { HistoryDatabase.instance.newsDao().deleteNews(NewsEntity().apply { id = newsId }) }
}
@JvmStatic
fun deleteGameEntity(gameId: String) {
runOnIoThread { HistoryDatabase.instance.gameDao().deleteGame(HistoryGameEntity(id = gameId)) }
}
@JvmStatic
fun deleteArticleEntity(articleId: String) {
runOnIoThread { HistoryDatabase.instance.articleDao().deleteArticle(ArticleEntity(id = articleId)) }
}
@JvmStatic
fun deleteAnswerEntity(answerId: String) {
runOnIoThread { HistoryDatabase.instance.answerDao().deleteAnswer(AnswerEntity().apply { primaryKey = answerId }) }
}
@JvmStatic
fun emptyDatabase() {
runOnIoThread { HistoryDatabase.instance.clearAllTables() }
}
private fun convertArticleDetailToArticle(articleDetailEntity: ArticleDetailEntity): ArticleEntity {
val articleEntity = ArticleEntity()
articleEntity.id = articleDetailEntity.id
articleEntity.brief = articleDetailEntity.content.removeInsertedContent().clearHtmlFormatCompletely().replace(" +".toRegex()," ")
articleEntity.count = articleDetailEntity.count
articleEntity.community = articleDetailEntity.community
articleEntity.time = articleDetailEntity.time
articleEntity.title = articleDetailEntity.title
articleEntity.user = articleDetailEntity.user
articleEntity.orderTag = System.currentTimeMillis()
return articleEntity
}
private fun convertAnswerDetailToAnswer(answerDetailEntity: AnswerDetailEntity): AnswerEntity {
val answerEntity = AnswerEntity()
answerEntity.id = answerDetailEntity.id
answerEntity.primaryKey = answerDetailEntity.id
answerEntity.commentCount = answerDetailEntity.commentCount
answerEntity.questions = answerDetailEntity.question
answerEntity.vote = answerDetailEntity.vote
answerEntity.user = answerDetailEntity.user
answerEntity.orderTag = System.currentTimeMillis()
answerEntity.brief = answerDetailEntity.content.removeInsertedContent().clearHtmlFormatCompletely().replace(" +".toRegex(), " ")
answerEntity.time = answerDetailEntity.time
return answerEntity
}
}

View File

@ -1,93 +0,0 @@
package com.gh.common.util;
import android.content.Context;
import com.lightgame.utils.Utils;
import org.json.JSONObject;
import retrofit2.HttpException;
/**
* Created by khy on 28/12/17.
*/
public class AskErrorResponseUtils {
public static void errorResponseControl(Context context, HttpException e) {
if (e == null) return;
int code = e.code();
try {
if (code == 403 || code == 401) {
JSONObject object = new JSONObject(e.response().errorBody().string());
errorResponseControl(context, object);
} else {
Utils.toast(context, "网络错误");
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
public static void errorResponseControl(Context context, JSONObject jsonObject) {
int errorCode = 0;
try {
errorCode = jsonObject.getInt("code");
switch (errorCode) {
case 403001:
Utils.toast(context, "标签名称太长了");
break;
case 403002:
Utils.toast(context, "已经被邀请了");
break;
case 403003:
Utils.toast(context, "每天最多可以邀请10次");
break;
case 403004:
Utils.toast(context, "客户端提供的ID无效空/无效ID");
break;
case 403005:
Utils.toast(context, "已经回答过了(限制频率)");
break;
case 403006:
Utils.toast(context, "图片数量达到限制点");
break;
case 403007:
Utils.toast(context, "不合法的用户");
break;
case 403008:
Utils.toast(context, "已投票");
break;
case 403009:
Utils.toast(context, "已经收藏过了");
break;
case 403010:
Utils.toast(context, "无效的标签栏");
break;
case 403011:
Utils.toast(context, "标题内容过长");
break;
case 403012:
Utils.toast(context, "描述内容过长");
break;
case 403013:
Utils.toast(context, "无效的标签");
break;
case 403014:
Utils.toast(context, "标签数量太多了");
break;
case 403015:
Utils.toast(context, "已经关注过了");
break;
case 404001:
Utils.toast(context, "请求的资源不存在");
break;
default:
Utils.toast(context, "网络错误");
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -7,6 +7,9 @@ import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.os.Build;
import com.halo.assistant.HaloApp;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
@ -186,15 +189,30 @@ public class BitmapUtils {
/**
* Drawable转Bitmap
* @param isSquare 是否是正方形
*/
public static Bitmap drawableToBitmap(Drawable drawable) {
public static Bitmap drawableToBitmap(Drawable drawable, boolean isSquare) {
if (drawable == null) {
return null;
}
int w,h;
// 取 drawable 的长宽
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
w = drawable.getIntrinsicWidth();
h = drawable.getIntrinsicHeight();
// 在低于 5.1 和运行内存小于 2G 的设备上减小图片大小,避免 OOM128 * 128 又不是不能看
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
|| DeviceUtils.getTotalRamSizeOfDevice(HaloApp.getInstance().getApplication()) < 2000) {
if (isSquare) {
w = w > 128 ? 128 : w;
h = h > 128 ? 128 : h;
} else {
w = w > 128 ? w / 2 : w;
h = h > 128 ? h / 2 : h;
}
}
// 取 drawable 的颜色格式
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;

View File

@ -46,7 +46,7 @@ object CollectionUtils {
try {
val string = e.response()?.errorBody()?.string()
val errorBody = JSONObject(string)
if (errorBody.getInt("detail") == 403009) {
if (errorBody.getInt("code") == 403009) {
listener.onSuccess()
return
}

View File

@ -8,6 +8,7 @@ import com.gh.gamecenter.MessageDetailActivity
import com.gh.gamecenter.adapter.OnCommentCallBackListener
import com.gh.gamecenter.entity.CommentEntity
import com.gh.gamecenter.entity.MeEntity
import com.gh.gamecenter.entity.Permissions
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.lightgame.utils.Utils
@ -66,10 +67,10 @@ object CommentHelper {
dialogOptions.add("举报")
commentEntity.me?.let {
if (it.isModerator || (it.moderatorPermissions.contains(MeEntity.HIDE_ANSWER_COMMENT)
|| it.moderatorPermissions.contains(MeEntity.TOP_ANSWER_COMMENT)
|| it.moderatorPermissions.contains(MeEntity.HIDE_COMMUNITY_ARTICLE)
|| it.moderatorPermissions.contains(MeEntity.TOP_COMMUNITY_ARTICLE_COMMENT))) {
if (it.isModerator || (it.moderatorPermissions.hideAnswerComment > Permissions.GUEST
|| it.moderatorPermissions.topAnswerComment > Permissions.GUEST
|| it.moderatorPermissions.hideCommunityArticleComment > Permissions.GUEST
|| it.moderatorPermissions.topCommunityArticleComment > Permissions.GUEST)) {
dialogOptions.add("管理")
}
}
@ -146,20 +147,37 @@ object CommentHelper {
val highlight = "置顶评论"
val hide = "隐藏评论"
if (me.moderatorPermissions.contains(MeEntity.TOP_ANSWER_COMMENT)
|| me.moderatorPermissions.contains(MeEntity.TOP_COMMUNITY_ARTICLE_COMMENT)) {
var canHighlightCommentDirectly = false
var canHideCommentDirectly = false
if (me.moderatorPermissions.topAnswerComment > Permissions.GUEST
|| me.moderatorPermissions.topCommunityArticleComment > Permissions.GUEST) {
dialogOptions.add(highlight)
if (me.moderatorPermissions.topAnswerComment > Permissions.REPORTER
|| me.moderatorPermissions.topCommunityArticleComment > Permissions.REPORTER ) {
canHighlightCommentDirectly = true
}
}
if (me.moderatorPermissions.contains(MeEntity.HIDE_ANSWER_COMMENT)
|| me.moderatorPermissions.contains(MeEntity.HIDE_COMMUNITY_ARTICLE_COMMENT)) {
if (me.moderatorPermissions.hideAnswerComment > Permissions.GUEST
|| me.moderatorPermissions.hideCommunityArticleComment > Permissions.GUEST) {
dialogOptions.add(hide)
if (me.moderatorPermissions.hideAnswerComment > Permissions.REPORTER
|| me.moderatorPermissions.hideCommunityArticleComment > Permissions.REPORTER ) {
canHideCommentDirectly = true
}
}
val content = if (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
"你的操作将提交给小编审核,确定提交吗?"
} else {
val highlightDialogHintContent = if (canHighlightCommentDirectly) {
"你的操作将立即生效,确定提交吗?(你的管理权限为:高级)"
} else {
"你的操作将提交给小编审核,确定提交吗?"
}
val hideDialogHintContent = if (canHideCommentDirectly) {
"你的操作将立即生效,确定提交吗?(你的管理权限为:高级)"
} else {
"你的操作将提交给小编审核,确定提交吗?"
}
val disabledOptions = arrayListOf<String>()
@ -191,10 +209,10 @@ object CommentHelper {
val highlightObserver = object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
if (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
Utils.toast(context, "提交成功")
} else {
if (canHighlightCommentDirectly) {
Utils.toast(context, "置顶成功,请刷新列表")
} else {
Utils.toast(context, "提交成功")
}
}
@ -217,7 +235,7 @@ object CommentHelper {
}
if (answerId != null) {
DialogUtils.showAlertDialog(context, highlight, content,
DialogUtils.showAlertDialog(context, highlight, highlightDialogHintContent,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.highlightAnswerComment(answerId, comment.id)
@ -226,7 +244,7 @@ object CommentHelper {
.subscribe(highlightObserver)
}, null)
} else {
DialogUtils.showAlertDialog(context, highlight, content,
DialogUtils.showAlertDialog(context, highlight, highlightDialogHintContent,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.highlightCommunityArticleComment(communityId, articleId, comment.id)
@ -240,10 +258,10 @@ object CommentHelper {
hide -> {
val hideObserver = object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
if (me.moderatorLevel == MeEntity.MODERATOR_LEVEL_PRIMARY) {
Utils.toast(context, "提交成功")
} else {
if (canHideCommentDirectly) {
Utils.toast(context, "隐藏成功,请刷新列表")
} else {
Utils.toast(context, "提交成功")
}
}
@ -266,7 +284,7 @@ object CommentHelper {
}
if (answerId != null) {
DialogUtils.showAlertDialog(context, hide, content,
DialogUtils.showAlertDialog(context, hide, hideDialogHintContent,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.hideAnswerComment(answerId, comment.id)
@ -275,7 +293,7 @@ object CommentHelper {
.subscribe(hideObserver)
}, null)
} else {
DialogUtils.showAlertDialog(context, hide, content,
DialogUtils.showAlertDialog(context, hide, hideDialogHintContent,
"确定", "取消", {
RetrofitManager.getInstance(context).api
.hideCommunityArticleComment(communityId, articleId, comment.id)

View File

@ -4,7 +4,6 @@ import android.app.Dialog;
import android.content.ClipboardManager;
import android.content.Context;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.view.View;
@ -20,11 +19,8 @@ import com.gh.gamecenter.adapter.OnCommentCallBackListener;
import com.gh.gamecenter.adapter.viewholder.CommentViewHolder;
import com.gh.gamecenter.entity.CommentEntity;
import com.gh.gamecenter.entity.MeEntity;
import com.gh.gamecenter.entity.RatingComment;
import com.gh.gamecenter.entity.UserInfoEntity;
import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.lightgame.utils.Utils;
import org.json.JSONException;
@ -37,11 +33,6 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.HttpException;
/**
@ -80,111 +71,6 @@ public class CommentUtils {
}
}
public static void showGameCommentOptions(final Context context,
final RatingComment comment,
final String gameId,
final String entrance) {
final Dialog dialog = new Dialog(context);
LinearLayout container = new LinearLayout(context);
container.setOrientation(LinearLayout.VERTICAL);
container.setBackgroundColor(Color.WHITE);
container.setPadding(0, DisplayUtils.dip2px(context, 12), 0, DisplayUtils.dip2px(context, 12));
List<String> dialogType = new ArrayList<>();
dialogType.add("复制");
dialogType.add("举报");
for (String s : dialogType) {
final TextView reportTv = new TextView(context);
reportTv.setText(s);
reportTv.setTextSize(17);
reportTv.setTextColor(ContextCompat.getColor(context, R.color.title));
reportTv.setBackgroundResource(R.drawable.textview_white_style);
int widthPixels = context.getResources().getDisplayMetrics().widthPixels;
reportTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
LinearLayout.LayoutParams.WRAP_CONTENT));
reportTv.setPadding(DisplayUtils.dip2px(context, 20), DisplayUtils.dip2px(context, 12),
0, DisplayUtils.dip2px(context, 12));
container.addView(reportTv);
reportTv.setOnClickListener(v -> {
dialog.cancel();
switch (reportTv.getText().toString()) {
case "复制":
copyText(comment.getContent(), context);
break;
case "举报":
CheckLoginUtils.checkLogin(context, entrance, () -> showGameCommentReportDialog(gameId, comment, context));
break;
}
});
}
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(container);
dialog.show();
}
private static void showGameCommentReportDialog(final String gameId, final RatingComment comment, final Context context) {
final String[] arrReportType = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息",
"违法有害信息", "其它"};
int widthPixels = context.getResources().getDisplayMetrics().widthPixels;
final Dialog reportTypeDialog = new Dialog(context);
LinearLayout container = new LinearLayout(context);
container.setOrientation(LinearLayout.VERTICAL);
container.setPadding(0, DisplayUtils.dip2px(context, 12), 0, DisplayUtils.dip2px(context, 12));
container.setBackgroundColor(Color.WHITE);
for (final String s : arrReportType) {
TextView reportTypeTv = new TextView(context);
reportTypeTv.setText(s);
reportTypeTv.setTextSize(17);
reportTypeTv.setTextColor(ContextCompat.getColor(context, R.color.title));
reportTypeTv.setBackgroundResource(R.drawable.textview_white_style);
reportTypeTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
LinearLayout.LayoutParams.WRAP_CONTENT));
reportTypeTv.setPadding(DisplayUtils.dip2px(context, 20), DisplayUtils.dip2px(context, 12),
0, DisplayUtils.dip2px(context, 12));
container.addView(reportTypeTv);
reportTypeTv.setOnClickListener(v -> {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("reason", s);
} catch (JSONException e) {
e.printStackTrace();
}
RequestBody body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString());
RetrofitManager.getInstance(context).getApi()
.reportGameComment(gameId, comment.getId(), body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<ResponseBody>() {
@Override
public void onResponse(@Nullable ResponseBody response) {
Utils.toast(context, "感谢您的举报");
}
@Override
public void onFailure(@Nullable HttpException e) {
Utils.toast(context, "举报失败,请先检查网络设置");
}
});
reportTypeDialog.cancel();
});
}
reportTypeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
reportTypeDialog.setContentView(container);
reportTypeDialog.show();
}
public static void showReportDialog(final CommentEntity commentEntity,
final Context context,
@ -263,135 +149,6 @@ public class CommentUtils {
}
// public static void showAnswerCommentOptions(final CommentEntity commentEntity, final Context context,
// final OnCommentCallBackListener listener, final String id,
// boolean showConversation, String answerId, String articleId, String articleCommunityId) {
//
// final Dialog dialog = new Dialog(context);
//
// LinearLayout container = new LinearLayout(context);
// container.setOrientation(LinearLayout.VERTICAL);
// container.setBackgroundColor(Color.WHITE);
// container.setPadding(0, DisplayUtils.dip2px(context, 12), 0, DisplayUtils.dip2px(context, 12));
//
// List<String> dialogType = new ArrayList<>();
//
// if (commentEntity.getMe() == null || !commentEntity.getMe().isAnswerCommented()) {
// dialogType.add("回复");
// }
//
// dialogType.add("复制");
// dialogType.add("举报");
//
// if (commentEntity.getParentUser() != null && showConversation) {
// dialogType.add("查看对话");
// }
//
// for (String s : dialogType) {
// final TextView reportTv = new TextView(context);
// reportTv.setText(s);
// reportTv.setTextSize(17);
// reportTv.setTextColor(ContextCompat.getColor(context, R.color.title));
// reportTv.setBackgroundResource(R.drawable.textview_white_style);
// int widthPixels = context.getResources().getDisplayMetrics().widthPixels;
// reportTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
// LinearLayout.LayoutParams.WRAP_CONTENT));
// reportTv.setPadding(DisplayUtils.dip2px(context, 20), DisplayUtils.dip2px(context, 12),
// 0, DisplayUtils.dip2px(context, 12));
// container.addView(reportTv);
//
// reportTv.setOnClickListener(v -> {
// dialog.cancel();
// switch (reportTv.getText().toString()) {
// case "回复":
// CheckLoginUtils.checkLogin(context, () -> {
// if (listener != null) {
// listener.onCommentCallback(commentEntity);
// } else if (!TextUtils.isEmpty(id)) {
// context.startActivity(MessageDetailActivity.getMessageDetailIntent(context, commentEntity, id));
// } else {
// Utils.toast(context, "缺少关键属性");
// }
// });
// break;
// case "复制":
// copyText(commentEntity.getContent(), context);
// break;
// case "举报":
// CheckLoginUtils.checkLogin(context, () -> showAnswerReportDialog(answerId, commentEntity, context));
// break;
// case "查看对话":
// if (TextUtils.isEmpty(articleId)) {
// context.startActivity(CommentDetailActivity.getAnswerCommentIntent(context, commentEntity.getId(), answerId, null));
// } else {
// context.startActivity(CommentDetailActivity.getCommunityArticleCommentIntent(context, articleId, commentEntity.getId(), articleCommunityId, null));
// }
// break;
// }
// });
// }
//
// dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
// dialog.setContentView(container);
// dialog.show();
// }
// private static void showAnswerReportDialog(final String answerId, final CommentEntity commentEntity, final Context context) {
// final String[] arrReportType = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息",
// "违法有害信息", "其它"};
// int widthPixels = context.getResources().getDisplayMetrics().widthPixels;
//
// final Dialog reportTypeDialog = new Dialog(context);
// LinearLayout container = new LinearLayout(context);
// container.setOrientation(LinearLayout.VERTICAL);
// container.setPadding(0, DisplayUtils.dip2px(context, 12), 0, DisplayUtils.dip2px(context, 12));
// container.setBackgroundColor(Color.WHITE);
//
// for (final String s : arrReportType) {
// TextView reportTypeTv = new TextView(context);
// reportTypeTv.setText(s);
// reportTypeTv.setTextSize(17);
// reportTypeTv.setTextColor(ContextCompat.getColor(context, R.color.title));
// reportTypeTv.setBackgroundResource(R.drawable.textview_white_style);
// reportTypeTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
// LinearLayout.LayoutParams.WRAP_CONTENT));
// reportTypeTv.setPadding(DisplayUtils.dip2px(context, 20), DisplayUtils.dip2px(context, 12),
// 0, DisplayUtils.dip2px(context, 12));
// container.addView(reportTypeTv);
//
// reportTypeTv.setOnClickListener(v -> {
// JSONObject jsonObject = new JSONObject();
// try {
// jsonObject.put("reason", s);
// } catch (JSONException e) {
// e.printStackTrace();
// }
//
// PostCommentUtils.postAnswerReportData(context, commentEntity.getId(), answerId, jsonObject.toString(),
// new PostCommentUtils.PostCommentListener() {
// @Override
// public void postSuccess(JSONObject response) {
// Utils.toast(context, "感谢您的举报");
// }
//
// @Override
// public void postFailed(Throwable error) {
// if (error != null) {
// Utils.toast(context, "举报失败" + error.getMessage());
// } else {
// Utils.toast(context, "举报失败,请稍候重试");
// }
// }
// });
// reportTypeDialog.cancel();
// });
// }
//
// reportTypeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
// reportTypeDialog.setContentView(container);
// reportTypeDialog.show();
// }
private static void showReportTypeDialog(final CommentEntity commentEntity, final Context context) {
final String[] arrReportType = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息",
"违法有害信息", "其它"};

View File

@ -0,0 +1,47 @@
package com.gh.common.util
import com.gh.gamecenter.packagehelper.PackageRepository
import com.gh.gamecenter.qa.entity.AskGameSelectEntity
object CommunityHelper {
/**
* 为已开通的社区排序
* 排序规则为将本地存在已安装游戏或已关联游戏的社区置顶
*/
fun sortOpenedCommunity(rawList: List<AskGameSelectEntity>?): ArrayList<AskGameSelectEntity> {
val sortedList = ArrayList<AskGameSelectEntity>()
rawList?.let {
for (game in rawList) {
var thisGameIsInstalled = false
for (installGame in PackageRepository.gameInstalled) {
if (PackageHelper.downloadPackageNameBlackList.contains(installGame.packageName)) {
continue
}
// 判断是否已安装
if (installGame.id == game.game.id) {
thisGameIsInstalled = true
break
}
// 判断是否关联了别游戏
for (relatedGameId in game.game.relation) {
if (installGame.id == relatedGameId) {
thisGameIsInstalled = true
break
}
}
}
// 将已安装的置顶
if (thisGameIsInstalled) {
sortedList.add(0, game)
} else {
sortedList.add(game)
}
}
}
return sortedList
}
}

View File

@ -2,7 +2,6 @@ package com.gh.common.util;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.widget.LinearLayout;
import com.facebook.drawee.drawable.ScalingUtils;
@ -93,12 +92,9 @@ public class ConcernContentUtils {
ScalingUtils.ScaleType.CENTER_CROP, list.get(position));
break;
}
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent checkIntent = ViewImageActivity.getViewImageIntent(context, (ArrayList<String>) list, position, entrance);
context.startActivity(checkIntent);
}
imageView.setOnClickListener(v -> {
Intent checkIntent = ViewImageActivity.getViewImageIntent(context, (ArrayList<String>) list, position, entrance);
context.startActivity(checkIntent);
});
return imageView;
}

View File

@ -21,6 +21,9 @@ import retrofit2.HttpException
*/
object ConcernUtils {
/**
* autoConcern:是否自动关注'关联关注'
*/
fun postConcernGameId(context: Context, gameId: String, listener: onConcernListener?, autoConcern: Boolean = false) {
val mode = if (autoConcern) "auto" else "manual"
@ -92,7 +95,13 @@ object ConcernUtils {
override fun onFailure(e: HttpException?) {
super.onFailure(e)
listener?.onError()
AskErrorResponseUtils.errorResponseControl(context, e)
var errorString: String? = null
try {
errorString = e?.response()?.errorBody()?.string()
} catch (e1: Exception) {
e1.printStackTrace()
}
ErrorHelper.handleError(context, errorString, false)
}
})
}
@ -111,7 +120,13 @@ object ConcernUtils {
override fun onFailure(e: HttpException?) {
super.onFailure(e)
listener?.onError()
AskErrorResponseUtils.errorResponseControl(context, e)
var errorString: String? = null
try {
errorString = e?.response()?.errorBody()?.string()
} catch (e1: Exception) {
e1.printStackTrace()
}
ErrorHelper.handleError(context, errorString, false)
}
})
}

View File

@ -72,6 +72,7 @@ public class DetailDownloadUtils {
switch (downloadEntity.getStatus()) {
case downloading:
case pause:
case overflow:
viewHolder.mDownloadPb.setText(R.string.downloading);
if (downloadEntity.isPluggable() && PackagesManager.INSTANCE.isInstalled(downloadEntity.getPackageName())) {
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.DOWNLOADING_PLUGIN);

View File

@ -1,91 +0,0 @@
/*
* Copyright (C) 2015 Baidu, Inc. All Rights Reserved.
*/
package com.gh.common.util;
import android.content.Context;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Created by sunpengfei on 15/11/4.
*/
public class DexUtils {
private static final int BUF_SIZE = 2048;
public static boolean prepareAssetsDex(Context context, File dexInternalStoragePath, String dex_file) {
BufferedInputStream bis = null;
OutputStream dexWriter = null;
try {
bis = new BufferedInputStream(context.getAssets().open(dex_file));
dexWriter = new BufferedOutputStream(new FileOutputStream(dexInternalStoragePath));
byte[] buf = new byte[BUF_SIZE];
int len;
while ((len = bis.read(buf, 0, BUF_SIZE)) > 0) {
dexWriter.write(buf, 0, len);
}
dexWriter.close();
bis.close();
return true;
} catch (IOException e) {
if (dexWriter != null) {
try {
dexWriter.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
return false;
}
}
public static boolean prepareDex(File dexInternalStoragePath, File dex_file) {
BufferedInputStream bis = null;
OutputStream dexWriter = null;
try {
bis = new BufferedInputStream(new FileInputStream(dex_file));
dexWriter = new BufferedOutputStream(new FileOutputStream(dexInternalStoragePath));
byte[] buf = new byte[BUF_SIZE];
int len;
while ((len = bis.read(buf, 0, BUF_SIZE)) > 0) {
dexWriter.write(buf, 0, len);
}
dexWriter.close();
bis.close();
return true;
} catch (IOException e) {
if (dexWriter != null) {
try {
dexWriter.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
return false;
}
}
}

View File

@ -130,7 +130,7 @@ public class DialogUtils {
ApplicationInfo appInfo = info.applicationInfo;
appInfo.sourceDir = apkPath;
appInfo.publicSourceDir = apkPath;
Bitmap bitmap = BitmapUtils.drawableToBitmap(appInfo.loadIcon(pm));
Bitmap bitmap = BitmapUtils.drawableToBitmap(appInfo.loadIcon(pm), true);
ImageView imageView = new ImageView(activity);
imageView.setLayoutParams(new LinearLayout.LayoutParams(DisplayUtils.dip2px(activity, 25)
@ -360,9 +360,16 @@ public class DialogUtils {
} else if (NetworkUtils.isWifiConnected(context) || filter4GorSize(context, size)) {
callBack.onResponse(false);
} else {
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "出现弹窗提示");
showDownloadDialog(context,
() -> callBack.onResponse(false),
() -> callBack.onResponse(true));
() -> {
callBack.onResponse(false);
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "立即下载");
},
() -> {
callBack.onResponse(true);
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "连上WiFi后自动下载");
});
}
}
@ -445,7 +452,53 @@ public class DialogUtils {
TextView titleTv = contentView.findViewById(R.id.dialog_title);
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
if (message.toString().contains("红包奖励")) {//将红包奖励四个字标红
String str = message.toString().substring(0, message.toString().indexOf("红包奖励")) + "<font color='#FF0000'>红包奖励</font>";
contentTv.setText(Html.fromHtml(str));
} else {
contentTv.setText(message);
}
titleTv.setText(title);
negativeTv.setText(negative);
positiveTv.setText(positive);
negativeTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (clListener != null) {
clListener.onCancel();
}
dialog.dismiss();
}
});
positiveTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (cmListener != null) {
cmListener.onConfirm();
}
dialog.dismiss();
}
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
return dialog;
}
public static Dialog showAlertDialog(Context context, String title, Spanned message
, String positive, String negative, final ConfirmListener cmListener, final CancelListener clListener) {
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_alert, null);
TextView contentTv = contentView.findViewById(R.id.dialog_content);
TextView titleTv = contentView.findViewById(R.id.dialog_title);
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
contentTv.setText(message);
titleTv.setText(title);
negativeTv.setText(negative);
@ -795,7 +848,7 @@ public class DialogUtils {
}
/**
* @param options 供以显示的选项
* @param options 供以显示的选项
* @param disabledOptions 显示为灰色的选项(是 options 的子集)
*/
public static void showListDialog(Context context,

View File

@ -99,7 +99,7 @@ object DirectUtils {
}
/**
* 跳转到文章详情
* 跳转到新闻详情
*/
@JvmStatic
fun directToArticle(context: Context, id: String, entrance: String? = null) {

View File

@ -83,7 +83,7 @@ public class DownloadItemUtils {
DownloadManager.getInstance(context).sendMessageDelayed(msg, 3000);
}
}
if (platform.equals(queue.peek())) {
if (platform != null && platform.equals(queue.peek())) {
if (entryMap == null) {
entryMap = new ArrayMap<>();
gameEntity.setEntryMap(entryMap);
@ -96,6 +96,13 @@ public class DownloadItemUtils {
}
}
// 下载按钮显示为查看,并且不提供下载功能
public static void updateItemWithViewOnlyStyle(GameViewHolder holder) {
holder.gameDownloadBtn.setVisibility(View.VISIBLE);
holder.gameDownloadBtn.setText("查看");
holder.gameDownloadBtn.setClickable(false);
}
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
boolean isShowPlatform) {
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game);
@ -229,7 +236,8 @@ public class DownloadItemUtils {
} else if (status.equals(DownloadStatus.pause)
|| status.equals(DownloadStatus.timeout)
|| status.equals(DownloadStatus.neterror)
|| status.equals(DownloadStatus.subscribe)) {
|| status.equals(DownloadStatus.subscribe)
|| status.equals(DownloadStatus.overflow)) {
holder.gameProgressbar.setProgress((int) (downloadEntity.getPercent() * 10));
if (isShowPlatform && platform != null) {
holder.gameDownloadSpeed.setText(String.format("%s - 暂停", platform));
@ -239,10 +247,10 @@ public class DownloadItemUtils {
holder.gameDownloadPercentage.setText(downloadEntity.getPercent() + "%");
if (isNormal) {
if (status.equals(DownloadStatus.pause)) {
holder.gameDownloadBtn.setText(R.string.downloading);
} else {
if (status.equals(DownloadStatus.waiting)) {
holder.gameDownloadBtn.setText(R.string.waiting);
} else {
holder.gameDownloadBtn.setText(R.string.downloading);
}
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
holder.gameDownloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));

View File

@ -25,7 +25,7 @@ public class EntranceUtils {
public static final String KEY_URL = "url";
public static final String KEY_GAMENAME = "gameName";
public static final String HOST_ARTICLE = "article";
public static final String HOST_COMMUNITY_ARTICLE = "community.article";
public static final String HOST_COMMUNITY_ARTICLE = "community_article";
public static final String HOST_GAME = "game";
public static final String HOST_GAME_DOWNLOAD = "game_download";
public static final String HOST_COLUMN = "column";
@ -98,7 +98,6 @@ public class EntranceUtils {
public static final String KEY_COMMUNITY_DATA = "communityData";
public static final String KEY_TRACE_EVENT = "trace_event";
public static final String KEY_SUBJECT_DATA = "subjectData";
public static final String KEY_SHOW_SELECT_COMMUNITY = "show_select_community";
public static final String KEY_USER_ID = "user_id";
public static final String KEY_QUESTION_TAG = "question_tag";
public static final String KEY_COLUMN_ID = "column_id";
@ -112,6 +111,7 @@ public class EntranceUtils {
public static final String KEY_QUESTION_MODERATOR_PATCH = "questionModeratorPatch";
public static final String KEY_SKIP_GAME_COMMENT = "skipGameComment";
public static final String KEY_OPEN_PLATFORM_WINDOW = "openPlatformWindow";
public static final String KEY_OPEN_KEYBOARD = "openKeyboard";
public static void jumpActivity(Context context, Bundle bundle) {

View File

@ -10,6 +10,54 @@ import com.lightgame.utils.Utils
*/
object ErrorHelper {
/**
* 手动匹配处理特定错误码
* [showHighPriorityHint] 用来标识有同样错误码可以触发两种处理时,为 true 时选择重要的
* [customizedHandler] 返回 true 为已处理该错误码false 则交由 [handleError] 处理
*/
fun handleErrorWithCustomizedHandler(context: Context,
errorString: String?,
showHighPriorityHint: Boolean = false,
customizedHandler: (code: Int) -> Boolean) {
val errorEntity = errorString?.toObject<ErrorEntity>()
if (errorEntity == null) {
Utils.toast(context, R.string.post_failure_hint)
return
}
if (!errorEntity.toast.isNullOrEmpty()) {
Utils.toast(context, errorEntity.toast)
return
}
if (customizedHandler(errorEntity.code ?: 0)) {
return
} else {
handleError(context, showHighPriorityHint, errorEntity)
}
}
/**
* [showHighPriorityHint] 用来标识有同样错误码可以触发两种处理时,为 true 时选择重要的
*/
@JvmStatic
fun handleError(context: Context, errorString: String?, showHighPriorityHint: Boolean = false) {
val errorEntity = errorString?.toObject<ErrorEntity>()
if (errorEntity == null) {
Utils.toast(context, R.string.post_failure_hint)
return
}
if (!errorEntity.toast.isNullOrEmpty()) {
Utils.toast(context, errorEntity.toast)
return
}
handleError(context, showHighPriorityHint, errorEntity)
}
/***
* 禁言错误,
*403050 评论回答
@ -24,23 +72,7 @@ object ErrorHelper {
*403054 更新社区文章
*403047 回答点赞
*/
/**
* [important] 用来标识有同样错误码可以触发两种处理时,为 true 时选择重要的
*/
fun handleError(context: Context, errorString: String?, important: Boolean = false) {
val errorEntity = errorString?.toObject<ErrorEntity>()
if (errorEntity == null) {
Utils.toast(context, R.string.post_failure_hint)
return
}
if (!errorEntity.toast.isNullOrEmpty()) {
Utils.toast(context, errorEntity.toast)
return
}
private fun handleError(context: Context, showHighPriorityHint: Boolean = false, errorEntity: ErrorEntity) {
when (errorEntity.code) {
403050,
403051,
@ -70,9 +102,10 @@ object ErrorHelper {
403014 -> Utils.toast(context, "标签数量太多了")
403015 -> Utils.toast(context, "已经关注过了")
404001 -> Utils.toast(context, "请求的资源不存在")
403016 -> Utils.toast(context, "标签内容可能包含敏感信息,请修改后再提交")
403018 -> Utils.toast(context, R.string.comment_failed_unable)
403020 -> if (important!!) {
403020 -> if (showHighPriorityHint) {
DialogUtils.showAlertDialog(context,
"限制提醒",
"提问过于频繁,请先休息一下哦",
@ -83,6 +116,8 @@ object ErrorHelper {
403021 -> Utils.toast(context, R.string.comment_failed_illegal)
403059 -> Utils.toast(context, "权限错误,请刷新后重试")
else -> Utils.toast(context, R.string.post_failure_hint)
}
}

View File

@ -1,26 +1,42 @@
package com.gh.common.util
import android.arch.lifecycle.*
import android.content.ClipboardManager
import android.content.Context
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentActivity
import android.support.v4.view.ViewPager
import android.text.Html
import android.text.Spanned
import android.view.View
import com.google.gson.reflect.TypeToken
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import okhttp3.MediaType
import okhttp3.RequestBody
import java.net.URI
/**
* 创建以 activity 为观察者上下文的 viewModel
*/
inline fun <reified VM : ViewModel> FragmentActivity.viewModelProvider(
provider: ViewModelProvider.Factory
provider: ViewModelProvider.Factory? = null
) =
ViewModelProviders.of(this, provider).get(VM::class.java)
/**
* 创建以 activity 为观察者上下文的 viewModel
*/
inline fun <reified VM : ViewModel> Fragment.viewModelProviderFromParent(
provider: ViewModelProvider.Factory? = null
) =
ViewModelProviders.of(requireActivity(), provider).get(VM::class.java)
/**
* 创建以 fragment 为观察者上下文的 viewModel
*/
inline fun <reified VM : ViewModel> Fragment.viewModelProvider(
provider: ViewModelProvider.Factory
provider: ViewModelProvider.Factory? = null
) =
ViewModelProviders.of(this, provider).get(VM::class.java)
@ -98,4 +114,58 @@ fun debounceActionWithInterval(id: Int, interval: Long = 300, action: (() -> Uni
fun View.debounceActionWithInterval(interval: Long = 300, action: (() -> Unit)? = null) {
debounceActionWithInterval(this.id, interval, action)
}
/**
* 告诉需要返回 true or false 的外层这个事件已经被消费(即返回 true
*/
inline fun consume(f: () -> Unit): Boolean {
f()
return true
}
/**
* String related
*/
fun String.fromHtml(): Spanned {
return Html.fromHtml(this)
}
// 去掉文章/答案的插入内容
fun String.removeInsertedContent(): String {
val textRegex = "(?s)<div class=\"gh-internal-content content-right\".*?</div>"
return this.replace(textRegex.toRegex(), "")
}
// 完全地清除所有 Html 格式
fun String.clearHtmlFormatCompletely(): String {
return Html.fromHtml(this).toString().replace('\n', 32.toChar())
.replace(160.toChar(), 32.toChar()).replace(65532.toChar(), 32.toChar()).trim { it <= ' ' }
}
// 如果该字符串长度超过固定长度的话,从头开始截取固定长度并返回
fun String.subStringIfPossible(length: Int): String {
return if (this.length > length) {
this.substring(0, length)
} else {
this
}
}
fun String.copyTextAndToast(toastText: String = "复制成功") {
val application = HaloApp.getInstance().application
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
cmb.text = this
Utils.toast(application, toastText)
}
fun Map<String, String>.createRequestBody(): RequestBody {
val json = GsonUtils.toJson(this)
return RequestBody.create(MediaType.parse("application/json"), json)
}
// 对在浏览器(WebView)显示的路径进行转码
fun String.decodeURI(): String {
return URI(null, null, this, null).rawPath
}

View File

@ -66,11 +66,11 @@ object GameRepositoryHelper {
* @param collectionId 补充游戏库相应专题 ID
* @param gameIdList 该专题里已经包含的游戏 ID 列表
*/
fun getOneUniqueGame(collectionId: String?, gameIdList: List<String>): GameEntity? {
fun getOneUniqueGame(collectionId: String?, gameIdList: HashSet<String>): GameEntity? {
collectionId?.let {
val collection = gameCollectionList.find { it.id == collectionId }
collection?.let {
val game = collection.data?.find { game -> findUniqueGame(game, gameIdList) }
val game = collection.data?.find { game -> isThisGameUnique(game, gameIdList) }
game?.let {
collection.data?.remove(game)
// 产品说要记录补充专题的曝光数,所以这个游戏附带了所在专题的名字
@ -82,7 +82,12 @@ object GameRepositoryHelper {
return null
}
private fun findUniqueGame(game: GameEntity, gameIdList: List<String>): Boolean {
private fun isThisGameUnique(game: GameEntity, gameIdList: HashSet<String>): Boolean {
// 若该补充游戏已经存在关联关系,判定为非唯一
for (relatedId in game.relatedGameIds!!) {
gameIdList.contains(relatedId)
return false
}
for (apk in game.getApk()) {
// 检查本地是否已安装该游戏,已过滤那部分框架服务的包名
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {

View File

@ -0,0 +1,20 @@
package com.gh.common.util
import android.content.Context
import com.zhihu.matisse.MimeType
import com.zhihu.matisse.filter.Filter
import com.zhihu.matisse.internal.entity.IncapableCause
import com.zhihu.matisse.internal.entity.Item
class GhMatisseFilter : Filter() {
override fun constraintTypes(): MutableSet<MimeType> {
return MimeType.ofVideo()
}
override fun filter(context: Context?, item: Item?): IncapableCause? {
if (!needFiltering(context, item)) return null
return IncapableCause(IncapableCause.TOAST, "暂不支持视频")
}
}

View File

@ -1,36 +0,0 @@
package com.gh.common.util;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class HMACUtils {
public static String encrypt(String data, String key) {
try {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
return byte2hex(mac.doFinal(data.getBytes()));
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
private static String byte2hex(byte[] ciphertext) {
StringBuilder builder = new StringBuilder();
String stmp;
for (int i = 0; ciphertext != null && i < ciphertext.length; i++) {
stmp = Integer.toHexString(ciphertext[i] & 0XFF);
if (stmp.length() == 1) {
builder.append('0');
}
builder.append(stmp);
}
return builder.toString().toLowerCase();
}
}

View File

@ -1,158 +0,0 @@
/*
* Copyright (C) 2015 Baidu, Inc. All Rights Reserved.
*/
package com.gh.common.util;
import android.annotation.TargetApi;
import android.content.Context;
import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import dalvik.system.DexClassLoader;
import dalvik.system.PathClassLoader;
/* compiled from: ProGuard */
public final class HotFix {
public static void patch(Context context, String patchDexFile, String patchClassName) {
if (patchDexFile != null && new File(patchDexFile).exists()) {
try {
if (hasLexClassLoader()) {
injectInAliyunOs(context, patchDexFile, patchClassName);
} else if (hasDexClassLoader()) {
injectAboveEqualApiLevel14(context, patchDexFile, patchClassName);
} else {
injectBelowApiLevel14(context, patchDexFile, patchClassName);
}
} catch (Throwable th) {
}
}
}
private static boolean hasLexClassLoader() {
try {
Class.forName("dalvik.system.LexClassLoader");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
private static void injectInAliyunOs(Context context, String patchDexFile, String patchClassName)
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException,
InstantiationException, NoSuchFieldException {
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
String replaceAll = new File(patchDexFile).getName().replaceAll("\\.[a-zA-Z0-9]+", ".lex");
Class cls = Class.forName("dalvik.system.LexClassLoader");
Object newInstance =
cls.getConstructor(new Class[]{String.class, String.class, String.class, ClassLoader.class}).newInstance(
new Object[]{context.getDir("dex", 0).getAbsolutePath() + File.separator + replaceAll,
context.getDir("dex", 0).getAbsolutePath(), patchDexFile, obj});
cls.getMethod("loadClass", new Class[]{String.class}).invoke(newInstance, new Object[]{patchClassName});
setField(obj, PathClassLoader.class, "mPaths",
appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(newInstance, cls, "mRawDexPath")));
setField(obj, PathClassLoader.class, "mFiles",
combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(newInstance, cls, "mFiles")));
setField(obj, PathClassLoader.class, "mZips",
combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(newInstance, cls, "mZips")));
setField(obj, PathClassLoader.class, "mLexs",
combineArray(getField(obj, PathClassLoader.class, "mLexs"), getField(newInstance, cls, "mDexs")));
}
private static boolean hasDexClassLoader() {
try {
Class.forName("dalvik.system.BaseDexClassLoader");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
private static void injectAboveEqualApiLevel14(Context context, String str, String str2)
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
PathClassLoader pathClassLoader = (PathClassLoader) context.getClassLoader();
Object a = combineArray(getDexElements(getPathList(pathClassLoader)),
getDexElements(getPathList(
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader()))));
Object a2 = getPathList(pathClassLoader);
setField(a2, a2.getClass(), "dexElements", a);
pathClassLoader.loadClass(str2);
}
@TargetApi(14)
private static void injectBelowApiLevel14(Context context, String str, String str2)
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
DexClassLoader dexClassLoader =
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader());
dexClassLoader.loadClass(str2);
setField(obj, PathClassLoader.class, "mPaths",
appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(dexClassLoader, DexClassLoader.class,
"mRawDexPath")
));
setField(obj, PathClassLoader.class, "mFiles",
combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(dexClassLoader, DexClassLoader.class,
"mFiles")
));
setField(obj, PathClassLoader.class, "mZips",
combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(dexClassLoader, DexClassLoader.class,
"mZips")));
setField(obj, PathClassLoader.class, "mDexs",
combineArray(getField(obj, PathClassLoader.class, "mDexs"), getField(dexClassLoader, DexClassLoader.class,
"mDexs")));
obj.loadClass(str2);
}
private static void setField(Object obj, Class cls, String str, Object obj2)
throws NoSuchFieldException, IllegalAccessException {
Field declaredField = cls.getDeclaredField(str);
declaredField.setAccessible(true);
declaredField.set(obj, obj2);
}
private static Object appendArray(Object obj, Object obj2) {
Class componentType = obj.getClass().getComponentType();
int length = Array.getLength(obj);
Object newInstance = Array.newInstance(componentType, length + 1);
Array.set(newInstance, 0, obj2);
for (int i = 1; i < length + 1; i++) {
Array.set(newInstance, i, Array.get(obj, i - 1));
}
return newInstance;
}
private static Object getField(Object obj, Class cls, String str)
throws NoSuchFieldException, IllegalAccessException {
Field declaredField = cls.getDeclaredField(str);
declaredField.setAccessible(true);
return declaredField.get(obj);
}
private static Object combineArray(Object obj, Object obj2) {
Class componentType = obj2.getClass().getComponentType();
int length = Array.getLength(obj2);
int length2 = Array.getLength(obj) + length;
Object newInstance = Array.newInstance(componentType, length2);
for (int i = 0; i < length2; i++) {
if (i < length) {
Array.set(newInstance, i, Array.get(obj2, i));
} else {
Array.set(newInstance, i, Array.get(obj, i - length));
}
}
return newInstance;
}
private static Object getDexElements(Object obj) throws NoSuchFieldException, IllegalAccessException {
return getField(obj, obj.getClass(), "dexElements");
}
private static Object getPathList(Object obj) throws ClassNotFoundException, NoSuchFieldException,
IllegalAccessException {
return getField(obj, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
}
}

View File

@ -9,22 +9,9 @@ import java.util.regex.Pattern;
* Created by khy on 27/12/17.
*/
public class AskUtils {
// public static String voteCountFormat(int voteCount) {
// String vote;
// if (voteCount >= 10000) {
// DecimalFormat df = new DecimalFormat("#.0万");
// vote = df.format(voteCount / 10000f);
// } else {
// vote = String.valueOf(voteCount);
// }
// return vote;
// }
public class HtmlUtils {
public static String stripHtml(String htmlStr) {
if (TextUtils.isEmpty(htmlStr)) return "";
String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
@ -45,5 +32,4 @@ public class AskUtils {
return htmlStr.trim(); //返回文本字符串
}
}

View File

@ -64,7 +64,7 @@ public class InstallUtils {
keys.add(packageName);
DownloadEntity downloadEntity = DownloadManager.getInstance(context).getDownloadEntityByPackageName(packageName);
String installVersion = PackageUtils.getVersionByPackage(context, packageName);
String installVersion = PackageUtils.getVersionByPackage(packageName);
if (!TextUtils.isEmpty(installVersion) && downloadEntity != null &&
installVersion.equals(downloadEntity.getVersionName())) {
if (!downloadEntity.isPluggable() || PackageUtils.isSignature(context, packageName)) {

View File

@ -1,32 +0,0 @@
package com.gh.common.util;
import android.support.v4.content.ContextCompat;
import android.widget.TextView;
import com.gh.gamecenter.R;
/**
* Created by khy on 2017/3/19.
*/
public class KaiFuUtils {
public static void setKaiFuType(TextView textView, String type) {
if (type == null) return;
textView.setText(type);
textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), R.color.tag_yellow));
// switch (type) {
// case "不删档内测":
// textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), R.color.content));
// break;
// case "删档内测":
// textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), R.color.content));
// break;
// case "公测":
// textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), R.color.tag_yellow));
// break;
// default:
// textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), R.color.tag_yellow));
// break;
// }
}
}

View File

@ -84,7 +84,7 @@ public class LibaoUtils {
.subscribe(new JSONObjectResponse() {
@Override
public void onResponse(JSONObject response) {
listener.postSucced(response);
listener.postSucceed(response);
}
@Override
@ -105,7 +105,7 @@ public class LibaoUtils {
.subscribe(new JSONObjectResponse() {
@Override
public void onResponse(JSONObject response) {
listener.postSucced(response);
listener.postSucceed(response);
}
@Override
@ -123,7 +123,7 @@ public class LibaoUtils {
.subscribe(new Response<ResponseBody>() {
@Override
public void onResponse(ResponseBody response) {
listener.postSucced(response);
listener.postSucceed(response);
}
@Override
@ -140,7 +140,7 @@ public class LibaoUtils {
.subscribe(new Response<List<LibaoStatusEntity>>() {
@Override
public void onResponse(List<LibaoStatusEntity> response) {
listener.postSucced(response);
listener.postSucceed(response);
}
@Override
@ -299,7 +299,7 @@ public class LibaoUtils {
final Dialog loadingDialog = DialogUtils.showWaitDialog(context, "淘号中...");
postLibaoTao(context, libaoEntity.getId(), new PostLibaoListener() {
@Override
public void postSucced(Object response) {
public void postSucceed(Object response) {
if (loadingDialog != null) loadingDialog.dismiss();
@ -431,7 +431,7 @@ public class LibaoUtils {
postLibaoLing(context, libaoEntity.getId(), new PostLibaoListener() {
@Override
public void postSucced(Object response) {
public void postSucceed(Object response) {
if (loadingDialog != null) loadingDialog.dismiss();
JSONObject responseBody = (JSONObject) response;
@ -629,7 +629,7 @@ public class LibaoUtils {
public interface PostLibaoListener {
void postSucced(Object response);
void postSucceed(Object response);
void postFailed(Throwable error);
}

View File

@ -1,9 +1,7 @@
package com.gh.common.util;
import android.content.Context;
import android.text.TextUtils;
import com.gh.gamecenter.R;
import com.gh.gamecenter.retrofit.JSONObjectResponse;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
@ -12,8 +10,6 @@ import com.lightgame.utils.Utils;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Iterator;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
@ -106,68 +102,6 @@ public class LoginUtils {
});
}
/**
* 请用 ErrorHelper.handleError 替代本方法
*/
@Deprecated
public static void userPostErrorToast(String errorString, Context context, boolean isQuestion) {
if (TextUtils.isEmpty(errorString)) {
Utils.toast(context, R.string.post_failure_hint);
return;
}
try {
JSONObject errorJson = new JSONObject(errorString);
Iterator<String> iterator = errorJson.keys();
while (iterator.hasNext()) {
String key = iterator.next();
if ("toast".equals(key)) {
Utils.toast(context, errorJson.get(key).toString());
return;
}
}
int errorCode = errorJson.getInt("code");
switch (errorCode) {
case 403018:
Utils.toast(context, R.string.comment_failed_unable);
case 403050:
case 403053:
case 403048:
case 403049:
case 403057:
case 403045:
case 403046:
case 403054:
Utils.toast(context, R.string.comment_failed_userbanned);
break;
case 403051:
Utils.toast(context, R.string.comment_failed_userblocked);
break;
case 403020:
if (isQuestion) {
DialogUtils.showAlertDialog(context, "限制提醒"
, "提问过于频繁,请先休息一下哦", "知道了"
, null, null, null);
} else {
Utils.toast(context, R.string.comment_failed_toofrequent);
}
break;
case 403021:
Utils.toast(context, R.string.comment_failed_illegal);
break;
case 403047:
Utils.toast(context, R.string.deny_vote_answer);
break;
default:
Utils.toast(context, R.string.post_failure_hint);
break;
}
} catch (Exception e) {
Utils.toast(context, R.string.post_failure_hint);
e.printStackTrace();
}
}
public static void captchaErrorHint(Context context, JSONObject content) {
try {
@ -327,6 +261,9 @@ public class LoginUtils {
case 403204:
Utils.toast(context, "获取验证码太频繁,请稍后再试");
break;
case 400212:
Utils.toast(context, "请输入正确的手机号");
break;
default:
Utils.toast(context, code + "");
break;

View File

@ -3,6 +3,7 @@ package com.gh.common.util;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.TelephonyManager;
public class NetworkUtils {
@ -119,4 +120,48 @@ public class NetworkUtils {
return "NONE";
}
/**
* 获取当前移动网络连接的类型信息(当连接的网络是移动网络时使用)
*
* @param context 上下文
* @return 当前移动网络连接的类型信息
*/
public static String getMobileNetworkType(Context context) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = connectivityManager.getActiveNetworkInfo();
if (info == null) return "unknown";
switch (info.getType()) {
// Unknown
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
return "unknown";
// Cellular Data2G
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_IDEN:
case TelephonyManager.NETWORK_TYPE_1xRTT:
return "2G";
// Cellular Data3G
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_HSPAP:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
return "3G";
// Cellular Data4G
case TelephonyManager.NETWORK_TYPE_LTE:
return "4G";
default:
return "unknown";
}
}
}

View File

@ -0,0 +1,44 @@
package com.gh.common.util
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.support.v4.content.ContextCompat
import android.view.Window
import android.widget.LinearLayout
import android.widget.TextView
import com.gh.gamecenter.R
object OptionDialogHelper {
fun showOptionDialog(context: Context, typeList: List<String>, callback: (String) -> Unit) {
val dialog = Dialog(context)
val container = LinearLayout(context)
container.orientation = LinearLayout.VERTICAL
container.setBackgroundColor(Color.WHITE)
container.setPadding(0, DisplayUtils.dip2px(context, 12f), 0, DisplayUtils.dip2px(context, 12f))
for (type in typeList) {
val reportTv = TextView(context)
reportTv.text = type
reportTv.textSize = 17f
reportTv.setTextColor(ContextCompat.getColor(context, R.color.title))
reportTv.setBackgroundResource(R.drawable.textview_white_style)
val widthPixels = context.resources.displayMetrics.widthPixels
reportTv.layoutParams = LinearLayout.LayoutParams(widthPixels * 9 / 10,
LinearLayout.LayoutParams.WRAP_CONTENT)
reportTv.setPadding(DisplayUtils.dip2px(context, 20f), DisplayUtils.dip2px(context, 12f),
0, DisplayUtils.dip2px(context, 12f))
container.addView(reportTv)
reportTv.setOnClickListener {
callback.invoke(reportTv.text.toString())
dialog.cancel()
}
}
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
dialog.setContentView(container)
dialog.show()
}
}

View File

@ -19,6 +19,7 @@ import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.GameUpdateEntity;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;
import org.json.JSONArray;
@ -79,7 +80,7 @@ public class PackageUtils {
for (ApkEntity apkEntity : gameEntity.getApkNormal()) {
String versionFromRequest = apkEntity.getVersion();
String versionFromInstalledApp = getVersionByPackage(context, apkEntity.getPackageName());
String versionFromInstalledApp = getVersionByPackage(apkEntity.getPackageName());
// 是否需要显示更新
boolean shouldShouldUpdate = apkEntity.getForce();
@ -310,9 +311,9 @@ public class PackageUtils {
/*
* 获取apk的版本
*/
public static String getVersionByPackage(Context context, String packageName) {
public static String getVersionByPackage(String packageName) {
try {
return context.getApplicationContext().getPackageManager().getPackageInfo(packageName,
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
} catch (NameNotFoundException e) {
e.printStackTrace();
@ -370,6 +371,25 @@ public class PackageUtils {
return jsonArray;
}
public static JSONObject getAppBasicInfoByPackageName(String packageName) {
JSONObject jsonObject = new JSONObject();
PackageManager pm = HaloApp.getInstance().getApplication().getPackageManager();
try {
PackageInfo packageInfo = HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
jsonObject.put("name", pm.getApplicationLabel(packageInfo.applicationInfo).toString());
jsonObject.put("package", packageName);
jsonObject.put("version", packageInfo.versionName);
}
return jsonObject;
} catch (JSONException | NameNotFoundException e) {
e.printStackTrace();
return jsonObject;
}
}
/*
* 启动应用
*/

View File

@ -133,7 +133,7 @@ public class PlatformUtils {
}
}
updataPlatform(platformMap, platformPicMap, platformPicUrlMap,
updatePlatform(platformMap, platformPicMap, platformPicUrlMap,
platformColorMap);
}
@ -184,7 +184,7 @@ public class PlatformUtils {
}
}
private void updataPlatform(ArrayMap<String, String> pMap,
private void updatePlatform(ArrayMap<String, String> pMap,
ArrayMap<String, Integer> pPMap, ArrayMap<String, String> pUMap,
ArrayMap<String, String> pCMap) {
platformMap = pMap;

View File

@ -0,0 +1,47 @@
package com.gh.common.util
import android.content.Context
import com.gh.gamecenter.receiver.UmengMessageReceiver
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.RequestBody
import okhttp3.ResponseBody
object PushHelper {
/**
* 提交推送点击事件,会尝试从 SP 读取之前失败的一并提交
*/
@JvmStatic
fun postPushClickAction(context: Context, clickEvent: UmengMessageReceiver.ClickEvent? = null) {
val clickEventList = arrayListOf<UmengMessageReceiver.ClickEvent>()
clickEvent?.let { clickEventList.add(it) }
val failedClickEventList = SPUtils.getString(UmengMessageReceiver.SP_CLICK_EVENT)
.toObject<ArrayList<UmengMessageReceiver.ClickEvent>>()
failedClickEventList?.let { clickEventList.addAll(it) }
// 没有要提交的事件
if (clickEventList.size == 0) return
val body = RequestBody.create(MediaType.parse("application/json"), clickEventList.toJson())
RetrofitManager.getInstance(context)
.api
.postUmengReceiveInfo(body)
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
SPUtils.setString(UmengMessageReceiver.SP_CLICK_EVENT, "")
}
override fun onFailure(exception: Exception) {
SPUtils.setString(UmengMessageReceiver.SP_CLICK_EVENT, clickEventList.toJson())
}
})
}
}

View File

@ -0,0 +1,54 @@
package com.gh.common.util
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import retrofit2.HttpException
/**
* 可以在此类发送一些无关页面操作的请求
*/
object SimpleRequestHelper {
private val mApi = RetrofitManager.getInstance(HaloApp.getInstance().application).api
fun reportGameComment(gameId: String, commentId: String, type: String) {
val map = HashMap<String, String>()
map["reason"] = type
mApi.reportGameComment(gameId, commentId, map.createRequestBody())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
Utils.toast(HaloApp.getInstance().application, "感谢您的举报")
}
override fun onFailure(e: HttpException?) {
ErrorHelper.handleError(HaloApp.getInstance().application, e?.response()?.errorBody()?.string())
}
})
}
fun reportGameCommentReply(gameId: String, commentId: String, replyId: String, type: String) {
val map = HashMap<String, String>()
map["reason"] = type
mApi.reportGameCommentReply(gameId, commentId, replyId, map.createRequestBody())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
Utils.toast(HaloApp.getInstance().application, "感谢您的举报")
}
override fun onFailure(e: HttpException?) {
ErrorHelper.handleError(HaloApp.getInstance().application, e?.response()?.errorBody()?.string())
}
})
}
}

View File

@ -45,6 +45,16 @@ object SPUtils {
return sp.getInt(key, defaultValue)
}
@JvmStatic
fun getLong(key: String, defaultValue: Long): Long {
return sp.getLong(key, defaultValue)
}
@JvmStatic
fun setLong(key: String, value: Long) {
return sp.edit().putLong(key, value).apply()
}
@JvmStatic
fun setBoolean(key: String, value: Boolean) {
sp.edit().putBoolean(key, value).apply()

View File

@ -1,6 +1,7 @@
package com.gh.common.util
import android.text.Editable
import android.text.InputFilter
import android.text.TextWatcher
import android.widget.EditText
import com.gh.gamecenter.R
@ -9,7 +10,7 @@ object TextHelper {
@JvmStatic
fun limitTheLengthOfEditText(editText: EditText, length: Int, exceedCallback: ExceedTextLengthLimitCallback? = null) {
editText.addTextChangedListener(object :TextWatcher {
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
@ -32,6 +33,22 @@ object TextHelper {
})
}
@JvmStatic
fun getFilter(maxLength: Int, msg: String)//限制最大长度-Toast弹窗提示
: InputFilter {
return InputFilter { source, start, end, dest, dstart, dend ->
val keep = maxLength - (dest.length - (dend - dstart))
if (keep < end - start) {
ToastUtils.showToast(msg)
}
when {
keep <= 0 -> ""
keep >= end - start -> null
else -> source.subSequence(start, start + keep)
}
}
}
interface ExceedTextLengthLimitCallback {
fun onExceed()
}

View File

@ -0,0 +1,40 @@
package com.gh.common.util
import android.widget.Toast
import com.halo.assistant.HaloApp
object ToastUtils {
/** 之前显示的内容 */
private var mOldMsg: String? = null
/** Toast对象 */
private var mToast: Toast? = null
/** 第一次时间 */
private var mOneTime: Long = 0
/** 第二次时间 */
private var mTwoTime: Long = 0
/**
* 显示Toast
* @param message
*/
fun showToast(message: String) {
if (mToast == null) {
mToast = Toast.makeText(HaloApp.getInstance().application, message, Toast.LENGTH_SHORT)
mToast!!.show()
mOneTime = System.currentTimeMillis()
} else {
mTwoTime = System.currentTimeMillis()
if (message == mOldMsg) {
if (mTwoTime - mOneTime > Toast.LENGTH_SHORT) {
mToast!!.show()
}
} else {
mOldMsg = message
mToast!!.setText(message)
mToast!!.show()
}
}
mOneTime = mTwoTime
}
}

View File

@ -18,6 +18,7 @@ import okhttp3.MultipartBody
import okhttp3.ResponseBody
import org.json.JSONObject
import java.io.File
import java.util.*
object UploadImageUtils {
@ -104,7 +105,7 @@ object UploadImageUtils {
@SuppressLint("CheckResult")
fun compressAndUploadImageList(type: UploadType, imgs: List<String>, compressGif: Boolean, listener: OnUploadImageListListener): Disposable? {
var subscription: Disposable? = null
val postImageList = HashMap<String, String>()
val postImageList = LinkedHashMap<String, String>()
Observable.create(ObservableOnSubscribe<Map<String, String>> {
val compressList = compressImageList(imgs, compressGif)
@ -114,7 +115,7 @@ object UploadImageUtils {
listTotal += img.length()
}
for (img in compressList) {
if (subscription?.isDisposed == true) return@ObservableOnSubscribe
if (subscription?.isDisposed == true) return@ObservableOnSubscribe
val requestBody = FileRequestBody<ResponseBody>(img, object : RetrofitCallback<ResponseBody>() {
override fun onProgress(total: Long, progress: Long) {
if (subscription?.isDisposed != true) {
@ -132,7 +133,7 @@ object UploadImageUtils {
if (!string.isNullOrEmpty()) {
val url = JSONObject(string).getString("url")
if (!url.isNullOrEmpty()) {
val map = HashMap<String, String>()
val map = LinkedHashMap<String, String>()
map[img.path] = url
it.onNext(map)
return
@ -142,8 +143,10 @@ object UploadImageUtils {
}
override fun onFailure(exception: Exception) {
if (subscription?.isDisposed == true) return
it.onError(exception)
// 若遇到错误且 subscription?.isDisposed 为 true 时会抛出 io.reactivex.exceptions.UndeliverableException 异常
// if (subscription?.isDisposed == true) return
// it.onError(exception) // fuck
it.onNext(Collections.emptyMap())
}
})
listProgress += img.length()
@ -152,7 +155,7 @@ object UploadImageUtils {
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<Map<String, String>> {
.subscribe(object : Observer<Map<String, String>?> {
override fun onSubscribe(d: Disposable) {
subscription = d
}
@ -166,10 +169,11 @@ object UploadImageUtils {
}
override fun onNext(t: Map<String, String>) {
postImageList.putAll(t)
if (!t.isEmpty()) postImageList.putAll(t)
}
override fun onError(e: Throwable) {
e.printStackTrace()
}
})
return subscription
@ -207,7 +211,7 @@ object UploadImageUtils {
}
interface OnUploadImageListListener {
fun onSuccess(imageUrl: Map<String, String>) // key:sourceImage value:compressImage
fun onSuccess(imageUrl: LinkedHashMap<String, String>) // key:sourceImage value:compressImage
fun onError() // 全部上传失败时回调
fun onProgress(total: Long, progress: Long)
}

View File

@ -102,7 +102,7 @@ public class DownloadProgressBar extends ProgressBar {
String txt = TextUtils.ellipsize(mText, mFakeTextPaint, width, TextUtils.TruncateAt.END).toString();
srcCanvas.drawText(txt, getWidth() / 2, baseline, mPaint);
mPaint.setXfermode(mDuffXFerMode);
if (getProgress() != 0 && getProgress() != MAX_LENGTH) {
if (getProgress() != 0) {
mPaint.setColor(DOWNLOAD_IMAGE_STYLE == mDownloadStyle ? Color.BLACK : Color.WHITE); // 反向颜色
}
@ -121,7 +121,6 @@ public class DownloadProgressBar extends ProgressBar {
public void setText(@StringRes int res) {
setText(getResources().getString(res));
invalidate(); // 文字绘制没有同步 就重绘多几遍吧 虽然不知到有没有用
}
public void setDownloadType(DownloadType downloadType) {

View File

@ -89,7 +89,8 @@ public class ExpendTextView extends android.support.v7.widget.AppCompatTextView
}
SpannableStringBuilder msp = new SpannableStringBuilder(content);
int length = msp.length();
msp.replace(length - mExpendText.length(), length, mExpendText);
int startPosition = length - mExpendText.length();
msp.replace(startPosition < 0 ? 0 : startPosition, length, mExpendText);
msp.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(TextPaint ds) {
@ -114,6 +115,12 @@ public class ExpendTextView extends android.support.v7.widget.AppCompatTextView
setMovementMethod(CustomLinkMovementMethod.getInstance());
}
public void setExpendMaxLines(int maxLines) {
mMaxLines = maxLines;
setMaxLines(maxLines);
}
public interface ExpandCallback {
void onExpand();
}

View File

@ -61,8 +61,6 @@ public class MessageSpannableTextView extends android.support.v7.widget.AppCompa
markData.setKey(key);
mMarkList.add(markData);
System.out.println(substring);
System.out.println(s);
} else {
builder.append(s);
if (i != split.length - 1 || sText.substring(sText.length() - 2, sText.length()).equals("}}")) {

View File

@ -13,12 +13,14 @@ import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.gh.common.util.AskUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.GsonUtils;
import com.gh.common.util.HtmlUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.RichEditorUtils;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.qa.entity.EditorInsertEntity;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
@ -90,6 +92,7 @@ public class RichEditor extends WebView {
private static final String SETUP_HTML = "file:///android_asset/editor.html";
private static final String CALLBACK_SCHEME = "re-callback://";
private static final String STATE_SCHEME = "re-state://";
private boolean isReady = false;
private String mContents;
private OnTextChangeListener mTextChangeListener;
@ -122,11 +125,12 @@ public class RichEditor extends WebView {
getSettings().setJavaScriptEnabled(true);
setWebChromeClient(new WebChromeClient()); // 不要重写这个方法否则无法加载
setWebViewClient(createWebViewClient());
// 临时开启让 H5 同事调试
if (BuildConfig.DEBUG && Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
setWebContentsDebuggingEnabled(true);
}
loadUrl(SETUP_HTML);
loadUrl(SETUP_HTML);
applyAttributes(context, attrs);
}
@ -213,7 +217,6 @@ public class RichEditor extends WebView {
}
// getSettings().setBlockNetworkImage(true); // 先不加载网络图片,因为后面有资源替换操作防止流量无故丢失
// contents = contents.replace("src=", "class=\"lazy\" data-src=");
try {
exec("javascript:RE.setHtml('" + URLEncoder.encode(contents, "UTF-8") + "');");
@ -226,7 +229,6 @@ public class RichEditor extends WebView {
replaceAllDfImageExcludeGif();
}
exec("javascript:RE.ImageClickListener()");
// exec("javascript:RE.lazyLoad()");
}
callback(contents);
@ -234,6 +236,8 @@ public class RichEditor extends WebView {
// No handling
}
mContents = contents;
showLinkStyle(); // 显示隐藏样式
// getSettings().setBlockNetworkImage(false); // 重新加载图片
}
@ -241,9 +245,26 @@ public class RichEditor extends WebView {
return TextUtils.isEmpty(mContents) ? "" : mContents;
}
public void setEditorFontColor(int color) {
String hex = convertHexColorString(color);
exec("javascript:RE.setBaseTextColor('" + hex + "');");
public void insertCustomStyleLink(EditorInsertEntity entity) {
if (entity == null) return;
// 转译
String brief = entity.getBrief();
String title = entity.getTitle();
brief = TextUtils.isEmpty(brief) ? "" : brief.replaceAll("[\\x00-\\x1F\\x7F]", "");
title = TextUtils.isEmpty(title) ? "" : title.replaceAll("[\\x00-\\x1F\\x7F]", "");
entity.setBrief(TextUtils.htmlEncode(brief));
entity.setTitle(TextUtils.htmlEncode(title));
entity.setIcon(TextUtils.htmlEncode(entity.getIcon()));
exec("javascript:RE.insertCustomStyleLink('" + GsonUtils.toJson(entity) + "');");
}
public void hideLinkStyle() {
exec("javascript:RE.hideLinkStyle();");
}
public void showLinkStyle() {
exec("javascript:RE.showLinkStyle();");
}
public void setEditorFontSize(int px) {
@ -290,30 +311,6 @@ public class RichEditor extends WebView {
exec("javascript:RE.setBackgroundImage('url(data:image/png;base64," + base64 + ")');");
}
public void setBackground(String url) {
exec("javascript:RE.setBackgroundImage('url(" + url + ")');");
}
public void setEditorWidth(int px) {
exec("javascript:RE.setWidth('" + px + "px');");
}
public void setEditorHeight(int px) {
exec("javascript:RE.setHeight('" + px + "px');");
}
public void setPlaceholder(String placeholder) {
exec("javascript:RE.setPlaceholder('" + placeholder + "');");
}
public void setEditorFocus() {
exec("javascript:RE.setEditorFocus();");
}
public void setInputEnabled(Boolean inputEnabled) {
exec("javascript:RE.setInputEnabled(" + inputEnabled + ")");
}
public void replaceAllDfImageExcludeGif() {
exec("javascript:RE.replaceAllDfImage('" +
ImageUtils.getLimitWidthRule(mDefaultImageWidth) + IMAGE_FLAG_DEFAULT + "','" +
@ -346,14 +343,6 @@ public class RichEditor extends WebView {
exec("javascript:" + jsCSSImport + "");
}
public void setTextColor(int color) {
exec("javascript:RE.prepareInsert();");
String hex = convertHexColorString(color);
exec("javascript:RE.setTextColor('" + hex + "');");
}
public void insertImage(String url) {
exec("javascript:RE.prepareInsert();");
exec("javascript:RE.insertImage('" + url + "');");
@ -374,6 +363,36 @@ public class RichEditor extends WebView {
exec("javascript:RE.insertLink('" + href + "', '" + title + "');");
}
public void setBackground(String url) {
exec("javascript:RE.setBackgroundImage('url(" + url + ")');");
}
public void setEditorWidth(int px) {
exec("javascript:RE.setWidth('" + px + "px');");
}
public void setEditorHeight(int px) {
exec("javascript:RE.setHeight('" + px + "px');");
}
public void setPlaceholder(String placeholder) {
exec("javascript:RE.setPlaceholder('" + placeholder + "');");
}
public void setEditorFocus() {
exec("javascript:RE.setEditorFocus();");
}
public void setInputEnabled(Boolean inputEnabled) {
exec("javascript:RE.setInputEnabled(" + inputEnabled + ")");
}
public void setTextColor(int color) {
String hex = convertHexColorString(color);
exec("javascript:RE.prepareInsert();");
exec("javascript:RE.setTextColor('" + hex + "');");
}
public void removeFormat() {
exec("javascript:RE.removeFormat();");
}
@ -451,7 +470,7 @@ public class RichEditor extends WebView {
}
public String getText() {
return AskUtils.stripHtml(mContents);
return HtmlUtils.stripHtml(mContents);
}

View File

@ -0,0 +1,64 @@
package com.gh.common.view
import android.content.Context
import android.support.v4.view.ViewPager
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
class VerticalViewPager @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
: ViewPager(context, attrs) {
init {
// The majority of the magic happens here
setPageTransformer(true, VerticalPageTransformer())
// The easiest way to get rid of the overscroll drawing that happens on the left and right
overScrollMode = View.OVER_SCROLL_NEVER
}
private inner class VerticalPageTransformer : ViewPager.PageTransformer {
override fun transformPage(view: View, position: Float) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.alpha = 0F
} else if (position <= 1) { // [-1,1]
view.alpha = 1F
// Counteract the default slide transition
view.translationX = view.width * -position
//set Y position to swipe in from top
val yPosition = position * view.height
view.translationY = yPosition
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.alpha = 0F
}
}
}
/**
* Swaps the X and Y coordinates of your touch event.
*/
private fun swapXY(ev: MotionEvent): MotionEvent {
val width = width.toFloat()
val height = height.toFloat()
val newX = ev.y / height * width
val newY = ev.x / width * height
ev.setLocation(newX, newY)
return ev
}
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
// val intercepted = super.onInterceptTouchEvent(swapXY(ev))
// return touch coordinates to original reference frame for any child views
// swapXY(ev)
// we do not need it view pager to intercept touch event
return false
}
}

View File

@ -18,6 +18,7 @@ import com.gh.common.util.DataCollectionUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.GdtHelper;
import com.gh.common.util.MD5Utils;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.PackageUtils;
import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity;
@ -92,8 +93,13 @@ public class DownloadManager implements DownloadStatusListener {
@Override
public void onTaskError(DownloadEntity entity) {
DownloadNotification.showDownloadingNotification(mContext);
downloadingMap.remove(entity.getUrl());
// 下载进度超出是任务出错,但不需要去掉状态栏通知 https://gitlab.ghzs.com/pm/halo-app-issues/issues/496
if (entity.getStatus() == DownloadStatus.overflow) {
MtaHelper.onEventWithBasicDeviceInfo("下载无法完成", "游戏", entity.getName());
} else {
DownloadNotification.showDownloadingNotification(mContext);
downloadingMap.remove(entity.getUrl());
}
}
@Override

View File

@ -29,7 +29,7 @@ public class DownloadNotification {
public static final String ACTION_INSTALL = "com.gh.gamecenter.INSTALL";
public static final String ACTION_DOWNLOAD = "com.gh.gamecenter.DOWNLOAD";
public static final int ICON = R.drawable.logo;
public static final int ICON = R.mipmap.logo;
public static final int NOTIFY_ID = 0x123;
public static final int WAIT_NOTIFY_ID = 0x124;
private static final String CHANNEL_ID = "Halo_Download";
@ -69,7 +69,7 @@ public class DownloadNotification {
}
final Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.logo)
.setSmallIcon(R.mipmap.logo)
.setTicker(title)
.setContentTitle(text)
.setContentText(title)

View File

@ -437,7 +437,7 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
byte[] receiveData = new byte[1024];
byte[] sendData;
Utils.log("=====ip::" + ipAddress);
if (!"192.168.43.1".equals(ipAddress)) {
if (!"logo.168.43.1".equals(ipAddress)) {
// 连接失败,可能是连接的热点已经关闭, 关闭动画,开启扫描
isStopScan = false;
handler.sendEmptyMessage(0);

View File

@ -100,7 +100,7 @@ public class GameDetailActivity extends NormalActivity {
}
/**
* 启动游戏详情页面
* 启动游戏详情页面,自动定位到评论页面
*/
public static void startGameDetailCommentActivity(Context context, String gameId, String entrance) {
Bundle bundle = new Bundle();

View File

@ -13,6 +13,8 @@ import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.ethanhua.skeleton.Skeleton;
import com.ethanhua.skeleton.ViewSkeletonScreen;
import com.gh.base.BaseActivity;
import com.gh.base.OnRequestCallBackListener;
import com.gh.common.util.DialogUtils;
@ -38,8 +40,6 @@ import java.util.ArrayList;
import butterknife.BindView;
import static com.gh.gamecenter.R.id.reuse_nodata_skip_tv_btn;
import static com.gh.gamecenter.R.id.reuse_nodata_skip_tv_hint;
import static com.gh.gamecenter.download.FileSendFragment.KC_REQUEST;
/**
@ -53,14 +53,18 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
RecyclerView mInstallRv;
@BindView(R.id.reuse_nodata_skip)
LinearLayout mNoDataSkip;
@BindView(reuse_nodata_skip_tv_hint)
@BindView(R.id.reuse_nodata_skip_tv_hint)
TextView mNoDataSkipHint;
@BindView(reuse_nodata_skip_tv_btn)
@BindView(R.id.reuse_nodata_skip_tv_btn)
TextView mNoDataSkipBtn;
@BindView(R.id.list_skeleton)
View mListSkeleton;
private PackageViewModel mPackageViewModel;
private InstallFragmentAdapter mAdapter;
private ViewSkeletonScreen mSkeleton;
private boolean isEverpause = false;
private DataWatcher dataWatcher = new DataWatcher() {
@ -103,6 +107,7 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
super.onCreate(savedInstanceState);
setNavigationTitle(getString(R.string.personale_mygame));
mNoDataSkip.setVisibility(View.GONE);
mSkeleton = Skeleton.bind(mListSkeleton).shimmer(false).load(R.layout.activity_install_skeleton).show();
mNoDataSkipHint.setText("暂无游戏");
mNoDataSkipBtn.setText("查看精品推荐");
mNoDataSkipBtn.setOnClickListener(v -> {
@ -113,12 +118,12 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
mInstallRv.setLayoutManager(new LinearLayoutManager(this));
((DefaultItemAnimator) mInstallRv.getItemAnimator()).setSupportsChangeAnimations(false);
mAdapter = new InstallFragmentAdapter(this);
mInstallRv.addItemDecoration(new VerticalItemDecoration(this, true));
mInstallRv.addItemDecoration(new VerticalItemDecoration(this, 8, true));
mInstallRv.setAdapter(mAdapter);
mPackageViewModel = ViewModelProviders.of(this, new PackageViewModel.Factory()).get(PackageViewModel.class);
mPackageViewModel.getGameInstalledLiveData().observe(this,
gameInstalls -> mAdapter.initData(PackagesManager.filterSameApk(gameInstalls)));
gameInstalls -> mAdapter.initData(PackagesManager.filterSameApk(PackagesManager.filterDownloadBlackPackage(gameInstalls))));
}
@Override
@ -148,7 +153,7 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
@Override
public void loadDone() {
mSkeleton.hide();
}
@Override
@ -163,6 +168,7 @@ public class InstallActivity extends BaseActivity implements InstallFragmentAdap
@Override
public void loadEmpty() {
mSkeleton.hide();
mInstallRv.setVisibility(View.GONE);
mNoDataSkip.setVisibility(View.VISIBLE);
}

View File

@ -35,6 +35,7 @@ import com.gh.gamecenter.entity.MeEntity;
import com.gh.gamecenter.entity.UserDataLibaoEntity;
import com.gh.gamecenter.eventbus.EBDownloadStatus;
import com.gh.gamecenter.eventbus.EBPackage;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.eventbus.EBUISwitch;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
@ -58,6 +59,7 @@ import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;
import static com.gh.gamecenter.R.id.reuse_tv_none_data;
import static com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG;
/**
* Created by khy on 2016/12/13.
@ -312,8 +314,12 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
.subscribe(new Response<LibaoEntity>() {
@Override
public void onResponse(LibaoEntity response) {
mLibaoEntity = response;
mLibaoEntity.setActive(true); // addLibaoDetail设置userData
response.setActive(true); // addLibaoDetail设置userData
if (mLibaoEntity != null) {
mLibaoEntity.resetLibaoEntity(response);
} else {
mLibaoEntity = response;
}
mAdapter.setLibaoEntity(mLibaoEntity);
mAdapter.notifyDataSetChanged();
getGameDigest();
@ -326,7 +332,7 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
private void getLibaoStatus(String libaoId) {
LibaoUtils.getLibaoStatus(this, libaoId, new LibaoUtils.PostLibaoListener() {
@Override
public void postSucced(Object response) {
public void postSucceed(Object response) {
List<LibaoStatusEntity> statusList = (List<LibaoStatusEntity>) response;
LibaoUtils.initLiBaoEntity(statusList.get(0), mLibaoEntity);
@ -490,4 +496,11 @@ public class LibaoDetailActivity extends BaseActivity implements LibaoDetailAdap
}
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBReuse reuse) {
if (reuse.getType().equals(LOGIN_TAG) && mLibaoEntity != null) { // 登入
getLibaoDigest(mLibaoEntity.getId());
}
}
}

View File

@ -1,5 +1,6 @@
package com.gh.gamecenter;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.app.NotificationManager;
import android.arch.lifecycle.ViewModelProviders;
@ -44,10 +45,12 @@ import com.gh.common.util.DirectUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.GsonUtils;
import com.gh.common.util.LogUtils;
import com.gh.common.util.LunchType;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.PlatformUtils;
import com.gh.common.util.PushHelper;
import com.gh.common.util.ThirdPartyPackageHelper;
import com.gh.common.util.UrlFilterUtils;
import com.gh.download.DownloadManager;
@ -70,6 +73,7 @@ import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.normal.NormalFragment;
import com.gh.gamecenter.packagehelper.PackageViewModel;
import com.gh.gamecenter.qa.AskFragment;
import com.gh.gamecenter.retrofit.BiResponse;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.gh.gamecenter.suggest.SuggestType;
@ -90,6 +94,7 @@ import com.tencent.bugly.crashreport.CrashReport;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;
import java.io.BufferedReader;
@ -259,10 +264,11 @@ public class MainActivity extends BaseActivity {
isNewFirstLaunch = mSp.getBoolean("isNewFirstLaunchV" + PackageUtils.getVersionName(), true);
if (isNewFirstLaunch) {
final LunchType lunchType = DeviceTokenUtils.getLaunchType();
// 延时两秒提交 APP 启动日志的,避免提交时还没获取到 GID
AppExecutor.getUiExecutor().executeWithDelay(() -> {
if (!this.isFinishing()) {
LogUtils.uploadDevice(DeviceTokenUtils.getLaunchType());
LogUtils.uploadDevice(lunchType);
}
}, 2000L);
getPluginUpdate();
@ -318,6 +324,10 @@ public class MainActivity extends BaseActivity {
if (getIntent() != null && getIntent().getExtras() != null && !isSkipped) {
doSkip();
}
handler.postDelayed(() -> {
PushHelper.postPushClickAction(this.getApplicationContext(), null);
}, 2000);
}
@Override
@ -337,7 +347,7 @@ public class MainActivity extends BaseActivity {
private void sendActivationInfo() {
RetrofitManager.getInstance(this)
.getApi().postBaiduActivationInfo()
.getApi().postActivationInfo()
.subscribeOn(Schedulers.io())
.subscribe(new Response<>());
}
@ -805,21 +815,15 @@ public class MainActivity extends BaseActivity {
for (GameDigestEntity gameDigestEntity : response) {
if (!TextUtils.isEmpty(gameDigestEntity.getId())) { // 关注游戏
if (finalDownloadEntity != null && gameDigestEntity.getId().equals(finalDownloadEntity.getGameId())) {
ConcernUtils.INSTANCE.postConcernGameId(MainActivity.this, gameDigestEntity.getId(), null, true);
ConcernUtils.INSTANCE.postConcernGameId(MainActivity.this, gameDigestEntity.getId(), null, false);
}
}
}
// 更新已安装游戏
RetrofitManager.getInstance(MainActivity.this).getApi()
.postPackage(UserManager.getInstance().getUserId(), packageName)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new Response<>());
}
});
}
postNewlyInstalledApp(packageName);
}
if ("卸载".equals(busFour.getType())) {
mPackageViewModel.addUninstalledGame(packageName);
@ -840,16 +844,58 @@ public class MainActivity extends BaseActivity {
}
// 更新已安装游戏
RetrofitManager.getInstance(this).getApi()
.deletePackage(UserManager.getInstance().getUserId(), packageName)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new Response<>());
deleteInstalledPackage(packageName);
}
DataCollectionUtils.uploadInorunstall(this, busFour.getType(), busFour.getPackageName());
}
@SuppressLint("CheckResult")
private void postNewlyInstalledApp(String packageName) {
JSONObject packageObject = PackageUtils.getAppBasicInfoByPackageName(packageName);
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"),
packageObject.toString());
// 更新已安装游戏
RetrofitManager.getInstance(MainActivity.this).getApi()
.postNewlyInstalledApp(HaloApp.getInstance().getGid(), requestBody)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new BiResponse<ResponseBody>() {
@Override
public void onSuccess(ResponseBody data) {
// do nothing
}
@Override
public void onFailure(@NotNull Exception exception) {
exception.printStackTrace();
}
});
}
@SuppressLint("CheckResult")
private void deleteInstalledPackage(String packageName) {
// 删除已安装游戏
RetrofitManager.getInstance(MainActivity.this).getApi()
.deleteInstalledApp(HaloApp.getInstance().getGid(), packageName)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new BiResponse<ResponseBody>() {
@Override
public void onSuccess(ResponseBody data) {
// do nothing
}
@Override
public void onFailure(@NotNull Exception exception) {
exception.printStackTrace();
}
});
}
// 接收登录和登出更新事件统计的 Meta
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBReuse reuse) {

View File

@ -24,6 +24,7 @@ import android.widget.TextView;
import com.gh.base.BaseActivity;
import com.gh.base.OnRequestCallBackListener;
import com.gh.common.history.HistoryHelper;
import com.gh.common.util.ApkActiveUtils;
import com.gh.common.util.CheckLoginUtils;
import com.gh.common.util.ClickUtils;
@ -46,6 +47,7 @@ import com.gh.gamecenter.eventbus.EBConcernChanged;
import com.gh.gamecenter.eventbus.EBDownloadStatus;
import com.gh.gamecenter.eventbus.EBNetworkState;
import com.gh.gamecenter.eventbus.EBPackage;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.newsdetail.NewsDetailAdapter;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
@ -66,6 +68,8 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;
import static com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG;
/**
* 文章详情页面 要启动该页面 需要传入一下参数 放入 EssayEntity中传过来 文章 id 文章标题 title 文章发表时间 time
@ -258,6 +262,8 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
if (mNewsEntity.getType() != null) {
setNavigationTitle(mNewsEntity.getType());
}
HistoryHelper.insertNewsEntity(mNewsEntity);
adapter.setId(mNewsEntity.getId());
adapter.setType(mNewsEntity.getType());
adapter.setTitle(mNewsEntity.getTitle());
@ -418,9 +424,7 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
@Override
protected void onResume() {
super.onResume();
if (gameEntity != null
&& gameEntity.getApk() != null
&& gameEntity.getApk().size() == 1) {
if (gameEntity != null && gameEntity.getApk().size() == 1) {
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), true);
}
DownloadManager.getInstance(this).addObserver(dataWatcher);
@ -487,6 +491,8 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
mNewsShare.setVisible(true);
HistoryHelper.insertNewsEntity(mNewsEntity);
DataUtils.onMtaEvent(NewsDetailActivity.this, "详情页面", "文章详情", response.getTitle());
}
@ -650,10 +656,7 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
// 接收下载被删除消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(EBDownloadStatus status) {
if ("delete".equals(status.getStatus())
&& gameEntity != null
&& gameEntity.getApk() != null
&& gameEntity.getApk().size() == 1) {
if ("delete".equals(status.getStatus()) && gameEntity != null && gameEntity.getApk().size() == 1) {
String url = gameEntity.getApk().get(0).getUrl();
if (url.equals(status.getUrl())) {
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), false);
@ -664,9 +667,7 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
// 接受安装、卸载消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBPackage busFour) {
if (gameEntity != null
&& gameEntity.getApk() != null
&& gameEntity.getApk().size() == 1) {
if (gameEntity != null && gameEntity.getApk().size() == 1) {
String packageName = gameEntity.getApk().get(0).getPackageName();
if (packageName.equals(busFour.getPackageName())) {
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), false);
@ -674,4 +675,11 @@ public class NewsDetailActivity extends BaseActivity implements OnClickListener,
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBReuse reuse) {
if (reuse.getType().equals(LOGIN_TAG) && adapter != null) { // 登入
adapter.getNewsDetail();
}
}
}

View File

@ -140,7 +140,7 @@ class PersonalHomeActivity : ListActivity<PersonalHistoryEntity, PersonalHomeVie
companion object {
@JvmStatic
fun startTargetActivity(context: Context, userId: String?, entrance: String, path: String?) {
fun startTargetActivity(context: Context, userId: String?, entrance: String?, path: String?) {
if (!userId.isNullOrEmpty()) {
val intent = Intent(context, PersonalHomeActivity::class.java)
intent.putExtra(EntranceUtils.KEY_USER_ID, userId)

View File

@ -7,6 +7,7 @@ import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentTransaction;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
@ -14,6 +15,7 @@ import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.gh.base.BaseActivity;
import com.gh.common.util.DataCollectionUtils;
@ -179,9 +181,7 @@ public class SearchActivity extends BaseActivity {
}
}
});
TextHelper.limitTheLengthOfEditText(searchInput, 50, () -> {
Utils.toast(searchInput.getContext(), "最多输入50个字");
});
searchInput.setFilters(new InputFilter[]{TextHelper.getFilter(50,"最多输入50个字")});
findViewById(R.id.btnGoBack).setOnClickListener(v -> finish());
}

View File

@ -19,7 +19,6 @@ import static com.gh.common.util.EntranceUtils.HOST_ANSWER;
import static com.gh.common.util.EntranceUtils.HOST_ARTICLE;
import static com.gh.common.util.EntranceUtils.HOST_COLUMN;
import static com.gh.common.util.EntranceUtils.HOST_COMMUNITY;
import static com.gh.common.util.EntranceUtils.HOST_COMMUNITY_ARTICLE;
import static com.gh.common.util.EntranceUtils.HOST_DOWNLOAD;
import static com.gh.common.util.EntranceUtils.HOST_GAME;
import static com.gh.common.util.EntranceUtils.HOST_QUESTION;
@ -103,7 +102,7 @@ public class SkipActivity extends BaseActivity {
}
startActivity(intent);
break;
case HOST_COMMUNITY_ARTICLE:
case "community.article":
DirectUtils.directToCommunityArticle(this, uri.getQueryParameter("articleId"), uri.getQueryParameter("communityId"), ENTRANCE_BROWSER);
break;
}

View File

@ -43,6 +43,7 @@ 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.ShareUtils;
import com.gh.common.util.UploadImageUtils;
import com.gh.gamecenter.entity.ErrorEntity;
import com.gh.gamecenter.entity.InstallGameEntity;
@ -60,6 +61,7 @@ import com.halo.assistant.HaloApp;
import com.lightgame.utils.Util_System_Keyboard;
import com.lightgame.utils.Util_System_Phone_State;
import com.lightgame.utils.Utils;
import com.walkud.rom.checker.RomIdentifier;
import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
@ -70,10 +72,10 @@ import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -137,6 +139,10 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
TextView mPlatformEt;
@BindView(R.id.suggest_platform_title)
TextView mPlatformTitle;
@BindView(R.id.suggest_link_et)
TextView mLinkEt;
@BindView(R.id.suggest_link_container)
View mLinkContainer;
public static final int MEDIA_STORE_REQUEST = 1;
public static final String SUGGESTION_HINT_TYPE = "SUGGESTION_HINT_TYPE";
@ -251,8 +257,8 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
MtaHelper.onEvent("广告位统计", "意见反馈_功能收录", ad.getTitle());
DirectUtils.directToLinkPage(this,
ad.toLinkEntity(),
"(意见反馈)",
"意见反馈-功能收录-广告位");
"(意见反馈-功能收录-广告位)",
"");
});
}
@ -366,6 +372,7 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
mPlatformContainer.setVisibility(View.GONE);
}
} else if (type == SuggestType.gameCollect) {
mLinkContainer.setVisibility(View.VISIBLE);
mSuggestGameLl.setVisibility(View.VISIBLE);
mGameNameTitle.setText(Html.fromHtml(getString(R.string.suggestion_game_name)));
mSuggestTypeContainer.setVisibility(View.GONE);
@ -605,7 +612,7 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
}
@Override
public void onSuccess(@NotNull Map<String, String> imageUrl) {
public void onSuccess(@NotNull LinkedHashMap<String, String> imageUrl) {
Utils.log("意见反馈:图片上传完成");
final JSONArray picArray = new JSONArray();
for (String s : imageUrl.keySet()) {
@ -637,6 +644,8 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
params.put("source", getString(R.string.app_name));
params.put("imei", Util_System_Phone_State.getDeviceId(this));
params.put("manufacturer", Build.MANUFACTURER);
params.put("rom", RomIdentifier.getRom().name() + " " + RomIdentifier.getRom().getVersionName());
params.put("link", mLinkEt.getText().toString());
params.put("suggestion_type", mSuggestType.getType());
String message;
@ -698,14 +707,12 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
if (postDialog != null) {
postDialog.dismissAllowingStateLoss();
}
toast("感谢您的反馈!");
setResult(SUGGEST_TYPE_REQUEST);
finish();
try {
Utils.log("sendSuggestion::onResponse->" + response.string());
} catch (IOException e) {
e.printStackTrace();
if (mHideHint.equals("APP闪退")) {
showKefuReportDialog();
} else {
toast("感谢您的反馈!");
finish();
}
}
@ -730,9 +737,10 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
} else if (error.getCode() == 403062) {
DialogUtils.showAlertDialog(SuggestionActivity.this,
"提示", "光环助手已收录游戏:" + error.getData().getGameName(),
"查看游戏", "仍然提交", () -> {
"退出并查看游戏", "仍然提交", () -> {
GameDetailActivity.startGameDetailActivity(SuggestionActivity.this,
error.getData().getGameId(), "(意见反馈-游戏收录-存在相同游戏)");
finish();
}, () -> {
try {
jsonObject.put("again", true);
@ -847,4 +855,35 @@ public class SuggestionActivity extends BaseActivity implements OnRequestCallBac
startActivityForResult(intent, MEDIA_STORE_REQUEST);
}
}
private void showKefuReportDialog() {
// 只有是APP闪退反馈成功后弹出联系客服的弹窗
String str = "您也可以联系客服进一步描述闪退的情况,如果您反馈的是新问题,即有机会获得红包奖励";
DialogUtils.showWarningDialog(SuggestionActivity.this, "反馈成功", Html.fromHtml(str.substring(0, str.indexOf("红包奖励")) + "<font color='#FF0000'>红包奖励</font>"), "暂不", "联系客服",
() -> {
if (ShareUtils.isQQClientAvailable(this)) {
finish();
DirectUtils.directToQqConversation(this, "2586716223");
} else {
toast("本机未安装QQ应用");
}
},
this::finish);
}
@Override
protected boolean handleBackPressed() {
if (!TextUtils.isEmpty(mSuggestContentEt.getText().toString()) ||
!TextUtils.isEmpty(mSuggestGameName.getText().toString()) ||
!TextUtils.isEmpty(mLinkEt.getText().toString()) ||
!TextUtils.isEmpty(mPlatformEt.getText().toString()) ||
mAdapter.getFileList().size() > 0 ||
mFunctionType != -1) {
DialogUtils.showAlertDialog(this, "提示",
"确定放弃反馈吗?", "继续反馈", "放弃",
null, this::finish);
return true;
}
return super.handleBackPressed();
}
}

View File

@ -114,7 +114,7 @@ public class CleanApkAdapter extends BaseRecyclerAdapter<KcSelectGameViewHolder>
appInfo.sourceDir = apk_path;
appInfo.publicSourceDir = apk_path;
Drawable apk_icon = appInfo.loadIcon(pm);
apkEntity.setGameBm(BitmapUtils.drawableToBitmap(apk_icon));
apkEntity.setGameBm(BitmapUtils.drawableToBitmap(apk_icon, true));
/** apk的绝对路劲 */
apkEntity.setGamePath(apk_path);
/** apk的版本名称 String */

View File

@ -201,8 +201,9 @@ public class InstallFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
if (this.gameList.size() != 0) {
isRemove = true;
notifyDataSetChanged();
initLocationMap();
mActivity.loadDone();
} else {
mActivity.loadEmpty();
}
@ -313,7 +314,7 @@ public class InstallFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
name = String.format("%s - %s", gameEntity.getName(),
PlatformUtils.getInstance(mContext).getPlatformName(gameEntity.getApk().get(0).getPlatform()));
holder.gameThumb.setImageDrawable(PackageUtils.getIconByPackage(mContext, gameEntity.getApk().get(0).getPackageName()));
holder.gameDes.setText(String.format("V%s", PackageUtils.getVersionByPackage(mContext, gameEntity.getApk().get(0).getPackageName())));
holder.gameDes.setText(String.format("V%s", PackageUtils.getVersionByPackage(gameEntity.getApk().get(0).getPackageName())));
} else {
name = gameEntity.getName();
ImageUtils.display(holder.gameThumb, gameEntity.getIcon());
@ -407,7 +408,7 @@ public class InstallFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
File file = new File(installedPackage.applicationInfo.sourceDir);
fileInfo.setSize(file.length());
Drawable drawable = installedPackage.applicationInfo.loadIcon(pm);
fileInfo.setBitmap(BitmapUtils.drawableToBitmap(drawable));
fileInfo.setBitmap(BitmapUtils.drawableToBitmap(drawable, true));
fileInfo.setFileTag(String.valueOf(System.currentTimeMillis()));
}
}

View File

@ -104,7 +104,7 @@ public class KcSelectGameAdapter extends BaseRecyclerAdapter<ViewHolder> {
installGameEntity.setGamePath(installedPackage.applicationInfo.sourceDir);
try {
Drawable drawable = installedPackage.applicationInfo.loadIcon(pm);
installGameEntity.setGameBm(BitmapUtils.drawableToBitmap(drawable));
installGameEntity.setGameBm(BitmapUtils.drawableToBitmap(drawable, true));
installGameEntity.setGameVersion(installedPackage.versionName);
installGameEntity.setGameName(installedPackage.applicationInfo.loadLabel(pm).toString());

View File

@ -245,7 +245,7 @@ public class LibaoDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
if (TextUtils.isEmpty(status)) {
LibaoUtils.getLibaoStatus(mContext, mLibaoEntity.getId(), new LibaoUtils.PostLibaoListener() {
@Override
public void postSucced(Object response) {
public void postSucceed(Object response) {
List<LibaoStatusEntity> statusList = (List<LibaoStatusEntity>) response;
if (statusList.size() != 0) {
mLibaoEntity.setStatus(statusList.get(0).getStatus());

View File

@ -314,7 +314,8 @@ public class PlatformAdapter extends BaseRecyclerAdapter<PlatformViewHolder> {
|| status.equals(DownloadStatus.timeout)
|| status.equals(DownloadStatus.neterror)
|| status.equals(DownloadStatus.downloading)
|| status.equals(DownloadStatus.waiting)) {
|| status.equals(DownloadStatus.waiting)
|| status.equals(DownloadStatus.overflow)) {
viewHolder.mDownloadItemTvStatus.setText(R.string.downloading);
} else if (status.equals(DownloadStatus.done)) {
viewHolder.mDownloadItemTvStatus.setText(R.string.install);

View File

@ -8,8 +8,6 @@ import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.gamecenter.R;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.SubjectEntity;
import butterknife.BindView;
@ -49,84 +47,4 @@ public class GameTestViewHolder extends GameViewHolder {
kaifuBottom = (TextView) itemView.findViewById(R.id.home2_game_kaifu_bottom);
}
// public void initGameTestViewHolder(Context context, GameFragmentAdapter adapter, List<SubjectEntity> subjectList,
// List<GameEntity> pluginList, int position,
// final OnGameTestItemClickListener onGameTestItemClickListener) {
// int offset = 1;
// if (!pluginList.isEmpty()) {
// offset += 1;
// }
// for (int i = 0, size = subjectList.size(); i < size; i++) {
// if (position > offset && position <= subjectList.get(i).getData().size() + offset) {
// final GameEntity gameEntity = subjectList.get(i).getData().get(position - offset - 1);
// if (gameEntity.getTest() != null) {
// int order = position - offset - 1;
// if (subjectList.get(i).getData().get(0).getImage() != null) {
// order--;
// }
// final SubjectEntity subjectEntity = subjectList.get(i);
// if (subjectEntity.isOrder()) {
// gameOrder.setVisibility(View.VISIBLE);
// gameOrder.setText(String.valueOf(order + 1));
// } else {
// gameOrder.setVisibility(View.GONE);
// }
//
// ImageUtils.Companion.display(gameThumb, gameEntity.getIcon());
// gameName.setText(gameEntity.getName());
// if (gameEntity.getApk() == null || gameEntity.getApk().isEmpty()) {
// gameDes.setText(gameEntity.getBrief());
// } else {
// gameDes.setText(String.format("%s %s", gameEntity.getApk().get(0).getSize(), gameEntity.getBrief()));
// }
//
// String type = gameEntity.getTest().getType();
// KaiFuUtils.setKaiFuType(gameTestType, type);
//
// if (gameEntity.getTest().getStart() == 0) {
// gameTestTime.setVisibility(View.GONE);
// } else {
// gameTestTime.setText(GameViewUtils.getGameTestDate(gameEntity.getTest().getStart()));
// }
//
// final int finalI = i;
// itemView.setOnClickListener(new OnClickListener() {
// @Override
// public void onClick(View v) {
// if (onGameTestItemClickListener != null) {
// onGameTestItemClickListener.onClick(gameEntity, subjectEntity, finalI);
// }
// }
// });
//
// if (gameEntity.getTest().getEnd() != 0) {
// long endTime = Long.valueOf(gameEntity.getTest().getEnd() + "000");
// long todayTime = new Date().getTime();
// if (todayTime > endTime) {
// // 测试时间已过
// gameEntity.setApk(null);
// }
// }
//
// DownloadItemUtils.setOnClickListener(context,
// gameDownloadBtn, gameEntity, i, adapter,
// StringUtils.buildString("(游戏-专题:",
// subjectEntity.getName(), "-列表[", String.valueOf(i + 1), "])"),
// StringUtils.buildString("游戏-专题-",
// subjectEntity.getName(), ":", gameEntity.getName()));
//
// DownloadItemUtils.updateItem(context, gameEntity, this, true);
//// adapter.initGameTest(this, gameEntity, order, subjectEntity);
// break;
// }
// }
// offset = subjectList.get(i).getData().size() + offset + 1;
// }
// }
public interface OnGameTestItemClickListener {
void onClick(GameEntity gameEntity, SubjectEntity subjectEntity, int position);
}
}

View File

@ -0,0 +1,11 @@
package com.gh.gamecenter.adapter.viewholder
import android.view.View
import android.widget.TextView
import com.gh.base.BaseRecyclerViewHolder
import com.gh.gamecenter.R
import kotterknife.bindView
class ListSectionItemViewHolder(view: View) : BaseRecyclerViewHolder<Any>(view) {
val sectionTitle by bindView<TextView>(R.id.list_section_title)
}

View File

@ -23,6 +23,7 @@ import java.util.List;
import butterknife.BindView;
import io.reactivex.Observable;
import io.reactivex.Single;
public abstract class ListActivity<T, VM extends BaseListViewModel /* 该泛型位置对应getViewModelClass */>
extends BaseActivity
@ -144,6 +145,11 @@ public abstract class ListActivity<T, VM extends BaseListViewModel /* 该泛型
return null;
}
@Override
public Single<List> provideDataSingle(int page) {
return null;
}
public void onLoadRefresh() {
mReuseNoConn.setVisibility(View.GONE);
mReuseNoData.setVisibility(View.GONE);

View File

@ -24,6 +24,7 @@ import java.util.List;
import butterknife.BindView;
import io.reactivex.Observable;
import io.reactivex.Single;
/**
* Created by khy on 2/12/17.
@ -161,6 +162,11 @@ public abstract class ListFragment<T, VM extends BaseListViewModel /* 该泛型
return null;
}
@Override
public Single<List<T>> provideDataSingle(int page) {
return null;
}
public void onLoadRefresh() {
mReuseNoConn.setVisibility(View.GONE);
mReuseNoData.setVisibility(View.GONE);

View File

@ -1,5 +1,6 @@
package com.gh.gamecenter.baselist;
import android.annotation.SuppressLint;
import android.app.Application;
import android.arch.lifecycle.MutableLiveData;
import android.support.annotation.NonNull;
@ -7,13 +8,17 @@ import android.support.annotation.NonNull;
import com.gh.common.util.ApkActiveUtils;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.retrofit.BiResponse;
import com.gh.gamecenter.retrofit.Response;
import com.halo.assistant.HaloApp;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;
@ -42,14 +47,16 @@ public abstract class ListViewModel<LD /*ListData*/, ID /*ItemData*/> extends Ba
mOverLimitSize = mCurLoadParams.getLoadSize() / 2;
}
@SuppressLint("CheckResult")
protected void loadData() {
if (mCurLoadParams == null) initLoadParams();
LoadParams loadParams = mRetryParams != null ? mRetryParams : mCurLoadParams;
Observable<List<LD>> listObservable = provideDataObservable(loadParams.getLoadOffset());
Single<List<LD>> listSingle = provideDataSingle(loadParams.getLoadOffset());
LoadStatus curStatus = mLoadStatusLiveData.getValue();
if (listObservable == null || curStatus != null &&
if ((listObservable == null && listSingle == null) || curStatus != null &&
curStatus != LoadStatus.INIT_LOADED &&
curStatus != LoadStatus.LIST_LOADED &&
curStatus != LoadStatus.INIT) return;
@ -60,43 +67,86 @@ public abstract class ListViewModel<LD /*ListData*/, ID /*ItemData*/> extends Ba
mLoadStatusLiveData.setValue(LoadStatus.LIST_LOADING);
}
listObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<List<LD>>() {
@Override
public void onResponse(List<LD> response) {
List<LD> previousData = mListLiveData.getValue();
if (previousData == null || mCurLoadParams.getLoadOffset() == LoadParams.DEFAULT_OFFSET ||
curStatus == LoadStatus.INIT) {
previousData = new ArrayList<>();
if (listObservable != null) {
listObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(this::filterData)
.subscribe(new Response<List<LD>>() {
@Override
public void onResponse(List<LD> response) {
List<LD> previousData = mListLiveData.getValue();
if (previousData == null || mCurLoadParams.getLoadOffset() == LoadParams.DEFAULT_OFFSET ||
curStatus == LoadStatus.INIT) {
previousData = new ArrayList<>();
}
// 针对游戏的一些操作(过滤隐藏APK,增加下载数据)
if (response.size() > 0 && response.get(0) instanceof GameEntity) {
for (LD entity : response) {
GameEntity game = (GameEntity) entity;
game.setEntryMap(DownloadManager.getInstance(HaloApp.getInstance()
.getApplication()).getEntryMap(game.getName()));
ApkActiveUtils.filterHideApk(game);
}
}
previousData.addAll(response);
mListLiveData.postValue(previousData);
loadStatusControl(response.size());
}
// 针对游戏的一些操作(过滤隐藏APK,增加下载数据)
if (response.size() > 0 && response.get(0) instanceof GameEntity) {
for (LD entity : response) {
GameEntity game = (GameEntity) entity;
game.setEntryMap(DownloadManager.getInstance(HaloApp.getInstance()
.getApplication()).getEntryMap(game.getName()));
ApkActiveUtils.filterHideApk(game);
@Override
public void onFailure(HttpException e) {
if (e != null && e.code() == 404) {
loadStatusControl(0);
} else {
loadStatusControl(REQUEST_FAILURE_SIZE);
mLoadExceptionLiveData.postValue(e);
}
}
});
} else if (listSingle != null) {
listSingle.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(this::filterData)
.subscribe(new BiResponse<List<LD>>() {
@Override
public void onFailure(@NotNull Exception exception) {
if (exception instanceof HttpException && ((HttpException) exception).code() == 404) {
loadStatusControl(0);
} else {
loadStatusControl(REQUEST_FAILURE_SIZE);
if (exception instanceof HttpException) {
mLoadExceptionLiveData.postValue((HttpException) exception);
}
}
}
previousData.addAll(response);
mListLiveData.postValue(previousData);
loadStatusControl(response.size());
}
@Override
public void onSuccess(List<LD> response) {
List<LD> previousData = mListLiveData.getValue();
if (previousData == null || mCurLoadParams.getLoadOffset() == LoadParams.DEFAULT_OFFSET ||
curStatus == LoadStatus.INIT) {
previousData = new ArrayList<>();
}
@Override
public void onFailure(HttpException e) {
if (e != null && e.code() == 404) {
loadStatusControl(0);
} else {
loadStatusControl(REQUEST_FAILURE_SIZE);
mLoadExceptionLiveData.postValue(e);
// 针对游戏的一些操作(过滤隐藏APK,增加下载数据)
if (response.size() > 0 && response.get(0) instanceof GameEntity) {
for (LD entity : response) {
GameEntity game = (GameEntity) entity;
game.setEntryMap(DownloadManager.getInstance(HaloApp.getInstance()
.getApplication()).getEntryMap(game.getName()));
ApkActiveUtils.filterHideApk(game);
}
}
previousData.addAll(response);
mListLiveData.postValue(previousData);
loadStatusControl(response.size());
}
}
});
});
}
}
protected void loadStatusControl(int size) {
@ -147,9 +197,18 @@ public abstract class ListViewModel<LD /*ListData*/, ID /*ItemData*/> extends Ba
loadData();
}
@Override
public Single<List<LD>> provideDataSingle(int page) {
return null;
}
protected abstract void mergeResultLiveData();
public MutableLiveData<HttpException> getLoadExceptionLiveData() {
return mLoadExceptionLiveData;
}
protected List<LD> filterData(@NonNull List<LD> list) {
return list;
}
}

View File

@ -8,6 +8,7 @@ import android.support.annotation.NonNull;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.Single;
/**
* Created by khy on 21/03/18.
@ -35,6 +36,11 @@ public class NormalListViewModel<T> extends ListViewModel<T, T> {
return mDataObservable.provideDataObservable(offset);
}
@Override
public Single<List<T>> provideDataSingle(int page) {
return mDataObservable.provideDataSingle(page);
}
public static class Factory extends ViewModelProvider.NewInstanceFactory {
@NonNull
private final Application mApplication;

View File

@ -3,6 +3,7 @@ package com.gh.gamecenter.baselist;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.Single;
/**
@ -11,4 +12,8 @@ import io.reactivex.Observable;
public interface OnDataObservable<T> {
Observable<List<T>> provideDataObservable(int page);
// 一般的网络请求只有成功或失败两种情况,并不会有 onNext 所以主流是使用 single ,
// 譬如 room 的 rxjava 支持就只支持 single 不支持 observable 所以这里增加了个 single 来供那些既兼容网络数据又兼容 room 数据的页面
Single<List<T>> provideDataSingle(int page);
}

View File

@ -13,9 +13,12 @@ import com.gh.gamecenter.R
import com.gh.gamecenter.baselist.ListAdapter
import com.gh.gamecenter.databinding.ItemCategoryBinding
import com.gh.gamecenter.entity.CategoryEntity
import net.cachapa.expandablelayout.ExpandableLayout
class CategoryDirectoryAdapter(context: Context, var categoryTitle: String) : ListAdapter<CategoryEntity>(context) {
class CategoryDirectoryAdapter(context: Context, var categoryTitle: String)
: ListAdapter<CategoryEntity>(context) {
var recyclerView: RecyclerView? = null
var expandStatusMap: HashMap<Int, Boolean> = HashMap()
private var sixteenDp: Int = 0
@ -39,13 +42,19 @@ class CategoryDirectoryAdapter(context: Context, var categoryTitle: String) : Li
expandableStatusMap = expandStatusMap,
isExpended = expandStatusMap[position] != null && expandStatusMap[position] == true,
marginTop = sixteenDp,
categoryTitle = categoryTitle)
categoryTitle = categoryTitle,
expandedAction = { recyclerView?.smoothScrollToPosition(position) })
}
}
}
internal class CategoryViewHolder(var binding: ItemCategoryBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindCategory(category: CategoryEntity, expandableStatusMap: HashMap<Int, Boolean>, isExpended: Boolean, marginTop: Int, categoryTitle: String) {
fun bindCategory(category: CategoryEntity,
expandableStatusMap: HashMap<Int, Boolean>,
isExpended: Boolean,
marginTop: Int,
categoryTitle: String,
expandedAction: () -> Unit) {
category.data?.let {
var subCategoryView: SubCategoryView? = null
@ -91,13 +100,14 @@ class CategoryDirectoryAdapter(context: Context, var categoryTitle: String) : Li
binding.containerExpandable.setExpanded(isExpended, false)
binding.containerExpandable.setOnExpansionUpdateListener { _, state ->
when (state) {
0 -> {
ExpandableLayout.State.COLLAPSED -> {
binding.ivToggle.setImageResource(R.drawable.ic_category_arrow_down)
expandableStatusMap[adapterPosition] = false
}
3 -> {
ExpandableLayout.State.EXPANDED -> {
binding.ivToggle.setImageResource(R.drawable.ic_category_arrow_up)
expandableStatusMap[adapterPosition] = true
expandedAction.invoke()
}
}
}

View File

@ -39,6 +39,7 @@ class CategoryDirectoryFragment : ListFragment<CategoryEntity, CategoryDirectory
super.onViewCreated(view, savedInstanceState)
setNavigationTitle(arguments?.getString(EntranceUtils.KEY_CATEGORY_TITLE))
mListRv.setBackgroundColor(Color.WHITE)
mAdapter.recyclerView = mListRv
mListRefresh?.isEnabled = false
mSkeleton = Skeleton.bind(mListSkeleton).shimmer(false).load(R.layout.fragment_category_skeleton).show()
}

View File

@ -2,6 +2,7 @@ package com.gh.gamecenter.category;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.ContextCompat;
import android.support.v4.util.ArrayMap;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
@ -20,7 +21,6 @@ import com.gh.common.util.DataCollectionUtils;
import com.gh.common.util.DownloadItemUtils;
import com.gh.common.util.GameViewUtils;
import com.gh.common.util.ImageUtils;
import com.gh.common.util.KaiFuUtils;
import com.gh.common.util.NewsUtils;
import com.gh.common.util.StringUtils;
import com.gh.download.DownloadManager;
@ -341,8 +341,8 @@ public class CategoryListAdapter extends BaseRecyclerAdapter<RecyclerView.ViewHo
holder.gameTestTime.setText(GameViewUtils.getGameTestDate(gameEntity.getTest().getStart()));
}
String type = gameEntity.getTest().getType();
KaiFuUtils.setKaiFuType(holder.gameTestType, type);
holder.gameTestType.setText(gameEntity.getTest().getType());
holder.gameTestType.setBackgroundColor(ContextCompat.getColor(mContext, R.color.tag_yellow));
ArrayList<ExposureSource> exposureSources = new ArrayList<>();
exposureSources.add(new ExposureSource(mTitle, mName));

View File

@ -2,6 +2,7 @@ package com.gh.gamecenter.collection;
import android.view.View;
import com.gh.common.history.HistoryDatabase;
import com.gh.common.util.CollectionUtils;
import com.gh.common.util.DialogUtils;
import com.gh.gamecenter.R;
@ -22,7 +23,7 @@ import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.Single;
/**
* Created by khy on 22/12/17.
@ -31,6 +32,13 @@ import io.reactivex.Observable;
public class AnswerFragment extends ListFragment<AnswerEntity, NormalListViewModel> {
private AnswerAdapter mAdapter;
private Type mType;
public static AnswerFragment getInstance(Type type) {
AnswerFragment fragment = new AnswerFragment();
fragment.mType = type;
return fragment;
}
@Override
protected ListAdapter provideListAdapter() {
@ -38,8 +46,12 @@ public class AnswerFragment extends ListFragment<AnswerEntity, NormalListViewMod
}
@Override
public Observable<List<AnswerEntity>> provideDataObservable(int page) {
return RetrofitManager.getInstance(getContext()).getApi().getCollectionAnswer(UserManager.getInstance().getUserId(), page);
public Single<List<AnswerEntity>> provideDataSingle(int page) {
if (mType == Type.COLLECTION) {
return Single.fromObservable(RetrofitManager.getInstance(getContext()).getApi().getCollectionAnswer(UserManager.getInstance().getUserId(), page));
} else {
return HistoryDatabase.Companion.getInstance().answerDao().getAnswersWithOffset(20, (page - 1) * 20);
}
}
@Override
@ -95,4 +107,10 @@ public class AnswerFragment extends ListFragment<AnswerEntity, NormalListViewMod
mListViewModel.load(LoadType.REFRESH);
}
}
public enum Type {
COLLECTION,
HISTORY
}
}

View File

@ -22,8 +22,22 @@ import org.greenrobot.eventbus.ThreadMode;
public class ArticleFragment extends ListFragment<NewsEntity, ArticleViewModel> {
private Type mType;
private ArticleAdapter mAdapter;
public static ArticleFragment getInstance(Type type) {
ArticleFragment fragment = new ArticleFragment();
fragment.mType = type;
return fragment;
}
@Override
protected ArticleViewModel provideListViewModel() {
ArticleViewModel viewModel = super.provideListViewModel();
viewModel.type = mType;
return viewModel;
}
@Override
protected ListAdapter provideListAdapter() {
return mAdapter == null ? mAdapter = new ArticleAdapter(getContext(), this) : mAdapter;
@ -37,20 +51,24 @@ public class ArticleFragment extends ListFragment<NewsEntity, ArticleViewModel>
}
}
@Override
public void onListClick(View view, int position, Object data) {
NewsEntity newsEntity = (NewsEntity) data;
if (!newsEntity.getActive()) {
showDeleteDialog(newsEntity.getId());
return;
if (mType == Type.COLLECTION) {
if (!newsEntity.getActive()) {
showDeleteDialog(newsEntity.getId());
return;
}
DataCollectionUtils.uploadClick(getContext(), "列表", "收藏-文章", newsEntity.getTitle());
NewsDetailActivity.startNewsDetailByCollection(getContext(), newsEntity, "(收藏:文章)");
} else {
DataCollectionUtils.uploadClick(getContext(), "列表", "浏览记录-文章", newsEntity.getTitle());
NewsDetailActivity.startNewsDetailByCollection(getContext(), newsEntity, "(浏览记录:文章)");
}
DataCollectionUtils.uploadClick(getContext(), "列表", "收藏-文章", newsEntity.getTitle());
//统计阅读量
mAdapter.statNewsViews(newsEntity, position);
NewsDetailActivity.startNewsDetailByCollection(getContext(), newsEntity, "(收藏:文章)");
}
private void showDeleteDialog(String articleId) {
@ -71,4 +89,10 @@ public class ArticleFragment extends ListFragment<NewsEntity, ArticleViewModel>
}
}), null);
}
public enum Type {
COLLECTION,
HISTORY
}
}

View File

@ -4,6 +4,7 @@ import android.app.Application;
import android.arch.lifecycle.LiveData;
import android.support.annotation.NonNull;
import com.gh.common.history.HistoryDatabase;
import com.gh.gamecenter.baselist.ListViewModel;
import com.gh.gamecenter.entity.NewsEntity;
import com.gh.gamecenter.entity.ViewsEntity;
@ -14,6 +15,7 @@ import com.gh.gamecenter.retrofit.RetrofitManager;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.Single;
/**
* Created by khy on 30/03/18.
@ -21,6 +23,7 @@ import io.reactivex.Observable;
public class ArticleViewModel extends ListViewModel<NewsEntity, NewsEntity> {
public ArticleFragment.Type type;
NewsViewsRepository<ViewsEntity> mNewsViewsRepository = new NewsViewsRepository<>();
@ -66,8 +69,17 @@ public class ArticleViewModel extends ListViewModel<NewsEntity, NewsEntity> {
}
@Override
public Single<List<NewsEntity>> provideDataSingle(int page) {
if (type == ArticleFragment.Type.COLLECTION) {
return Single.fromObservable(RetrofitManager.getInstance(getApplication()).getApi().getCollectionArticle(UserManager.getInstance().getUserId(), page));
} else {
return HistoryDatabase.Companion.getInstance().newsDao().getNewsWithOffset(20, (page - 1) * 20);
}
}
@Override
public Observable<List<NewsEntity>> provideDataObservable(int page) {
return RetrofitManager.getInstance(getApplication()).getApi().getCollectionArticle(UserManager.getInstance().getUserId(), page);
return null;
}
}

View File

@ -37,10 +37,10 @@ public class CollectionWrapperFragment extends BaseFragment_TabLayout {
@Override
protected void initFragmentList(List<Fragment> fragments) {
fragments.add(new AnswerFragment());
fragments.add(new CommunityArticleFragment());
fragments.add(AnswerFragment.getInstance(AnswerFragment.Type.COLLECTION));
fragments.add(CommunityArticleFragment.getInstance(CommunityArticleFragment.Type.COLLECTION));
fragments.add(new ToolsFragment());
fragments.add(new ArticleFragment());
fragments.add(ArticleFragment.getInstance(ArticleFragment.Type.COLLECTION));
for (Fragment fragment : mFragmentsList) {
fragment.setArguments(getArguments());
}

View File

@ -5,16 +5,14 @@ import com.gh.common.util.CollectionUtils
import com.gh.gamecenter.baselist.ListFragment
import com.gh.gamecenter.baselist.LoadType
import com.gh.gamecenter.eventbus.EBCollectionChanged
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.qa.entity.ArticleEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import io.reactivex.Observable
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
class CommunityArticleFragment : ListFragment<ArticleEntity, CommunityArticleViewModel>() {
var mAdapter: CommunityArticleAdapter? = null
private var mType = Type.COLLECTION
private var mAdapter: CommunityArticleAdapter? = null
override fun provideListAdapter(): CommunityArticleAdapter {
if (mAdapter == null) {
@ -24,18 +22,30 @@ class CommunityArticleFragment : ListFragment<ArticleEntity, CommunityArticleVie
}
override fun provideListViewModel(): CommunityArticleViewModel {
return ViewModelProviders.of(this).get(CommunityArticleViewModel::class.java)
}
override fun provideDataObservable(page: Int): Observable<MutableList<ArticleEntity>> {
return RetrofitManager.getInstance(context).api.getCollectionCommunityArticle(UserManager.getInstance().userId, page)
return ViewModelProviders.of(this).get(CommunityArticleViewModel::class.java).apply { type = mType }
}
// 收藏事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(changed: EBCollectionChanged) {
if (changed.collectionType == CollectionUtils.CollectionType.communityArticle) {
if (changed.collectionType == CollectionUtils.CollectionType.communityArticle
&& mType == Type.COLLECTION) {
mListViewModel.load(LoadType.REFRESH)
}
}
companion object {
@JvmStatic
fun getInstance(type: Type): CommunityArticleFragment {
val fragment = CommunityArticleFragment()
fragment.mType = type
return fragment
}
}
enum class Type {
COLLECTION,
HISTORY
}
}

View File

@ -2,6 +2,7 @@ package com.gh.gamecenter.collection
import android.app.Application
import anet.channel.util.Utils.context
import com.gh.common.history.HistoryDatabase
import com.gh.gamecenter.R
import com.gh.gamecenter.baselist.ListViewModel
import com.gh.gamecenter.manager.UserManager
@ -10,6 +11,7 @@ import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.lightgame.utils.Utils
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
@ -18,9 +20,18 @@ import retrofit2.HttpException
class CommunityArticleViewModel(application: Application) : ListViewModel<ArticleEntity, ArticleEntity>(application) {
var type: CommunityArticleFragment.Type = CommunityArticleFragment.Type.COLLECTION
override fun provideDataObservable(page: Int): Observable<MutableList<ArticleEntity>>? {
return RetrofitManager.getInstance(context).api.getCollectionCommunityArticle(UserManager.getInstance().userId, page)
return null
}
override fun provideDataSingle(page: Int): Single<List<ArticleEntity>> {
return if (type == CommunityArticleFragment.Type.COLLECTION) {
Single.fromObservable(RetrofitManager.getInstance(context).api.getCollectionCommunityArticle(UserManager.getInstance().userId, page))
} else {
HistoryDatabase.instance.articleDao().getArticleWithOffset(20, (page - 1) * 20)
}
}
override fun mergeResultLiveData() {

View File

@ -2,6 +2,7 @@ package com.gh.gamecenter.discover
import android.databinding.DataBindingUtil
import android.os.Bundle
import android.support.v4.content.ContextCompat
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
@ -59,10 +60,10 @@ class DiscoverFragment : BaseFragment<Any>() {
lp.width = ViewGroup.LayoutParams.MATCH_PARENT
if (index % 2 == 0) {
lp.height = DisplayUtils.dip2px(0.5F)
view.setBackgroundColor(resources.getColor(R.color.cutting_line))
divider.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.cutting_line))
} else {
lp.height = DisplayUtils.dip2px(8f)
view.setBackgroundColor(resources.getColor(R.color.background))
divider.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.background))
}
divider.layoutParams = lp
@ -79,7 +80,7 @@ class DiscoverFragment : BaseFragment<Any>() {
discoverAdView.setOnClickListener {
MtaHelper.onEvent("发现", "广告-${ad.title}")
MtaHelper.onEvent("广告位统计", "发现_功能列表", ad.title)
DirectUtils.directToLinkPage(requireContext(), ad.toLinkEntity(), "(首页:发现)", "发现-广告位")
DirectUtils.directToLinkPage(requireContext(), ad.toLinkEntity(), "(发现-广告位)", "")
}
mDiscoverContainer.addView(discoverAdView)
}

View File

@ -136,7 +136,7 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
ApplicationInfo appInfo = info.applicationInfo;
appInfo.sourceDir = apkPath;
appInfo.publicSourceDir = apkPath;
Bitmap bitmap = BitmapUtils.drawableToBitmap(appInfo.loadIcon(pm));
Bitmap bitmap = BitmapUtils.drawableToBitmap(appInfo.loadIcon(pm), true);
viewHolder.dmIcon.setImageBitmap(bitmap);
}
} catch (JSONException e) {
@ -147,7 +147,7 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
// viewHolder.dmIcon.setImageURI(icon);
ImageUtils.display(viewHolder.dmIcon, icon);
} else {
ImageUtils.display(viewHolder.dmIcon, R.drawable.logo);
ImageUtils.display(viewHolder.dmIcon, R.mipmap.logo);
}
String downloadTitle;
@ -238,6 +238,17 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
} else {
viewHolder.dmDownloads.setText("已暂停");
}
} else if (status.equals(DownloadStatus.overflow)) {
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
viewHolder.dmDownloads.setLayoutParams(lparams);
viewHolder.dmDownloads.setTextColor(mContext.getResources().getColor(R.color.red));
viewHolder.dmDownloads.setText("数据异常,请重新下载");
viewHolder.dmDelete.setVisibility(View.VISIBLE);
viewHolder.dmStartorpause.setBackgroundResource(R.drawable.game_item_btn_pause_style);
viewHolder.dmStartorpause.setText("失败");
viewHolder.dmStartorpause.setTextColor(Color.WHITE);
viewHolder.dmSpeed.setText(downloadEntity.getPercent() + "%");
}
viewHolder.dmProgressbar.setProgress((int) (downloadEntity.getPercent() * 10));
@ -326,6 +337,13 @@ class GameDownloadFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
PackageUtils.launchApplicationByPackageName(mContext, downloadEntity.getPackageName());
break;
case "失败":
DialogUtils.showAlertDialog(mContext
, "下载失败"
, "安装包数据校验失败,无法完成下载,建议删除任务重新下载"
, "知道了", null, null, null);
break;
}
DataUtils.onMtaEvent(HaloApp.getInstance().getApplication(), "下载管理", "游戏下载", str);

View File

@ -296,7 +296,7 @@ class GameUpdateFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
final GameUpdateEntity updateEntity = updateList.get(position - 1);
if (updateEntity.getName().contains("光环助手")) {
ImageUtils.display(viewHolder.guIcon, R.drawable.logo);
ImageUtils.display(viewHolder.guIcon, R.mipmap.logo);
} else {
ImageUtils.display(viewHolder.guIcon, updateEntity.getIcon());
}
@ -318,8 +318,7 @@ class GameUpdateFragmentAdapter extends BaseRecyclerAdapter<ViewHolder> {
viewHolder.guName.postDelayed(() -> viewHolder.guName.setSelected(true), 2000);
}
String currentVersion = PackageUtils.getVersionByPackage(
mContext, updateEntity.getPackageName());
String currentVersion = PackageUtils.getVersionByPackage(updateEntity.getPackageName());
if (TextUtils.isEmpty(currentVersion)) {
viewHolder.guCurrent.setText("当前:无");
} else {

View File

@ -4,4 +4,4 @@ import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
@Parcelize
data class ColorEntity(var color: String, var value: String): Parcelable
data class ColorEntity(var color: String = "", var value: String = ""): Parcelable

View File

@ -51,8 +51,8 @@ class GameDetailEntity : Parcelable {
var notice: MutableList<NewsEntity>? = null
@SerializedName("type_tag")
var gameTag: List<String>? = null
@SerializedName("tag_style")
var tagStyle: ArrayList<TagStyleEntity> = ArrayList()
@SerializedName("server")
var serverEntity: GameDetailServer? = null
@ -113,7 +113,7 @@ class GameDetailEntity : Parcelable {
dest.writeByte(if (this.isSkinTest) 1.toByte() else 0.toByte())
dest.writeParcelable(this.contact, flags)
dest.writeTypedList(this.notice)
dest.writeStringList(this.gameTag)
dest.writeTypedList(this.tagStyle)
dest.writeParcelable(this.serverEntity, flags)
dest.writeTypedList(this.relatedGames)
dest.writeString(this.fulishuoming)
@ -124,7 +124,7 @@ class GameDetailEntity : Parcelable {
protected constructor(`in`: Parcel) {
this.tag = `in`.createTypedArrayList(TagEntity.CREATOR)
this.tips = `in`.readParcelable<TipsEntity>(TipsEntity::class.java.classLoader)
this.tips = `in`.readParcelable(TipsEntity::class.java.classLoader)
this.news = `in`.createTypedArrayList(NewsEntity.CREATOR)
this.gallery = `in`.createStringArrayList()
this.des = `in`.readString()
@ -133,13 +133,13 @@ class GameDetailEntity : Parcelable {
this.shareCode = `in`.readString()
this.downloadOffText = `in`.readString()
this.isSkinTest = `in`.readByte().toInt() != 0
this.contact = `in`.readParcelable<GameDetailContact>(GameDetailContact::class.java.classLoader)
this.contact = `in`.readParcelable(GameDetailContact::class.java.classLoader)
this.notice = `in`.createTypedArrayList(NewsEntity.CREATOR)
this.gameTag = `in`.createStringArrayList()
this.serverEntity = `in`.readParcelable<GameDetailServer>(GameDetailServer::class.java.classLoader)
this.tagStyle = `in`.createTypedArrayList(TagStyleEntity.CREATOR)
this.serverEntity = `in`.readParcelable(GameDetailServer::class.java.classLoader)
this.relatedGames = `in`.createTypedArrayList(GameDetailRelatedGame.CREATOR)
this.fulishuoming = `in`.readString()
this.me = `in`.readParcelable<MeEntity>(MeEntity::class.java.classLoader)
this.me = `in`.readParcelable(MeEntity::class.java.classLoader)
}
companion object {

View File

@ -12,68 +12,100 @@ import kotlinx.android.parcel.Parcelize
@Parcelize
data class GameEntity(
@SerializedName("_id")
var id: String? = null,
var id: String = "",
var icon: String? = null,
var name: String? = null,
@SerializedName("name")
private var mName: String? = null, // 将 name 变成私有 mName 调用 name 时直接拼接成 mName + nameSuffix
@SerializedName("name_suffix")
var nameSuffix: String = "",
var brief: String? = null,
private var tag: ArrayList<String>? = null,
private var apk: ArrayList<ApkEntity>? = null,
@SerializedName("apk_normal")
private var apkNormal: ArrayList<ApkEntity>? = null,
@SerializedName("apk_search")
var apkSearch: ArrayList<ApkEntity>? = null,
@SerializedName("apk_index")
var apkIndex: ArrayList<ApkEntity>? = null,
var collection: ArrayList<GameCollectionEntity> = ArrayList(),
var slide: String? = null,
var test: TestEntity? = null,
@SerializedName("d_button_add_word")
var downloadAddWord: String? = null,
var image: String? = null,
var type: String? = null,
var isPluggable: Boolean = false,
var link: String? = null,
@SerializedName("apk_link")
var apkLink: ArrayList<ApkLink>? = null,
@SerializedName("concern_article_exists")
var isNewsExists: Boolean = true,
@SerializedName("download_off_text")
var downloadOffText: String? = null,
@SerializedName("libao_exists")
var isLibaoExists: Boolean = false,
@SerializedName("server_remark")
var serverRemark: String? = null,
@SerializedName("server_type")
var serverType: String? = null,
@SerializedName("server_label")
var serverLabel: ColorEntity? = null,
@SerializedName("server")
var serverEntity: KaiFuCalendarEntity? = null,
@SerializedName("server_genre")
var serverGenre: String? = null,
var kaifuTimeHint: Long? = null,
var subjectData: GameSubjectData? = null,
@SerializedName("tag_style")
var tagStyle: List<TagStyleEntity> = ArrayList(),
var tagStyle: ArrayList<TagStyleEntity> = ArrayList(),
var des: String? = null,
// 用来标记在专题中的序号,仅用于曝光记录
var sequence: Int? = -1,
// 用来标记平台名称,仅用于曝光记录
var platform: String? = "",
// 用来标记下载的类型,仅用于曝光记录
@SerializedName("download_type")
var downloadType: String? = "",
// 用来标记下载完成的类型,仅用于曝光记录
@SerializedName("download_complete_type")
var downloadCompleteType: String? = "",
// 用于开服表标记是否为置顶项目
@SerializedName("is_fixed_top")
var fixedTop: Boolean? = false,
var fixedTopHint: Boolean? = false,
@SerializedName("download_notice")
val downloadAd: LinkEntity? = null,
// 社区名字,用于首页替换游戏曝光时使用
var subjectName: String? = null) : Parcelable {
var subjectName: String? = null,
// 关联应用,供首页替换游戏确定该游戏是否应该被替换使用
@SerializedName("relation_game_ids")
var relatedGameIds: ArrayList<String>? = arrayListOf(),
@SerializedName("is_related")
var isRelated: Boolean = false) : Parcelable {
@IgnoredOnParcel
private var entryMap: ArrayMap<String, DownloadEntity>? = ArrayMap()
@ -81,13 +113,24 @@ data class GameEntity(
@IgnoredOnParcel
var gameLocation: GameLocation? = null
constructor(id: String?) : this() {
@IgnoredOnParcel
var name: String?
get() = mName + nameSuffix
set(value) {
mName = value
}
@IgnoredOnParcel
val nameWithoutSuffix: String?
get() = mName
constructor(id: String) : this() {
this.id = id
}
constructor(id: String?, name: String?) : this() {
constructor(id: String, name: String?) : this() {
this.id = id
this.name = name
this.mName = name
}
fun getTag(): ArrayList<String> {
@ -143,7 +186,7 @@ data class GameEntity(
val gameEntity = GameEntity()
gameEntity.id = id
gameEntity.icon = icon
gameEntity.name = name
gameEntity.mName = name
gameEntity.brief = brief
if (tag != null) {
gameEntity.tag = ArrayList(tag!!)

View File

@ -32,7 +32,7 @@ data class GameUpdateEntity(
fun transformGameEntity(): GameEntity {
val gameEntity = GameEntity()
gameEntity.id = id
gameEntity.id = id ?: ""
gameEntity.name = name
gameEntity.icon = icon
gameEntity.setTag(tag)

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