Compare commits

...

127 Commits

Author SHA1 Message Date
72303637d8 feat: test coil integration 2025-04-09 09:32:24 +08:00
8084cda37d Merge branch 'hotfix/v5.40.1-1151/update_upload_sdk' into 'release'
更新火山云上传 SDK

See merge request halo/android/assistant-android!2143
2025-04-02 11:53:34 +08:00
e624f34de1 fix: 禁用火山云上传分片功能 2025-04-02 10:29:56 +08:00
b832c0c14f Merge branch 'hotfix/v5.40.1-1151/GHZSCY-7796' into 'release'
云存档引导游戏下载问题 https://jira.shanqu.cc/browse/GHZSCY-7796

See merge request halo/android/assistant-android!2142
2025-04-01 17:38:48 +08:00
6610c43937 chore: 更新火山云上传 SDK 2025-04-01 17:38:19 +08:00
ec29d94fb7 fix: 云存档引导游戏下载问题 https://jira.shanqu.cc/browse/GHZSCY-7796 2025-04-01 14:44:46 +08:00
b6ec74d789 chore: 版本更新只 5.40.1 2025-03-31 14:31:26 +08:00
2d7224cf16 Merge branch 'fix/crashes' into 'release'
修复Sentry闪退

See merge request halo/android/assistant-android!2139
2025-03-31 11:43:45 +08:00
3f45344b54 Merge branch 'feat/update-qy-sdk' into 'release'
feat:更新奇游加速器sdk

See merge request halo/android/assistant-android!2138
2025-03-31 11:39:28 +08:00
1c3dbce08d feat:更新奇游加速器sdk 2025-03-31 11:39:28 +08:00
7844800b0e fix: 禁用RecyclerView动画效果避免异常闪退 https://sentry.shanqu.cc/organizations/lightgame/issues/441824/?project=22 2025-03-31 11:38:05 +08:00
ebcfd9c85d fix: 修复游戏详情页偶发空指针闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/443716/?project=22 2025-03-31 11:37:07 +08:00
3825315f65 Merge branch 'hotfix/v5.40.0-1150/router-crash' into 'release'
fix: 尝试修复进程启动时路由异常导致的闪退问题

See merge request halo/android/assistant-android!2137
2025-03-28 17:53:50 +08:00
3ffe4f9bc6 fix: 尝试修复路由异步初始化导致的闪退问题 2025-03-28 17:05:59 +08:00
b2fc01ae48 Merge branch 'feat/va-relative' into 'release'
Revert 畅玩实名认证特殊字符

See merge request halo/android/assistant-android!2135
2025-03-25 17:29:42 +08:00
06f932af14 Revert 畅玩实名认证特殊字符 2025-03-25 17:29:13 +08:00
c2fe3bb64a Merge branch 'hotfix/GHZSCY-7702' into 'release'
Revert "fix: "点"符号设置颜色"

See merge request halo/android/assistant-android!2134
2025-03-25 17:24:30 +08:00
b1b231a309 Revert "feat: 【光环助手】实名认证特殊字符输入优化 https://jira.shanqu.cc/browse/GHZSCY-7702"
This reverts commit cc05dabb93.
2025-03-25 17:23:29 +08:00
e5161ae350 Revert "fix: "点"符号设置颜色"
This reverts commit 2ba39188f7.
2025-03-25 17:22:58 +08:00
4dfa7733ad Merge branch 'feat/va-relative' into 'dev'
feat: 5.40.0 va相关的更新

See merge request halo/android/assistant-android!2133
2025-03-25 14:32:58 +08:00
3906d9b84b feat: 5.40.0 va相关的更新 2025-03-25 14:31:39 +08:00
775e6cc689 Merge branch 'feat/remove-duplicate-log' into 'dev'
删除多余的日志上报

See merge request halo/android/assistant-android!2132
2025-03-25 14:25:39 +08:00
019b9f3f82 删除多余的日志上报 2025-03-25 14:24:05 +08:00
49f752dab5 Merge branch 'fix/jg_push_source_entrance' into 'dev'
fix: 修复极光推送跳转没有携带来源信息的问题

See merge request halo/android/assistant-android!2131
2025-03-25 10:45:05 +08:00
0cbda119d4 fix: 修复极光推送跳转没有携带来源信息的问题 2025-03-25 10:43:59 +08:00
aed8e50db3 feat: 重新启用在华为 Android 10 上的开屏广告,测试闪退情况 2025-03-25 10:17:57 +08:00
da5bb9eaf3 Merge branch 'feat/GHZSCY-7525' into 'dev'
feat: 头条推广包转化归因优化及SDK更新 https://jira.shanqu.cc/browse/GHZSCY-7525.cc/browse/GHZSCY-7525

See merge request halo/android/assistant-android!2130
2025-03-25 09:57:44 +08:00
d7593de98b feat: 头条推广包转化归因优化及SDK更新 https://jira.shanqu.cc/browse/GHZSCY-7525.cc/browse/GHZSCY-7525 2025-03-25 09:57:08 +08:00
69d2d699fe Merge branch 'feat/GHZSCY-7712' into 'dev'
feat: 后台功能面板组件交互优化—客户端 https://jira.shanqu.cc/browse/GHZSCY-7712

See merge request halo/android/assistant-android!2129
2025-03-24 14:31:32 +08:00
a438ef16c0 feat: 后台功能面板组件交互优化—客户端 https://jira.shanqu.cc/browse/GHZSCY-7712 2025-03-24 14:31:32 +08:00
d5a2cecd29 Merge branch 'fix/GHZSCY-7737' into 'dev'
fix:【光环助手】游戏详情下载触发跳转异常 https://jira.shanqu.cc/browse/GHZSCY-7737

See merge request halo/android/assistant-android!2128
2025-03-24 11:30:23 +08:00
65a4e675fa fix:【光环助手】游戏详情下载触发跳转异常 https://jira.shanqu.cc/browse/GHZSCY-7737 2025-03-24 11:30:23 +08:00
ec3e6d5f7b Merge branch 'fix/GHZSCY-7691' into 'dev'
fix: 2025/3/14 - 埋点补充 https://jira.shanqu.cc/browse/GHZSCY-7691

See merge request halo/android/assistant-android!2116
2025-03-24 10:03:53 +08:00
07b0afce03 fix: 2025/3/14 - 埋点补充 https://jira.shanqu.cc/browse/GHZSCY-7691 2025-03-24 10:03:53 +08:00
852a6d32d6 Merge branch 'fix/GHZSCY-7736' into 'dev'
fix: 间距显示问题-客户端 https://jira.shanqu.cc/browse/GHZSCY-7736

See merge request halo/android/assistant-android!2127
2025-03-24 09:44:19 +08:00
55022d8b1c fix: 间距显示问题-客户端 https://jira.shanqu.cc/browse/GHZSCY-7736 2025-03-24 09:42:26 +08:00
eb7d407e92 Merge branch 'fix/GHZSCY-7735' into 'dev'
fix: 版本求更新显示优化—客户端 https://jira.shanqu.cc/browse/GHZSCY-7735

See merge request halo/android/assistant-android!2126
2025-03-21 18:02:02 +08:00
733cd1e198 fix: 版本求更新显示优化—客户端 https://jira.shanqu.cc/browse/GHZSCY-7735 2025-03-21 17:57:02 +08:00
1d767018f6 Merge branch 'fix/va/unity-crash' into 'dev'
fix: 部分unity游戏启动闪退

See merge request halo/android/assistant-android!2125
2025-03-21 17:36:55 +08:00
0a3616a1c0 fix: 部分unity游戏启动闪退 2025-03-21 17:36:09 +08:00
05108ab478 Merge branch 'fix/crash-in-splash' into 'dev'
fix:java.lang.RuntimeException: Unable to start activity...

See merge request halo/android/assistant-android!2124
2025-03-21 11:23:33 +08:00
508c90cc63 fix:java.lang.RuntimeException: Unable to start activity... 2025-03-21 11:23:33 +08:00
6242f79f80 Merge branch 'fix/GHZSCY-7728' into 'dev'
fix: 部分位置跳转到游戏开服表无【新增】功能 https://jira.shanqu.cc/browse/GHZSCY-7728

See merge request halo/android/assistant-android!2123
2025-03-20 16:29:36 +08:00
71dd964440 fix: 部分位置跳转到游戏开服表无【新增】功能 https://jira.shanqu.cc/browse/GHZSCY-7728 2025-03-20 16:25:22 +08:00
63fc720c40 Merge remote-tracking branch 'origin/release' into dev 2025-03-20 15:42:57 +08:00
5da02c4b64 Merge branch 'hotfix/v5.39.5-1195/rank_text_width_issue' into 'release'
fix: 修复搜索页推荐榜单文字宽度问题

See merge request halo/android/assistant-android!2122
2025-03-20 15:16:40 +08:00
f94b28a085 fix: 修复搜索页推荐榜单文字宽度问题 2025-03-20 15:15:24 +08:00
e8a199b5c0 Merge branch 'feat/GHZSCY-7702' into 'dev'
fix: "点"符号设置颜色

See merge request halo/android/assistant-android!2121
2025-03-20 11:06:51 +08:00
2ba39188f7 fix: "点"符号设置颜色 2025-03-20 11:06:37 +08:00
963074d5d8 Merge branch 'feat/GHZSCY-7704' into 'dev'
fix: “点”符号大小和颜色设置

See merge request halo/android/assistant-android!2120
2025-03-20 10:51:39 +08:00
cc629819d9 fix: “点”符号大小和颜色设置 2025-03-20 10:51:13 +08:00
d82505ab5d Merge branch 'feat/GHZSCY-7704' into 'dev'
feat: [畅玩]实名认证特殊符号以及字符限制优化 https://jira.shanqu.cc/browse/GHZSCY-7704

See merge request halo/android/assistant-android!2119
2025-03-20 09:46:54 +08:00
a917214b36 feat: [畅玩]实名认证特殊符号以及字符限制优化 https://jira.shanqu.cc/browse/GHZSCY-7704 2025-03-20 09:46:34 +08:00
bdf9094799 Merge branch 'feat/common-chips' into 'dev'
feat:添加通用组件:选项标签Chips

See merge request halo/android/assistant-android!2118
2025-03-20 09:45:39 +08:00
df0d0604b9 feat:添加通用组件:选项标签Chips 2025-03-20 09:39:51 +08:00
f100d906ab Merge branch 'feat/GHZSCY-7702' into 'dev'
feat: 【光环助手】实名认证特殊字符输入优化 https://jira.shanqu.cc/browse/GHZSCY-7702

See merge request halo/android/assistant-android!2117
2025-03-19 17:51:51 +08:00
cc05dabb93 feat: 【光环助手】实名认证特殊字符输入优化 https://jira.shanqu.cc/browse/GHZSCY-7702 2025-03-19 17:45:52 +08:00
bd39ac2eaf Merge branch 'fix/drop_font_color_in_dark_mode' into 'dev'
fix: 修复部分富文本中的颜色在深色模式下没有去除的问题

See merge request halo/android/assistant-android!2115
2025-03-19 17:10:52 +08:00
31903d21c0 fix: 修复部分富文本中的颜色在深色模式下没有去除的问题 2025-03-19 17:03:45 +08:00
266fcc4c38 Merge branch 'feat/GHZSCY-7642' into 'dev'
feat: 优化汉化UI

See merge request halo/android/assistant-android!2114
2025-03-19 11:31:34 +08:00
075ed04191 feat: 优化汉化UI 2025-03-19 11:30:55 +08:00
c804c2f7fd Merge branch 'feat/GHZSCY-7642' into 'dev'
feat: 畅玩汉化翻译功能

See merge request halo/android/assistant-android!2113
2025-03-18 11:39:09 +08:00
882f0a7b3e feat: 畅玩汉化翻译功能 2025-03-18 11:37:18 +08:00
3cf86a500b Merge branch 'feat/GHZSCY-7568' into 'dev'
feat: 游戏详情改版补充优化1—客户端(1) https://jira.shanqu.cc/browse/GHZSCY-7568

See merge request halo/android/assistant-android!2112
2025-03-18 11:14:49 +08:00
3cd70b5b8f feat: 游戏详情改版补充优化1—客户端(1) https://jira.shanqu.cc/browse/GHZSCY-7568 2025-03-18 11:14:49 +08:00
60f35a89b4 Merge branch 'feat/GHZSCY-6982-2' into 'dev'
feat:【光环助手】搜索业务:神策埋点相关搜索结果点击事件新增序号属性position https://jira.shanqu.cc/browse/GHZSCY-6982

See merge request halo/android/assistant-android!2111
2025-03-17 15:43:10 +08:00
1503c23246 feat:【光环助手】搜索业务:神策埋点相关搜索结果点击事件新增序号属性position https://jira.shanqu.cc/browse/GHZSCY-6982 2025-03-17 15:38:01 +08:00
ea9e91618f Merge branch 'fix/GHZSCY-7685' into 'dev'
fix:游戏预约功能(第六期)—0313运营测试-客户端...

See merge request halo/android/assistant-android!2110
2025-03-17 11:12:07 +08:00
d52fcc2185 fix:游戏预约功能(第六期)—0313运营测试-客户端... 2025-03-17 11:12:07 +08:00
db047c36d7 Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	dependencies.gradle
2025-03-14 15:22:00 +08:00
1e58bec4a0 Merge branch 'feat/GHZSCY-7668' into 'dev'
feat: 光环助手测试包增加相关快捷功能 https://jira.shanqu.cc/browse/GHZSCY-7668

See merge request halo/android/assistant-android!2109
2025-03-14 15:19:22 +08:00
87ff1a64b3 Merge branch 'fix/improper-router' into 'release'
fix: 修复光环未正常启动也能使用路由跳转至指定页面的问题

See merge request halo/android/assistant-android!2108
2025-03-14 15:16:21 +08:00
b3678d7a54 fix: 修复光环未正常启动也能使用路由跳转至指定页面的问题 2025-03-14 14:28:53 +08:00
c7fa04792b chore: 版本更新至 5.39.5 2025-03-14 10:14:08 +08:00
76ea531419 Merge branch 'fix/GHZSCY-7687' into 'release'
fix:【光环助手】搜索内容标签点击跳转异常 https://jira.shanqu.cc/browse/GHZSCY-7687

See merge request halo/android/assistant-android!2107
2025-03-13 18:20:31 +08:00
d821da0b2c fix:【光环助手】搜索内容标签点击跳转异常 https://jira.shanqu.cc/browse/GHZSCY-7687 2025-03-13 18:20:31 +08:00
d9b137504a Merge branch 'fix/GHZSCY-7661' into 'release'
fix:【光环助手】游戏详情自定义tab关联自定义页面的视频播放问题 https://jira.shanqu.cc/browse/GHZSCY-7661

See merge request halo/android/assistant-android!2105
2025-03-13 16:36:39 +08:00
93369f5676 fix:【光环助手】游戏详情自定义tab关联自定义页面的视频播放问题 https://jira.shanqu.cc/browse/GHZSCY-7661 2025-03-13 16:36:39 +08:00
b109c3bf6f Merge branch 'fix/GHZSCY-7681' into 'dev'
fix: 视频/图片上传问题 https://jira.shanqu.cc/browse/GHZSCY-7681

See merge request halo/android/assistant-android!2106
2025-03-13 16:03:36 +08:00
bb80560a49 fix: 视频/图片上传问题 https://jira.shanqu.cc/browse/GHZSCY-7681 2025-03-13 16:02:48 +08:00
c43a9e3b6e feat: 光环助手测试包增加相关快捷功能 https://jira.shanqu.cc/browse/GHZSCY-7668 2025-03-13 14:53:03 +08:00
34d255d258 Merge branch 'feat/GHZSCY-7676' into 'release'
fix: 新游开测相关功能优化(第四期)—0313运营测试-客户端 https://jira.shanqu.cc/browse/GHZSCY-7676

See merge request halo/android/assistant-android!2104
2025-03-13 13:43:15 +08:00
3ca17cea07 fix: 新游开测相关功能优化(第四期)—0313运营测试-客户端 https://jira.shanqu.cc/browse/GHZSCY-7676 2025-03-13 13:40:10 +08:00
d3e23bfbb5 Merge branch 'feat/GHZSCY-6834' into 'dev'
feat:游戏预约功能(第六期)—客户端 https://jira.shanqu.cc/browse/GHZSCY-6834

See merge request halo/android/assistant-android!2102
2025-03-11 16:53:11 +08:00
273a9f010d feat:游戏预约功能(第六期)—客户端 https://jira.shanqu.cc/browse/GHZSCY-6834 2025-03-11 16:53:11 +08:00
e8cbaf89ff Merge branch 'feat/GHZSCY-6817' into 'dev'
feat:游戏专题新增“竖式图文列表”样式—客户端 https://jira.shanqu.cc/browse/GHZSCY-6817

See merge request halo/android/assistant-android!2101
2025-03-11 14:45:23 +08:00
0e3586a556 Merge branch 'feat/GHZSCY-7048' into 'dev'
feat: 推广包快手API新增次留上报 https://jira.shanqu.cc/browse/GHZSCY-7048

See merge request halo/android/assistant-android!2099
2025-03-11 14:38:02 +08:00
d546651c06 feat:游戏专题新增“竖式图文列表”样式—客户端 https://jira.shanqu.cc/browse/GHZSCY-6817 2025-03-11 14:24:46 +08:00
815f567f44 Merge branch 'feat/GHZSCY-6812' into 'dev'
feat:https://jira.shanqu.cc/browse/GHZSCY-6812 发表内容输入规则优化—客户端

See merge request halo/android/assistant-android!2100
2025-03-11 14:20:41 +08:00
ba3e9357a1 feat:https://jira.shanqu.cc/browse/GHZSCY-6812 发表内容输入规则优化—客户端 2025-03-11 14:20:41 +08:00
312448daae Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	dependencies.gradle
2025-03-11 10:53:15 +08:00
a00a1ced7e Merge branch 'fix/message_link_skip' into 'release'
fix: 修复消息中心跳转问题

See merge request halo/android/assistant-android!2098
2025-03-11 10:42:18 +08:00
1587ca8e6a fix: 修复消息中心跳转问题 2025-03-11 10:35:39 +08:00
86b4761a1c Merge branch 'fix/game_detail_dark_mode' into 'release'
fix: 修复游戏详情页闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/379887/events/0f296b9965884a4f944867479ad7d6c7/?project=22

See merge request halo/android/assistant-android!2097
2025-03-10 10:04:15 +08:00
0446d87b24 fix: 修复游戏详情切换深色模式出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/440456/events/3cfa315cbb734e9688984dddf75fefbd/?project=22 2025-03-10 09:48:04 +08:00
6338fb4dd0 Merge branch 'fix/game_detail_video' into 'release'
fix: 修复游戏详情部分16:9视频存在黑边的问题

See merge request halo/android/assistant-android!2096
2025-03-07 11:54:32 +08:00
6056b7ce1f fix: 修复游戏详情部分16:9视频存在黑边的问题 2025-03-07 11:50:08 +08:00
d51d3c16fe Merge branch 'fix/GHZSCY-7609' into 'release'
fix:【光环助手】UI显示问题 https://jira.shanqu.cc/browse/GHZSCY-7609

See merge request halo/android/assistant-android!2095
2025-03-07 11:34:56 +08:00
d3858ba38f fix:【光环助手】UI显示问题 https://jira.shanqu.cc/browse/GHZSCY-7609 2025-03-07 11:31:21 +08:00
3cbee34b8a chore: 版本更新至 5.39.4 2025-03-07 09:31:21 +08:00
ec88f52603 Merge branch 'fix/GHZSCY-7625' into 'release'
fix: 2025/3/6 - 验收问题 - 客户端 https://jira.shanqu.cc/browse/GHZSCY-7625

See merge request halo/android/assistant-android!2094
2025-03-06 17:46:23 +08:00
b669e216c4 fix: 2025/3/6 - 验收问题 - 客户端 https://jira.shanqu.cc/browse/GHZSCY-7625 2025-03-06 17:46:06 +08:00
795b640870 Merge branch 'feat/GHZSCY-7623' into 'release'
feat: 神策埋点事件优化 https://jira.shanqu.cc/browse/GHZSCY-7622

See merge request halo/android/assistant-android!2092
2025-03-06 14:10:31 +08:00
099d026e73 feat: 神策埋点事件优化 https://jira.shanqu.cc/browse/GHZSCY-7622 2025-03-06 14:09:22 +08:00
162381527c Merge branch 'fix/fix-set-acct-token-failed' into 'release'
https://sentry.shanqu.cc/organizations/lightgame/issues/440135 此bug为奇游sdk setToken失败,errro_message为The SDK is not initialized, please call init in Application to initialize the SDK

See merge request halo/android/assistant-android!2091
2025-03-06 11:26:00 +08:00
dedbe1d18c https://sentry.shanqu.cc/organizations/lightgame/issues/440135 此bug为奇游sdk setToken失败,errro_message为The SDK is not initialized, please call init in Application to initialize the SDK 2025-03-06 11:26:00 +08:00
b775c2f0a9 Merge branch 'fix/game_detail_dark_mode_crash' into 'release'
fix: 修复游戏详情切换深色模式出现的闪退问题...

See merge request halo/android/assistant-android!2090
2025-03-06 09:38:36 +08:00
7e079bc8fa fix: 修复游戏详情切换深色模式出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/440241/?project=22&referrer=issue-stream&statsPeriod=14d 2025-03-06 09:33:48 +08:00
b719763f2d Merge branch 'fix/GHZSCY-7613' into 'release'
Revert "ci"

See merge request halo/android/assistant-android!2089
2025-03-05 17:23:50 +08:00
fdc04bf8cb fix:【光环助手】轮播banner背景显示问题 https://jira.shanqu.cc/browse/GHZSCY-7613 2025-03-05 17:23:50 +08:00
27811b027f chore: 版本更新至 5.39.3 2025-03-05 15:07:47 +08:00
4e8b8435b8 Merge branch 'hotfix/v5.39.2-1132/remove_useless_sentry_event' into 'release'
build: 移除无用的 sentry 事件

See merge request halo/android/assistant-android!2088
2025-03-05 15:04:58 +08:00
a7efd9528e build: 移除无用的 sentry 事件 2025-03-05 15:04:21 +08:00
982e3a9739 Merge branch 'fix/empty_stack_crash' into 'release'
fix: 修复更新页面BusinessId出现的闪退问题...

See merge request halo/android/assistant-android!2087
2025-03-05 14:50:21 +08:00
a942cdbe51 fix: 修复更新页面BusinessId出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/440154/?project=22 2025-03-05 14:43:29 +08:00
f6f0a54cb4 Merge branch 'fix/game_detail_crash' into 'release'
fix: 修复游戏详情页闪退问题...

See merge request halo/android/assistant-android!2086
2025-03-05 14:01:40 +08:00
e26856220a fix: 修复游戏详情页闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/379887/events/0f296b9965884a4f944867479ad7d6c7/?project=22 2025-03-05 13:49:38 +08:00
0f36d7ccfa Merge branch 'fix/GHZSCY-7608' into 'release'
fix:【光环助手】奇游加速器第二期迭代-03/04测试-客户端 https://jira.shanqu.cc/browse/GHZSCY-7608

See merge request halo/android/assistant-android!2084
2025-03-05 11:30:06 +08:00
d0c6a499f8 Merge branch 'fix/GHZSCY-7612' into 'release'
fix:【光环助手】功能标签引导的出现时机问题 https://jira.shanqu.cc/browse/GHZSCY-7612

See merge request halo/android/assistant-android!2085
2025-03-05 11:25:25 +08:00
c56963fab3 fix:【光环助手】功能标签引导的出现时机问题 https://jira.shanqu.cc/browse/GHZSCY-7612 2025-03-05 11:19:43 +08:00
0faa0b490a fix:【光环助手】奇游加速器第二期迭代-03/04测试-客户端 https://jira.shanqu.cc/browse/GHZSCY-7608 2025-03-05 11:19:27 +08:00
51cc1e3104 Merge branch 'fix/game_detail_web' into 'release'
fix: 修复游戏详情网页不能左右滑动切换Tab的问题

See merge request halo/android/assistant-android!2083
2025-03-05 10:50:11 +08:00
ae0ef717d5 fix: 修复游戏详情网页不能左右滑动切换Tab的问题 2025-03-05 10:40:21 +08:00
02ed9c247a Merge branch 'fix/game_detail_divider' into 'release'
fix: 修复光环助手的游戏详情页分割线显示问题

See merge request halo/android/assistant-android!2082
2025-03-04 17:03:23 +08:00
a747917370 fix: 修复光环助手的游戏详情页分割线显示问题 2025-03-04 17:01:02 +08:00
66ffb5cedc chore: 版本更新值 5.39.2 2025-03-04 16:13:30 +08:00
5d4648b3d2 feat: 推广包快手API新增次留上报 https://jira.shanqu.cc/browse/GHZSCY-7048 2024-11-27 15:59:53 +08:00
174 changed files with 2808 additions and 466 deletions

View File

@ -386,6 +386,15 @@ dependencies {
implementation "com.j256.ormlite:ormlite-android:${ormlite}"
implementation "com.j256.ormlite:ormlite-core:${ormlite}"
implementation("io.coil-kt:coil:2.6.0") {
exclude group: "androidx.core"
exclude group: "androidx.lifecycle"
}
implementation("io.coil-kt:coil-svg:2.6.0") {
exclude group: "androidx.core"
exclude group: "androidx.lifecycle"
}
implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

View File

@ -77,6 +77,7 @@
### TEA
-keep class com.gh.gamecenter.TeaHelper { *; }
-keep class com.bytedance.ads.convert.broadcast.common.EncryptionTools {*;}
### EasyFloat
-keep class com.lzf.easyfloat.* {*;}

Binary file not shown.

View File

@ -71,6 +71,10 @@
<!-- 适配 双开/分身 游戏授权登录 -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<!-- 日历 -->
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-sdk tools:overrideLibrary="
com.shuyu.gsyvideoplayer,
com.shuyu.gsyvideoplayer.lib,

View File

@ -180,12 +180,12 @@ object AdDelegateHelper {
config.ownerAd?.startAd?.let { it.id = config.ownerAd.id }
// HarmonyOS 2.2.0 版本不展示第三方开屏广告 (因为会引起奇怪的闪退)
if (MetaUtil.getRom().name == "HarmonyOS"
&& MetaUtil.getRom().versionName == "2.2.0"
&& config.displayRule.adSource == "third_party_ads") {
return
}
// if (MetaUtil.getRom().name == "HarmonyOS"
// && MetaUtil.getRom().versionName == "2.2.0"
// && config.displayRule.adSource == "third_party_ads") {
//
// return
// }
mSplashAd = config
}

View File

@ -3,6 +3,8 @@ package com.gh.common
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Base64
import android.view.View
import android.webkit.JavascriptInterface
@ -11,6 +13,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.*
import com.gh.common.util.LogUtils
@ -18,6 +21,7 @@ import com.gh.download.DownloadManager
import com.gh.download.PackageObserver
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.ImageViewerActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.callback.BiCallback
import com.gh.gamecenter.common.constant.Constants
@ -77,7 +81,7 @@ import java.util.*
class DefaultJsApi(
var context: Context,
val entrance: String = "",
private var mFragment: Fragment? = null,
private val mFragment: Fragment? = null,
private var mBbsId: String? = "",
private var mOriginUrl: String? = "",
private val mForumName: String? = "",
@ -94,6 +98,8 @@ class DefaultJsApi(
private var mDownloadHandler: CompletionHandler<Any>? = null // 下载信息回调
private var mExposureEvent: ExposureEvent? = null // 活动曝光实体
private val handler = Handler(Looper.getMainLooper())
init {
if (mFragment != null) {
EventBus.getDefault().register(this)
@ -240,6 +246,12 @@ class DefaultJsApi(
VHelper.launch(context, packageName)
}
} else {
val wechatPkgName = "com.tencent.mm"
if (packageName == wechatPkgName && !PackageUtils.isInstalled(context, wechatPkgName)) {
// 如果是微信客户端,需要检查是否安装微信
ToastUtils.showToast(R.string.wechat_app_not_install_tips.toResString())
return@runOnUiThread
}
PackageLauncher.launchApp(context, packageName = packageName)
}
}
@ -502,6 +514,44 @@ class DefaultJsApi(
}
}
@JavascriptInterface
fun saveWechatQRCode(msg: Any) {
val base64StringData = msg.toString()
runOnUiThread {
(context as? FragmentActivity)?.checkStoragePermissionBeforeAction {
runOnIoThread {
val base64String = base64StringData.replace("data:image/png;base64", "")
tryWithDefaultCatch {
val imageFile =
File(HaloApp.getInstance().cacheDir.absolutePath + File.separator + System.currentTimeMillis() + ".png")
val decodedString = Base64.decode(base64String, Base64.DEFAULT)
val bos = BufferedOutputStream(FileOutputStream(imageFile))
bos.write(decodedString)
bos.flush()
bos.close()
ImageUtils.saveImageToFile(imageFile, "", true) {
// 这里是 ui 线程
// 保存微信二维码成功1s 以后跳转微信
if (mFragment != null && mFragment.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
handler.removeCallbacksAndMessages(null)
handler.postDelayed({
val wechatPkgName = "com.tencent.mm"
if (!PackageUtils.isInstalled(context, wechatPkgName)) {
ToastUtils.showToast(R.string.wechat_app_not_install_tips.toResString())
return@postDelayed
}
PackageLauncher.launchApp(context, packageName = wechatPkgName)
}, 1000)
}
}
}
}
}
}
}
@JavascriptInterface
fun loginWithCallback(msg: Any, handler: CompletionHandler<Any>) {
mLoginHandler = handler
@ -798,6 +848,8 @@ class DefaultJsApi(
}
EventBus.getDefault().unregister(this@DefaultJsApi)
handler.removeCallbacksAndMessages(null)
}
}

View File

@ -1,5 +1,10 @@
package com.gh.common.databind;
import static com.gh.gamecenter.entity.SubjectEntity.SUBJECT_TAG_SELLING_POINT;
import static com.gh.gamecenter.entity.SubjectEntity.SUBJECT_TAG_TEST;
import static com.gh.gamecenter.entity.SubjectEntity.SUBJECT_TAG_TYPE;
import static com.gh.gamecenter.entity.SubjectEntity.SUBJECT_TAG_UPDATE;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
@ -48,6 +53,7 @@ import com.gh.download.server.BrowserInstallHelper;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.common.databinding.LayoutGameItemSellingPointBinding;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.utils.DarkModeUtils;
import com.gh.gamecenter.common.utils.ExtensionsKt;
@ -55,6 +61,7 @@ import com.gh.gamecenter.common.utils.FileUtils;
import com.gh.gamecenter.common.utils.NewFlatLogUtils;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.core.utils.MtaHelper;
import com.gh.gamecenter.core.utils.TimeUtils;
import com.gh.gamecenter.core.utils.ToastUtils;
import com.gh.gamecenter.feature.entity.ApkEntity;
import com.gh.gamecenter.feature.entity.GameEntity;
@ -289,7 +296,7 @@ public class BindingAdapters {
});
break;
case RESERVED:
ReservationHelper.showCancelReservationDialog(progressBar.getContext(),gameEntity, () -> {
ReservationHelper.showCancelReservationDialog(progressBar.getContext(), gameEntity, () -> {
ReservationHelper.cancelReservation(gameEntity, () -> {
updateReservation(progressBar, gameEntity);
});
@ -472,39 +479,37 @@ public class BindingAdapters {
}
}
// 包含测试开服标签
public static void setGameTags(LinearLayout layout, GameEntity gameEntity) {
/**
* 包含测试开服标签
*
* @param layout
* @param gameEntity
* @param subjectTag 默认为 “”只有游戏专题可以配置subjectTag
*/
public static void setGameTags(LinearLayout layout, GameEntity gameEntity, String subjectTag) {
try {
if (layout.getVisibility() == View.GONE) return;
ArrayList<TagStyleEntity> tagStyle = new ArrayList<>();
TestEntity test = gameEntity.getTest();
if (test != null
// 这个判断用于开测表列表
&& !"type_tag".equals(test.getGameTag())) {
if ("custom".equals(test.getGameTag())) {
TagStyleEntity typeTag = new TagStyleEntity();
if (!TextUtils.isEmpty(test.getText())) {
typeTag.setName(test.getText() != null ? test.getText() : "");
} else {
typeTag.setName(test.getType() != null ? test.getType() : "");
}
typeTag.setBackground("E8F3FF");
typeTag.setColor("1383EB");
tagStyle.add(typeTag);
} else {
TagStyleEntity typeTag = new TagStyleEntity();
boolean isDarkModeOn = DarkModeUtils.INSTANCE.isDarkModeOn(layout.getContext());
typeTag.setName(test.getType() != null ? test.getType() : "");
typeTag.setBackground("1AFFA142");
typeTag.setColor(isDarkModeOn ? "EB9238" : "FFA142");
tagStyle.add(typeTag);
if (test != null && subjectTag.equals(SUBJECT_TAG_TEST)) {
// 显示开测表标签
TagStyleEntity typeTag = new TagStyleEntity();
boolean isDarkModeOn = DarkModeUtils.INSTANCE.isDarkModeOn(layout.getContext());
typeTag.setName(test.getType() != null ? test.getType() : "");
typeTag.setBackground("1AFFA142");
typeTag.setColor(isDarkModeOn ? "EB9238" : "FFA142");
tagStyle.add(typeTag);
TagStyleEntity timeTag = new TagStyleEntity();
TagStyleEntity timeTag = new TagStyleEntity();
if (test.getStartPending()) {
timeTag.setName(test.getStartText());
} else {
timeTag.setName(GameViewUtils.getGameTestDate(test.getStart()));
timeTag.setBackground("1A06CEA8");
timeTag.setColor(isDarkModeOn ? "07A385" : "06CEA8");
tagStyle.add(timeTag);
}
timeTag.setBackground("1A06CEA8");
timeTag.setColor(isDarkModeOn ? "07A385" : "06CEA8");
tagStyle.add(timeTag);
} else {
tagStyle = gameEntity.getTagStyle();
}
@ -514,6 +519,59 @@ public class BindingAdapters {
}
}
public static void setGameTagsWithSellingPoint(LinearLayout layout, LayoutGameItemSellingPointBinding binding, GameEntity gameEntity, String subjectTag) {
if (subjectTag.equals(SUBJECT_TAG_SELLING_POINT)) {
layout.setVisibility(View.GONE);
binding.getRoot().setVisibility(View.VISIBLE);
GameEntity.SellingPoints sellingPoints = gameEntity.getSellingPoints();
if (sellingPoints != null) {
binding.tvSellingPoints.setVisibility(View.VISIBLE);
binding.tvSellingPoints.setText(sellingPoints.getText());
} else {
binding.tvSellingPoints.setVisibility(View.GONE);
}
Context context = layout.getContext();
binding.gtcvTags.removeAllViews();
ArrayList<TagStyleEntity> tagStyle = gameEntity.getTagStyle();
for (int i = 0; i < tagStyle.size(); i++) {
if (i < 3) {
TextView textView = new TextView(layout.getContext());
textView.setTextColor(ExtensionsKt.toColor(com.gh.gamecenter.common.R.color.text_tertiary, context));
textView.setTextSize(10);
textView.setText((i == 0 ? "" : "·") + tagStyle.get(i).getName());
binding.gtcvTags.addView(textView);
}
}
} else {
layout.setVisibility(View.VISIBLE);
binding.getRoot().setVisibility(View.GONE);
switch (subjectTag) {
case SUBJECT_TAG_UPDATE:
List<TagStyleEntity> updateTags = new ArrayList<>();
TagStyleEntity updateTag = new TagStyleEntity(
"local_generated",
TimeUtils.getFormatTime(gameEntity.getUpdateTime(), "MM-dd") + " 更新",
"",
"1383EB",
"E8F3FF",
"1383EB",
false
);
updateTags.add(updateTag);
GameViewUtils.setLabelList(layout.getContext(), layout, updateTags);
break;
case SUBJECT_TAG_TYPE:
GameViewUtils.setLabelList(layout.getContext(), layout, gameEntity.getTagStyle());
break;
default:
setGameTags(layout, gameEntity, subjectTag);
break;
}
}
}
public static void setVideoDetailGameTags(LinearLayout layout, GameEntity gameEntity) {
try {
ArrayList<TagStyleEntity> tagStyle = new ArrayList<>();

View File

@ -16,6 +16,7 @@ import com.gh.common.pop.EditBindWechatPop
import com.gh.common.pop.RealNameTipsPop
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.WechatConfigEntity
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toObject
@ -83,79 +84,90 @@ class ReserveSuccessReminderDialog(
handlers.clear()
binding.flContentContainer.removeAllViews()
val smsConfig = reserveReminder.smsConfig
val wechatConfig = reserveReminder.wechatConfig
when {
reserveReminder.onlyShowWechatReminder && !wechatConfig.isReminderEnable -> { // 只显示微信:未开启
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
arrayListOf(OnlyWechatReminderUnableHandler(16.dp, binding.flContentContainer, this))
val configTypes = mutableListOf<Int>()
// 短信
if (reserveReminder.hasSmsConfig) {
if (reserveReminder.smsConfig.notice) {
configTypes.add(SMS_REMINDER_ENABLE_TYPE)
} else {
configTypes.add(SMS_REMINDER_UNABLE_TYPE)
}
reserveReminder.onlyShowWechatReminder && wechatConfig.isReminderEnable -> { // 只显示微信:已开
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
arrayListOf(
WechatReminderEnableHandler(
reserveReminder.wechatConfig.nickName,
8.dp,
binding.flContentContainer,
this
)
)
}
!smsConfig.notice && !wechatConfig.isReminderEnable -> { // 短信,微信未开启
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
arrayListOf(
SmsReminderUnableHandler(16.dp, binding.flContentContainer, this),
WechatReminderUnableHandler(8.dp, binding.flContentContainer, this)
)
}
smsConfig.notice && wechatConfig.isReminderEnable -> {// 短信,微信已开启
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
arrayListOf(
SmsReminderEnableHandler(reserveReminder.smsConfig, 8.dp, binding.flContentContainer, this),
WechatReminderEnableHandler(
reserveReminder.wechatConfig.nickName,
8.dp,
binding.flContentContainer,
this
)
)
}
smsConfig.notice && !wechatConfig.isReminderEnable -> { // 短信开启,微信未开启
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
arrayListOf(
SmsReminderEnableHandler(smsConfig, 8.dp, binding.flContentContainer, this),
WechatReminderUnableHandler(16.dp, binding.flContentContainer, this)
)
}
!smsConfig.notice && wechatConfig.isReminderEnable -> { // 微信开启,短信未开启
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
arrayListOf(
WechatReminderEnableHandler(
wechatConfig.nickName,
8.dp,
binding.flContentContainer,
this
),
SmsReminderUnableHandler(16.dp, binding.flContentContainer, this)
)
}
else -> {
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
arrayListOf()
}
}.let {
handlers.clear()
handlers.addAll(it)
}
// 微信
if (reserveReminder.wechatConfig.isReminderEnable) {
configTypes.add(WECHAT_REMINDER_ENABLE_TYPE)
} else {
configTypes.add(WECHAT_REMINDER_UNABLE_TYPE)
}
// 日历
if (reserveReminder.hasCalendarConfig) {
if (reserveReminder.calendarConfig.notice) {
configTypes.add(CALENDAR_REMINDER_ENABLE_TYPE)
} else {
configTypes.add(CALENDAR_REMINDER_UNABLE_TYPE)
}
}
if (configTypes.size == 1) {
// 只有微信提醒
if (configTypes.first() == WECHAT_REMINDER_ENABLE_TYPE) {
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
handlers.add(
WechatReminderEnableHandler(reserveReminder.wechatConfig, 8.dp, binding.flContentContainer, this)
)
} else {
binding.tvContent.setText(R.string.reverse_success_without_reminder_tips)
handlers.add(OnlyWechatReminderUnableHandler(16.dp, binding.flContentContainer, this))
}
} else {
binding.tvContent.setText(R.string.reverse_success_with_reminder_tips)
var isLargerSpacing = true
fun getPaddingTop(): Int {
val paddingTop = if (isLargerSpacing) 16.dp else 8.dp
isLargerSpacing = false
return paddingTop
}
configTypes.sorted().forEach {
when (it) {
SMS_REMINDER_ENABLE_TYPE -> {
isLargerSpacing = true
SmsReminderEnableHandler(reserveReminder.smsConfig, 8.dp, binding.flContentContainer, this)
}
SMS_REMINDER_UNABLE_TYPE -> {
SmsReminderUnableHandler(getPaddingTop(), binding.flContentContainer, this)
}
WECHAT_REMINDER_ENABLE_TYPE -> {
isLargerSpacing = true
WechatReminderEnableHandler(
reserveReminder.wechatConfig,
8.dp,
binding.flContentContainer,
this
)
}
WECHAT_REMINDER_UNABLE_TYPE ->
WechatReminderUnableHandler(getPaddingTop(), binding.flContentContainer, this)
CALENDAR_REMINDER_ENABLE_TYPE -> {
isLargerSpacing = true
CalendarReminderEnableHandler(8.dp, binding.flContentContainer, this)
}
CALENDAR_REMINDER_UNABLE_TYPE ->
CalendarReminderUnableHandler(getPaddingTop(), binding.flContentContainer, this)
else -> null
}?.let(handlers::add)
}
}
handlers.forEach {
binding.flContentContainer.addView(it.init())
}
@ -220,9 +232,14 @@ class ReserveSuccessReminderDialog(
listener.changeWechatBinding()
}
override fun updateCalendarReminder() {
listener.updateCalendarReminder()
}
override fun onStart() {
super.onStart()
window?.let {
it.setDimAmount(0.4F)
it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
val params = it.attributes
params.width = DisplayUtils.dip2px(300F)
@ -244,6 +261,13 @@ class ReserveSuccessReminderDialog(
private val Int.dp: Int
get() = DisplayUtils.dip2px(this.toFloat())
private const val SMS_REMINDER_ENABLE_TYPE = 1
private const val WECHAT_REMINDER_ENABLE_TYPE = 2
private const val CALENDAR_REMINDER_ENABLE_TYPE = 3
private const val SMS_REMINDER_UNABLE_TYPE = 4
private const val WECHAT_REMINDER_UNABLE_TYPE = 5
private const val CALENDAR_REMINDER_UNABLE_TYPE = 6
fun create(context: Context, listener: OnReserveReminderListener) =
ReserveSuccessReminderDialog(
context,
@ -360,7 +384,7 @@ class ReserveSuccessReminderDialog(
}
class WechatReminderEnableHandler(
private val nickName: String,
private val wechatConfig: WechatConfigEntity,
topMargin: Int,
parent: ViewGroup,
listener: OnReserveSuccessListener
@ -380,7 +404,7 @@ class ReserveSuccessReminderDialog(
}.root
override fun initView() {
binding.tvWechat.text = nickName
binding.tvWechat.text = wechatConfig.nickName
binding.vModifyWechat.setOnClickListener {
editWechatPop.showAsDropDown(
binding.ivModifyWechat,
@ -411,6 +435,51 @@ class ReserveSuccessReminderDialog(
}
class CalendarReminderUnableHandler(
topMargin: Int,
parent: ViewGroup,
listener: OnReserveSuccessListener
) : ReminderContentHandler(topMargin, parent, listener) {
private lateinit var binding: LayoutReserveWechatReminderUnableBinding
// 复用微信提醒未开启状态布局
override fun createView(inflater: LayoutInflater) =
LayoutReserveWechatReminderUnableBinding.inflate(inflater, parent, false)
.also {
binding = it
}.root
override fun initView() {
binding.tvWechatReminderTitle.setText(R.string.calendar_reminders)
binding.tvWechatReminderDescription.setText(R.string.calendar_reminders_description)
binding.vWechatAdd.setOnClickListener {
listener.updateCalendarReminder()
}
}
}
class CalendarReminderEnableHandler(
topMargin: Int,
parent: ViewGroup,
listener: OnReserveSuccessListener
) : ReminderContentHandler(topMargin, parent, listener) {
private lateinit var binding: LayoutReserveCalendarReminderUnableBinding
override fun createView(inflater: LayoutInflater) =
LayoutReserveCalendarReminderUnableBinding.inflate(inflater, parent, false)
.also {
binding = it
}.root
override fun initView() {
}
}
}
@ -425,4 +494,6 @@ interface OnReserveSuccessListener {
fun verifyPhoneNumber()
fun changeWechatBinding()
fun updateCalendarReminder()
}

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.PackageFlavorHelper
import com.gh.gamecenter.common.utils.debounceActionWithInterval
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.common.utils.toObject
@ -123,10 +124,16 @@ object RegionSettingHelper {
mIsInit = false
}
val fakeIp = if (PackageFlavorHelper.IS_TEST_FLAVOR) {
SPUtils.getString(Constants.SP_TEST_FLAVOR_IP)
} else {
""
}
// 使用默认的 Schdulers.io() 可能会触发 OOM
RetrofitManager.getInstance()
.api
.getRegionSetting(HaloApp.getInstance().channel)
.getRegionSetting(HaloApp.getInstance().channel, fakeIp)
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<RegionSetting>() {
override fun onSuccess(data: RegionSetting) {

View File

@ -0,0 +1,29 @@
package com.gh.common.interceptor
import com.gh.gamecenter.common.constant.RouteConsts
import com.halo.assistant.HaloApp
import com.therouter.router.RouteItem
import com.therouter.router.interceptor.RouterReplaceInterceptor
import com.therouter.router.matchRouteMap
/**
* 主拦截器
*/
class MainInterceptor: RouterReplaceInterceptor() {
override fun replace(routeItem: RouteItem?): RouteItem? {
if (routeItem == null) return null
// 用户是否已经同意隐私政策
val isUserAcceptPrivacyPolicy = HaloApp.isUserAcceptPrivacyPolicy(HaloApp.getInstance())
// 如果用户已经同意隐私政策并且应用已经启动,直接返回 routeItem ,运行跳转
if (isUserAcceptPrivacyPolicy && HaloApp.getInstance().isAlreadyUpAndRunning) {
return routeItem
}
// 指向调整为 SplashScreenActivity
return matchRouteMap(RouteConsts.activity.splashActivity)
}
}

View File

@ -4,8 +4,10 @@ import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import com.gh.common.databind.BindingAdapters
import com.gh.gamecenter.common.databinding.LayoutGameItemSellingPointBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.provider.IBindingAdaptersProvider
import com.gh.gamecenter.home.custom.adapter.CustomViewExt
@com.therouter.inject.ServiceProvider
class BindingAdaptersProviderImpl : IBindingAdaptersProvider {
@ -18,7 +20,7 @@ class BindingAdaptersProviderImpl : IBindingAdaptersProvider {
}
override fun setGameTags(layout: LinearLayout, gameEntity: GameEntity) {
BindingAdapters.setGameTags(layout, gameEntity)
BindingAdapters.setGameTags(layout, gameEntity, "")
}
override fun setMessageUnread(view: TextView, unreadCount: Int) {
@ -28,4 +30,17 @@ class BindingAdaptersProviderImpl : IBindingAdaptersProvider {
override fun setGame(view: View, gameEntity: GameEntity) {
BindingAdapters.setGame(view, gameEntity)
}
override fun setGameTagsWithSellingPoints(
layout: LinearLayout,
sellingPointsBinding: LayoutGameItemSellingPointBinding,
gameEntity: GameEntity,
subjectTag: String
) {
BindingAdapters.setGameTagsWithSellingPoint(layout, sellingPointsBinding, gameEntity, subjectTag)
}
override fun setGameDescription(tvDesc: TextView, briefStyle: String, game: GameEntity) {
CustomViewExt.setDescription(tvDesc, briefStyle, game)
}
}

View File

@ -2,6 +2,8 @@ package com.gh.common.provider
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.entity.GameUpdateEntity
@ -11,6 +13,7 @@ import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.provider.IDownloadButtonClickedProvider
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.gamecenter.packagehelper.PackageRepository
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.utils.Utils
@ -27,6 +30,9 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
var packageName = ""
var exposureSourceList: List<ExposureSource>? = null
var customPageTrackData: CustomPageTrackData? = null
val pushMessageId = (HaloApp.get(Constants.PUSH_MESSAGE_ID, false) as? String) ?: ""
val pushLinkId = (HaloApp.get(Constants.PUSH_LINK_ENTITY, false) as? LinkEntity)?.link ?: ""
val isFromPush = pushMessageId.isNotEmpty()
val boundedObject = downloadButton.getObject()
@ -136,6 +142,9 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
"last_page_name", GlobalActivityManager.getLastPageEntity().pageName,
"last_page_id", GlobalActivityManager.getLastPageEntity().pageId,
"last_page_business_id", GlobalActivityManager.getLastPageEntity().pageBusinessId,
"is_from_push_notifications", isFromPush,
"message_id", pushMessageId,
"link_id", pushLinkId,
*customPageKV
)
}

View File

@ -1,5 +1,6 @@
package com.gh.common.provider
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.core.provider.IAcceleratorDataHolderProvider
import com.gh.gamecenter.feature.entity.VipEntity
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
@ -12,6 +13,18 @@ class IAcceleratorDataHolderProviderImpl : IAcceleratorDataHolderProvider {
}
}
override fun addInitFunResult(result: String) {
AcceleratorDataHolder.instance.addInitFunResult(result)
}
override fun getInitFunResults(): List<String> {
return AcceleratorDataHolder.instance.initResults
}
override fun getGhVersionName(): String {
return PackageUtils.getGhVersionName()
}
override fun clear() {
AcceleratorDataHolder.instance.clear()
}

View File

@ -2,6 +2,7 @@ package com.gh.common.util
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.retrofit.RetrofitManager
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
@ -12,15 +13,18 @@ import okhttp3.ResponseBody
object ActivationHelper {
private const val HAS_SENT_ACTIVATED_INFO = "has_sent_activated_info"
private const val SENT_ACTIVATED_INFO_TIME = "sent_activated_info_time"
private const val HAS_SENT_RETENTION_INFO = "has_sent_retention_info"
var mHasSentActivatedInfo = SPUtils.getBoolean(HAS_SENT_ACTIVATED_INFO, false)
private var hasSentActivatedInfo = SPUtils.getBoolean(HAS_SENT_ACTIVATED_INFO, false)
private var hasSentRetentionInfo = SPUtils.getBoolean(HAS_SENT_RETENTION_INFO, false)
/**
* 发送激活信息 (用于推广)
*/
@JvmStatic
fun sendActivationInfo() {
if (!mHasSentActivatedInfo) {
if (!hasSentActivatedInfo) {
RetrofitManager.getInstance()
.api.postActivationInfo()
.subscribeOn(Schedulers.io())
@ -28,8 +32,36 @@ object ActivationHelper {
override fun onResponse(response: ResponseBody?) {
super.onResponse(response)
mHasSentActivatedInfo = true
hasSentActivatedInfo = true
SPUtils.setBoolean(HAS_SENT_ACTIVATED_INFO, true)
SPUtils.setLong(SENT_ACTIVATED_INFO_TIME, System.currentTimeMillis())
}
})
}
}
/**
* 发送次日留存信息 (用于推广)
*/
@JvmStatic
fun sendRetentionInfo() {
if (hasSentActivatedInfo && !hasSentRetentionInfo) {
val activateTimeMillis = SPUtils.getLong(SENT_ACTIVATED_INFO_TIME, 0)
val currentTimeMillis = System.currentTimeMillis()
if (!TimeUtils.isNextDay(activateTimeMillis, currentTimeMillis)) {
return
}
RetrofitManager.getInstance()
.api.postRetentionInfo()
.subscribeOn(Schedulers.io())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
super.onResponse(response)
hasSentRetentionInfo = true
SPUtils.setBoolean(HAS_SENT_RETENTION_INFO, true)
}
})
}

View File

@ -111,7 +111,6 @@ public class DataUtils {
try {
HaloApp.getInstance().getContentResolver().insert(Uri.parse("content://com.gh.gamecenter.provider/device"), values);
} catch (Exception exception) {
SentryHelper.INSTANCE.onEvent("DEVICE_INSERT_ERROR", "exception_digest", exception.getLocalizedMessage());
exception.printStackTrace();
}
});
@ -196,7 +195,6 @@ public class DataUtils {
// TODO 将 com.gh.gamecenter 改成 BuildConfig.ApplicationID
HaloApp.getInstance().getContentResolver().insert(Uri.parse("content://com.gh.gamecenter.provider/certification"), values);
} catch (Exception exception) {
SentryHelper.INSTANCE.onEvent("CERTIFICATION_INSERT_ERROR", "exception_digest", exception.getLocalizedMessage());
exception.printStackTrace();
}
}

View File

@ -854,7 +854,8 @@ object DirectUtils {
entrance: String? = null,
autoDownload: Boolean? = null,
tab: String? = "",
traceEvent: ExposureEvent? = null
traceEvent: ExposureEvent? = null,
from: String? = null
) {
if (id.isEmpty()) return
@ -862,6 +863,7 @@ object DirectUtils {
.path(RouteConsts.activity.gameDetailActivity)
.appendQueryParameter(KEY_ENTRANCE, entrance)
.appendQueryParameter(KEY_GAME_ID, id)
.appendQueryParameter(KEY_FROM, from)
.build()
TheRouter

View File

@ -655,7 +655,11 @@ object DownloadItemUtils {
}
// 缺省情况下回落到游戏简介
if (TextUtils.isEmpty(briefStyle) || briefStyle!!.contains("brief") || briefStyle.contains("recommend")) {
if (TextUtils.isEmpty(briefStyle)
|| briefStyle!!.contains("brief")
|| briefStyle.contains("recommend")
|| briefStyle.contains("test&appointment")
) {
holder.gameDes?.visibility = View.VISIBLE
} else {
holder.gameDes?.visibility = View.GONE

View File

@ -14,6 +14,7 @@ import com.gh.gamecenter.common.base.GlobalActivityManager.getLastPageEntity
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.callback.ConfirmListener
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.entity.SimpleGameEntity
import com.gh.gamecenter.common.entity.SuggestType
import com.gh.gamecenter.common.eventbus.EBShowDialog
@ -556,6 +557,10 @@ object DownloadObserver {
} else {
arrayOf()
}
val pushMessageId = (HaloApp.get(Constants.PUSH_MESSAGE_ID, false) as? String) ?: ""
val pushLinkId = (HaloApp.get(Constants.PUSH_LINK_ENTITY, false) as? LinkEntity)?.link ?: ""
val isFromPush = pushMessageId.isNotEmpty()
SensorsBridge.trackEventWithExposureSource(
"DownloadProcessFinish",
exposureEvent?.source,
@ -572,6 +577,9 @@ object DownloadObserver {
"last_page_business_id", getLastPageEntity().pageBusinessId,
"download_status", downloadEntity.meta[Constants.DOWNLOAD_STATUS_IN_CHINESE] ?: "",
"download_type", if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
"is_from_push_notifications", isFromPush,
"message_id", pushMessageId,
"link_id", pushLinkId,
*kvs
)
}

View File

@ -95,7 +95,8 @@ object ReservationHelper {
it.categoryChinese,
data.wechatConfig.isReminderEnable,
if (data.hasSmsConfig) data.smsConfig.notice else null,
if (data.isEnableAutoDownload) data.wifiAutoDownload else null
if (data.isEnableAutoDownload) data.wifiAutoDownload else null,
if (data.hasCalendarConfig) false else null
)
}

View File

@ -208,20 +208,7 @@ object XapkInstaller : XApkUnZipCallback, XApkUnZipOutputFactory {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, df.uri)
}
tempLauncher =
activity.registerActivityResultLauncher(ActivityResultContracts.OpenDocumentTree()) { uri ->
if (uri != null) {
activity.contentResolver.takePersistableUriPermission(
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
useDocStyleToUnzip = true
unzipAction.invoke()
}
tempLauncher?.unregister()
}
tempLauncher = null
tempLauncher?.launch(obbUri)
},

View File

@ -29,6 +29,7 @@ import com.gh.common.util.PackageUtils;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.common.base.GlobalActivityManager;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.common.utils.DeviceUtils;
import com.gh.gamecenter.common.utils.ExtensionsKt;
@ -451,8 +452,15 @@ public class DownloadManager implements DownloadStatusListener {
trackDownloadType = "本地下载";
}
String pushMessageId = HaloApp.get(Constants.PUSH_MESSAGE_ID, false) instanceof String
? (String) HaloApp.get(Constants.PUSH_MESSAGE_ID, false)
: "";
String pushLinkId = HaloApp.get(Constants.PUSH_LINK_ENTITY, false) instanceof LinkEntity
? ((LinkEntity) HaloApp.get(Constants.PUSH_LINK_ENTITY, false)).getLink()
: "";
boolean isFromPush = !pushMessageId.isEmpty();
String[] arrayKv = {
Object[] arrayKv = {
"game_id", gameEntity.getId(),
"game_name", gameEntity.getName(),
"game_type", gameEntity.getCategoryChinese(),
@ -465,16 +473,19 @@ public class DownloadManager implements DownloadStatusListener {
"last_page_id", GlobalActivityManager.getLastPageEntity().getPageId(),
"last_page_business_id", GlobalActivityManager.getLastPageEntity().getPageBusinessId(),
"download_status", gameEntity.getDownloadStatusChinese(),
"download_type", trackDownloadType
"download_type", trackDownloadType,
"is_from_push_notifications", isFromPush,
"message_id", pushMessageId,
"link_id", pushLinkId,
};
List<String> kvs = new ArrayList<>(Arrays.asList(arrayKv));
List<Object> kvs = new ArrayList<>(Arrays.asList(arrayKv));
if (customPageTrackData != null) {
kvs.addAll(Arrays.asList(customPageTrackData.toKV()));
}
SensorsBridge.trackEventWithExposureSource("DownloadProcessBegin",
downloadExposureEvent.getSource(), kvs.toArray(new String[0])
downloadExposureEvent.getSource(), kvs.toArray(new Object[0])
);
//TODO remove

View File

@ -164,7 +164,8 @@ class DownloadDialog : BaseDraggableDialogFragment() {
true,
mTraceEvent,
mEntrance,
mLocation
mLocation,
onDownloadClickAction
)
mBinding.collectionList.layoutManager = createLayoutManager(itemList)
mBinding.collectionList.adapter = mCollectionAdapter

View File

@ -119,6 +119,7 @@ import com.sina.weibo.sdk.auth.AuthInfo;
import com.sina.weibo.sdk.openapi.IWBAPI;
import com.sina.weibo.sdk.openapi.WBAPIFactory;
import com.therouter.TheRouter;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.jetbrains.annotations.NotNull;
@ -222,7 +223,7 @@ public class MainActivity extends BaseActivity {
DialogHelper.showCenterWarningDialog(this, "发生闪退", "光环助手发生了闪退,建议安装到最新版本修复异常"
, "马上反馈", "马上安装修复",
() -> {
DirectUtils.directToGameDetail(this, Constants.GHZS_GAME_ID, "", "crash", true, "desc", null);
DirectUtils.directToGameDetail(this, Constants.GHZS_GAME_ID, "", "crash", true, "desc", null, "");
return null;
},
() -> {
@ -255,9 +256,12 @@ public class MainActivity extends BaseActivity {
// 跳转至其它页面
if (getIntent() != null
&& getIntent().getExtras() != null
&& getIntent().getBooleanExtra(EntranceConsts.KEY_REQUIRE_REDIRECT, false)) {
doSkip();
&& getIntent().getExtras() != null) {
if (getIntent().getBooleanExtra(EntranceConsts.KEY_REQUIRE_REDIRECT, false)) {
doSkip();
} else if (!TextUtils.isEmpty(getIntent().getStringExtra(EntranceConsts.KEY_THE_ROUTER_PATH))) {
doRedirect(getIntent().getStringExtra(EntranceConsts.KEY_THE_ROUTER_PATH));
}
}
// debug 模式下的快速跳转页面
@ -456,6 +460,10 @@ public class MainActivity extends BaseActivity {
handler.removeCallbacksAndMessages(null);
releaseExoSourceCache();
// 移除推送触发启动记录
HaloApp.remove(Constants.PUSH_MESSAGE_ID);
HaloApp.remove(Constants.PUSH_LINK_ENTITY);
}
/**
@ -820,6 +828,19 @@ public class MainActivity extends BaseActivity {
}, 500);
}
/**
* 重定向至 TheRouter 配置的页面
*/
private void doRedirect(String path) {
if (getIntent().getExtras() != null) {
// 更新 intent 数据,避免页面重建重新跳转
getIntent().getExtras().putString(EntranceConsts.KEY_THE_ROUTER_PATH, "");
AppExecutor.getUiExecutor().executeWithDelay(() -> {
TheRouter.build(path).navigation(this);
}, 500L);
}
}
@NonNull
private Function0<Unit> launchGame(String gamePackageName) {
return () -> {

View File

@ -1,6 +1,7 @@
package com.gh.gamecenter;
import static com.gh.gamecenter.common.constant.EntranceConsts.ENTRANCE_BROWSER;
import static com.gh.gamecenter.common.constant.EntranceConsts.ENTRANCE_OTHER;
import static com.gh.gamecenter.common.constant.EntranceConsts.ENTRANCE_PUSH;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ANSWER;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_ARCHIVE_LOGIN;
@ -35,6 +36,7 @@ import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_VIDEO_STREAM
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_VIDEO_STREAMING_HOME;
import static com.gh.gamecenter.common.constant.EntranceConsts.HOST_WEB;
import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_DATA;
import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_FROM;
import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_GAME_NAME;
import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_NAME;
import static com.gh.gamecenter.common.constant.EntranceConsts.KEY_PACKAGENAME;
@ -100,7 +102,6 @@ public class SkipActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Uri uri = getIntent().getData();
Bundle bundle;
if (uri != null) {
@ -160,7 +161,8 @@ public class SkipActivity extends BaseActivity {
DirectUtils.directToArticle(this, path, entrance);
break;
case HOST_GAME:
DirectUtils.directToGameDetail(this, path, "", entrance, "true".equals(uri.getQueryParameter("auto_download")), to, null);
String from = uri.getQueryParameter(KEY_FROM);
DirectUtils.directToGameDetail(this, path, "", entrance, "true".equals(uri.getQueryParameter("auto_download")), to, null, from);
break;
case HOST_COLUMN:
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), entrance, null, SubjectData.SubjectType.NORMAL);
@ -180,7 +182,7 @@ public class SkipActivity extends BaseActivity {
DirectUtils.directToAnswerDetail(this, path, entrance, pathName);
break;
case HOST_QUESTION:
DirectUtils.directToQuestionDetail(this, path, entrance, pathName, "");
DirectUtils.directToQuestionDetail(this, path, entrance, pathName, isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
break;
case HOST_TOOLBOX:
DirectUtils.directToToolbox(this, uri.getQueryParameter("gameId"), uri.getQueryParameter("toolboxUrl"), entrance);
@ -190,7 +192,7 @@ public class SkipActivity extends BaseActivity {
break;
// 社区文章格式一
case "community.article":
DirectUtils.directToCommunityArticle(this, uri.getQueryParameter("articleId"), uri.getQueryParameter("communityId"), entrance, pathName, "");
DirectUtils.directToCommunityArticle(this, uri.getQueryParameter("articleId"), uri.getQueryParameter("communityId"), entrance, pathName, isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
break;
// 社区文章格式二
case "communities":
@ -211,13 +213,13 @@ public class SkipActivity extends BaseActivity {
}
}
if ("articles".equals(type)) {
DirectUtils.directToCommunityArticle(this, typeId, communityId, entrance, pathName, "");
DirectUtils.directToCommunityArticle(this, typeId, communityId, entrance, pathName, isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
break;
}
break;
case HOST_VIDEO:
DirectUtils.directToVideoDetail(this, path, VideoDetailContainerViewModel.Location.HOTTEST_GAME_VIDEO.getValue(),
false, id, entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer, "");
false, id, entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer, isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
break;
case HOST_UPLOAD_VIDEO://跳转上传视频
String titleParameter = uri.getQueryParameter("title");
@ -237,7 +239,7 @@ public class SkipActivity extends BaseActivity {
break;
case HOST_VIDEO_SINGLE:
DirectUtils.directToVideoDetail(this, path, VideoDetailContainerViewModel.Location.SINGLE_VIDEO.getValue(),
false, "", entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer, "");
false, "", entrance, pathName, TextUtils.isEmpty(referer) ? "" : referer, isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
break;
case HOST_VIDEO_MORE:
gameId = uri.getQueryParameter("gameId");
@ -294,7 +296,7 @@ public class SkipActivity extends BaseActivity {
EntranceUtils.jumpActivityCompat(this, bundle);
break;
case EntranceConsts.HOST_VIDEO_DETAIL:
DirectUtils.directToVideoDetail(this, path, entrance, "", "");
DirectUtils.directToVideoDetail(this, path, entrance, "", isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
break;
case HOST_LIBAO:
DirectUtils.directToGiftDetail(this, path, entrance);
@ -315,7 +317,7 @@ public class SkipActivity extends BaseActivity {
break;
case HOST_COLUMN_COLLECTION:
DirectUtils.directToColumnCollection(this, path, -1, entrance, "", "", "", "", null,false);
DirectUtils.directToColumnCollection(this, path, -1, entrance, "", "", "", "", null, false);
break;
case EntranceConsts.HOST_BLOCK:
name = uri.getQueryParameter("name");
@ -357,7 +359,7 @@ public class SkipActivity extends BaseActivity {
byte[] linkData = Base64.decode(dataString, Base64.DEFAULT);
String linkDataString = new String(linkData, "UTF-8");
LaunchRedirect launchRedirect = GsonUtils.fromJson(linkDataString, LaunchRedirect.class);
DirectUtils.directToLinkPage(this, launchRedirect, entrance, "", "");
DirectUtils.directToLinkPage(this, launchRedirect, entrance, "", isFromPush ? ENTRANCE_PUSH : ENTRANCE_OTHER);
}
} catch (Exception e) {
e.printStackTrace();
@ -414,13 +416,13 @@ public class SkipActivity extends BaseActivity {
break;
case HOST_ARCHIVE_LOGIN:
String gamePkg = uri.getQueryParameter(EntranceConsts.KEY_GAME_PKG);
if(CheckLoginUtils.isLogin()) {
if (CheckLoginUtils.isLogin()) {
VHelper.INSTANCE.updateAuthorizeInfo(true);
} else {
Bundle newBundle = new Bundle();
newBundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
EntranceUtils.jumpActivityCompat(this, newBundle, null, (resultCode, data) -> {
if(CheckLoginUtils.isLogin()) {
if (CheckLoginUtils.isLogin()) {
VHelper.INSTANCE.updateAuthorizeInfo(true);
}
VHelper.launch(this, gamePkg, false, false);

View File

@ -5,6 +5,7 @@ import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.preference.PreferenceManager
@ -26,6 +27,9 @@ import com.gh.common.util.UsageStatsHelper.checkAndPostUsageStats
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.base.activity.BaseActivity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.constant.EntranceConsts.KEY_FROM
import com.gh.gamecenter.common.constant.EntranceConsts.KEY_GAMEID
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.tracker.TrackerLogger
import com.gh.gamecenter.common.utils.*
@ -90,8 +94,9 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
showPrivacyDialog()
} else {
val spanBuilder = buildSpannedString {
append("这个弹窗只会在右上角有环境标签的测试包出现" +
"\n进入应用以后还可以到关于我们页面长按应用图标重新选择"
append(
"这个弹窗只会在右上角有环境标签的测试包出现" +
"\n进入应用以后还可以到关于我们页面长按应用图标重新选择"
)
bold {
color(com.gh.gamecenter.common.R.color.text_theme.toColor(this@SplashScreenActivity)) {
@ -104,7 +109,7 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
executeDex2OatInAdvance()
DialogHelper.showDialog(
context = this,
title ="选择环境",
title = "选择环境",
content = spanBuilder,
confirmText = "正式环境",
cancelText = "测试环境",
@ -145,6 +150,10 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
val trackEvent = JSONObject()
// 是否首次使用神策
val isFirstTime = SPUtils.getBoolean(Constants.SP_SENSORS_IS_FIRST_TIME, true)
val therouterPath = intent.extras?.getString(EntranceConsts.KEY_THE_ROUTER_PATH) ?: ""
val uri = Uri.parse(therouterPath)
val isFromWechat = WECHAT_APPOINTMENT == if (!uri.isOpaque) uri.getQueryParameter(KEY_FROM) else false
val gameId = if (!uri.isOpaque) uri.getQueryParameter(KEY_GAMEID) else ""
tryCatchInRelease {
trackEvent.run {
put("\$is_first_time", isFirstTime)
@ -154,6 +163,10 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
put("signature", signatureHash)
put("app_name", appProvider?.getAppName())
put("install_first_time", if (HaloApp.getInstance().isBrandNewInstall) "" else "")
if (isFromWechat) {
put("source_entrance", WECHAT_NOTIFICATION)
put("page_business_id", gameId)
}
}
}
SensorsBridge.trackEvent("AppLaunch", trackEvent)
@ -324,6 +337,9 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen {
const val HONOR_CULPRIT_ID = 12324
const val HONOR_CULPRIT_CHANNEL = "荣耀通道"
private const val WECHAT_APPOINTMENT = "wechat_appointment"
private const val WECHAT_NOTIFICATION = "微信通知"
@JvmStatic
fun getSplashScreenIntent(context: Context?, bundle: Bundle?): Intent {
val intent = Intent(context, SplashScreenActivity::class.java)

View File

@ -107,12 +107,12 @@ class DetailViewHolder(
// 注意 View 的命名
init {
downloadBottom = view.findViewById(R.id.detail_ll_bottom)
downloadPb = view.findViewById(R.id.detail_progressbar)
downloadTips = view.findViewById(R.id.downloadTipsLottie)
downloadPb = downloadBottom.findViewById(R.id.detail_progressbar)
downloadTips = downloadBottom.findViewById(R.id.downloadTipsLottie)
overlayTv = view.findViewById(R.id.overlayTv)
overlayContainer = view.findViewById(R.id.overlayContainer)
extraOverlayTv = view.findViewById(R.id.extraOverlayTv)
multiVersionDownloadTv = view.findViewById(R.id.multiVersionDownloadTv)
multiVersionDownloadTv = downloadBottom.findViewById(R.id.multiVersionDownloadTv)
localDownloadContainer = view.findViewById(R.id.localDownloadContainer)
localDownloadSizeTv = view.findViewById(R.id.localDownloadSizeTv)
localDownloadTitleTv = view.findViewById(R.id.localDownloadTitleTv)

View File

@ -242,7 +242,7 @@ class CategoryV2ListAdapter(
gameIconView.displayGameIcon(gameEntity)
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
BindingAdapters.setGameName(gameName, gameEntity, false)
BindingAdapters.setGameTags(labelList, gameEntity)
BindingAdapters.setGameTags(labelList, gameEntity, "")
gameRating.setDrawableStart(if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable() else null)
gameRating.text = if (gameEntity.commentCount > 3) {
if (gameEntity.star == 10.0F) "10" else gameEntity.star.toString()

View File

@ -15,6 +15,7 @@ import com.gh.gamecenter.common.base.BaseSimpleDao
import com.gh.gamecenter.common.base.GlobalActivityManager.getCurrentPageEntity
import com.gh.gamecenter.common.base.GlobalActivityManager.getLastPageEntity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.GsonUtils.toJson
@ -629,6 +630,7 @@ class UpdatableGameViewModel(
downloadEntity.addMetaExtra(Constants.APK_MD5, update.md5)
downloadEntity.addMetaExtra(Constants.GAME_NAME, update.name)
downloadEntity.addMetaExtra(Constants.GAME_CATEGORY_IN_CHINESE, update.categoryChinese)
downloadEntity.addMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE, update.downloadStatusChinese)
downloadEntity.putGameCategory(update.category ?: "")
if (update.isModdedGame) {
downloadEntity.addMetaExtra(Constants.EXTRA_IS_MODDED_GAME, "true")
@ -685,6 +687,9 @@ class UpdatableGameViewModel(
// 收集下载数据
DataCollectionUtils.uploadDownload(getApplication(), downloadEntity, "开始")
val pushMessageId = (HaloApp.get(Constants.PUSH_MESSAGE_ID, false) as? String) ?: ""
val pushLinkId = (HaloApp.get(Constants.PUSH_LINK_ENTITY, false) as? LinkEntity)?.link ?: ""
val isFromPush = pushMessageId.isNotEmpty()
SensorsBridge.trackEventWithExposureSource(
"DownloadProcessBegin",
event.source,
@ -700,6 +705,9 @@ class UpdatableGameViewModel(
"last_page_business_id", getLastPageEntity().pageBusinessId,
"download_status", update.downloadStatusChinese,
"download_type", "本地下载",
"is_from_push_notifications", isFromPush,
"message_id", pushMessageId,
"link_id", pushLinkId,
)
}

View File

@ -11,6 +11,8 @@ class ReserveReminderEntity(
private var _smsConfig: SmsConfig? = null,
@SerializedName("wechat_config")
private var _wechatConfig: WechatConfigEntity? = null,
@SerializedName("calendar_config")
private var _calendarConfig: CalendarConfig? = null,
@SerializedName("mirror_type")
private val _mirrorType: String? = null,
@SerializedName("wifi_auto_download")
@ -34,8 +36,14 @@ class ReserveReminderEntity(
_wechatConfig = value
}
val onlyShowWechatReminder: Boolean
get() = _smsConfig == null
val hasCalendarConfig: Boolean
get() = _calendarConfig != null
var calendarConfig: CalendarConfig
get() = _calendarConfig ?: CalendarConfig()
set(value) {
_calendarConfig = value
}
val mirrorType: String
get() = _mirrorType ?: ""
@ -81,4 +89,39 @@ class ReserveReminderEntity(
}
}
@Parcelize
class CalendarConfig(
@SerializedName("notice")
private val _notice: Boolean? = null,
@SerializedName("title")
private val _title: String? = null,
@SerializedName("time_start")
private val _timeStart: Long? = null,
@SerializedName("time_end")
private val _timeEnd: Long? = null,
@SerializedName("advance_seconds")
private val _advanceSeconds: Long? = null,
@SerializedName("remark")
private val _remark: String? = null
) : Parcelable {
val notice: Boolean
get() = _notice ?: false
val title: String
get() = _title ?: ""
val timeStart: Long
get() = _timeStart ?: 0L
val timeEnd: Long
get() = _timeEnd ?: 0L
val advanceSeconds: Long
get() = _advanceSeconds ?: 0L
val remark: String
get() = _remark ?: ""
}
}

View File

@ -130,12 +130,13 @@ data class SubjectEntity(
@IgnoredOnParcel
private var filteredData: MutableList<GameEntity>? = null
val subjectType: SubjectData.SubjectType get() = when {
isQQColumn -> SubjectData.SubjectType.QQ_GAME
isWechatColumnCPM -> SubjectData.SubjectType.WECHAT_GAME_CPM
isWechatColumn -> SubjectData.SubjectType.WECHAT_GAME
else -> SubjectData.SubjectType.NORMAL
}
val subjectType: SubjectData.SubjectType
get() = when {
isQQColumn -> SubjectData.SubjectType.QQ_GAME
isWechatColumnCPM -> SubjectData.SubjectType.WECHAT_GAME_CPM
isWechatColumn -> SubjectData.SubjectType.WECHAT_GAME
else -> SubjectData.SubjectType.NORMAL
}
val isMiniGame: Boolean get() = isQQColumn || isWechatColumn
@ -148,4 +149,11 @@ data class SubjectEntity(
val list: Int
get() = max(min(_list ?: 0, data?.size ?: 0), 1)
companion object {
const val SUBJECT_TAG_UPDATE = "update" // 更新时间
const val SUBJECT_TAG_TYPE = "type" // 游戏标签
const val SUBJECT_TAG_TEST = "test" // 开测时间
const val SUBJECT_TAG_SELLING_POINT = "selling_points&type" // 卖点文案+游戏标签
}
}

View File

@ -37,9 +37,9 @@ class UserSearchListFragment : LazyListFragment<FollowersOrFansEntity, UserSearc
SensorsBridge.trackUserSearchResultClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
mListViewModel.sourceEntrance,
mSearchKey,
SearchActivity.toTrackSearchType(mSearchType),
mListViewModel.sourceEntrance,
userId,
position
)

View File

@ -3,10 +3,10 @@ package com.gh.gamecenter.game.vertical
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.os.Build
import android.text.TextUtils
import android.util.AttributeSet
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import android.widget.Space
@ -17,11 +17,12 @@ import androidx.core.content.ContextCompat
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieDrawable
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.gamecenter.feature.view.GameIconView
import com.gh.gamecenter.R
import com.gh.gamecenter.common.databinding.LayoutGameItemSellingPointBinding
import com.gh.gamecenter.common.utils.setDrawableEnd
import com.gh.gamecenter.common.view.GameTagContainerView
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.gamecenter.feature.view.GameIconView
import splitties.dimensions.dip
import splitties.views.backgroundColor
import splitties.views.dsl.constraintlayout.*
@ -63,6 +64,7 @@ class GameItemUi(override val ctx: Context) : Ui {
var gamePlayCountTv: TextView
var mGameDesSpace: Space
var sellingPointsBinding: LayoutGameItemSellingPointBinding
override val root: ConstraintLayout = constraintLayout {
padding = dip(16)
@ -84,6 +86,7 @@ class GameItemUi(override val ctx: Context) : Ui {
gameTagContainer = GameTagContainerView(ctx).apply { id = R.id.label_list }
mGameDesSpace = space { }.apply { id = R.id.gameDesSpace }
recommendConstraintLayout = initRecommendConstraintLayout()
sellingPointsBinding = LayoutGameItemSellingPointBinding.inflate(LayoutInflater.from(context))
add(iconIv, lParams(dip(64), dip(64)) {
topOfParent()
@ -142,6 +145,12 @@ class GameItemUi(override val ctx: Context) : Ui {
endToEndOf(mGameDesSpace)
orientation = LinearLayout.HORIZONTAL
})
add(sellingPointsBinding.root, lParams(0, wrapContent) {
topToBottomOf(mGameDesSpace)
bottomToBottomOf(iconIv)
startToEndOf(gamePlayCountTv)
endToEndOf(mGameDesSpace)
})
add(gamePlayCountTv, lParams(wrapContent, wrapContent) {
topToBottomOf(mGameDesSpace)
bottomToBottomOf(iconIv)
@ -197,7 +206,8 @@ class GameItemUi(override val ctx: Context) : Ui {
startPadding = dip(2)
endPadding = dip(2)
ellipsize = TextUtils.TruncateAt.END
background = ContextCompat.getDrawable(context, com.gh.gamecenter.feature.R.drawable.bg_advance_download_game_subtitle)
background =
ContextCompat.getDrawable(context, com.gh.gamecenter.feature.R.drawable.bg_advance_download_game_subtitle)
setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.text_secondary))
visibility = View.GONE
}
@ -305,7 +315,12 @@ class GameItemUi(override val ctx: Context) : Ui {
gravity = Gravity.CENTER
text = "展开"
setTextColor(ContextCompat.getColor(context, com.gh.gamecenter.common.R.color.white))
setDrawableEnd(AppCompatResources.getDrawable(context, com.gh.gamecenter.feature.R.drawable.ic_jump_universal))
setDrawableEnd(
AppCompatResources.getDrawable(
context,
com.gh.gamecenter.feature.R.drawable.ic_jump_universal
)
)
compoundDrawablePadding = dip(2)
visibility = View.GONE
}

View File

@ -166,7 +166,7 @@ class GameVerticalAdapter(
false
)
BindingAdapters.setGame(iconIv, gameEntity)
BindingAdapters.setGameTags(gameTagContainer, gameEntity)
BindingAdapters.setGameTags(gameTagContainer, gameEntity, subjectData?.tag ?: "")
GameItemViewHolder.initServerType(gameNameTv, serverTypeTv, gameEntity)
gameDesTv.text = gameEntity.decoratedDes
GameItemViewHolder.initGameSubtitleAndAdLabel(
@ -225,10 +225,10 @@ class GameVerticalAdapter(
subjectData?.briefStyle
)
DownloadItemUtils.setOnClickListener(
context, downloadTv, gameEntity, position,
adapter, entrance, location = location, traceEvent = gameEntity.exposureEvent
)
DownloadItemUtils.setOnClickListener(
context, downloadTv, gameEntity, position,
adapter, entrance, location = location, traceEvent = gameEntity.exposureEvent
)
root.setPadding(paddingStart, 8F.dip2px(), paddingEnd, 8F.dip2px())
}

View File

@ -610,7 +610,7 @@ open class GameCollectionDetailAdapter(
gameIconView.displayGameIcon(gameEntity)
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
BindingAdapters.setGameName(gameName, gameEntity, false)
BindingAdapters.setGameTags(labelList, gameEntity)
BindingAdapters.setGameTags(labelList, gameEntity, "")
gameRating.setDrawableStart(
if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable(mContext) else null
)

View File

@ -45,7 +45,6 @@ import com.google.gson.JsonArray
import com.google.gson.reflect.TypeToken
import com.halo.assistant.HaloApp
import com.halo.assistant.accelerator.repository.AccelerationRepository
import com.halo.assistant.accelerator.repository.AcceleratorDataHolder
import com.lightgame.utils.Utils
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
@ -133,7 +132,9 @@ class GameDetailViewModel(
private var isGameUpdatable = false
private val compositeDisposable = CompositeDisposable()
private var userRelatedInfoReceivedCallback: (() -> Unit)? = null
init {
loadData()
}
@ -769,8 +770,14 @@ class GameDetailViewModel(
.subscribe({
unifiedUserTrendEntity = it
emitter.onSuccess(Result.success(it))
userRelatedInfoReceivedCallback?.invoke()
userRelatedInfoReceivedCallback = null
}, {
emitter.onSuccess(Result.failure(it))
userRelatedInfoReceivedCallback?.invoke()
userRelatedInfoReceivedCallback = null
})
}
@ -800,9 +807,21 @@ class GameDetailViewModel(
tabSelectedLiveData.postValue(Event(LinkEntity(type = type)))
}
fun performContentCardClicked(contentCardType: String): Boolean {
/**
* 发送内容卡片点击事件
* @param contentCardType 内容卡片类型
* @param waitForUserRelatedResult 是否等待用户相关信息请求结果
* @return 是否成功触发点击事件
*/
fun performContentCardClicked(contentCardType: String, waitForUserRelatedResult: Boolean = false): Boolean {
return if (contentCardList?.any { it.link.type == contentCardType } == true) {
contentCardClickedLiveData.postValue(Event(contentCardType))
if (waitForUserRelatedResult && CheckLoginUtils.isLogin()) {
userRelatedInfoReceivedCallback = {
contentCardClickedLiveData.postValue(Event(contentCardType))
}
} else {
contentCardClickedLiveData.postValue(Event(contentCardType))
}
true
} else {
false
@ -812,7 +831,7 @@ class GameDetailViewModel(
fun performScrollToServer(): Boolean {
// 如果该游戏的【内容卡片】在详情中显示类型为【游戏开服】的卡片时,触发点击类型为【游戏开服】的内容卡片进入开服日历表页面
// 如果该游戏的【内容卡片】在详情中没有【游戏开服】的卡片时,定位到游戏详情页-详情tab-【游戏开服】组件
return if (performContentCardClicked(ContentCardEntity.TYPE_SERVER)) {
return if (performContentCardClicked(ContentCardEntity.TYPE_SERVER, true)) {
true
} else if (detailDataListLiveData.value?.any { it.linkServer != null } == true) {
scrollToListPositionLiveData.postValue(Event(LinkEntity(type = GameDetailData.TYPE_SERVER)))
@ -962,7 +981,7 @@ class GameDetailViewModel(
unifiedUserTrendEntity.game?.let {
if (it.isEmpty()) return@let
for (game in it) {
meLiveData.postValue(game.me)
meLiveData.value = game.me
break
}
}

View File

@ -45,6 +45,7 @@ import com.gh.gamecenter.common.base.fragment.BaseLazyFragment
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.eventbus.EBReuse
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.json.json
import com.gh.gamecenter.common.mvvm.Status
@ -471,8 +472,8 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
}, 120)
val viewHolder = detailViewHolder
binding.divider.isVisible = true
DetailDownloadUtils.updateViewHolder(viewHolder)
binding.divider.isVisible = binding.detailLlBottom.root.isVisible
if (autoDownload || isOpenPlatformWindow && gameEntity!!.getApk().size > 1) {
viewHolder.downloadPb.performClick()
@ -727,6 +728,8 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
fragment = fragment ?: WebFragment()
bundle.putString(EntranceConsts.KEY_ENTRANCE, "游戏专区")
bundle.putString(EntranceConsts.KEY_URL, zone.link)
bundle.putBoolean(WebFragment.KEY_ENABLE_HORIZONTAL_SCROLL_DISPATCH, true)
bundle.putBoolean(WebFragment.KEY_FORCE_ENABLE_NESTED_SCROLL, true)
} else {
fragment = fragment ?: FuLiFragment()
}
@ -735,6 +738,12 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
GameDetailTabEntity.TYPE_WEB -> {
fragment = fragment ?: WebFragment()
bundle.putString(EntranceConsts.KEY_URL, tabEntity.link?.link)
bundle.putBoolean(WebFragment.KEY_ENABLE_HORIZONTAL_SCROLL_DISPATCH, true)
bundle.putBoolean(WebFragment.KEY_FORCE_ENABLE_NESTED_SCROLL, true)
bundle.putBoolean(
WebFragment.KEY_LEAVE_WEB_PAGE_TO_HANDLE_BACK_PRESSED,
tabEntity.link?.link?.contains("leave_web_page_handle_back_pressed=true") == true
)
}
GameDetailTabEntity.TYPE_GIFT -> {
@ -749,6 +758,7 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
bundle.putString(EntranceConsts.KEY_CUSTOM_PAGE_ID, tabEntity.link?.link)
bundle.putString(EntranceConsts.KEY_CUSTOM_PAGE_NAME, tabEntity.link?.text)
bundle.putBoolean(EntranceConsts.KEY_SHOW_FLOATING_WINDOW, false)
bundle.putBoolean(EntranceConsts.KEY_SHOW_PULL_DOWN_PUSH, false)
}
}
fragment?.let {
@ -757,7 +767,7 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
}
}
viewPager.setRestoredCurItem(destinationTab)
currentVpPosition = destinationTab
onPageSelected(destinationTab)
viewPager.offscreenPageLimit = fragmentsList.size
viewPager.adapter =
FragmentAdapter(childFragmentManager, fragmentsList, tabEntityList.map { it.name })
@ -1102,6 +1112,13 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
return true
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(reuse: EBReuse) {
if ("download" == reuse.type) {
downloadBinding.detailProgressbar.performClick()
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(status: EBDownloadStatus) {
updateDownloadCountHint(packageViewModel.filterSameUpdateLiveData.value)
@ -1541,9 +1558,12 @@ class GameDetailWrapperFragment : BaseLazyFragment(), IScrollable {
downloadMenuIcon?.setImageResource(R.drawable.toolbar_download)
if (::viewModel.isInitialized) {
updateConcernMenuIcon(viewModel.meLiveData.value?.isGameConcerned ?: false)
detailViewHolder.downloadPb.buttonStyle = detailViewHolder.downloadPb.buttonStyle
if (detailViewHolder.downloadTips.visibility == View.VISIBLE) {
detailViewHolder.downloadTips.setDownloadTipsAnimation(detailViewHolder.downloadTips.isAnimating)
if (gameEntity != null) {
val viewHolder = detailViewHolder
viewHolder.downloadPb.buttonStyle = detailViewHolder.downloadPb.buttonStyle
if (viewHolder.downloadTips.isVisible) {
viewHolder.downloadTips.setDownloadTipsAnimation(detailViewHolder.downloadTips.isAnimating)
}
}
}
controlReserveBtn()

View File

@ -21,13 +21,14 @@ class StartingAcceleratorViewModel : ViewModel() {
val useCase = AccelerationUseCase()
private val _restartingAcceleratorAction = MutableLiveData<Event<Boolean>>()
val restartingAcceleratorAction: LiveData<Event<Boolean>> = _restartingAcceleratorAction
private val _restartingAcceleratorAction = MutableLiveData<Event<Unit>>()
val restartingAcceleratorAction: LiveData<Event<Unit>> = _restartingAcceleratorAction
fun loadAcceleratorToken() {
val userId = UserManager.getInstance().userId
if (userId.isNotBlank()) {
UserRepository.getInstance().setAcceleratorToken(userId) {
_restartingAcceleratorAction.value = Event(it)
// 这里就算setToken失败也要调用启动加速失败会走正常的日志上报
_restartingAcceleratorAction.value = Event(Unit)
}
}
}

View File

@ -27,7 +27,6 @@ import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.StartingAcceleratorViewModel
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.DISTRICT_SERVER_HAVA
import com.gh.gamecenter.gamedetail.accelerator.GameDetailAcceleratorUiHelper.Companion.SOURCE_ENTRANCE_GAME_DETAIL
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_ENABLE_VIP
import com.gh.gamecenter.gamedetail.accelerator.dialog.AcceleratorDialogFragment.Companion.SPEED_START_FAILURE
import com.gh.gamecenter.livedata.EventObserver
import com.gh.gamecenter.login.user.UserManager
@ -76,7 +75,7 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
is AccelerateState.Failure -> {
// 有些错误需要额外处理,这里直接跳过错误提示(如token失效登录时token设置失败)
if ((state.isTokenExpired || state.isTokenEmpty) && refreshTokenCount < REFRESH_TOKEN_MAX_COUNT) {
if ((state.isTokenInvalid) && refreshTokenCount < REFRESH_TOKEN_MAX_COUNT) {
// do nothing
} else {
if (!state.isSkipError) {
@ -109,7 +108,7 @@ class StartingAcceleratorDialogFragment : BaseDialogFragment() {
is AccelerateState.Normal -> {
if (state.isTokenExpired || state.isTokenEmpty) {
if (state.isTokenInvalid) {
// token过期/登录时token设置失败,在此获取token并重新启动加速(最多重试三次)
if (refreshTokenCount < REFRESH_TOKEN_MAX_COUNT) {
viewModel.loadAcceleratorToken()

View File

@ -271,8 +271,7 @@ class GameDetailFragment : LazyFragment(), IScrollable {
}
val infoTagData = viewModel.infoTagLiveData.value
val isFunctionTagShow = infoTagData?.requestSpeedStatus == "on" || !infoTagData?.infoTags.isNullOrEmpty()
val showFunctionTagGuide = isFunctionTagShow && SPUtils.getBoolean(Constants.SP_SHOW_GAME_DETAIL_FUNCTION_TAG_GUIDE, true)
val showFunctionTagGuide = !infoTagData?.infoTags.isNullOrEmpty() && SPUtils.getBoolean(Constants.SP_SHOW_GAME_DETAIL_FUNCTION_TAG_GUIDE, true)
if (!isPerformedSuccess && showFunctionTagGuide) {
binding.coverRv.post {
showFunctionTagGuide()
@ -308,7 +307,7 @@ class GameDetailFragment : LazyFragment(), IScrollable {
private fun initDetailRv() {
binding.detailRv.run {
(itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
itemAnimator = null
layoutManager = detailLayoutManager
adapter = detailListAdapter
addOnScrollListener(object : OnScrollListener() {
@ -924,6 +923,7 @@ class GameDetailFragment : LazyFragment(), IScrollable {
// 登录事件/礼包状态变更事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(reuse: EBReuse) {
if (!::viewModel.isInitialized) return
if (reuse.type == Constants.LOGIN_TAG || (reuse.type == Constants.LIBAO_CHANGED_TAG && !isSupportVisible)) {
viewModel.getUserRelatedInfoAndGiftStatus()
}
@ -932,6 +932,7 @@ class GameDetailFragment : LazyFragment(), IScrollable {
// 更新评分
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(data: EBStar) {
if (!::binding.isInitialized) return
if (binding.scoreContainer.isVisible) {
val showScore = data.commentCount > 3
binding.scoreIv.setImageResource(if (showScore) R.drawable.text_game_detail_score else R.drawable.text_game_detail_no_score)
@ -944,6 +945,8 @@ class GameDetailFragment : LazyFragment(), IScrollable {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (!::viewModel.isInitialized) return
val commentPosition = detailListAdapter.currentList.indexOfFirst { it.linkComment != null }
if (resultCode == Activity.RESULT_OK) {
if (GameDetailCommentItemViewHolder.RATING_REPLY_REQUEST == requestCode || GameDetailCommentItemViewHolder.RATING_PATCH_REQUEST == requestCode) {
@ -995,6 +998,8 @@ class GameDetailFragment : LazyFragment(), IScrollable {
override fun onDarkModeChanged() {
super.onDarkModeChanged()
if (!::binding.isInitialized || !::viewModel.isInitialized) return
binding.coverSfv.run {
setIndicatorBackground(com.gh.gamecenter.common.R.drawable.background_shape_white_radius_999.toDrawable(requireContext()))
setTextColor(

View File

@ -150,7 +150,7 @@ class GameDetailCoverAdapter(
val ratio = imageWidth / imageHeight.toFloat()
ConstraintSet().also {
it.clone(holder.binding.root)
it.setDimensionRatio(holder.binding.galleryIv.id, if (isLandscape) "h,344:193" else "")
it.setDimensionRatio(holder.binding.galleryIv.id, if (isLandscape) "h,16:9" else "")
}.applyTo(holder.binding.root)
holder.binding.root.updateLayoutParams<MarginLayoutParams> {
width = if (isLandscape || isSingleGallery) ViewGroup.LayoutParams.MATCH_PARENT else ViewGroup.LayoutParams.WRAP_CONTENT

View File

@ -51,7 +51,7 @@ class GameDetailRelatedGameAdapter(
holder.binding.root.setPadding(paddingStart, 8F.dip2px(), paddingEnd, 8F.dip2px())
holder.binding.gameNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
holder.binding.gameNameTv.text = gameEntity.name
BindingAdapters.setGameTags(holder.binding.gameLabelLl, gameEntity)
BindingAdapters.setGameTags(holder.binding.gameLabelLl, gameEntity, "")
holder.binding.gameIconView.displayGameIcon(gameEntity)
holder.binding.gameIconView.setBorderColor(com.gh.gamecenter.common.R.color.resource_border)
holder.itemView.setOnClickListener {

View File

@ -46,7 +46,7 @@ class GameDetailBriefItemViewHolder(
highlightedTextClickListener = TextHelper.CopyToClipboardHighlightedTextClick()
)
briefTv.post {
expandTv.isVisible = briefTv.lineCount == 3 && briefTv.layout.getEllipsisCount(2) > 0
expandTv.isVisible = briefTv.lineCount == 3 && (briefTv.layout?.getEllipsisCount(2) ?: 0) > 0
}
expandTv.setOnClickListener {
SensorsBridge.trackGameDetailModuleClick(

View File

@ -179,17 +179,23 @@ class GameDetailComprehensivePanelItemViewHolder(
override fun onBindViewHolder(holder: ComprehensivePanelFunctionItemViewHolder, position: Int) {
val data = dataList.getOrNull(position) ?: return
holder.binding.numberIv.setImageResource(R.drawable.bg_game_detail_comprehensive_panel_function_number)
holder.binding.numberIv.goneIf(dataList.size < 2) {
holder.binding.numberIv.setImageResource(R.drawable.bg_game_detail_comprehensive_panel_function_number)
}
holder.binding.numberTv.run {
setTextColor(com.gh.gamecenter.common.R.color.text_aw_primary.toColor(context))
setTypeface(Typeface.createFromAsset(context.assets, Constants.DIN_FONT_PATH))
text = (position + 1).toString()
goneIf(dataList.size < 2) {
setTextColor(com.gh.gamecenter.common.R.color.text_aw_primary.toColor(context))
setTypeface(Typeface.createFromAsset(context.assets, Constants.DIN_FONT_PATH))
text = (position + 1).toString()
}
}
holder.binding.contentTv.run {
setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
maxLines = if (parentViewHolder.showPart && !parentViewHolder.isExpand) 1 else Int.MAX_VALUE
text = data.text
post {
if (layout == null) return@post
val hasEllipsize = layout.getEllipsisCount(0) > 0
if (parentViewHolder.showPart && hasEllipsize && !parentViewHolder.binding.expandTv.isVisible) {
parentViewHolder.binding.expandTv.isVisible = true

View File

@ -211,7 +211,7 @@ class GameDetailContentCardSingleItemViewHolder(
ServersCalendarActivity.getIntent(
context,
viewModel.game!!, contentCardEntity.server!!,
MeEntity()
viewModel.meLiveData.value ?: MeEntity()
)
)
}

View File

@ -27,7 +27,7 @@ class GameDetailDeveloperWordItemViewHolder(
.fromHtmlCompat(PicassoImageGetter(contentTv), ExtraTagHandler())
)
contentTv.post {
expandTv.isVisible = (contentTv.lineCount == 3 && contentTv.layout.getEllipsisCount(2) > 0) || contentTv.lineCount > 3
expandTv.isVisible = (contentTv.lineCount == 3 && (contentTv.layout?.getEllipsisCount(2) ?: 0) > 0) || contentTv.lineCount > 3
}
expandTv.background = R.drawable.bg_ui_surface_expand_gradient.toDrawable(context)
expandTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))

View File

@ -120,14 +120,14 @@ class GameDetailInfoItemViewHolder(
nameTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
infoTv.setTextColor(if (data.name == TYPE_ICP) com.gh.gamecenter.common.R.color.text_theme.toColor(context) else com.gh.gamecenter.common.R.color.text_secondary.toColor(context))
actionTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))
nameTv.text = if (data.name == TYPE_CONTACT) data.contact?.hint else normalTypeNameMap[data.name]
nameTv.text = if (data.name == TYPE_CONTACT) data.text else normalTypeNameMap[data.name]
infoTv.text = when (data.name) {
TYPE_INTERNET -> if (data.value == "yes") "" else ""
TYPE_UPDATE_TIME -> data.value.toLongOrNull()?.let { TimeUtils.getFormatTime(it) }
else -> data.value
}
actionTv.goneIf(data.name != TYPE_CONTACT || data.contact == null) {
val actionString = if (data.contact?.type == "qq") ACTION_CONTACT else if (data.contact?.key.isNullOrEmpty()) ACTION_COPY else ACTION_JOIN
actionTv.goneIf(data.name != TYPE_CONTACT) {
val actionString = if (data.type == "qq") ACTION_CONTACT else if (data.key.isNotEmpty()) ACTION_JOIN else ACTION_COPY
actionTv.text = actionString
actionTv.setOnClickListener {
when (actionString) {
@ -141,7 +141,7 @@ class GameDetailInfoItemViewHolder(
ACTION_JOIN -> {
if (ShareUtils.isQQClientAvailable(context)) {
DirectUtils.directToQqGroup(context, data.contact?.key)
DirectUtils.directToQqGroup(context, data.key)
} else {
data.value.copyTextAndToast("已复制")
}
@ -191,11 +191,11 @@ class GameDetailInfoItemViewHolder(
const val TYPE_CREDIT_CODE = "credit_code"
const val TYPE_SIZE = "size"
const val TYPE_SUPPLIER = "supplier"
const val TYPE_CONTACT = "contact"
const val TYPE_CONTACT = "qq/qq_qun"
const val ACTION_COPY = "复制"
const val ACTION_JOIN = "加入"
const val ACTION_CONTACT = "咨询"
const val ACTION_CONTACT = "添加"
// 固定信息类型
val staticTypeNameMap = mapOf(

View File

@ -53,7 +53,7 @@ class GameDetailServerItemViewHolder(
context,
viewModel.game!!,
entity,
null
viewModel.meLiveData.value
)
context.startActivity(intent)
viewModel.game?.let {

View File

@ -36,7 +36,7 @@ class GameDetailUpdateItemViewHolder(
}
contentTv.text = entity.updateDes
contentTv.post {
expandTv.isVisible = contentTv.lineCount == 3 && contentTv.layout.getEllipsisCount(2) > 0
expandTv.isVisible = contentTv.lineCount == 3 && (contentTv.layout?.getEllipsisCount(2) ?: 0) > 0
}
expandTv.background = R.drawable.bg_ui_surface_expand_gradient.toDrawable(context)
expandTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(context))

View File

@ -408,12 +408,14 @@ data class GameDetailInfo(
@Parcelize
data class InfoItem(
val name: String = "",
val type: String = "",
val text: String = "",
val key: String = "", // QQ群KEY
val value: String = "",
@SerializedName("is_first")
val isFirst: Boolean = true, // 是否显示在一级页面
val order: Int = -1, // 排序
val permissions: List<Permission>? = null,
val contact: Contact? = null
): Parcelable
}

View File

@ -63,7 +63,7 @@ class HistoryApkListAdapter(
holder.binding.expandTv.setTextColor(com.gh.gamecenter.common.R.color.text_theme.toColor(mContext))
holder.binding.updateDescTv.text = apkEntity.updateDesc
holder.binding.updateDescTv.post {
holder.binding.expandTv.isVisible = holder.binding.updateDescTv.lineCount == 3 && holder.binding.updateDescTv.layout.getEllipsisCount(2) > 0
holder.binding.expandTv.isVisible = holder.binding.updateDescTv.lineCount == 3 && (holder.binding.updateDescTv.layout?.getEllipsisCount(2) ?: 0) > 0
}
holder.binding.versionTv.text = "版本${apkEntity.version}"
holder.binding.releaseDateTv.text = TimeUtils.getFormatTime(apkEntity.updateTime)

View File

@ -513,12 +513,13 @@ class RatingEditActivity : ToolBarActivity(), KeyboardHeightObserver {
ToastUtils.showToast("请先给游戏打分", if (mIsKeyBoardShow) Gravity.CENTER else -1)
return@OnReturnValue
}
if (content.isEmpty()) {
val contentLength = content.count { !it.isWhitespace() }
if (contentLength == 0) {
ToastUtils.showToast("评论内容不能为空喔~", if (mIsKeyBoardShow) Gravity.CENTER else -1)
return@OnReturnValue
}
if (content.length > 10000) {
if (contentLength > 10000) {
ToastUtils.showToast("评论最多10000个字", if (mIsKeyBoardShow) Gravity.CENTER else -1)
return@OnReturnValue
}

View File

@ -112,6 +112,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
private var bottomTabName = ""
private var tabIndex = -1
private var showFloatingWindow = true
private var showPullDownPush = true
private lateinit var pageLocation: PageLocation
@ -143,6 +144,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
bottomTabName = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, "") ?: ""
tabIndex = arguments?.getInt(EntranceConsts.KEY_TAB_INDEX, -1) ?: -1
showFloatingWindow = arguments?.getBoolean(EntranceConsts.KEY_SHOW_FLOATING_WINDOW, true) ?: true
showPullDownPush = arguments?.getBoolean(EntranceConsts.KEY_SHOW_PULL_DOWN_PUSH, true) ?: true
val tabName = arguments?.getString(EntranceConsts.KEY_TAB_NAME, "") ?: ""
val multiTabNavId = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: ""
val multiTabNavName = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""
@ -587,7 +589,9 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable, IB
private fun buildPriorityChain() {
val videoHandler = VideoHandler(24, scrollCalculatorHelper)
priorityChain.addHandler(pullDownPushHandler)
if (showPullDownPush) {
priorityChain.addHandler(pullDownPushHandler)
}
if (showFloatingWindow) {
val floatingWindowHandler = CustomFloatingWindowHandler(23)

View File

@ -187,7 +187,7 @@ class CustomFoldSlideLargeImageItemAdapter(
binding.gStar.goneIf(!(data.data.showStar && game.commentCount > 3)) {
binding.tvStar.text = if (game.star == 10.0F) "10" else game.star.toString()
}
BindingAdapters.setGameTags(binding.llLabel, game)
BindingAdapters.setGameTags(binding.llLabel, game, "")
binding.cvContainer.setCardBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(itemView.context))
try {

View File

@ -91,7 +91,7 @@ class CustomGamePluginAdapter(
binding.gameRating.textSize =
(if (gameEntity.commentCount > 3) 12 else 10).toFloat()
BindingAdapters.setGameName(binding.gameName, gameEntity, true)
BindingAdapters.setGameTags(binding.labelList, gameEntity)
BindingAdapters.setGameTags(binding.labelList, gameEntity, "")
binding.gameRating.setDrawableStart(
if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable() else null,
null,

View File

@ -142,7 +142,7 @@ class CustomGameRefreshVerticalAdapter(
false
)
BindingAdapters.setGame(iconIv, gameEntity)
BindingAdapters.setGameTags(gameTagContainer, gameEntity)
BindingAdapters.setGameTags(gameTagContainer, gameEntity, "")
GameItemViewHolder.initServerType(gameNameTv, serverTypeTv, gameEntity)
gameDesTv.text = gameEntity.decoratedDes
GameItemViewHolder.initGameSubtitleAndAdLabel(

View File

@ -59,7 +59,8 @@ class CustomGameVerticalAdapter(
briefStyle = _data.briefStyle,
adIconActive = _data.adIconActive,
showSubscript = _data.showIndexIconSubscript,
showSubTitle = _data.showIndexSubtitle
showSubTitle = _data.showIndexSubtitle,
subjectTag = _data.tag ?: ""
)
holder.itemView.setOnClickListener {
@ -116,7 +117,8 @@ class CustomGameVerticalAdapter(
briefStyle: String,
adIconActive: Boolean,
showSubscript: Boolean,
showSubTitle: Boolean
showSubTitle: Boolean,
subjectTag: String = ""
) {
val context = itemView.context
@ -141,16 +143,23 @@ class CustomGameVerticalAdapter(
with(ui) {
gameNameTv.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
serverTypeTv.setTextColor(com.gh.gamecenter.common.R.color.primary_theme.toColor(context))
downloadTv.background = com.gh.gamecenter.common.R.drawable.download_button_normal_style.toDrawable(context)
downloadTv.background =
com.gh.gamecenter.common.R.drawable.download_button_normal_style.toDrawable(context)
gameDesTv.setTextColor(com.gh.gamecenter.common.R.color.text_tertiary.toColor(context))
BindingAdapters.setGameName(
gameNameTv,
gameEntity,
false
)
iconIv.displayGameIconWithIfShowSubscript(gameEntity, showSubscript)
BindingAdapters.setGameTags(gameTagContainer, gameEntity)
BindingAdapters.setGameTagsWithSellingPoint(
gameTagContainer,
sellingPointsBinding,
gameEntity,
subjectTag
)
GameItemViewHolder.initServerType(gameNameTv, serverTypeTv, gameEntity)
val styleResId = R.style.CustomPageGameRating

View File

@ -46,6 +46,7 @@ import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_GAME_HORIZONTAL_TIME_LINE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_GAME_ICON_MATRIX
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_GAME_LONG_LIST
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_GAME_VERTICAL_IMAGE_TEXT
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_GAME_VERTICAL_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_HORIZONTAL_SLIDE_VIDEO_LIST
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_PAGE_ITEM_TYPE_MINI_GAME_RECENT_PLAY
@ -76,7 +77,7 @@ class CustomPageAdapter(
/**
* 记录第一个显示的 itemView 的位置
* note由于组件中可能在第一个位置配置了 va最近在玩 qq小游戏最近在玩 微信小游戏最近在玩
* note由于组件中可能在第一个位置配置了 va最近在玩 qq小游戏最近在玩 微信小游戏最近在玩 加速-最近在玩
* 当后台配置了这几个组件时用户还没有玩过游戏这几个组件会加入到显示列表中由于还没有数据ItemView处于隐藏状态
* 所以:使用 viewHolder.bindingAdapterPosition == 0 来判断是否是第一个组件时会出现不准的情况
*/
@ -94,35 +95,44 @@ class CustomPageAdapter(
super.submitList(dataWithFooter)
}
/**
* 查找第一个出现的组件 在 data 中的位置
* 请注意:这里的 return 不能删除
*/
fun updateFirstItemId() {
currentList.forEachIndexed { index, item ->
when (item) {
is CustomRecentGamesItem -> {
if (item.data.isNotEmpty()) {
_firstShowPosition.value = index
return
}
}
is CustomRecentWeChatMiniGamesItem -> {
if (item.data.isNotEmpty()) {
_firstShowPosition.value = index
return
}
}
is CustomRecentQqMiniGamesItem -> {
if (item.data.isNotEmpty()) {
_firstShowPosition.value = index
return
}
}
is CustomRecentAcceleratorItem -> {
if (item.data.isNotEmpty()) {
_firstShowPosition.value = index
return
}
}
else -> {
_firstShowPosition.value = index
return
}
}
}
@ -276,6 +286,9 @@ class CustomPageAdapter(
CUSTOM_PAGE_ITEM_TYPE_DOUBLE_GAME_WELFARE_CARD ->
CustomDoubleWelfareCardViewHolder(viewModel, parent.toBinding())
CUSTOM_PAGE_ITEM_TYPE_GAME_VERTICAL_IMAGE_TEXT ->
CustomGameVerticalImageTextViewHolder(viewModel, parent.toBinding())
CUSTOM_PAGE_ITEM_TYPE_ACCELERATOR_RECENT_PLAYED -> {
CustomRecentAcceleratorViewHolder(viewModel, parent.toBinding())
}
@ -476,15 +489,15 @@ class CustomPageAdapter(
val positionList = ArrayList<GameAndPosition>()
viewModel.getNewGameTestUserCase(item.link.link ?: "none")
.getDataListLiveData().value?.forEach { gameDataWrapper ->
val gameEntity = gameDataWrapper.gameData
if (gameEntity != null) {
for (apkEntity in gameEntity.getApk()) {
if (apkEntity.packageName == packageName) {
positionList.add(GameAndPosition(gameEntity, position))
val gameEntity = gameDataWrapper.gameData
if (gameEntity != null) {
for (apkEntity in gameEntity.getApk()) {
if (apkEntity.packageName == packageName) {
positionList.add(GameAndPosition(gameEntity, position))
}
}
}
}
}
positionList
}

View File

@ -1,9 +1,14 @@
package com.gh.gamecenter.home.custom.adapter
package com.gh.gamecenter.home.custom.adapter
import android.content.Context
import android.widget.TextView
import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.goneIf
import com.gh.gamecenter.common.utils.toResString
import com.gh.gamecenter.common.utils.visibleIf
import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.feature.entity.GameEntity
import kotlin.math.roundToInt
object CustomViewExt {
@ -45,9 +50,48 @@ object CustomViewExt {
"size&brief" -> getBriefWithSize()
"star&brief" -> game.brief
"recommend" -> game.columnRecommend?.text ?: getBriefWithSize()
"test&appointment" -> getBriefWithTestAndAppointment(game, tvDesc.context)
else -> getBriefWithSize()
}
tvDesc.text = brief
}
private fun getBriefWithTestAndAppointment(game: GameEntity, context: Context) =
if (game.test?.startPending == true) {
val startText = game.test?.startText ?: ""
if (startText.isBlank()) {
getBookVolumeText(game.appointmentCount, context, false)
} else {
"$startText${getBookVolumeText(game.appointmentCount, context, true)}"
}
} else {
"${getTestDescription(game)}${getBookVolumeText(game.appointmentCount, context, true)}"
}
private fun getTestDescription(game: GameEntity): String {
val timeText = TimeUtils.formatTestTime(game.test?.start ?: 0L)
val eventName = if (game.test?.type == "删档内测") {
R.string.first_release.toResString()
} else {
R.string.go_live.toResString()
}
return "$timeText$eventName"
}
private fun getBookVolumeText(number: Int, context: Context, showDivider: Boolean): String =
when {
number == 0 -> ""
number <= 99999 -> context.getString(
R.string.number_of_reservations,
if (showDivider) " | $number" else "$number"
)
else -> context.getString(
R.string.number_of_reservations,
if (showDivider) " | ${(number / 10000F).roundToInt()}W" else "${(number / 10000F).roundToInt()}W"
)
}
}

View File

@ -112,6 +112,7 @@ abstract class CustomPageItem(
const val COMPONENTS_SUBJECT_TYPE_GAME_EXPAND = "game_expand"
const val COMPONENTS_SUBJECT_TYPE_SINGLE_GAME_CARD = "game_single_card"
const val COMPONENTS_SUBJECT_TYPE_DOUBLE_GAME_WELFARE_CARD = "game_double_welfare_card"
const val COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_IMAGE_TEXT = "game_vertical_image_text"
// 合集
const val COMPONENTS_COLLECTION_STYLE_RANKING_LIST = "ranking-list"
@ -180,6 +181,7 @@ abstract class CustomPageItem(
const val CUSTOM_PAGE_ITEM_TYPE_DOUBLE_GAME_WELFARE_CARD = 37
const val CUSTOM_PAGE_ITEM_TYPE_PK = 38
const val CUSTOM_PAGE_ITEM_TYPE_ACCELERATOR_RECENT_PLAYED = 39
const val CUSTOM_PAGE_ITEM_TYPE_GAME_VERTICAL_IMAGE_TEXT = 40
// 专题样式 to itemType
val subjectTypeMap: HashMap<String, Int> = hashMapOf(
@ -196,6 +198,7 @@ abstract class CustomPageItem(
COMPONENTS_SUBJECT_TYPE_GAME to CUSTOM_PAGE_ITEM_TYPE_GAME_HOME_GAME_ITEM,
COMPONENTS_SUBJECT_TYPE_SINGLE_GAME_CARD to CUSTOM_PAGE_ITEM_TYPE_SINGLE_GAME_CARD,
COMPONENTS_SUBJECT_TYPE_DOUBLE_GAME_WELFARE_CARD to CUSTOM_PAGE_ITEM_TYPE_DOUBLE_GAME_WELFARE_CARD,
COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_IMAGE_TEXT to CUSTOM_PAGE_ITEM_TYPE_GAME_VERTICAL_IMAGE_TEXT
)
// 专题样式 to 组件样式名称
@ -214,7 +217,8 @@ abstract class CustomPageItem(
COMPONENTS_SUBJECT_TYPE_GAME to "展开大图",
COMPONENTS_SUBJECT_TYPE_GAME_EXPAND to "展开大图",
COMPONENTS_SUBJECT_TYPE_SINGLE_GAME_CARD to "单游戏卡片",
COMPONENTS_SUBJECT_TYPE_DOUBLE_GAME_WELFARE_CARD to "双列福利卡片"
COMPONENTS_SUBJECT_TYPE_DOUBLE_GAME_WELFARE_CARD to "双列福利卡片",
COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_IMAGE_TEXT to "竖式图文列表"
)
}

View File

@ -23,6 +23,12 @@ import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.entity.PullDownPush
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.entity.SubjectEntity.Companion.SUBJECT_TAG_SELLING_POINT
import com.gh.gamecenter.entity.SubjectEntity.Companion.SUBJECT_TAG_UPDATE
import com.gh.gamecenter.feature.entity.FloatingWindowEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PluginLocation
import com.gh.gamecenter.feature.entity.TagStyleEntity
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.gamedetail.rating.edit.RatingEditActivity
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_BANNER
@ -47,6 +53,7 @@ import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_S
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_HORIZONTAL_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_TIMELINE_HORIZONTAL_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_IMAGE_TEXT
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_SLIDE
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_COLUMN
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.CUSTOM_LINK_TYPE_GAME
@ -710,29 +717,21 @@ class CustomPageRepository private constructor(
// 替换游戏
substituteGameIfNeeded(gameSubject)
if (gameSubject.tag == "update") {
// 优先显示更新标签
gameSubject.data?.forEach {
it.tagStyle.clear()
it.tagStyle.add(
TagStyleEntity(
id = "local_generated",
name = TimeUtils.getFormatTime(it.updateTime, "MM-dd") + " 更新",
color = "1383EB",
background = "E8F3FF",
column = "1383EB"
)
)
}
}
when (gameSubject.type) {
COMPONENTS_GAME_SUBJECT_TYPE_DOUBLE_CARD, COMPONENTS_SUBJECT_TYPE_DOUBLE_GAME_WELFARE_CARD -> {
// 双列卡片 双列福利卡片
COMPONENTS_GAME_SUBJECT_TYPE_DOUBLE_CARD, COMPONENTS_SUBJECT_TYPE_DOUBLE_GAME_WELFARE_CARD, COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_IMAGE_TEXT -> {
// 双列卡片 双列福利卡片 竖式图文列表
val gameCount = gameSubject.data?.size ?: 0
if (gameCount >= COMPONENT_TYPE_COLUMN_LIMIT_TWO_COUNT) {
val isMustFullyCover = gameSubject.type == COMPONENTS_SUBJECT_TYPE_GAME_VERTICAL_IMAGE_TEXT
val subjectItems =
convertSplitSubjectItems(link, subjectEntity, currentPosition, componentPosition, 2, false)
convertSplitSubjectItems(
link,
subjectEntity,
currentPosition,
componentPosition,
2,
isMustFullyCover
)
list.addAll(subjectItems)
currentPosition += subjectItems.size
}

View File

@ -10,6 +10,7 @@ import com.gh.gamecenter.common.utils.toColor
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.databinding.CommonCollection12ItemCustomBinding
import com.gh.gamecenter.databinding.CommonCollectionItemBinding
import com.gh.gamecenter.databinding.CommonCollectionItemCustomBinding
import com.gh.gamecenter.entity.CommonCollectionContentEntity
import com.gh.gamecenter.home.custom.model.CustomPageData
import com.gh.gamecenter.home.custom.model.CustomPageItem.Companion.COMMON_CONTENT_COLLECTION_LAYOUT_DOUBLE_ROW_VERTICAL_CARD
@ -50,14 +51,9 @@ class CommonContentCollection12Ui(
} else {
width / 2
}
val leftBinding = CommonCollectionItemBinding.bind(binding.leftView.root)
val rightBinding = CommonCollectionItemBinding.bind(binding.rightView.root)
bindSubView(
data[leftPosition],
leftBinding,
binding.leftView,
collection.layout,
width,
height,
@ -69,7 +65,7 @@ class CommonContentCollection12Ui(
binding.rightView.root.visibility = View.VISIBLE
bindSubView(
data[rightPosition],
rightBinding,
binding.rightView,
collection.layout,
width,
height,
@ -99,7 +95,7 @@ class CommonContentCollection12Ui(
private fun bindSubView(
contentEntity: CommonCollectionContentEntity,
subBinding: CommonCollectionItemBinding,
subBinding: CommonCollectionItemCustomBinding,
layout: Int,
width: Int,
height: Int,

View File

@ -17,6 +17,7 @@ import com.gh.gamecenter.common.view.DrawableView
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.StringUtils
import com.gh.gamecenter.databinding.GameItemCustomBinding
import com.gh.gamecenter.entity.SubjectEntity.Companion.SUBJECT_TAG_SELLING_POINT
import com.gh.gamecenter.feature.R
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
@ -65,7 +66,8 @@ class CustomGameItemViewHolder(
root.setPadding(root.paddingLeft, root.paddingTop, root.paddingRight, paddingBottom)
clContainer.background = com.gh.gamecenter.common.R.drawable.reuse_listview_item_style.toDrawable(root.context)
clContainer.background =
com.gh.gamecenter.common.R.drawable.reuse_listview_item_style.toDrawable(root.context)
selectIv.setImageDrawable(DrawableView.getCheckSelectorDrawable(root.context))
gameKaifuType.setBackgroundColor(com.gh.gamecenter.common.R.color.primary_theme.toColor(root.context))
gameName.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(root.context))
@ -75,7 +77,7 @@ class CustomGameItemViewHolder(
gameIconView.displayGameIconWithIfShowSubscript(entity, item.data.showIndexIconSubscript)
val provider = TheRouter.get(IBindingAdaptersProvider::class.java)
provider?.setGameName(gameName, entity, false)
provider?.setGameTags(labelList, entity)
provider?.setGameTagsWithSellingPoints(labelList, layoutSellingPoints, entity, subject.tag ?: "")
CustomViewExt.setGameRatting(gameRating, subject.briefStyle, entity)
CustomViewExt.setDescription(gameDes, subject.briefStyle, entity)

View File

@ -0,0 +1,121 @@
package com.gh.gamecenter.home.custom.viewholder
import android.view.ViewGroup.MarginLayoutParams
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.databinding.GameVerticalImageTextBinding
import com.gh.gamecenter.databinding.RecyclerGameVerticalImageTextBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.home.custom.CustomPageViewModel
import com.gh.gamecenter.home.custom.createExposureEvent
import com.gh.gamecenter.home.custom.eventlistener.SubjectEventHelper
import com.gh.gamecenter.home.custom.model.CustomPageItem
import com.gh.gamecenter.home.custom.model.CustomSplitSubjectItem
class CustomGameVerticalImageTextViewHolder(
viewModel: CustomPageViewModel,
private val binding: RecyclerGameVerticalImageTextBinding
) : BaseCustomViewHolder(viewModel, binding.root) {
private val posterWidth by lazy {
(itemView.context.resources.displayMetrics.widthPixels - 40F.dip2px()) / 2
}
override val childEventHelper: SubjectEventHelper by lazy {
SubjectEventHelper(viewModel)
}
override fun bindView(item: CustomPageItem) {
super.bindView(item)
if (item is CustomSplitSubjectItem) {
val gameList = item.data.data ?: return
fillExposureList(item)
setSplitSubjectTitle(binding.layoutTitle, item, childEventHelper)
(itemView.layoutParams as? MarginLayoutParams)?.let {
it.bottomMargin = 16F.dip2px()
itemView.layoutParams = it
}
val leftPosition = item.startChildPosition
val rightPosition = leftPosition + 1
val hasLeft = gameList.size > leftPosition
if (hasLeft) {
bindSubView(
item,
gameList[leftPosition],
binding.leftCardView,
leftPosition
)
}
val hasRight = gameList.size > rightPosition
binding.rightCardView.root.visibleIf(hasRight) {
bindSubView(
item,
gameList[rightPosition],
binding.rightCardView,
rightPosition
)
}
}
}
private fun bindSubView(
item: CustomSplitSubjectItem,
gameEntity: GameEntity,
subBinding: GameVerticalImageTextBinding,
position: Int
) {
subBinding.run {
commonCollectionImage.setTag(ImageUtils.TAG_TARGET_WIDTH, posterWidth)
commonCollectionImage.post {
if (gameEntity.columnImage.isBlank()) {
commonCollectionImage.display(gameEntity.image)
} else {
commonCollectionImage.display(gameEntity.columnImage)
}
}
gameName.text = gameEntity.name
GameItemViewHolder.initGameSubtitleAndAdLabelOnGameSubject(
gameEntity,
gameSubtitle,
canShowTitle = item.data.showIndexSubtitle
)
tvExplain.goneIf(gameEntity.explainText.isBlank()) {
tvExplain.text = gameEntity.explainText
}
tvRecommend.text = gameEntity.recommendText
root.setOnClickListener {
childEventHelper.navigateToGameDetailPage(position, gameEntity)
}
}
}
private fun fillExposureList(item: CustomSplitSubjectItem) {
val eventList = arrayListOf<ExposureEvent>()
runOnIoThread(true) {
for (i in item.startChildPosition..item.endChildPosition) {
val game = item.data.data?.getOrNull(i) ?: break
val event = createExposureEvent(
game,
item.exposureSource,
pageConfigure.exposureSourceList,
i,
item.componentPosition,
createTrackData(item)
)
game.exposureEvent = event
eventList.add(event)
}
}
item.exposureEventList = eventList
}
}

View File

@ -187,7 +187,7 @@ class CustomHomeGameItemViewHolder(
binding.gameRating.text = game.star.toString()
binding.gameRating2.text = game.star.toString()
binding.gameRating.setDrawableStart(R.drawable.home_game_rating, 12F.dip2px(), 12F.dip2px())
BindingAdapters.setGameTags(binding.gameTags, game)
BindingAdapters.setGameTags(binding.gameTags, game, "")
GameItemViewHolder.initGameSubtitleAndAdLabelOnGameSubject(
game,

View File

@ -93,7 +93,7 @@ class CustomHomeHorizontalSlideVideoItemViewHolder(
binding.gameIcon.displayGameIconWithIfShowSubscript(gameEntity, showSubscript)
binding.gameName.text = gameEntity.name
binding.gameName.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(binding.root.context))
BindingAdapters.setGameTags(binding.gameTags, gameEntity)
BindingAdapters.setGameTags(binding.gameTags, gameEntity, "")
GameItemViewHolder.initGameSubtitleAndAdLabelOnGameSubject(
gameEntity,
binding.gameSubtitleTv,

View File

@ -75,7 +75,7 @@ class HomeHorizontalSlideVideoItemViewHolder(val binding: ItemHomeHorizontalSlid
binding.gameIcon.displayGameIcon(gameEntity)
binding.gameName.text = gameEntity.name
binding.gameName.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(binding.root.context))
BindingAdapters.setGameTags(binding.gameTags, gameEntity)
BindingAdapters.setGameTags(binding.gameTags, gameEntity, "")
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, binding.gameSubtitleTv)
MiniGameItemHelper.setMiniGameUsage(binding.gamePlayCount, gameEntity)

View File

@ -43,7 +43,7 @@ class HomeGameTestV2GameListViewHolder(
mBinding.run {
gameIconView.displayGameIcon(gameEntity)
BindingAdapters.setGameName(gameName, gameEntity, false)
BindingAdapters.setGameTags(labelList, gameEntity)
BindingAdapters.setGameTags(labelList, gameEntity, "")
GameItemViewHolder.initGameSubtitleAndAdLabel(gameEntity, gameSubtitleTv)
@ -62,8 +62,8 @@ class HomeGameTestV2GameListViewHolder(
)
//开服日期
val gameTimeText = if (gameEntity.openTest?.startPending == true) {
gameEntity.openTest?.startText ?: ""
val gameTimeText = if (gameEntity.test?.startPending == true) {
gameEntity.test?.startText ?: ""
} else {
getGameTimeText(gameEntity)
}

View File

@ -81,7 +81,7 @@ class MyFollowedGameAdapter(context: Context, var mViewModel: MyFollowedGameView
gameIconView.displayGameIcon(gameEntity)
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
BindingAdapters.setGameName(gameName, gameEntity, false)
BindingAdapters.setGameTags(labelList, gameEntity)
BindingAdapters.setGameTags(labelList, gameEntity, "")
gameRating.setDrawableStart(if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable() else null)
gameRating.setPadding(0, 0, if (gameEntity.commentCount > 3) 8F.dip2px() else 0, 0)
gameRating.text = if (gameEntity.commentCount > 3) {

View File

@ -133,7 +133,7 @@ class MyReservationAdapter(context: Context, var mViewModel: MyReservationViewMo
gameIconView.displayGameIcon(gameEntity)
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
BindingAdapters.setGameName(gameName, gameEntity, false)
BindingAdapters.setGameTags(labelList, gameEntity)
BindingAdapters.setGameTags(labelList, gameEntity, "")
gameRating.setDrawableStart(
if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable(mContext) else null
)

View File

@ -118,7 +118,7 @@ open class PlayedGameAdapter(
gameIconView.displayGameIcon(gameEntity)
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
BindingAdapters.setGameName(gameName, gameEntity, false)
BindingAdapters.setGameTags(labelList, gameEntity)
BindingAdapters.setGameTags(labelList, gameEntity, "")
gameRating.setDrawableStart(if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable() else null)
gameRating.setPadding(0, 0, if (gameEntity.commentCount > 3) 8F.dip2px() else 0, 0)
gameRating.text = if (gameEntity.commentCount > 3) {

View File

@ -86,6 +86,7 @@ class ArticleDetailFragment : BaseCommentFragment<CommentItemData, ArticleDetail
gameForumType = it?.community?.game?.categoryChinese ?: "",
activityTag = it?.tagActivityName ?: "",
articleType = "帖子",
articleId = it?.id ?: "",
sourceEntrance = sourceEntrance
)
}

View File

@ -74,6 +74,7 @@ class NewQuestionDetailFragment :
gameForumType = it?.community?.game?.categoryChinese ?: "",
activityTag = it?.tagActivityName ?: "",
articleType = "提问帖",
articleId = it?.id ?: "",
sourceEntrance = sourceEntrance
)
}

View File

@ -108,6 +108,7 @@ class ForumVideoDetailFragment : BaseLazyTabFragment() {
gameForumType = it?.data?.bbs?.game?.categoryChinese ?: "",
activityTag = it?.data?.tagActivityName ?: "",
articleType = "视频贴",
articleId = it?.data?.id ?: "",
sourceEntrance = sourceEntrance
)
}

View File

@ -594,10 +594,10 @@ class VideoPublishFragment : ToolbarFragment(), KeyboardHeightObserver {
handleFileNotFound()
toast("上传失败,视频文件不存在")
} else {
mBinding.uploadStatus.text = "网络错误,中断上传"
mBinding.uploadStatus.text = "网络错误,中断上传 $errorMsg"
mBinding.pauseButton.setImageResource(R.drawable.upload_resume)
mBinding.pauseButton.visibility = View.VISIBLE
toast("网络错误,请检查网络正常后再重试")
toast("网络错误,请检查网络正常后再重试 $errorMsg")
}
mBinding.uploadSpeed.visibility = View.GONE
}

View File

@ -222,7 +222,7 @@ public interface ApiService {
* 获取地区配置
*/
@GET("region_setting")
Single<RegionSetting> getRegionSetting(@Query("channel") String channel);
Single<RegionSetting> getRegionSetting(@Query("channel") String channel, @Query("ip") String ip);
/**
* 根据包名获取游戏摘要
@ -1308,6 +1308,13 @@ public interface ApiService {
@POST("./app:activate")
Observable<ResponseBody> postActivationInfo();
/**
* 次日留存
*/
@POST("./app:retention")
Observable<ResponseBody> postRetentionInfo();
/**
* 获取首页游戏补充库
*/

View File

@ -40,6 +40,7 @@ class SearchDefaultRankAdapter(
}
val labelName = if (rank.link.type == "game") gameEntity?.name else rank.name.ifBlank { rank.link.text }
name.text = labelName
name.requestLayout()
index.run {
typeface = Typeface.createFromAsset(mContext.assets, Constants.DIN_FONT_PATH)
text = (position + 1).toString()

View File

@ -135,7 +135,7 @@ class SearchGameFirstItemViewHolder(
gameIconView.displayGameIcon(gameEntity)
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
BindingAdapters.setGameName(gameName, gameEntity, false)
BindingAdapters.setGameTags(labelList, gameEntity)
BindingAdapters.setGameTags(labelList, gameEntity, "")
gameRating.setDrawableStart(if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable() else null)
gameRating.setPadding(0, 0, if (gameEntity.commentCount > 3) 8F.dip2px() else 0, 0)
gameRating.text = if (gameEntity.commentCount > 3) {
@ -159,7 +159,7 @@ class SearchGameFirstItemViewHolder(
adLabelTv
)
}
binding.gameItemIncluded.root.setPadding(16F.dip2px(), 16F.dip2px(), 16F.dip2px(), 16F.dip2px())
binding.gameItemIncluded.root.setPadding(16F.dip2px(), 0, 16F.dip2px(), 0)
SearchGameIndexItemViewHolder.initServerType(gameEntity, binding.gameItemIncluded)
val exposureSources = ArrayList<ExposureSource>()

View File

@ -141,7 +141,7 @@ class SearchGameIndexAdapter(
gameIconView.displayGameIcon(gameEntity)
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
BindingAdapters.setGameName(gameName, gameEntity, false)
BindingAdapters.setGameTags(labelList, gameEntity)
BindingAdapters.setGameTags(labelList, gameEntity, "")
gameRating.setDrawableStart(if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable() else null)
gameRating.setPadding(0, 0, if (gameEntity.commentCount > 3) 8F.dip2px() else 0, 0)
gameRating.text = if (gameEntity.commentCount > 3) {

View File

@ -7,6 +7,8 @@ import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.DrawableView
@ -124,6 +126,32 @@ class SearchSubjectItemViewHolder(var binding: SearchSubjectItemBinding) : Recyc
text = "游戏"
)
}
if (it.isMiniGame()) {
SensorsBridge.trackMiniGameSearchResultClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
sourceEntrance,
key,
SearchActivity.toTrackSearchType(type),
it.id,
it.name ?: "",
it.categoryChinese,
bindingAdapterPosition
)
} else {
SensorsBridge.trackGameSearchResultClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
sourceEntrance,
key,
SearchActivity.toTrackSearchType(type),
it.id,
it.name ?: "",
it.categoryChinese,
bindingAdapterPosition
)
}
}
headContainer.adLabelTv.goneIf(!entity.adIconActive)
headContainer.headTitle.text = entity.name
@ -144,6 +172,17 @@ class SearchSubjectItemViewHolder(var binding: SearchSubjectItemBinding) : Recyc
SubjectData.SubjectType.NORMAL
}
)
SensorsBridge.trackGameSearchResultClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
sourceEntrance,
key,
SearchActivity.toTrackSearchType(type),
"",
"",
"",
bindingAdapterPosition
)
} else if (entity.adId.isNotEmpty() && entity.codeId.isNotEmpty()) {
SubjectActivity.startAdSubjectActivity(
context,

View File

@ -260,7 +260,8 @@ class SearchGameResultAdapter(
holder.binding.gameItemIncluded,
item,
mContext,
this
this,
sourceEntrance
)
}
}
@ -382,7 +383,7 @@ class SearchGameResultAdapter(
gameIconView.displayGameIcon(gameEntity)
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
BindingAdapters.setGameName(gameName, gameEntity, false)
BindingAdapters.setGameTags(labelList, gameEntity)
BindingAdapters.setGameTags(labelList, gameEntity, "")
gameRating.setDrawableStart(if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable() else null)
gameRating.setPadding(0, 0, if (gameEntity.commentCount > 3) 8F.dip2px() else 0, 0)
gameRating.text = if (gameEntity.commentCount > 3) {
@ -478,7 +479,8 @@ class SearchGameResultAdapter(
binding.gameItemIncluded,
item,
mContext,
this
this,
sourceEntrance
)
}
@ -899,7 +901,8 @@ class SearchGameResultAdapter(
binding: SearchGameItemBinding,
item: SearchItemData,
context: Context,
adapter: SearchGameResultAdapter
adapter: SearchGameResultAdapter,
sourceEntrance: String
) {
val gameEntity = item.game ?: return
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) {
@ -944,7 +947,33 @@ class SearchGameResultAdapter(
location = "小游戏搜索结果列表",
searchContent = key,
)
SensorsBridge.trackMiniGameSearchResultClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
sourceEntrance,
key,
SearchActivity.toTrackSearchType(type),
gameEntity.id,
gameEntity.name ?: "",
gameEntity.categoryChinese,
position
)
} else {
SensorsBridge.trackGameSearchResultClick(
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
sourceEntrance,
key,
SearchActivity.toTrackSearchType(type),
gameEntity.id,
gameEntity.name ?: "",
gameEntity.categoryChinese,
position
)
}
},
refreshCallback = null
) {

View File

@ -104,8 +104,8 @@ class GameBigImageViewHolder(val binding: ItemGameServerTestBigImageBinding) :
binding.infoContainer.background = com.gh.gamecenter.common.R.drawable.reuse_listview_item_style.toDrawable(binding.root.context)
binding.gameIcon.displayGameIcon(gameEntity)
binding.gameName.text = gameEntity.name
val time = if (gameEntity.openTest?.startPending == true) {
gameEntity.openTest?.startText ?: ""
val time = if (gameEntity.test?.startPending == true) {
gameEntity.test?.startText ?: ""
} else {
TimeUtils.getGameServerTestTransformedTime(gameEntity.time?.time ?: 0L)
}

View File

@ -69,8 +69,8 @@ class GameServerTestV2ItemViewHolder(val binding: ItemGameServerTestV2Binding) :
binding.infoContainer.background = com.gh.gamecenter.common.R.drawable.reuse_listview_item_style.toDrawable(binding.root.context)
binding.gameIcon.displayGameIcon(gameEntity)
binding.gameName.text = gameEntity.name
val time = if (gameEntity.openTest?.startPending == true) {
gameEntity.openTest?.startText ?: ""
val time = if (gameEntity.test?.startPending == true) {
gameEntity.test?.startText ?: ""
} else {
TimeUtils.getGameServerTestTransformedTime(gameEntity.time?.time ?: 0L)
}

View File

@ -83,7 +83,7 @@ class GameServerTestV2ViewModel(application: Application) : AndroidViewModel(app
companion object {
const val RECENT_GAME = "近期"
const val TODAY_GAME = "今天"
const val FUTURE_GAME = "未来"
const val FUTURE_GAME = "预约"
}
class Factory(private val mApplication: Application) :

View File

@ -185,7 +185,7 @@ class SimulatorGameListAdapter(
gameIconView.displayGameIcon(gameEntity)
gameRating.textSize = if (gameEntity.commentCount > 3) 12F else 10F
BindingAdapters.setGameName(gameName, gameEntity, false)
BindingAdapters.setGameTags(labelList, gameEntity)
BindingAdapters.setGameTags(labelList, gameEntity, "")
gameRating.setDrawableStart(if (gameEntity.commentCount > 3) com.gh.gamecenter.feature.R.drawable.game_horizontal_rating.toDrawable() else null)
gameRating.setPadding(0, 0, if (gameEntity.commentCount > 3) 8F.dip2px() else 0, 0)
gameRating.text = if (gameEntity.commentCount > 3) {

View File

@ -52,7 +52,7 @@ class UploadThread(
.setCancelHook(true)
.setCheckpointFile(recordDirectory)
.setPartSize(10 * 1024 * 1024)
.setTaskNum(2)
.setTaskNum(1)
.setDataTransferListener {
Utils.log(
"OssUpload",
@ -74,9 +74,9 @@ class UploadThread(
mUploadInput = this
}
val config = TransportConfig.builder()
.readTimeoutMills(15 * 1000)
.writeTimeoutMills(15 * 1000)
.connectTimeoutMills(15 * 1000)
.readTimeoutMills(5 * 1000)
.writeTimeoutMills(5 * 1000)
.connectTimeoutMills(5 * 1000)
.maxRetryCount(2)
.build()

View File

@ -1,5 +1,8 @@
package com.gh.gamecenter.wrapper
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.PorterDuff
import android.net.Uri
import android.os.Bundle
@ -14,6 +17,11 @@ import androidx.core.text.color
import androidx.core.view.doOnNextLayout
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import coil.Coil
import coil.decode.SvgDecoder
import coil.load
import coil.request.ImageRequest
import coil.transform.Transformation
import com.ethanhua.skeleton.Skeleton
import com.ethanhua.skeleton.SkeletonScreen
import com.gh.common.iinterface.ISuperiorChain
@ -39,6 +47,7 @@ import com.gh.gamecenter.entity.BottomTab
import com.gh.gamecenter.login.entity.UserInfoEntity
import com.halo.assistant.HaloApp
import com.lightgame.listeners.OnBackPressedListener
import com.lightgame.utils.Utils
import org.greenrobot.eventbus.EventBus
class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBackPressedListener, ISuperiorChain, IBusiness {
@ -158,6 +167,15 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val request = ImageRequest.Builder(requireContext())
.data("https://www.svgrepo.com/show/43967/colours-samples.svg") // Provide the SVG resource ID
.decoderFactory(SvgDecoder.Factory())
.transformations(SvgColorTintTransformation(requireContext().getColor(com.gh.gamecenter.common.R.color.primary_theme)))
.target(mBinding.svgIv)
.build()
Coil.imageLoader(requireContext()).enqueue(request)
mViewModel?.tabSelectedLiveData?.observe(viewLifecycleOwner) {
val selectedTab = it.getContentWithHandled()
if (selectedTab is MainSelectedEvent.SelectedTab && selectedTab.bottomTabIndex != -1) {
@ -443,3 +461,19 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
override fun getBusinessId(): Pair<String, String> = (mCurrentFragment as? IBusiness)?.getBusinessId() ?: Pair("", "")
}
class SvgColorTintTransformation(
private val tintColor: Int
) : Transformation {
override val cacheKey: String = "${javaClass.name}-$tintColor"
override suspend fun transform(input: Bitmap, size: coil.size.Size): Bitmap {
val bitmap = input.copy(Bitmap.Config.ARGB_8888, true) // Create a mutable copy
val canvas = Canvas(bitmap)
val paint = Paint()
paint.colorFilter = android.graphics.PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN)
canvas.drawBitmap(input, 0f, 0f, paint)
return bitmap
}
}

View File

@ -3,6 +3,8 @@ package com.gh.vspace
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.text.InputFilter
import android.text.Spanned
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
@ -70,11 +72,27 @@ class VFeedbackDialogFragment : BaseDialogFragment() {
mBinding.closeIv.setOnClickListener {
dismissAllowingStateLoss()
}
mBinding.feedbackEt.doOnTextChanged { _, _, _, count ->
if (count == 500) {
ToastHelper.showToast(requireContext(), "最多输入500个字")
}
mBinding.feedbackEt.filters = arrayOf(object : InputFilter {
override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence {
val count = dest?.count { !it.isWhitespace() } ?: 0
if(count >= 500){
ToastHelper.showToast(requireContext(), "最多输入500个字")
return ""
}else{
return source?:""
}
}
})
mBinding.feedbackEt.doOnTextChanged { _, _, _, _ ->
updateSubmitButton()
}
mBinding.dontShowAgainTv.enlargeTouchArea()
@ -142,8 +160,7 @@ class VFeedbackDialogFragment : BaseDialogFragment() {
private fun updateSubmitButton() {
val isTagSelected = mTagList?.any { it.checked } ?: false
if (mBinding.feedbackEt.text.isNotEmpty() || isTagSelected) {
if (mBinding.feedbackEt.text.trim().isNotBlank() || isTagSelected) {
mBinding.submitTv.isEnabled = true
mBinding.submitTv.alpha = 1F
} else {

View File

@ -6,7 +6,6 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.database.sqlite.SQLiteDiskIOException
import android.database.sqlite.SQLiteException
import android.database.sqlite.SQLiteFullException
import android.net.Uri
import android.os.Build
@ -35,6 +34,7 @@ import com.gh.gamecenter.*
import com.gh.gamecenter.category2.CategoryV2Activity
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.eventbus.EBReuse
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.common.json.json
@ -87,8 +87,6 @@ import com.lightgame.download.DownloadEntity
import com.lightgame.utils.AppManager
import com.lightgame.utils.Utils
import com.lightgame.view.CheckableLinearLayout
import io.reactivex.Completable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
@ -1940,6 +1938,10 @@ object VHelper {
"game_schema_type", if (originDownloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位"
)
val pushMessageId = (HaloApp.get(Constants.PUSH_MESSAGE_ID, false) as? String) ?: ""
val pushLinkId = (HaloApp.get(Constants.PUSH_LINK_ENTITY, false) as? LinkEntity)?.link ?: ""
val isFromPush = pushMessageId.isNotEmpty()
SensorsBridge.trackEventWithExposureSource(
"DownloadProcessBegin",
event.source,
@ -1954,6 +1956,9 @@ object VHelper {
"last_page_id", GlobalActivityManager.getLastPageEntity().pageId,
"last_page_business_id", GlobalActivityManager.getLastPageEntity().pageBusinessId,
"download_type", "畅玩下载",
"is_from_push_notifications", isFromPush,
"message_id", pushMessageId,
"link_id", pushLinkId,
)
}

View File

@ -27,6 +27,7 @@ import com.gh.ad.AdDelegateHelper;
import com.gh.base.GlobalActivityLifecycleObserver;
import com.gh.common.FixedRateJobHelper;
import com.gh.common.filter.RegionSettingHelper;
import com.gh.common.interceptor.MainInterceptor;
import com.gh.common.prioritychain.GlobalPriorityChainHelper;
import com.gh.common.util.ActivationHelper;
import com.gh.common.util.DataUtils;
@ -46,6 +47,7 @@ import com.gh.download.simple.SimpleDownloadDatabase;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.common.constant.Config;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.common.image.EmptyDecoder;
import com.gh.gamecenter.common.tracker.Tracker;
@ -290,6 +292,7 @@ public class HaloApp extends MultiDexApplication {
private void initRouter() {
TheRouter.init(this);
NavigatorKt.addRouterReplaceInterceptor(new MainInterceptor());
NavigatorKt.addRouterReplaceInterceptor(new LoginInterceptor());
}
@ -332,6 +335,12 @@ public class HaloApp extends MultiDexApplication {
SignatureRepository.INSTANCE.init();
// 初始化奇游sdk需要放在 UserRepository.getInstance().init() 前面必须先初始化sdk才能 setQyToken
IAcceleratorProvider acceleratorProvider = TheRouter.get(IAcceleratorProvider.class);
if (acceleratorProvider != null) {
acceleratorProvider.init(EnvHelper.isDevEnv(), this, PackageUtils.getGhVersionName());
}
// 刷新内存中的用户信息,避免应用进程重建时因没有用户信息数据而显示为掉登录状态
// 同时避免请求实名信息时没有用户信息导致实名信息变更为设备实名的问题
UserRepository.getInstance().init();
@ -360,6 +369,9 @@ public class HaloApp extends MultiDexApplication {
LogUtils.uploadDevice(launchType);
ActivationHelper.sendActivationInfo();
} else {
// 发送次日留存信息
ActivationHelper.sendRetentionInfo();
}
return null;
});
@ -423,10 +435,6 @@ public class HaloApp extends MultiDexApplication {
}
}, delay);
IAcceleratorProvider acceleratorProvider = TheRouter.get(IAcceleratorProvider.class);
if (acceleratorProvider != null) {
acceleratorProvider.init(EnvHelper.isDevEnv(), this, PackageUtils.getGhVersionName());
}
AcceleratorDataHolder.Companion.getInstance().init();
}
@ -485,6 +493,11 @@ public class HaloApp extends MultiDexApplication {
pushProvider.initialize(this);
pushProvider.setOnPushOpenedCallback((id, title, content, linkType, linkId) -> {
SensorsBridge.trackJiGuangPushClick(id, title, content, linkType, linkId);
put(Constants.PUSH_MESSAGE_ID, id);
LinkEntity link = new LinkEntity();
link.setLink(linkId);
link.setType(linkType);
put(Constants.PUSH_LINK_ENTITY, link);
return null;
});
}

View File

@ -20,6 +20,14 @@ class AcceleratorDataHolder {
private val listeners = mutableSetOf<OnDataHolderListener>()
private val _initResults = arrayListOf<String>()
val initResults: List<String>
get() = _initResults
fun addInitFunResult(result: String) {
_initResults.add(result)
}
private var _hasAcctGameInfoInLocal = false
val hasAcctGameInfoInLocal: Boolean
get() = _hasAcctGameInfoInLocal
@ -62,27 +70,26 @@ class AcceleratorDataHolder {
""
}
private var _vipEntity: VipEntity? = null
val vipEntity: VipEntity?
get() = _vipEntity
var vipEntity: VipEntity? = null
private set
val isVip: Boolean
get() = _vipEntity?.vipStatus ?: false
get() = vipEntity?.vipStatus ?: false
val isNewUser: Boolean
get() = _vipEntity?.isNewUser ?: false
get() = vipEntity?.isNewUser ?: false
val memberType: String
get() = when {
!CheckLoginUtils.isLogin() -> MEMBER_TYPE_NOT_LOGIN
_vipEntity?.vipStatus == true && _vipEntity?.isTryVip == true -> MEMBER_TYPE_FREE_MEMBER
_vipEntity?.vipStatus == true -> MEMBER_TYPE_PAID_MEMBER
vipEntity?.vipStatus == true && vipEntity?.isTryVip == true -> MEMBER_TYPE_FREE_MEMBER
vipEntity?.vipStatus == true -> MEMBER_TYPE_PAID_MEMBER
else -> MEMBER_TYPE_NONE_MEMBER
}
fun setVipEntity(vip: VipEntity) {
if (_vipEntity != vip) {
_vipEntity = vip
if (vipEntity != vip) {
vipEntity = vip
listeners.forEach {
it.onVipStateChanged(vip)
}
@ -98,7 +105,7 @@ class AcceleratorDataHolder {
}
fun clear() {
_vipEntity = null
vipEntity = null
listeners.clear()
}

View File

@ -117,6 +117,7 @@ class WebFragment : LazyFragment(), IScrollable {
private var mLeaveWebpageToHandleTitle = false //是否由网页处理标题
private var mClearHistoryOnLoaded = false // 是否加载完成以后清理掉旧的加载历史
private var mIsWebViewInstalled = true // 当前设备是否存在可用的 WebView
private var mForceEnableNestedScroll = false // 强制启用嵌套滚动
private var mTimeElapsedHelper: TimeElapsedHelper? = null
private lateinit var mJsApi: DefaultJsApi
@ -347,6 +348,7 @@ class WebFragment : LazyFragment(), IScrollable {
mIsSecurityCertification = args.getBoolean(KEY_IS_SECURITY_CERTIFICATION, false)
mLeaveWebpageToHandleTitle = args.getBoolean(KEY_LEAVE_WEB_PAGE_TO_HANDLE_TITLE, false)
mWebUrl = dealWithUrl(args.getString(EntranceConsts.KEY_URL, ""))
mForceEnableNestedScroll = args.getBoolean(KEY_ENABLE_HORIZONTAL_SCROLL_DISPATCH)
}
mJsApi = DefaultJsApi(
requireContext(),
@ -698,6 +700,9 @@ class WebFragment : LazyFragment(), IScrollable {
if (mIsHorizontalDispatcherEnabled) {
webview.enableHorizontalScrollDispatch()
}
if (mForceEnableNestedScroll) {
webview.enableForceNestedScroll()
}
webview.addJavascriptObject(mJsApi, null)
webview.addJavascriptObject(ShareNativeCallback(), "share")
webview.addJavascriptObject(InternalJsApi(), "internal")
@ -1047,6 +1052,7 @@ class WebFragment : LazyFragment(), IScrollable {
const val KEY_GAME_NAME = "game_name"
const val KEY_CLOSE_BUTTON = "close_button"
const val KEY_ENABLE_HORIZONTAL_SCROLL_DISPATCH = "enable_horizontal_scroll_dispatch"
const val KEY_FORCE_ENABLE_NESTED_SCROLL = "force_enable_nested_scroll"
private const val REQUEST_PICK_IMAGE = 101
}
}

View File

@ -109,7 +109,7 @@ public class GamePluginAdapter extends BaseRecyclerAdapter {
binding.gameItemIncluded.gameIconView.displayGameIcon(gameEntity);
binding.gameItemIncluded.gameRating.setTextSize(gameEntity.getCommentCount() > 3 ? 12 : 10);
BindingAdapters.setGameName(binding.gameItemIncluded.gameName, gameEntity, true);
BindingAdapters.setGameTags(binding.gameItemIncluded.labelList, gameEntity);
BindingAdapters.setGameTags(binding.gameItemIncluded.labelList, gameEntity, "");
ExtensionsKt.setDrawableStart(binding.gameItemIncluded.gameRating, gameEntity.getCommentCount() > 3 ? ExtensionsKt.toDrawable(com.gh.gamecenter.feature.R.drawable.game_horizontal_rating) : null, null, null);
binding.gameItemIncluded.gameRating.setPadding(0, 0, gameEntity.getCommentCount() > 3 ? DisplayUtils.dip2px(8) : 0, 0);
binding.gameItemIncluded.gameRating.setText(gameEntity.getCommentCount() > 3 ? (gameEntity.getStar() == 10.0 ? "10" : String.valueOf(gameEntity.getStar())) : "");

View File

@ -15,6 +15,7 @@ import com.gh.gamecenter.ShellActivity.Companion.getIntent
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.WechatConfigEntity
import com.gh.gamecenter.common.utils.PermissionHelper
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.core.utils.CurrentActivityHolder
@ -131,6 +132,13 @@ class ReserveReminderContainerFragment : Fragment(), OnReserveReminderListener {
requireContext().startActivity(intent)
}
override fun updateCalendarReminder() {
trackAppointmentSuccessDialogClick("开启日历提醒")
PermissionHelper.checkCalendarPermissions(this, game?.id ?: "", game?.name ?: "", game?.categoryChinese ?: "") {
viewModel.addCalendarEvent(game?.id ?: "", reserveReminderEntity.calendarConfig)
}
}
private fun showPhoneNumberDialog(dialogType: Int, phone: String, serviceId: String = "") {
isCanDismissed = false
@ -175,7 +183,11 @@ class ReserveReminderContainerFragment : Fragment(), OnReserveReminderListener {
game?.id ?: "",
game?.name ?: "",
game?.categoryChinese ?: "",
"关闭弹窗"
"关闭弹窗",
wechatRemind = reserveReminderEntity.wechatConfig.isReminderEnable,
messageRemind = if (reserveReminderEntity.hasSmsConfig) reserveReminderEntity.smsConfig.notice else null,
automaticDownload = reserveReminderEntity.isEnableAutoDownload,
calendarRemind = if (reserveReminderEntity.hasCalendarConfig) reserveReminderEntity.calendarConfig.notice else null
)
val ft = parentFragmentManager.beginTransaction()
ft.remove(this)
@ -199,6 +211,7 @@ class ReserveReminderContainerFragment : Fragment(), OnReserveReminderListener {
)
}
companion object {
private const val KEY_RESERVE_REMINDER = "key_reserve_reminder"
@ -254,4 +267,6 @@ interface OnReserveReminderListener {
fun enableAutoDownload(isEnable: Boolean)
fun realName()
fun updateCalendarReminder()
}

View File

@ -1,9 +1,11 @@
package com.halo.assistant.fragment.reserve
import android.annotation.SuppressLint
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.Message
import com.gh.gamecenter.common.utils.CalendarEventUtils
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.entity.ReserveModifyEntity
@ -13,6 +15,7 @@ import com.gh.gamecenter.entity.ValidateCodeResponse
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.retrofit.service.ApiService
import com.halo.assistant.HaloApp
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
import okhttp3.RequestBody
@ -92,6 +95,31 @@ class ReserveReminderRepository(
return apiService.reserveSetting(requestBody)
}
@SuppressLint("CheckResult")
fun addCalendarEvent(gameId: String, calendarConfig: ReserveReminderEntity.CalendarConfig) =
Single.create {
val calendarEvent = CalendarEventUtils.CalendarEvent(
title = calendarConfig.title,
startTime = calendarConfig.timeStart * 1000,
endTIme = calendarConfig.timeEnd * 1000,
reminderTime = calendarConfig.advanceSeconds * 1000,
remark = calendarConfig.remark
)
val eventId = CalendarEventUtils.addCalendarEvent(calendarEvent, HaloApp.getInstance())
if (eventId != null) {
it.onSuccess(eventId)
} else {
it.onError(Throwable(message = "Failed to add calendar event"))
}
}.doOnSuccess {
val body = hashMapOf(
"calendar_config" to hashMapOf("notice" to true)
).toRequestBody()
apiService.reserveModify(gameId, body)
.subscribe({}, {})
}
companion object {
private const val MESSAGE_WHAT_ENABLE_AUTO_DOWNLOAD = 1

View File

@ -1,10 +1,14 @@
package com.halo.assistant.fragment.reserve
import android.annotation.SuppressLint
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toResString
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.ReserveModifyEntity
import com.gh.gamecenter.entity.ReserveReminderEntity
import com.gh.gamecenter.entity.ValidateCodeResponse
@ -12,7 +16,7 @@ import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.livedata.Event
import io.reactivex.disposables.CompositeDisposable
class ReserveReminderViewModel : ViewModel() {
class ReserveReminderViewModel(app: Application) : AndroidViewModel(app) {
private val repository = ReserveReminderRepository.newInstance()
@ -59,6 +63,27 @@ class ReserveReminderViewModel : ViewModel() {
repository.enableAutoDownload(game, enable)
}
/**
* 日历添加事件
* 如果在日历添加期间,用户退出当前页面,操作仍然继续
* 所以这里不和ui层生命周期绑定
*/
@SuppressLint("CheckResult")
fun addCalendarEvent(gameId: String, calendarConfig: ReserveReminderEntity.CalendarConfig) {
repository.addCalendarEvent(gameId, calendarConfig)
.compose(singleToMain())
.subscribe(object : BiResponse<Long>() {
override fun onSuccess(data: Long) {
ToastUtils.showToast(com.gh.gamecenter.common.R.string.add_calendar_event_successfully.toResString())
val reminderEntity = _reserveReminder.value ?: return
reminderEntity.calendarConfig = ReserveReminderEntity.CalendarConfig(_notice = true)
updateReserveReminder(reminderEntity)
}
})
}
override fun onCleared() {
composeDisposable.clear()

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/ui_container_1" />
<corners android:radius="4dp" />
<corners android:radius="8dp" />
</shape>

View File

@ -4,5 +4,5 @@
android:endColor="#0A2496FF"/>
<stroke android:color="#142496FF"
android:width="1dp"/>
<corners android:radius="4dp"/>
<corners android:radius="8dp"/>
</shape>

View File

@ -1,4 +1,5 @@
<com.gh.gamecenter.common.view.MaterializedConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<com.gh.gamecenter.common.view.MaterializedConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
@ -109,8 +110,8 @@
android:id="@+id/installApiContentTv"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="16dp"
android:text="您未授予已安装列表权限,可能导致无法安装及更新等异常情况,建议开启权限!"
android:textSize="@dimen/secondary_size"
app:layout_constraintBottom_toBottomOf="parent"
@ -152,4 +153,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/svgIv"
android:layout_width="100dp"
android:layout_height="100dp" />
</com.gh.gamecenter.common.view.MaterializedConstraintLayout>

View File

@ -156,12 +156,12 @@
style="@style/CustomPageGameRating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="10"
app:layout_constraintBottom_toBottomOf="@id/gameDesSpace"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="@+id/gameDesSpace"
app:layout_constraintRight_toLeftOf="@+id/game_des"
app:layout_constraintTop_toTopOf="@+id/gameDesSpace"
app:layout_constraintBottom_toBottomOf="@id/gameDesSpace" />
tools:text="10" />
<TextView
android:id="@+id/game_des"
@ -172,10 +172,10 @@
android:singleLine="true"
android:textColor="@color/text_tertiary"
android:textSize="10sp"
android:layout_marginTop="6dp"
app:layout_constraintLeft_toRightOf="@+id/game_rating"
app:layout_constraintRight_toRightOf="@+id/gameDesSpace"
app:layout_constraintTop_toTopOf="@+id/gameDesSpace"
app:layout_constraintBottom_toBottomOf="@id/gameDesSpace"
tools:text="巫妖王再怒霜之哀殤又飢渴" />
<LinearLayout
@ -263,21 +263,31 @@
app:layout_constraintRight_toRightOf="@+id/gameDesSpace"
app:layout_constraintTop_toBottomOf="@+id/gameDesSpace" />
<include
android:id="@+id/layout_selling_points"
layout="@layout/layout_game_item_selling_point"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@+id/gameIconView"
app:layout_constraintLeft_toRightOf="@+id/game_play_count"
app:layout_constraintRight_toRightOf="@+id/gameDesSpace"
app:layout_constraintTop_toBottomOf="@+id/gameDesSpace" />
<TextView
android:id="@+id/game_play_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:visibility="visible"
android:layout_marginRight="8dp"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="@color/text_tertiary"
android:textSize="11sp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/gameIconView"
app:layout_constraintLeft_toLeftOf="@+id/gameDesSpace"
app:layout_constraintRight_toLeftOf="@+id/label_list"
app:layout_constraintTop_toBottomOf="@+id/gameDesSpace"
android:textSize="11sp"
android:gravity="center"
android:layout_marginRight="8dp"
android:textColor="@color/text_tertiary"
tools:text="999.9万人玩过" />
<TextView

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