Compare commits
596 Commits
main
...
develop_wi
| Author | SHA1 | Date |
|---|---|---|
|
|
9e996fb5ca | |
|
|
e9b7af5de3 | |
|
|
580f81a67b | |
|
|
fd0a5725e3 | |
|
|
b795f4458a | |
|
|
999e882af3 | |
|
|
1f07381e19 | |
|
|
b4a2bf3410 | |
|
|
b491186524 | |
|
|
75f8111c13 | |
|
|
da258f69f6 | |
|
|
45b63e870e | |
|
|
6f34b5b990 | |
|
|
13ee0de952 | |
|
|
479e8aad93 | |
|
|
91260dc651 | |
|
|
38e13bf461 | |
|
|
ace9afbbbc | |
|
|
4eb4633d75 | |
|
|
ca586f4b3b | |
|
|
c6bbcfba64 | |
|
|
3781711e2e | |
|
|
10b42951a8 | |
|
|
2b3b5f905f | |
|
|
e2371468b5 | |
|
|
af6e5e6ef1 | |
|
|
1995e0b43f | |
|
|
68d4bc2948 | |
|
|
7fff655e81 | |
|
|
02d6712928 | |
|
|
5ebb3153b8 | |
|
|
0fc80a387e | |
|
|
c3a1455482 | |
|
|
19f1dbe676 | |
|
|
5f7131e00c | |
|
|
55c79e7d7e | |
|
|
93f1cf9921 | |
|
|
4f7d2c495a | |
|
|
b374519bb9 | |
|
|
26df5def50 | |
|
|
44efca168c | |
|
|
efb6eb02bc | |
|
|
3745010e38 | |
|
|
090e819e84 | |
|
|
1a9ea870e5 | |
|
|
a2a458e6d9 | |
|
|
439d04706b | |
|
|
292c187a7a | |
|
|
b53faa22ec | |
|
|
3fb4f3c4cc | |
|
|
34d10148b2 | |
|
|
1b80c05503 | |
|
|
7a7af80d31 | |
|
|
9be0e2246b | |
|
|
396161e152 | |
|
|
3c13586113 | |
|
|
51d3581513 | |
|
|
4f624189c8 | |
|
|
096138fc89 | |
|
|
1864a20dd2 | |
|
|
e5c70e3d25 | |
|
|
0b91a47f05 | |
|
|
7d93fb2a3b | |
|
|
f587a99e71 | |
|
|
560b680484 | |
|
|
4b4c2b8f07 | |
|
|
d82655602e | |
|
|
9eed617b38 | |
|
|
153f385503 | |
|
|
e5797d5f80 | |
|
|
60fa7faa2f | |
|
|
afbc0cb815 | |
|
|
d12cccb13c | |
|
|
c9e9984ee6 | |
|
|
93ca811144 | |
|
|
732fa61869 | |
|
|
324d9fcdcf | |
|
|
14f6ddabb1 | |
|
|
0233f4476f | |
|
|
0262a19fba | |
|
|
20cf340eba | |
|
|
3dcd943f5d | |
|
|
44380be0f1 | |
|
|
4e28a5e436 | |
|
|
309b2d1662 | |
|
|
57ef04f86e | |
|
|
aed14e7277 | |
|
|
8822f94268 | |
|
|
7b86f83177 | |
|
|
fa18c550ed | |
|
|
3ffa288046 | |
|
|
0d5bbc5813 | |
|
|
028249864d | |
|
|
c4924b8fa7 | |
|
|
84b7519992 | |
|
|
5c1c6bd002 | |
|
|
4912fddee0 | |
|
|
c7482eda72 | |
|
|
466e83dadd | |
|
|
f0e781def1 | |
|
|
468f1255e4 | |
|
|
7847159a61 | |
|
|
a77f9709d8 | |
|
|
dae7ab4da9 | |
|
|
49a96758aa | |
|
|
f7df0fa888 | |
|
|
ee79f241e1 | |
|
|
edff0c408e | |
|
|
90620fbcaa | |
|
|
78c57b41ef | |
|
|
577527472a | |
|
|
04b35f09a0 | |
|
|
e28606c7d8 | |
|
|
922df7550e | |
|
|
ed5eec84af | |
|
|
383b0a2be3 | |
|
|
f56455c269 | |
|
|
c277d73277 | |
|
|
2488046089 | |
|
|
774d4a4379 | |
|
|
597b3935fa | |
|
|
4d56fe2515 | |
|
|
36e999a439 | |
|
|
a9160244b3 | |
|
|
15512e8b30 | |
|
|
53781eb544 | |
|
|
1d01835f48 | |
|
|
5e0cdb524c | |
|
|
a09bc4abf9 | |
|
|
5753fccee5 | |
|
|
387d5d99b2 | |
|
|
a651faf106 | |
|
|
ddbf7dd400 | |
|
|
0ffbda3334 | |
|
|
5d49ce6a96 | |
|
|
1e487a4f8d | |
|
|
6dcd2a93a2 | |
|
|
111e1a88b2 | |
|
|
e7ab378394 | |
|
|
ceb91122b0 | |
|
|
89ced0be17 | |
|
|
c55cf6baf0 | |
|
|
54d943869f | |
|
|
d5e9bacab4 | |
|
|
0f8a41e1a1 | |
|
|
12b467d553 | |
|
|
eec7770215 | |
|
|
dc4ad47b9f | |
|
|
4d80c09fb9 | |
|
|
7b24d8e3ff | |
|
|
6d741d9ce5 | |
|
|
e051962bd8 | |
|
|
d770804d32 | |
|
|
7f21fb10a5 | |
|
|
2be4afaf07 | |
|
|
24f4b46b45 | |
|
|
3fdb6a1a59 | |
|
|
ec8d7f9da0 | |
|
|
255f5223e8 | |
|
|
80b4e66aca | |
|
|
91dfd9e5ae | |
|
|
9bed3e5467 | |
|
|
be09270891 | |
|
|
2a3c1cd35c | |
|
|
b8bb2bbffe | |
|
|
241dda68c1 | |
|
|
30522430a9 | |
|
|
bb00fb9dfb | |
|
|
670e1819f0 | |
|
|
446e882db2 | |
|
|
adf08dceb0 | |
|
|
2ae95eea06 | |
|
|
bca9728977 | |
|
|
9fa41f37cb | |
|
|
f69449e982 | |
|
|
4d997c1c00 | |
|
|
c1c8f25c65 | |
|
|
0b4e7b3ad3 | |
|
|
e4fd9f924a | |
|
|
37b6e641e3 | |
|
|
c8f5ca7e97 | |
|
|
387adc3343 | |
|
|
9a7eb9f1ec | |
|
|
55f7621eed | |
|
|
99bafde438 | |
|
|
5209af76ad | |
|
|
7d1e4b64b1 | |
|
|
d368441ddf | |
|
|
f41c3a0c63 | |
|
|
427b17bd85 | |
|
|
7a381c1ff6 | |
|
|
bb684928ca | |
|
|
d60f608115 | |
|
|
c641fa9931 | |
|
|
7e6366ff78 | |
|
|
5c142961f3 | |
|
|
53d1f25d0c | |
|
|
b04725abf8 | |
|
|
1045282908 | |
|
|
b02f07a3cc | |
|
|
24ab07d4b2 | |
|
|
decd41b82d | |
|
|
2859edcc89 | |
|
|
82d7f7d9d8 | |
|
|
e2bdd75db4 | |
|
|
b73333f46f | |
|
|
ecaa1ae372 | |
|
|
0cba07f90a | |
|
|
104cb4b36b | |
|
|
7ef097b157 | |
|
|
a59dcba040 | |
|
|
0c8e6a2efe | |
|
|
d47129dea7 | |
|
|
ba220384cb | |
|
|
daa1d2b2ad | |
|
|
7950369c09 | |
|
|
4268521b7a | |
|
|
64a093782e | |
|
|
c2191c5990 | |
|
|
7bb5217fc8 | |
|
|
2a09e6f930 | |
|
|
105e2878b6 | |
|
|
61d5761ab0 | |
|
|
5a7e413d83 | |
|
|
00910ad616 | |
|
|
db0fdcc700 | |
|
|
ccd4d7750e | |
|
|
28eed14ab4 | |
|
|
2028831590 | |
|
|
bcb11ef936 | |
|
|
4351f8f3c2 | |
|
|
fbfd00db69 | |
|
|
b7f82f247e | |
|
|
70da2d05a3 | |
|
|
72cbad2b2f | |
|
|
3da237172b | |
|
|
9281096819 | |
|
|
8892f45258 | |
|
|
f8c6101d07 | |
|
|
24f2d63a4a | |
|
|
cec3ba6ba8 | |
|
|
85bceb3b68 | |
|
|
54d878cd94 | |
|
|
9fec4aeac6 | |
|
|
81ad6111f4 | |
|
|
10e988fd83 | |
|
|
6fdceb52e2 | |
|
|
074a3374df | |
|
|
3285bd7b06 | |
|
|
f645aabc70 | |
|
|
0d092b8422 | |
|
|
fa47bba027 | |
|
|
042fc1cb05 | |
|
|
eceb294da1 | |
|
|
d1bbf7c523 | |
|
|
af87e4da5d | |
|
|
6c858ca0d7 | |
|
|
6371d8075c | |
|
|
b3a7a610a5 | |
|
|
1123dc2c9e | |
|
|
a722d84f06 | |
|
|
acac3099a6 | |
|
|
ac91577c41 | |
|
|
07bab8b94e | |
|
|
9ef0b062af | |
|
|
c5d7234d92 | |
|
|
810a8e1329 | |
|
|
2e17e79616 | |
|
|
85a247d6fd | |
|
|
1912a9f669 | |
|
|
53d1acedc9 | |
|
|
80038162cf | |
|
|
26892b1227 | |
|
|
d775268e11 | |
|
|
e0938dac56 | |
|
|
eb85079523 | |
|
|
dc4871c8b0 | |
|
|
ac41cdf3f0 | |
|
|
9ef7ebe5c1 | |
|
|
9955d77a33 | |
|
|
17f80a6539 | |
|
|
9575b2a8f7 | |
|
|
804df4e915 | |
|
|
cf70646ef3 | |
|
|
dc0c47659b | |
|
|
b532d1daa8 | |
|
|
19f9895f23 | |
|
|
d4216c017c | |
|
|
05a8460a05 | |
|
|
e14736ed01 | |
|
|
0184772698 | |
|
|
705901d55c | |
|
|
191d19a908 | |
|
|
37cbac1a2e | |
|
|
1489be0c64 | |
|
|
c050c4b6ba | |
|
|
d632807122 | |
|
|
efc140f512 | |
|
|
64ff009736 | |
|
|
8a442dbd54 | |
|
|
5630c02394 | |
|
|
8f038ca3ea | |
|
|
5e5ba292bd | |
|
|
c36b187f6b | |
|
|
6018362656 | |
|
|
b59b858352 | |
|
|
11a091a725 | |
|
|
4c7c4fb56c | |
|
|
7ef5257a16 | |
|
|
88c1520177 | |
|
|
cd85982048 | |
|
|
b3fb4f0327 | |
|
|
20f17da637 | |
|
|
12aeabe6c4 | |
|
|
ef2f079b2e | |
|
|
96c3a11f1d | |
|
|
ee4616a245 | |
|
|
cff0703f24 | |
|
|
c7f430d58c | |
|
|
eb581c16ae | |
|
|
2527c6369f | |
|
|
4960deb7c3 | |
|
|
f5a9c11f62 | |
|
|
395ec8a371 | |
|
|
c6fe2c7c33 | |
|
|
35c1119ddb | |
|
|
bbee6dd808 | |
|
|
8559ac16c1 | |
|
|
8a045117ea | |
|
|
5d217d025b | |
|
|
b010c1e4d2 | |
|
|
1405041810 | |
|
|
a75d47a04c | |
|
|
63e867ad72 | |
|
|
2d3326a00e | |
|
|
0f56ad235e | |
|
|
0f1a88e087 | |
|
|
a5b4df0854 | |
|
|
2cc2315306 | |
|
|
9dde21580f | |
|
|
ca097b392e | |
|
|
03aae381b2 | |
|
|
3fa2c5638f | |
|
|
ab540875e6 | |
|
|
900f39e3bd | |
|
|
08a81b1c7e | |
|
|
6a8c0cc4df | |
|
|
8412415f86 | |
|
|
95cb9da2af | |
|
|
461a24de94 | |
|
|
5c03d0cb06 | |
|
|
adfa6bca79 | |
|
|
727321ad70 | |
|
|
2001936032 | |
|
|
c5c7ba71b7 | |
|
|
885bc67994 | |
|
|
7976c1f358 | |
|
|
84f367bdca | |
|
|
aefd72680b | |
|
|
a3b0386c9d | |
|
|
fc62d3a0cb | |
|
|
32553d70d1 | |
|
|
0e9eebd85a | |
|
|
4ab33f382c | |
|
|
59c80a6e58 | |
|
|
95da77184d | |
|
|
64556c9d7b | |
|
|
05f9af12de | |
|
|
3a3a7c10bd | |
|
|
3b4e8522ec | |
|
|
8cbc29db36 | |
|
|
150c1a7107 | |
|
|
64242f4905 | |
|
|
6ff7704cad | |
|
|
f737254d0c | |
|
|
183d31151b | |
|
|
cacdbbbb9e | |
|
|
7e774a2733 | |
|
|
09b7eba3e7 | |
|
|
cf5250d7ec | |
|
|
05721bcd46 | |
|
|
45c808618e | |
|
|
c4b54f5e2e | |
|
|
f2637531e4 | |
|
|
fe3f7e90ad | |
|
|
9ba4eec4ed | |
|
|
a284e3cde5 | |
|
|
e6cb9715d7 | |
|
|
837d4e8f5a | |
|
|
04e770da82 | |
|
|
debb8acbcf | |
|
|
e030324b5d | |
|
|
7b73b833c6 | |
|
|
2c807ca4ee | |
|
|
f567e1bad9 | |
|
|
f78ae33ef3 | |
|
|
03b5f0fba1 | |
|
|
64aa22a0de | |
|
|
328cbd205d | |
|
|
02587b7e21 | |
|
|
0a635e3b32 | |
|
|
f0cad1497f | |
|
|
37f73e12c5 | |
|
|
1aea476277 | |
|
|
38b8a8d23c | |
|
|
c2bb7ec0e7 | |
|
|
333e7616de | |
|
|
189a85896a | |
|
|
8c9dd06295 | |
|
|
470c11d5b8 | |
|
|
f54cb905f9 | |
|
|
d392527e4d | |
|
|
8d3b2a6d03 | |
|
|
50341765a2 | |
|
|
9c83bbe0c1 | |
|
|
e996a48bec | |
|
|
8ec2821cc9 | |
|
|
3b657bef61 | |
|
|
936176f400 | |
|
|
e325c00546 | |
|
|
92e073062e | |
|
|
70cac6cd49 | |
|
|
c90b15a7a2 | |
|
|
d8b43d1082 | |
|
|
f5a81c6b61 | |
|
|
2c0a52ec48 | |
|
|
e251550ffb | |
|
|
afa8b2405c | |
|
|
cef3efaa4e | |
|
|
c981ffe950 | |
|
|
867c075794 | |
|
|
b5fc00b996 | |
|
|
ec9dabdc0e | |
|
|
1b38648b3a | |
|
|
08a09d8cf3 | |
|
|
75a7355665 | |
|
|
e36722ced8 | |
|
|
3bebde7111 | |
|
|
17441a0d78 | |
|
|
96a3e641ce | |
|
|
ba4c5708db | |
|
|
02bc2837bd | |
|
|
8932c39064 | |
|
|
90dbd265f0 | |
|
|
c1070ab095 | |
|
|
21ace7f399 | |
|
|
109b01d9c6 | |
|
|
994d205a7e | |
|
|
e0ede99c67 | |
|
|
9059a5a415 | |
|
|
5487b28be4 | |
|
|
41f7f9a246 | |
|
|
b136df0f73 | |
|
|
4e07aa4630 | |
|
|
c944b543b1 | |
|
|
672f9cfb04 | |
|
|
a765fc7967 | |
|
|
53f75e0779 | |
|
|
1e73375a16 | |
|
|
f889dc5072 | |
|
|
8f2786b5b9 | |
|
|
ae45b72717 | |
|
|
9066b775a8 | |
|
|
6cd007e6d4 | |
|
|
b9afc0fa14 | |
|
|
f8e8657159 | |
|
|
de9f32ae5b | |
|
|
f8face95c6 | |
|
|
f5ceeffaa8 | |
|
|
4a0a37e715 | |
|
|
968c5354a1 | |
|
|
b09e9718a0 | |
|
|
c0cd9cce33 | |
|
|
da01786fd0 | |
|
|
5e86192b93 | |
|
|
3dfeaf54bf | |
|
|
1a3b70076a | |
|
|
2ebaf58f56 | |
|
|
c9d281abcd | |
|
|
32e4d6a6e7 | |
|
|
cea438caa8 | |
|
|
c669384d3c | |
|
|
c2b41a5309 | |
|
|
a237f7f5ac | |
|
|
2c791929ee | |
|
|
80812b5a2c | |
|
|
97344d2604 | |
|
|
595dfa7a9c | |
|
|
8c48316daa | |
|
|
1a1edbb763 | |
|
|
b1dde3ef6c | |
|
|
6322e04a36 | |
|
|
04c3223e5a | |
|
|
edc968f004 | |
|
|
542420b17a | |
|
|
a20e0053c1 | |
|
|
549817ef6e | |
|
|
6925c42372 | |
|
|
33e7503c70 | |
|
|
3b51532a34 | |
|
|
ff2eab0da9 | |
|
|
0d31395d7a | |
|
|
06fc43a454 | |
|
|
a0ee013152 | |
|
|
66e47c4328 | |
|
|
68f1119b4a | |
|
|
a95b8b84e9 | |
|
|
2dc819f916 | |
|
|
ce0d5084ba | |
|
|
1988f2448c | |
|
|
0f06e04a4e | |
|
|
3f10238136 | |
|
|
b7ca0babe5 | |
|
|
47020ca736 | |
|
|
b143f6a67d | |
|
|
f934dd66ae | |
|
|
435faca163 | |
|
|
6dd6502c5a | |
|
|
09d74032a9 | |
|
|
fedae8b98f | |
|
|
fb1c6011e0 | |
|
|
f4b10782f0 | |
|
|
b8d848e0bf | |
|
|
2e2f37c586 | |
|
|
dc65bd0562 | |
|
|
6831cfa898 | |
|
|
9bf2e8fef0 | |
|
|
4feda5f879 | |
|
|
4c4500b895 | |
|
|
81ab5823ec | |
|
|
294100b146 | |
|
|
2b8b0fb38d | |
|
|
9e2b880a32 | |
|
|
57ae7ff4ff | |
|
|
95742607a0 | |
|
|
f2cbc14727 | |
|
|
47e4d3dba5 | |
|
|
abe2f0ab90 | |
|
|
3b0abf5235 | |
|
|
9189b845ef | |
|
|
929a95ed9c | |
|
|
0991ab3993 | |
|
|
4ff522f3cd | |
|
|
a6c56d6539 | |
|
|
d7be7c30cb | |
|
|
66bcd4eb51 | |
|
|
114f7befbc | |
|
|
0bf9922be7 | |
|
|
e6c0220019 | |
|
|
ff0ee2d612 | |
|
|
82ff8c5c51 | |
|
|
77d93b0211 | |
|
|
3c081c230a | |
|
|
e93d76f316 | |
|
|
483fa7e930 | |
|
|
ca1f3662b0 | |
|
|
460270212d | |
|
|
ef8d084744 | |
|
|
797d1c01a9 | |
|
|
554eaf31a3 | |
|
|
9d8fc70c10 | |
|
|
16efb504e3 | |
|
|
62db69b1d4 | |
|
|
93543545c5 | |
|
|
32d201030d | |
|
|
6f650df200 | |
|
|
0e034f340d | |
|
|
b07c1cf4ab | |
|
|
0b0805d6bc | |
|
|
da56a8cb42 | |
|
|
97f9a39e95 | |
|
|
a063466f15 | |
|
|
dc7ff87e33 | |
|
|
63d636ff1a | |
|
|
1542db851e | |
|
|
f4aebf8e9c | |
|
|
6ea2af01fe | |
|
|
738b0b3ae9 | |
|
|
5fdf3a4ad9 | |
|
|
e00bf1da76 | |
|
|
f5162cb3a8 | |
|
|
df87261b62 | |
|
|
58b33b9399 | |
|
|
8b37a63a4a | |
|
|
cfe4acbb78 | |
|
|
a8ab37a17b | |
|
|
86214129b6 | |
|
|
fc7fd9d578 | |
|
|
b099f4cd99 | |
|
|
9efe53bf0d | |
|
|
cb1e475a83 | |
|
|
de9f003d26 | |
|
|
df332187d6 | |
|
|
88c2d8cf34 | |
|
|
3eb186063f | |
|
|
5a15d7d997 |
|
|
@ -33,3 +33,4 @@ google-services.json
|
||||||
# Android Profiling
|
# Android Profiling
|
||||||
*.hprof
|
*.hprof
|
||||||
|
|
||||||
|
/.kotlin/sessions/kotlin-compiler-2258332710725417628.salive
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.androidLibrary)
|
||||||
|
alias(libs.plugins.kotlinAndroid)
|
||||||
|
id("com.google.firebase.crashlytics")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.gamedog.statisticreporter"
|
||||||
|
compileSdk = 36
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk = 24
|
||||||
|
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
consumerProguardFiles("consumer-rules.pro")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "11"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.androidx.core.ktx)
|
||||||
|
implementation(libs.appcompat)
|
||||||
|
implementation(libs.material)
|
||||||
|
implementation(project(":base"))
|
||||||
|
testImplementation(libs.junit)
|
||||||
|
androidTestImplementation(libs.androidx.test.ext.junit)
|
||||||
|
androidTestImplementation(libs.espresso.core)
|
||||||
|
|
||||||
|
|
||||||
|
implementation(project(":core:architecture"))
|
||||||
|
implementation(project(":bill"))
|
||||||
|
|
||||||
|
api("com.adjust.sdk:adjust-android:5.5.0")
|
||||||
|
api("com.android.installreferrer:installreferrer:2.2")
|
||||||
|
// Add the following if you are using the Adjust SDK inside web views on your app
|
||||||
|
api("com.adjust.sdk:adjust-android-webbridge:5.5.0")
|
||||||
|
api("com.android.installreferrer:installreferrer:2.2")
|
||||||
|
api("com.adjust.sdk:adjust-android-huawei-referrer:5.0.0")
|
||||||
|
api("com.google.android.gms:play-services-ads-identifier:18.2.0")
|
||||||
|
implementation("cn.thinkingdata.android:ThinkingAnalyticsSDK:3.0.2")
|
||||||
|
|
||||||
|
|
||||||
|
// 导入 Firebase BoM(Bill of Materials)统一管理版本
|
||||||
|
implementation(platform("com.google.firebase:firebase-bom:33.16.0"))
|
||||||
|
|
||||||
|
// 添加你需要的 Firebase 产品依赖(无需指定版本号)
|
||||||
|
implementation("com.google.firebase:firebase-analytics")
|
||||||
|
implementation("com.google.firebase:firebase-crashlytics")
|
||||||
|
implementation("com.google.firebase:firebase-config")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
|
# ---------------------------------- 基础配置 ----------------------------------
|
||||||
|
# 代码优化次数,通常设为5
|
||||||
|
-optimizationpasses 5
|
||||||
|
# 不使用混合大小写类名
|
||||||
|
-dontusemixedcaseclassnames
|
||||||
|
# 不忽略非公共库类
|
||||||
|
-dontskipnonpubliclibraryclasses
|
||||||
|
# 不进行预校验(Android不需要,可加快速度)
|
||||||
|
-dontpreverify
|
||||||
|
# 打印混淆详情
|
||||||
|
-verbose
|
||||||
|
# 忽略警告
|
||||||
|
-ignorewarnings
|
||||||
|
|
||||||
|
# ---------------------------------- 保留重要属性 ----------------------------------
|
||||||
|
# 保留泛型签名(重要,避免JSON解析等类型转换错误)
|
||||||
|
-keepattributes Signature
|
||||||
|
# 保留注解(如@Keep, @SerializedName等)
|
||||||
|
-keepattributes *Annotation*
|
||||||
|
# 保留异常信息
|
||||||
|
-keepattributes Exceptions
|
||||||
|
# 保留源代码文件名和行号(便于崩溃日志分析)
|
||||||
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# ---------------------------------- 保留Android基本组件 ----------------------------------
|
||||||
|
# 保留四大组件及其子类
|
||||||
|
-keep public class * extends android.app.Activity
|
||||||
|
-keep public class * extends android.app.Application
|
||||||
|
-keep public class * extends android.app.Service
|
||||||
|
-keep public class * extends android.content.BroadcastReceiver
|
||||||
|
-keep public class * extends android.content.ContentProvider
|
||||||
|
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||||
|
-keep public class * extends android.preference.Preference
|
||||||
|
|
||||||
|
# 保持 Native 方法不被混淆
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保持 Parcelable 序列化类不被混淆
|
||||||
|
-keep class * implements android.os.Parcelable {
|
||||||
|
public static final android.os.Parcelable$Creator *;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保持 Serializable 序列化的类成员不被混淆
|
||||||
|
-keepclassmembers class * implements java.io.Serializable {
|
||||||
|
static final long serialVersionUID;
|
||||||
|
private static final java.io.ObjectStreamField[] serialPersistentFields;
|
||||||
|
private void writeObject(java.io.ObjectOutputStream);
|
||||||
|
private void readObject(java.io.ObjectInputStream);
|
||||||
|
java.lang.Object writeReplace();
|
||||||
|
java.lang.Object readResolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保持自定义 View 的构造方法不被混淆(用于 XML 布局)
|
||||||
|
-keep public class * extends android.view.View {
|
||||||
|
public <init>(android.content.Context);
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet);
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||||
|
public void set*(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保持枚举类不被混淆
|
||||||
|
-keepclassmembers enum * {
|
||||||
|
public static **[] values();
|
||||||
|
public static ** valueOf(java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保持由 JSON 转换的 Bean 类(或者你的数据模型类)不被混淆
|
||||||
|
-keep class com.gamedog.vididin.beans.** { *; }
|
||||||
|
-keep class com.gamedog.vididin.router.** { *; }
|
||||||
|
|
||||||
|
|
||||||
|
# 保留R文件中的静态字段(保证资源反射能正常工作)
|
||||||
|
-keepclassmembers class **.R$* {
|
||||||
|
public static <fields>;
|
||||||
|
}
|
||||||
|
|
||||||
|
# gson
|
||||||
|
-keep class com.google.gson.** { *; }
|
||||||
|
-keep class sun.misc.Unsafe { *; }
|
||||||
|
-keep class com.google.gson.stream.** { *; }
|
||||||
|
# 明确保护被@SerializedName注解的字段
|
||||||
|
-keepclassmembers class * {
|
||||||
|
@com.google.gson.annotations.SerializedName <fields>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#okhttp
|
||||||
|
# OkHttp3
|
||||||
|
-dontwarn okhttp3.**
|
||||||
|
-keep class okhttp3.** { *; }
|
||||||
|
-keep interface okhttp3.** { *; }
|
||||||
|
-dontwarn okio.**
|
||||||
|
# Retrofit2
|
||||||
|
-dontwarn retrofit2.**
|
||||||
|
-keep class retrofit2.** { *; }
|
||||||
|
-keepattributes Signature, Exceptions
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.gamedog.statisticreporter
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
fun useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
assertEquals("com.gamedog.statisticreporter.test", appContext.packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
|
|
||||||
|
</manifest>
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
package com.gamedog.statisticreporter
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.remax.bill.BuildConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广告日志工具类
|
||||||
|
* 提供统一的日志输出控制和管理
|
||||||
|
*/
|
||||||
|
object StatisticLogger {
|
||||||
|
private const val TAG = "StatisticModule"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志开关,默认为true
|
||||||
|
*/
|
||||||
|
private var isLogEnabled = BuildConfig.DEBUG
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置日志开关
|
||||||
|
* @param enabled 是否启用日志
|
||||||
|
*/
|
||||||
|
fun setLogEnabled(enabled: Boolean) {
|
||||||
|
isLogEnabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取日志开关状态
|
||||||
|
* @return 是否启用日志
|
||||||
|
*/
|
||||||
|
fun isLogEnabled(): Boolean = isLogEnabled
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug日志
|
||||||
|
* @param message 日志消息
|
||||||
|
*/
|
||||||
|
fun d(message: String) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.d(TAG, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug日志(带参数)
|
||||||
|
* @param message 日志消息模板
|
||||||
|
* @param args 参数列表
|
||||||
|
*/
|
||||||
|
fun d(message: String, vararg args: Any?) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.d(TAG, message.format(*args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning日志
|
||||||
|
* @param message 日志消息
|
||||||
|
*/
|
||||||
|
fun w(message: String) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.w(TAG, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning日志(带参数)
|
||||||
|
* @param message 日志消息模板
|
||||||
|
* @param args 参数列表
|
||||||
|
*/
|
||||||
|
fun w(message: String, vararg args: Any?) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.w(TAG, message.format(*args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error日志
|
||||||
|
* @param message 日志消息
|
||||||
|
*/
|
||||||
|
fun e(message: String) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.e(TAG, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error日志(带异常)
|
||||||
|
* @param message 日志消息
|
||||||
|
* @param throwable 异常对象
|
||||||
|
*/
|
||||||
|
fun e(message: String, throwable: Throwable?) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.e(TAG, message, throwable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error日志(带参数)
|
||||||
|
* @param message 日志消息模板
|
||||||
|
* @param args 参数列表
|
||||||
|
*/
|
||||||
|
fun e(message: String, vararg args: Any?) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.e(TAG, message.format(*args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error日志(带参数和异常)
|
||||||
|
* @param message 日志消息模板
|
||||||
|
* @param throwable 异常对象
|
||||||
|
* @param args 参数列表
|
||||||
|
*/
|
||||||
|
fun e(message: String, throwable: Throwable?, vararg args: Any?) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.e(TAG, message.format(*args), throwable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Info日志
|
||||||
|
* @param message 日志消息
|
||||||
|
*/
|
||||||
|
fun i(message: String) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.i(TAG, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Info日志(带参数)
|
||||||
|
* @param message 日志消息模板
|
||||||
|
* @param args 参数列表
|
||||||
|
*/
|
||||||
|
fun i(message: String, vararg args: Any?) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.i(TAG, message.format(*args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verbose日志
|
||||||
|
* @param message 日志消息
|
||||||
|
*/
|
||||||
|
fun v(message: String) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.v(TAG, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verbose日志(带参数)
|
||||||
|
* @param message 日志消息模板
|
||||||
|
* @param args 参数列表
|
||||||
|
*/
|
||||||
|
fun v(message: String, vararg args: Any?) {
|
||||||
|
if (isLogEnabled) {
|
||||||
|
Log.v(TAG, message.format(*args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
package com.gamedog.statisticreporter
|
||||||
|
|
||||||
|
import com.gamedog.statisticreporter.adjust.AdjustManager
|
||||||
|
import com.gamedog.statisticreporter.firbase.FireBaseManager
|
||||||
|
import com.gamedog.statisticreporter.shushu.ShushuManager
|
||||||
|
import com.remax.base.report.DataReportManager
|
||||||
|
import com.remax.base.report.DataReporter
|
||||||
|
import com.remax.bill.BuildConfig
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
object StatisticUtil {
|
||||||
|
|
||||||
|
private lateinit var mGoldTimesFun: () -> Int
|
||||||
|
private lateinit var mCashTimesFun: () -> Int
|
||||||
|
private lateinit var mGoldFun: () -> Long
|
||||||
|
private lateinit var mCashFun: () -> Double
|
||||||
|
private val mBgScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||||
|
|
||||||
|
const val KEY_Loading_Start: String = "Loading_Start"
|
||||||
|
const val KEY_Loading_End: String = "Loading_End"
|
||||||
|
const val KEY_Home_Show: String = "Home_Show"
|
||||||
|
const val KEY_Guide: String = "Guide"
|
||||||
|
const val KEY_RV_Button_Show: String = "RV_Button_Show"
|
||||||
|
const val KEY_RV_Button_Click: String = "RV_Button_Click"
|
||||||
|
const val KEY_Video_Play_Start: String = "Video_Play_Start"
|
||||||
|
const val KEY_Video_Play_End: String = "Video_Play_End"
|
||||||
|
const val KEY_Welfare_Show: String = "Welfare_Show"
|
||||||
|
const val KEY_Chest_Claim_Click: String = "Chest_Claim_Click"
|
||||||
|
const val KEY_Welfare_Task_Click: String = "Welfare_Task_Click"
|
||||||
|
const val KEY_H5_Button_Click: String = "H5_Button_Click"
|
||||||
|
const val KEY_H5_Show: String = "H5_Show"
|
||||||
|
const val KEY_lottery_Button_Click: String = "lottery_Button_Click"
|
||||||
|
const val KEY_lottery_Show: String = "lottery_Show"
|
||||||
|
const val KEY_Daily_Task_Complete: String = "Daily_Task_Complete"
|
||||||
|
const val KEY_Daily_Sign: String = "Daily_Sign"
|
||||||
|
const val KEY_Withdraw_Click: String = "Withdraw_Click"
|
||||||
|
const val KEY_Withdrawal_Show: String = "Withdrawal_Show"
|
||||||
|
const val KEY_Withdrawal_finsh: String = "Withdrawal_finsh"
|
||||||
|
const val KEY_Withdrawal_Info: String = "Withdrawal_Info"
|
||||||
|
const val KEY_Withdrawal_Apply: String = "Withdrawal_Apply"
|
||||||
|
const val KEY_Withdrawal_Reason: String = "Withdrawal_Reason"
|
||||||
|
const val KEY_Push_Request_Show: String = "Push_Request_Show"
|
||||||
|
const val KEY_Push_Request_Result: String = "Push_Request_Result"
|
||||||
|
const val KEY_Push_Show: String = "Push_Show"
|
||||||
|
const val KEY_Push_Click: String = "Push_Click"
|
||||||
|
const val KEY_Push_EnterGame: String = "Push_EnterGame"
|
||||||
|
const val KEY_adjust_init: String = "adjust_init"
|
||||||
|
const val KEY_adjust_get_success: String = "adjust_get_success"
|
||||||
|
const val ad_click: String = "ad_click"
|
||||||
|
const val KEY_ad_close: String = "ad_close"
|
||||||
|
const val KEY_ad_start_load: String = "ad_start_load"
|
||||||
|
const val KEY_ad_loaded: String = "ad_loaded"
|
||||||
|
const val KEY_ad_load_fail: String = "ad_load_fail"
|
||||||
|
const val KEY_ad_show_fail: String = "ad_show_fail"
|
||||||
|
const val KEY_ad_position: String = "ad_position"
|
||||||
|
const val KEY_ad_impression: String = "ad_impression"
|
||||||
|
|
||||||
|
|
||||||
|
fun reportEvents(eventKey: String, eventData: Map<String, Any>? = null) {
|
||||||
|
mBgScope.launch {
|
||||||
|
|
||||||
|
val superPropertiesMap = mapOf("Money_Num" to mCashFun.invoke(),
|
||||||
|
"Coin_Num" to mGoldFun.invoke(),
|
||||||
|
"RV_Times_Coins" to mGoldTimesFun.invoke(),
|
||||||
|
"RV_Times_Money" to mCashTimesFun.invoke(),
|
||||||
|
"ad_network" to AdjustManager.instance().getNetwork(),
|
||||||
|
"adid" to AdjustManager.instance().getAaId()
|
||||||
|
)
|
||||||
|
FireBaseManager.instance().reportEvent(eventKey, eventData, superPropertiesMap)
|
||||||
|
val shushuManager = ShushuManager.instance()
|
||||||
|
shushuManager.reportEvent(eventKey, eventData, superPropertiesMap)
|
||||||
|
StatisticLogger.d("[reportEvents] shushuReady=${shushuManager.isSdkReady()} eventKey=$eventKey")
|
||||||
|
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
StatisticLogger.d("[reportEvents] Events reported to shushu&Firebase: type=$eventKey")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
initAdReporter()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun initAdReporter() {
|
||||||
|
DataReportManager.addReporters(object : DataReporter {
|
||||||
|
override fun getName(): String {
|
||||||
|
return "ThinkingData" //
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reportData(
|
||||||
|
eventName: String,
|
||||||
|
data: Map<String, Any>
|
||||||
|
) {
|
||||||
|
reportEvents(eventName, data)
|
||||||
|
val dataStr = try {
|
||||||
|
data.entries
|
||||||
|
.sortedBy { it.key }
|
||||||
|
.joinToString(prefix = "{", postfix = "}") { (k, v) -> "$k=$v" }
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
"format_failed:${t.javaClass.simpleName}"
|
||||||
|
}
|
||||||
|
StatisticLogger.d("[DataReporter] eventName: $eventName data=$dataStr")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setCommonParams(params: Map<String, Any>) {
|
||||||
|
FireBaseManager.instance().setCommonParams(params)
|
||||||
|
ShushuManager.instance().setCommonParams(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setUserParams(params: Map<String, Any>) {
|
||||||
|
FireBaseManager.instance().setUserParams(params)
|
||||||
|
ShushuManager.instance().setUserParams(params)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun initCallbacks(cashCallback: ()->Double, goldCallback: ()->Long,
|
||||||
|
cashTimesCallback: ()->Int, goldTimesCallback: ()->Int) {
|
||||||
|
mCashFun = cashCallback
|
||||||
|
mGoldFun = goldCallback
|
||||||
|
mCashTimesFun = cashTimesCallback
|
||||||
|
mGoldTimesFun = goldTimesCallback
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,368 @@
|
||||||
|
package com.gamedog.statisticreporter.adjust
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import android.text.TextUtils
|
||||||
|
import com.adjust.sdk.Adjust
|
||||||
|
import com.adjust.sdk.AdjustAdRevenue
|
||||||
|
import com.adjust.sdk.AdjustAttribution
|
||||||
|
import com.adjust.sdk.AdjustConfig
|
||||||
|
import com.adjust.sdk.AdjustEvent
|
||||||
|
import com.adjust.sdk.LogLevel
|
||||||
|
import com.adjust.sdk.OnAttributionChangedListener
|
||||||
|
import com.adjust.sdk.OnGoogleAdIdReadListener
|
||||||
|
import com.adjust.sdk.OnSessionTrackingFailedListener
|
||||||
|
import com.adjust.sdk.OnSessionTrackingSucceededListener
|
||||||
|
import com.ama.core.architecture.BaseApp
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.DateUtil
|
||||||
|
import com.ama.core.architecture.util.SpUtil
|
||||||
|
import com.gamedog.statisticreporter.StatisticLogger
|
||||||
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
|
import com.gamedog.statisticreporter.adjust.AdjustManager.Companion.USER_TYPE_BUY
|
||||||
|
import com.remax.base.ads.AdRevenueData
|
||||||
|
import com.remax.base.ads.AdRevenueManager
|
||||||
|
import com.remax.base.ads.AdRevenueReporter
|
||||||
|
import com.remax.base.controller.UserChannelController
|
||||||
|
import com.remax.base.report.DataReportManager
|
||||||
|
import com.remax.bill.BuildConfig
|
||||||
|
|
||||||
|
|
||||||
|
class AdjustManager private constructor() {
|
||||||
|
companion object {
|
||||||
|
@Volatile
|
||||||
|
private var INSTANCE: AdjustManager? = null
|
||||||
|
|
||||||
|
fun instance(): AdjustManager {
|
||||||
|
return INSTANCE ?: synchronized(this) {
|
||||||
|
INSTANCE ?: AdjustManager().also { INSTANCE = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const val ATTRI_TYPE_ORGANIC = "Organic"
|
||||||
|
const val ATTRI_TYPE_UNTRUSTED = "Untrusted Devices"
|
||||||
|
const val ATTRI_TYPE_GOOGLE = "Google Organic Search"
|
||||||
|
|
||||||
|
const val USER_TYPE_NORMAL = 1
|
||||||
|
const val USER_TYPE_BUY = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private var mGaid: String = ""
|
||||||
|
private var mAdid: String = ""
|
||||||
|
private var mAttribution: AdjustAttribution? = null
|
||||||
|
private var initStartTime: Long = 0
|
||||||
|
|
||||||
|
private var mAdjustInitStartMs: Long = 0
|
||||||
|
private val mAppContext = BaseApp.appContext()
|
||||||
|
private val mSpHelper = SpHelper()
|
||||||
|
private val mUserFromCheckRunnable = kotlinx.coroutines.Runnable {
|
||||||
|
run {
|
||||||
|
// 所有用户一开始都是自然用户的状态,需要通过调用setOnAttributionChangedListener这个方法(这个方法就是返回用户改变后的状态),获得买量来源信息
|
||||||
|
Adjust.getAttribution { attribution ->
|
||||||
|
mAttribution = attribution
|
||||||
|
val networkFrom = attribution.network
|
||||||
|
var userTypeInt = 0
|
||||||
|
if (!TextUtils.isEmpty(networkFrom)) {
|
||||||
|
if (networkFrom.contains(ATTRI_TYPE_GOOGLE) || networkFrom.contains(ATTRI_TYPE_UNTRUSTED)) {
|
||||||
|
userTypeInt = USER_TYPE_NORMAL
|
||||||
|
} else if (!networkFrom.contains(ATTRI_TYPE_ORGANIC)) {
|
||||||
|
userTypeInt = USER_TYPE_BUY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userTypeInt > 0) {
|
||||||
|
saveUserType(userTypeInt)
|
||||||
|
mChecker.stopPolling()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveUserType(userType: Int) {
|
||||||
|
mSpHelper.saveUserType(userType)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mChecker: PollCheckHelper = PollCheckHelper(180,
|
||||||
|
3, mUserFromCheckRunnable, {
|
||||||
|
saveUserType(USER_TYPE_NORMAL)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun initSdk(appToken: String) {
|
||||||
|
initStartTime = DateUtil.getCurTimeMs()
|
||||||
|
|
||||||
|
CommonParamsManager.initLoginParams()
|
||||||
|
StatisticLogger.d("登录参数初始化完成 - login_day: ${CommonParamsManager.loginDay ?: ""}, is_new: ${CommonParamsManager.isNew ?: ""}")
|
||||||
|
|
||||||
|
/// 先设置登录参数到DataReportManager
|
||||||
|
val loginParams = CommonParamsManager.getAllCommonParams()
|
||||||
|
val userParams = CommonParamsManager.getUserCommonParams()
|
||||||
|
DataReportManager.setCommonParams(loginParams)
|
||||||
|
DataReportManager.setUserParams(userParams)
|
||||||
|
StatisticLogger.d("登录参数已设置到DataReportManager: $loginParams")
|
||||||
|
// 初始化埋点
|
||||||
|
DataReportManager.reportData("adjust_init", mapOf())
|
||||||
|
|
||||||
|
|
||||||
|
val isDebug = BuildConfig.DEBUG
|
||||||
|
val environment = if (/*isDebug*/false) AdjustConfig.ENVIRONMENT_SANDBOX else AdjustConfig.ENVIRONMENT_PRODUCTION
|
||||||
|
val config = AdjustConfig(mAppContext, appToken, environment).apply {
|
||||||
|
setLogLevel(if (isDebug) LogLevel.VERBOSE else LogLevel.WARN)
|
||||||
|
enableSendingInBackground()
|
||||||
|
enableCostDataInAttribution()
|
||||||
|
/*enableCoppaCompliance()
|
||||||
|
enableCostDataInAttribution()*/
|
||||||
|
|
||||||
|
onSessionTrackingFailedListener = OnSessionTrackingFailedListener { failSession ->
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onSessionTrackingSucceededListener = OnSessionTrackingSucceededListener {
|
||||||
|
val test = 111
|
||||||
|
}
|
||||||
|
|
||||||
|
onAttributionChangedListener = OnAttributionChangedListener { attribution->
|
||||||
|
handleAttribution(attribution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_adjust_init)
|
||||||
|
mAdjustInitStartMs = System.currentTimeMillis()
|
||||||
|
Adjust.initSdk(config)
|
||||||
|
Adjust.enable()
|
||||||
|
|
||||||
|
Adjust.getGoogleAdId(BaseApp.appContext(), OnGoogleAdIdReadListener { gaId->
|
||||||
|
mGaid = gaId
|
||||||
|
})
|
||||||
|
|
||||||
|
Adjust.getAdid { adId->
|
||||||
|
mAdid = adId
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mSpHelper.hasIdentityUserType()) {
|
||||||
|
mChecker.startPolling()
|
||||||
|
} else {
|
||||||
|
Adjust.getAttribution {
|
||||||
|
handleAttribution(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AdRevenueManager.addReporter(object: AdRevenueReporter {
|
||||||
|
override fun reportAdRevenue(adRevenueData: AdRevenueData) {
|
||||||
|
reportAdRevenueInfo(adRevenueData)
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleAttribution(attr: AdjustAttribution) {
|
||||||
|
mAttribution = attr
|
||||||
|
|
||||||
|
// 设置公共参数,并限制长度
|
||||||
|
CommonParamsManager.adNetwork = (attr.network ?: "").take(10)
|
||||||
|
CommonParamsManager.campaign = (attr.campaign ?: "").take(20)
|
||||||
|
CommonParamsManager.adgroup = (attr.adgroup ?: "").take(10)
|
||||||
|
CommonParamsManager.creative = (attr.creative ?: "").take(20)
|
||||||
|
|
||||||
|
StatisticLogger.d("公共参数设置完成 - ad_network: ${CommonParamsManager.adNetwork}, campaign: ${CommonParamsManager.campaign}, adgroup: ${CommonParamsManager.adgroup}, creative: ${CommonParamsManager.creative}")
|
||||||
|
|
||||||
|
// 将公共参数设置到DataReportManager
|
||||||
|
val commonParams = CommonParamsManager.getAllCommonParams()
|
||||||
|
val userParams = CommonParamsManager.getUserCommonParams()
|
||||||
|
DataReportManager.setCommonParams(commonParams)
|
||||||
|
DataReportManager.setUserParams(userParams)
|
||||||
|
StatisticLogger.d("公共参数已设置到DataReportManager: $commonParams")
|
||||||
|
|
||||||
|
// 计算从初始化开始到归因回调的总耗时(秒数,向上取整)
|
||||||
|
val totalDurationSeconds = kotlin.math.ceil((System.currentTimeMillis() - initStartTime) / 1000.0).toInt()
|
||||||
|
StatisticLogger.d("Adjust初始化到归因回调总耗时: ${totalDurationSeconds}秒")
|
||||||
|
DataReportManager.reportData(StatisticUtil.KEY_adjust_get_success, mapOf("pass_time" to totalDurationSeconds))
|
||||||
|
|
||||||
|
|
||||||
|
// 设置当前用户渠道类型
|
||||||
|
// val userChannelType = if (StatisticLogger.isLogEnabled()) {
|
||||||
|
// // 内部版本强制设置为买量类型
|
||||||
|
// StatisticLogger.d("内部版本强制设置为买量类型")
|
||||||
|
// UserChannelController.UserChannelType.PAID
|
||||||
|
// } else {
|
||||||
|
// determineUserChannelType(attr)
|
||||||
|
// }
|
||||||
|
val userChannelType = determineUserChannelType(attr)
|
||||||
|
StatisticLogger.d("根据归因数据判断用户渠道类型: $userChannelType")
|
||||||
|
|
||||||
|
// val userChannelType = UserChannelController.UserChannelType.NATURAL
|
||||||
|
// StatisticLogger.d("根据归因数据判断用户渠道类型: $userChannelType")
|
||||||
|
|
||||||
|
// 设置用户渠道类型
|
||||||
|
val success = UserChannelController.setChannel(userChannelType)
|
||||||
|
if (success) {
|
||||||
|
StatisticLogger.i("用户渠道类型设置成功: $userChannelType")
|
||||||
|
} else {
|
||||||
|
StatisticLogger.w("用户渠道类型已经设置过,无法修改")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun determineUserChannelType(attribution: AdjustAttribution): UserChannelController.UserChannelType {
|
||||||
|
// 获取归因数据的关键字段
|
||||||
|
val network = attribution.network?.lowercase()
|
||||||
|
val trackerName = attribution.trackerName?.lowercase()
|
||||||
|
val campaign = attribution.campaign?.lowercase()
|
||||||
|
|
||||||
|
StatisticLogger.d("归因数据 - network: $network, trackerName: $trackerName, campaign: $campaign")
|
||||||
|
|
||||||
|
// 判断是否为自然渠道的条件
|
||||||
|
val isOrganic = when {
|
||||||
|
// 1. Organic - 有机渠道
|
||||||
|
network == "organic" -> {
|
||||||
|
StatisticLogger.d("检测到Organic渠道")
|
||||||
|
true
|
||||||
|
}
|
||||||
|
// 2. Untrusted Devices - 不可信设备
|
||||||
|
network == "untrusted devices" -> {
|
||||||
|
StatisticLogger.d("检测到Untrusted Devices渠道")
|
||||||
|
true
|
||||||
|
}
|
||||||
|
// 3. Google Organic Search - Google有机搜索
|
||||||
|
network == "google organic search" -> {
|
||||||
|
StatisticLogger.d("检测到Google Organic Search渠道")
|
||||||
|
true
|
||||||
|
}
|
||||||
|
// 4. 其他情况都认为是买量渠道
|
||||||
|
else -> {
|
||||||
|
StatisticLogger.d("检测到买量渠道 - network: $network")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (isOrganic) {
|
||||||
|
UserChannelController.UserChannelType.NATURAL
|
||||||
|
} else {
|
||||||
|
UserChannelController.UserChannelType.PAID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reportAdRevenueInfo(revenueValue: AdRevenueData) {
|
||||||
|
val adjustAdRevenue = AdjustAdRevenue(getRandomFixSourceStr()).apply {
|
||||||
|
setRevenue(revenueValue.revenue.value, revenueValue.revenue.currencyCode /*"USD"*/) // ad收益数值及单位
|
||||||
|
setAdRevenueNetwork(revenueValue.adRevenueNetwork) // 渠道来源
|
||||||
|
setAdRevenueUnit(revenueValue.adRevenueUnit) // ad收入来源单元
|
||||||
|
setAdRevenuePlacement(revenueValue.adRevenuePlacement) // 位置
|
||||||
|
}
|
||||||
|
Adjust.trackAdRevenue(adjustAdRevenue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* val event = AdjustEvent("g3mfiw")
|
||||||
|
* event.setCallbackId("f2e728d8-271b-49ab-80ea-27830a215147")
|
||||||
|
*/
|
||||||
|
fun reportAdjustEvent(event: AdjustEvent, callbackId: String?) {
|
||||||
|
callbackId?.let {
|
||||||
|
event.callbackId = callbackId
|
||||||
|
}
|
||||||
|
Adjust.trackEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isUserBuy(): Boolean {
|
||||||
|
return mSpHelper.isUserBuy()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------- PRIVATE ------------------------//
|
||||||
|
private fun getRandomFixSourceStr(): String {
|
||||||
|
val randomInt = AndroidUtil.randomInt(1, 10)
|
||||||
|
return if (randomInt <= 2) "ironsource_sdk" else "applovin_max_sdk"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNetwork(): String {
|
||||||
|
return mAttribution?.network ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getGaId(): String {
|
||||||
|
return mGaid
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAaId(): String {
|
||||||
|
return mAdid
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SpHelper {
|
||||||
|
companion object {
|
||||||
|
const val KEY_USER_FROM_TYPE = "KEY_USER_FROM_TYPE" // 1:自然用户 2:买量用户
|
||||||
|
}
|
||||||
|
|
||||||
|
private var mUserType = SpUtil.instance().getInt(KEY_USER_FROM_TYPE)
|
||||||
|
|
||||||
|
fun hasIdentityUserType(): Boolean {
|
||||||
|
return mUserType > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveUserType(userType: Int) {
|
||||||
|
mUserType = userType
|
||||||
|
SpUtil.instance().putInt(KEY_USER_FROM_TYPE, mUserType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isUserBuy(): Boolean {
|
||||||
|
return mUserType == USER_TYPE_BUY
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PollCheckHelper(private val mTotalCheckSec: Int,
|
||||||
|
private val mTotalCheckGapSec: Int,
|
||||||
|
private val mCheckRunnable: Runnable,
|
||||||
|
private val mFinishCallback: ()->Unit) {
|
||||||
|
|
||||||
|
private var handlerThread: HandlerThread? = null
|
||||||
|
private var handler: Handler? = null
|
||||||
|
private var mStartMs: Long = 0L
|
||||||
|
private var mPollRunnable: Runnable? = null
|
||||||
|
private var mHasStop = false
|
||||||
|
private var mHasStarted = false
|
||||||
|
|
||||||
|
|
||||||
|
fun startPolling() {
|
||||||
|
if (mHasStarted) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handlerThread = HandlerThread("PollingThread").apply { start() }
|
||||||
|
handler = Handler(handlerThread!!.looper)
|
||||||
|
mStartMs = System.currentTimeMillis()
|
||||||
|
|
||||||
|
mPollRunnable = Runnable {
|
||||||
|
mCheckRunnable.run()
|
||||||
|
val hasExpired = System.currentTimeMillis() - mStartMs >= mTotalCheckSec * 1000
|
||||||
|
if (hasExpired || mHasStop) {
|
||||||
|
stopPolling()
|
||||||
|
if (hasExpired) {
|
||||||
|
mFinishCallback.invoke()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handler?.postDelayed(mPollRunnable!!, mTotalCheckGapSec * 1000L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler?.post(mPollRunnable!!)
|
||||||
|
mHasStarted = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopPolling() {
|
||||||
|
mHasStop = true
|
||||||
|
mPollRunnable?.let {
|
||||||
|
handler?.removeCallbacks(it)
|
||||||
|
}
|
||||||
|
handlerThread?.quitSafely()
|
||||||
|
mPollRunnable = null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
package com.gamedog.statisticreporter.adjust
|
||||||
|
|
||||||
|
import com.remax.base.ext.KvStringDelegate
|
||||||
|
import java.util.Calendar
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公共参数管理器
|
||||||
|
* 管理数据上报的公共参数,使用KvStringDelegate持久化
|
||||||
|
*/
|
||||||
|
object CommonParamsManager {
|
||||||
|
|
||||||
|
private const val KEY_AD_NETWORK = "common_param_ad_network"
|
||||||
|
private const val KEY_CAMPAIGN = "common_param_campaign"
|
||||||
|
private const val KEY_ADGROUP = "common_param_adgroup"
|
||||||
|
private const val KEY_CREATIVE = "common_param_creative"
|
||||||
|
private const val KEY_LOGIN_DAY = "common_param_login_day"
|
||||||
|
private const val KEY_IS_NEW = "common_param_is_new"
|
||||||
|
private const val KEY_FIRST_INSTALL_DATE = "first_install_date"
|
||||||
|
|
||||||
|
// 使用KvStringDelegate进行持久化存储,默认值为空字符串
|
||||||
|
var adNetwork by KvStringDelegate(KEY_AD_NETWORK, "")
|
||||||
|
var campaign by KvStringDelegate(KEY_CAMPAIGN, "")
|
||||||
|
var adgroup by KvStringDelegate(KEY_ADGROUP, "")
|
||||||
|
var creative by KvStringDelegate(KEY_CREATIVE, "")
|
||||||
|
var loginDay by KvStringDelegate(KEY_LOGIN_DAY, "")
|
||||||
|
var isNew by KvStringDelegate(KEY_IS_NEW, "")
|
||||||
|
private var firstInstallDate by KvStringDelegate(KEY_FIRST_INSTALL_DATE, "")
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化登录相关参数
|
||||||
|
* 在应用启动时调用,自动计算login_day和is_new
|
||||||
|
*/
|
||||||
|
fun initLoginParams() {
|
||||||
|
val currentDate = getCurrentDateString()
|
||||||
|
val storedFirstInstallDate = firstInstallDate ?: ""
|
||||||
|
|
||||||
|
if (storedFirstInstallDate.isEmpty()) {
|
||||||
|
// 首次安装,记录安装日期
|
||||||
|
firstInstallDate = currentDate
|
||||||
|
loginDay = "0"
|
||||||
|
isNew = "Y"
|
||||||
|
} else {
|
||||||
|
// 非首次安装,计算登录天数
|
||||||
|
val daysDiff = calculateDaysDifference(storedFirstInstallDate, currentDate)
|
||||||
|
loginDay = daysDiff.toString()
|
||||||
|
isNew = if (daysDiff == 0) "Y" else "N"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前日期字符串(格式:yyyy-MM-dd)
|
||||||
|
* @return 当前日期字符串
|
||||||
|
*/
|
||||||
|
private fun getCurrentDateString(): String {
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
val year = calendar.get(Calendar.YEAR)
|
||||||
|
val month = calendar.get(Calendar.MONTH) + 1
|
||||||
|
val day = calendar.get(Calendar.DAY_OF_MONTH)
|
||||||
|
return String.format(Locale.ENGLISH, "%04d-%02d-%02d", year, month, day)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算两个日期之间的天数差
|
||||||
|
* @param startDate 开始日期(格式:yyyy-MM-dd)
|
||||||
|
* @param endDate 结束日期(格式:yyyy-MM-dd)
|
||||||
|
* @return 天数差
|
||||||
|
*/
|
||||||
|
private fun calculateDaysDifference(startDate: String, endDate: String): Int {
|
||||||
|
return try {
|
||||||
|
val startCalendar = parseDateToCalendar(startDate)
|
||||||
|
val endCalendar = parseDateToCalendar(endDate)
|
||||||
|
|
||||||
|
if (startCalendar == null || endCalendar == null) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置时间部分,只比较日期
|
||||||
|
startCalendar.set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
startCalendar.set(Calendar.MINUTE, 0)
|
||||||
|
startCalendar.set(Calendar.SECOND, 0)
|
||||||
|
startCalendar.set(Calendar.MILLISECOND, 0)
|
||||||
|
|
||||||
|
endCalendar.set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
endCalendar.set(Calendar.MINUTE, 0)
|
||||||
|
endCalendar.set(Calendar.SECOND, 0)
|
||||||
|
endCalendar.set(Calendar.MILLISECOND, 0)
|
||||||
|
|
||||||
|
// 计算天数差
|
||||||
|
val diffInMillis = endCalendar.timeInMillis - startCalendar.timeInMillis
|
||||||
|
(diffInMillis / (24 * 60 * 60 * 1000)).toInt()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将日期字符串解析为Calendar对象
|
||||||
|
* @param dateString 日期字符串(格式:yyyy-MM-dd)
|
||||||
|
* @return Calendar对象,解析失败返回null
|
||||||
|
*/
|
||||||
|
private fun parseDateToCalendar(dateString: String): Calendar? {
|
||||||
|
return try {
|
||||||
|
val parts = dateString.split("-")
|
||||||
|
if (parts.size != 3) return null
|
||||||
|
|
||||||
|
val year = parts[0].toInt()
|
||||||
|
val month = parts[1].toInt() - 1 // Calendar的月份从0开始
|
||||||
|
val day = parts[2].toInt()
|
||||||
|
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
calendar.set(year, month, day)
|
||||||
|
calendar
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有公共参数
|
||||||
|
* @return 公共参数Map
|
||||||
|
*/
|
||||||
|
fun getAllCommonParams(): Map<String, String> {
|
||||||
|
return mapOf(
|
||||||
|
"ad_network" to (adNetwork ?: ""),
|
||||||
|
"campaign" to (campaign ?: ""),
|
||||||
|
"adgroup" to (adgroup ?: ""),
|
||||||
|
"creative" to (creative ?: ""),
|
||||||
|
"login_day" to (loginDay ?: ""),
|
||||||
|
"is_new" to (isNew ?: "")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUserCommonParams(): Map<String, String> {
|
||||||
|
return mapOf(
|
||||||
|
"user_ad_network" to (adNetwork ?: ""),
|
||||||
|
"user_campaign" to (campaign ?: ""),
|
||||||
|
"user_adgroup" to (adgroup ?: ""),
|
||||||
|
"user_creative" to (creative ?: ""),
|
||||||
|
"user_login_day" to (loginDay ?: ""),
|
||||||
|
"user_is_new" to (isNew ?: "")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,313 @@
|
||||||
|
package com.gamedog.statisticreporter.firbase
|
||||||
|
|
||||||
|
|
||||||
|
import android.R.string
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import cn.thinkingdata.analytics.TDAnalytics
|
||||||
|
import com.ama.core.architecture.BaseApp
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil.Companion.gson
|
||||||
|
import com.gamedog.statisticreporter.StatisticLogger
|
||||||
|
import com.google.firebase.Firebase
|
||||||
|
import com.google.firebase.FirebaseApp
|
||||||
|
import com.google.firebase.analytics.FirebaseAnalytics
|
||||||
|
import com.google.firebase.analytics.analytics
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
|
|
||||||
|
class FireBaseManager private constructor() {
|
||||||
|
companion object {
|
||||||
|
@Volatile
|
||||||
|
private var INSTANCE: FireBaseManager? = null
|
||||||
|
|
||||||
|
fun instance(): FireBaseManager {
|
||||||
|
return INSTANCE ?: synchronized(this) {
|
||||||
|
INSTANCE ?: FireBaseManager().also { INSTANCE = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val mAppContext = BaseApp.appContext()
|
||||||
|
private val mBgScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||||
|
private val mMainScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
||||||
|
|
||||||
|
private lateinit var mFbAnalytics: FirebaseAnalytics
|
||||||
|
private val mDefaultParams = ConcurrentHashMap<String, Any>()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
FirebaseApp.initializeApp(mAppContext)
|
||||||
|
|
||||||
|
if (!::mFbAnalytics.isInitialized) {
|
||||||
|
mFbAnalytics = Firebase.analytics// FirebaseAnalytics.getInstance(mAppContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reportEvent(
|
||||||
|
eventName: String,
|
||||||
|
parameters: Map<String, Any>? = null,
|
||||||
|
superPropertiesMap: Map<String, Any>
|
||||||
|
) {
|
||||||
|
if (!::mFbAnalytics.isInitialized) {
|
||||||
|
throw IllegalStateException("FirebaseAnalyticsUtil not initialized. Call init() first.")
|
||||||
|
}
|
||||||
|
|
||||||
|
val bundle = Bundle().apply {
|
||||||
|
// 默认参数添加
|
||||||
|
mDefaultParams.forEach { (key, value) ->
|
||||||
|
when (value) {
|
||||||
|
is String -> putString(key, value)
|
||||||
|
is Int -> putInt(key, value)
|
||||||
|
is Long -> putLong(key, value)
|
||||||
|
is Double -> putDouble(key, value)
|
||||||
|
is Float -> putFloat(key, value)
|
||||||
|
is Boolean -> putBoolean(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
superPropertiesMap.forEach { (key, value) ->
|
||||||
|
when (value) {
|
||||||
|
is String -> putString(key, value)
|
||||||
|
is Int -> putInt(key, value)
|
||||||
|
is Long -> putLong(key, value)
|
||||||
|
is Double -> putDouble(key, value)
|
||||||
|
is Float -> putFloat(key, value)
|
||||||
|
is Boolean -> putBoolean(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 本次事件特定参数添加
|
||||||
|
parameters?.forEach { (key, value) ->
|
||||||
|
when (value) {
|
||||||
|
is String -> putString(key, value)
|
||||||
|
is Int -> putInt(key, value)
|
||||||
|
is Long -> putLong(key, value)
|
||||||
|
is Double -> putDouble(key, value)
|
||||||
|
is Float -> putFloat(key, value)
|
||||||
|
is Boolean -> putBoolean(key, value)
|
||||||
|
else -> putString(key, value.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mFbAnalytics.logEvent(eventName, bundle)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getSSSuperProperties(): String{
|
||||||
|
val superPros = TDAnalytics.getSuperProperties()
|
||||||
|
return superPros.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDistinctId(): String{
|
||||||
|
return TDAnalytics.getDistinctId()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录推荐事件(使用 Firebase 预设事件类型)
|
||||||
|
* @param eventType 事件类型,如 FirebaseAnalytics.Event.SELECT_CONTENT
|
||||||
|
* @param parameters 事件参数
|
||||||
|
*/
|
||||||
|
fun reportRecommendedEvent(eventType: String, parameters: Bundle) {
|
||||||
|
if (!::mFbAnalytics.isInitialized) {
|
||||||
|
throw IllegalStateException("FirebaseAnalyticsUtil not initialized. Call init() first.")
|
||||||
|
}
|
||||||
|
mFbAnalytics.logEvent(eventType, parameters)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户属性
|
||||||
|
* @param propertyName 属性名称
|
||||||
|
* @param propertyValue 属性值
|
||||||
|
*/
|
||||||
|
fun setUserProperty(propertyName: String, propertyValue: String) {
|
||||||
|
if (!::mFbAnalytics.isInitialized) return
|
||||||
|
mFbAnalytics.setUserProperty(propertyName, propertyValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户ID
|
||||||
|
* @param userId 用户唯一标识
|
||||||
|
*/
|
||||||
|
fun setUserId(userId: String) {
|
||||||
|
if (!::mFbAnalytics.isInitialized) return
|
||||||
|
mFbAnalytics.setUserId(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前屏幕
|
||||||
|
* @param screenName 屏幕名称
|
||||||
|
* @param screenClass 屏幕类名(可选)
|
||||||
|
*/
|
||||||
|
fun setCurrentScreen(context: Context, screenName: String, screenClass: String? = null) {
|
||||||
|
if (!::mFbAnalytics.isInitialized) return
|
||||||
|
|
||||||
|
val bundle = Bundle().apply {
|
||||||
|
putString(FirebaseAnalytics.Param.SCREEN_NAME, screenName)
|
||||||
|
screenClass?.let { putString(FirebaseAnalytics.Param.SCREEN_CLASS, it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
mFbAnalytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, bundle)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置默认事件参数(将自动添加到每个事件中)
|
||||||
|
* @param parameters 默认参数映射
|
||||||
|
*/
|
||||||
|
fun setDefaultEventParameters(parameters: Map<String, Any>) {
|
||||||
|
mDefaultParams.clear()
|
||||||
|
mDefaultParams.putAll(parameters)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加单个默认事件参数
|
||||||
|
*/
|
||||||
|
fun addDefaultEventParameter(key: String, value: Any) {
|
||||||
|
mDefaultParams[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除所有默认事件参数
|
||||||
|
*/
|
||||||
|
fun clearDefaultEventParameters() {
|
||||||
|
mDefaultParams.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUserParams(params: Map<String, Any>) {
|
||||||
|
try {
|
||||||
|
// 如果获取为空,则异步等待阻塞获取
|
||||||
|
/*if (analytics == null) {
|
||||||
|
StatisticLogger.d("Firebase Analytics未就绪,开始异步等待...")
|
||||||
|
analytics = runBlocking {
|
||||||
|
waitForFirebaseAnalytics()
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (mFbAnalytics == null) {
|
||||||
|
StatisticLogger.w("无法获取Firebase Analytics实例,跳过设置用户参数")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Firebase Analytics使用setUserProperty设置用户属性
|
||||||
|
params.forEach { (key, value) ->
|
||||||
|
try {
|
||||||
|
mFbAnalytics.setUserProperty(key, value.toString())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("设置Firebase Analytics用户属性失败: $key = $value", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatisticLogger.d("Firebase Analytics用户参数设置完成: ${mapToJson(params)}")
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("Firebase Analytics设置用户参数失败", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setCommonParams(params: Map<String, Any>) {
|
||||||
|
try {
|
||||||
|
// 如果获取为空,则异步等待阻塞获取
|
||||||
|
/*if (mFbAnalytics == null) {
|
||||||
|
StatisticLogger.d("Firebase Analytics未就绪,开始异步等待...")
|
||||||
|
mFbAnalytics = runBlocking {
|
||||||
|
waitForFirebaseAnalytics()
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (mFbAnalytics == null) {
|
||||||
|
StatisticLogger.w("无法获取Firebase Analytics实例,跳过设置公共参数")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Firebase Analytics使用setDefaultEventParameters设置默认事件参数
|
||||||
|
val bundle = mapToBundle(params)
|
||||||
|
try {
|
||||||
|
mFbAnalytics.setDefaultEventParameters(bundle)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("设置Firebase Analytics默认事件参数失败", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
StatisticLogger.d("Firebase Analytics公共参数设置完成: ${mapToJson(params)}")
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("Firebase Analytics设置公共参数失败", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mapToBundle(map: Map<String, Any>): Bundle {
|
||||||
|
val bundle = Bundle()
|
||||||
|
try {
|
||||||
|
map.forEach { (key, value) ->
|
||||||
|
when (value) {
|
||||||
|
is String -> bundle.putString(key, value)
|
||||||
|
is Int -> bundle.putInt(key, value)
|
||||||
|
is Long -> bundle.putLong(key, value)
|
||||||
|
is Double -> bundle.putDouble(key, value)
|
||||||
|
is Float -> bundle.putFloat(key, value)
|
||||||
|
is Boolean -> bundle.putBoolean(key, value)
|
||||||
|
else -> bundle.putString(key, value.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("Map转Bundle失败: ${e.message}")
|
||||||
|
}
|
||||||
|
return bundle
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将Map转换为JSON字符串(用于日志)
|
||||||
|
* @param map 要转换的Map
|
||||||
|
* @return JSON字符串
|
||||||
|
*/
|
||||||
|
private fun mapToJson(map: Map<String, Any>): String {
|
||||||
|
return try {
|
||||||
|
gson.toJson(map)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("Map转JSON失败: ${e.message}")
|
||||||
|
"{}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private suspend fun waitForFirebaseAnalytics(): FirebaseAnalytics? {
|
||||||
|
var attempts = 0
|
||||||
|
val maxAttempts = 10 // 最多尝试10次
|
||||||
|
val delayMs = 100L // 每次等待100ms
|
||||||
|
|
||||||
|
while (attempts < maxAttempts) {
|
||||||
|
val analytics = getFirebaseAnalytics()
|
||||||
|
if (analytics != null) {
|
||||||
|
return analytics
|
||||||
|
}
|
||||||
|
|
||||||
|
StatisticLogger.d("Firebase Analytics未就绪,等待中... (${attempts + 1}/$maxAttempts)")
|
||||||
|
delay(delayMs)
|
||||||
|
attempts++
|
||||||
|
}
|
||||||
|
|
||||||
|
StatisticLogger.e("等待Firebase Analytics超时,无法获取实例")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFirebaseAnalytics(): FirebaseAnalytics? {
|
||||||
|
return try {
|
||||||
|
val context = BaseApp.appContext()
|
||||||
|
return FirebaseAnalytics.getInstance(context)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("获取Firebase Analytics实例失败", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,238 @@
|
||||||
|
package com.gamedog.statisticreporter.shushu
|
||||||
|
|
||||||
|
|
||||||
|
import cn.thinkingdata.analytics.TDAnalytics
|
||||||
|
import cn.thinkingdata.analytics.TDAnalytics.TDAutoTrackEventType
|
||||||
|
import cn.thinkingdata.analytics.TDConfig
|
||||||
|
import cn.thinkingdata.analytics.ThinkingAnalyticsSDK
|
||||||
|
import com.ama.core.architecture.BaseApp
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil.Companion.gson
|
||||||
|
import com.gamedog.statisticreporter.StatisticLogger
|
||||||
|
import java.util.ArrayDeque
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ShushuManager private constructor() {
|
||||||
|
companion object {
|
||||||
|
@Volatile
|
||||||
|
private var INSTANCE: ShushuManager? = null
|
||||||
|
|
||||||
|
fun instance(): ShushuManager {
|
||||||
|
return INSTANCE ?: synchronized(this) {
|
||||||
|
INSTANCE ?: ShushuManager().also { INSTANCE = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val mAppContext = BaseApp.appContext()
|
||||||
|
private val mBgScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||||
|
private val mMainScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
||||||
|
lateinit var mShushuSdk: ThinkingAnalyticsSDK
|
||||||
|
|
||||||
|
private data class PendingEvent(
|
||||||
|
val eventKey: String,
|
||||||
|
val params: Map<String, Any>?,
|
||||||
|
val superProperties: Map<String, Any>
|
||||||
|
)
|
||||||
|
|
||||||
|
private val initStarted = AtomicBoolean(false)
|
||||||
|
@Volatile
|
||||||
|
private var sdkReady: Boolean = false
|
||||||
|
|
||||||
|
private val pendingEventsLock = Any()
|
||||||
|
private val pendingEvents = ArrayDeque<PendingEvent>()
|
||||||
|
private val trackLock = Any()
|
||||||
|
private val maxPendingEvents = 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun initShushu(shushuAppId: String, shushuServerUrl: String) {
|
||||||
|
if (sdkReady) return
|
||||||
|
if (!initStarted.compareAndSet(false, true)) return
|
||||||
|
mMainScope.launch {
|
||||||
|
try {
|
||||||
|
TDAnalytics.init(mAppContext, shushuAppId, shushuServerUrl)
|
||||||
|
|
||||||
|
val config = TDConfig.getInstance(mAppContext, shushuAppId, shushuServerUrl)
|
||||||
|
config.setMode(/*if (BuildConfig.DEBUG) TDConfig.ModeEnum.DEBUG else*/ TDConfig.ModeEnum.DEBUG)
|
||||||
|
// config.setMode(/*if (BuildConfig.DEBUG) TDConfig.ModeEnum.DEBUG else*/ TDConfig.ModeEnum.NORMAL)
|
||||||
|
mShushuSdk = ThinkingAnalyticsSDK.sharedInstance(config)
|
||||||
|
|
||||||
|
StatisticLogger.d("数数DeviceID: ${TDAnalytics.getDeviceId()}")
|
||||||
|
configAutoTrack()
|
||||||
|
sdkReady = true
|
||||||
|
flushPendingEventsAsync()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
initStarted.set(false)
|
||||||
|
StatisticLogger.e("数数SDK初始化失败", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录用户的具体行为事件。
|
||||||
|
* 用户点击按钮、浏览页面、完成购买等。
|
||||||
|
*/
|
||||||
|
fun reportEvent(eventKey: String, params: Map<String, Any>?, superProperties: Map<String, Any>) {
|
||||||
|
if (!sdkReady) {
|
||||||
|
enqueuePendingEvent(eventKey, params, superProperties)
|
||||||
|
if (sdkReady) flushPendingEventsAsync()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
reportEventInternal(eventKey, params, superProperties)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户属性(会覆盖同名属性)。
|
||||||
|
* 记录用户会员等级、姓名等相对固定的属性。
|
||||||
|
*/
|
||||||
|
fun reportUser() {
|
||||||
|
try {
|
||||||
|
val userProperties = JSONObject().apply {
|
||||||
|
put("user_level", "VIP3") // 用户等级
|
||||||
|
put("registration_date", "2025-01-01") // 注册日期
|
||||||
|
put("total_orders", 15) // 总订单数
|
||||||
|
}
|
||||||
|
TDAnalytics.userSet(userProperties)
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置全局事件属性,自动附加到每个事件。
|
||||||
|
* 应用版本号、用户渠道来源等所有事件都带有的属性。
|
||||||
|
*/
|
||||||
|
fun reportSuper() {
|
||||||
|
try {
|
||||||
|
val superProperties = JSONObject().apply {
|
||||||
|
put("app_version", "1.2.0")
|
||||||
|
put("channel", "xx应用市场")
|
||||||
|
put("user_city", "北京")
|
||||||
|
}
|
||||||
|
TDAnalytics.setSuperProperties(superProperties)
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置账号ID,将后续行为关联到具体用户。
|
||||||
|
* 用户登录成功时调用。
|
||||||
|
*/
|
||||||
|
fun reportLogin(userUUID: String) {
|
||||||
|
TDAnalytics.login(userUUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------- PRIVATE ------------------------//
|
||||||
|
|
||||||
|
private fun configAutoTrack() {
|
||||||
|
TDAnalytics.enableAutoTrack(TDAutoTrackEventType.APP_START or TDAutoTrackEventType.APP_END or TDAutoTrackEventType.APP_INSTALL )
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mapToJsonObject(map: Map<String, Any>): JSONObject {
|
||||||
|
return try {
|
||||||
|
val jsonString = gson.toJson(map)
|
||||||
|
JSONObject(jsonString)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("Map转JSONObject失败: ${e.message}")
|
||||||
|
JSONObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setCommonParams(params: Map<String, Any>) {
|
||||||
|
try {
|
||||||
|
// 将Map转换为JSONObject
|
||||||
|
val jsonObject = mapToJsonObject(params)
|
||||||
|
|
||||||
|
// 数数SDK使用userSet设置用户属性,传入JSONObject
|
||||||
|
TDAnalytics.setSuperProperties(jsonObject)
|
||||||
|
|
||||||
|
StatisticLogger.d("数数SDK公共参数设置完成: $jsonObject")
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("数数SDK设置公共参数失败", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun setUserParams(params: Map<String, Any>) {
|
||||||
|
try {
|
||||||
|
// 将Map转换为JSONObject
|
||||||
|
val jsonObject = mapToJsonObject(params)
|
||||||
|
|
||||||
|
// 数数SDK使用userSet设置用户属性,传入JSONObject
|
||||||
|
TDAnalytics.userSet(jsonObject)
|
||||||
|
|
||||||
|
StatisticLogger.d("数数SDK用户参数设置完成: $jsonObject")
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("数数SDK设置用户参数失败", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isSdkReady(): Boolean {
|
||||||
|
return sdkReady && this::mShushuSdk.isInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun enqueuePendingEvent(eventKey: String, params: Map<String, Any>?, superProperties: Map<String, Any>) {
|
||||||
|
val safeParams = params?.toMap()
|
||||||
|
val safeSuper = superProperties.toMap()
|
||||||
|
synchronized(pendingEventsLock) {
|
||||||
|
if (pendingEvents.size >= maxPendingEvents) {
|
||||||
|
if (pendingEvents.isNotEmpty()) {
|
||||||
|
pendingEvents.removeFirst()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pendingEvents.addLast(PendingEvent(eventKey, safeParams, safeSuper))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun flushPendingEventsAsync() {
|
||||||
|
mBgScope.launch {
|
||||||
|
flushPendingEvents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun flushPendingEvents() {
|
||||||
|
if (!sdkReady) return
|
||||||
|
val batch = ArrayList<PendingEvent>()
|
||||||
|
synchronized(pendingEventsLock) {
|
||||||
|
while (pendingEvents.isNotEmpty()) {
|
||||||
|
batch.add(pendingEvents.removeFirst())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (batch.isEmpty()) return
|
||||||
|
batch.forEach { pending ->
|
||||||
|
reportEventInternal(pending.eventKey, pending.params, pending.superProperties)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reportEventInternal(eventKey: String, params: Map<String, Any>?, superProperties: Map<String, Any>) {
|
||||||
|
try {
|
||||||
|
synchronized(trackLock) {
|
||||||
|
TDAnalytics.setSuperProperties(JSONObject(superProperties))
|
||||||
|
val jsonObj = params?.let { JSONObject(it) }
|
||||||
|
TDAnalytics.track(eventKey, jsonObj)
|
||||||
|
StatisticLogger.d("数数SDK事件上报: $eventKey $jsonObj")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
StatisticLogger.e("数数SDK事件上报失败: $eventKey", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.gamedog.statisticreporter
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
fun addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +1,5 @@
|
||||||
/build
|
/build
|
||||||
|
/release/baselineProfiles/0/app-release.dm
|
||||||
|
/release/baselineProfiles/1/app-release.dm
|
||||||
|
/release/output-metadata.json
|
||||||
|
/release/app-release.apk.zip
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,16 @@ plugins {
|
||||||
// alias(libs.plugins.ksp)
|
// alias(libs.plugins.ksp)
|
||||||
alias(libs.plugins.protobuf)
|
alias(libs.plugins.protobuf)
|
||||||
id 'kotlin-kapt'
|
id 'kotlin-kapt'
|
||||||
|
id("com.google.gms.google-services")
|
||||||
|
id("com.google.firebase.crashlytics")
|
||||||
}
|
}
|
||||||
|
def buildTime = new Date().format('yyyyMMdd_HHmmss')
|
||||||
android {
|
android {
|
||||||
namespace = "com.gamedog.vididin"
|
namespace = "com.viddin.videos.free"
|
||||||
compileSdk libs.versions.compileSdk.get().toInteger()
|
compileSdk libs.versions.compileSdk.get().toInteger()
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.gamedog.vididin"
|
applicationId "com.viddin.videos.free"
|
||||||
minSdk libs.versions.minSdk.get().toInteger()
|
minSdk libs.versions.minSdk.get().toInteger()
|
||||||
targetSdk libs.versions.targetSdk.get().toInteger()
|
targetSdk libs.versions.targetSdk.get().toInteger()
|
||||||
versionCode libs.versions.versionCode.get().toInteger()
|
versionCode libs.versions.versionCode.get().toInteger()
|
||||||
|
|
@ -21,12 +23,28 @@ android {
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applicationVariants.configureEach { variant ->
|
||||||
|
variant.outputs.configureEach {
|
||||||
|
outputFileName = "${variant.applicationId}_${variant.versionName}_${variant.versionCode}_${variant.buildType.name}_${buildTime}.apk"
|
||||||
|
}
|
||||||
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
debug {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
}
|
||||||
|
release {
|
||||||
|
minifyEnabled true
|
||||||
|
debuggable false
|
||||||
|
firebaseCrashlytics {
|
||||||
|
mappingFileUploadEnabled false
|
||||||
|
}
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility libs.versions.javaVersion.get().toInteger()
|
sourceCompatibility libs.versions.javaVersion.get().toInteger()
|
||||||
targetCompatibility libs.versions.javaVersion.get().toInteger()
|
targetCompatibility libs.versions.javaVersion.get().toInteger()
|
||||||
|
|
@ -39,6 +57,10 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kapt {
|
||||||
|
correctErrorTypes = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protobuf {
|
protobuf {
|
||||||
protoc {
|
protoc {
|
||||||
|
|
@ -61,6 +83,9 @@ protobuf {
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation project(':base')
|
||||||
|
implementation project(':notification')
|
||||||
|
implementation libs.firebase.analytics
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.androidx.test.ext.junit)
|
androidTestImplementation(libs.androidx.test.ext.junit)
|
||||||
androidTestImplementation(libs.espresso.core)
|
androidTestImplementation(libs.espresso.core)
|
||||||
|
|
@ -68,11 +93,8 @@ dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation(project(":core:network"))
|
implementation(project(":core:network"))
|
||||||
implementation(project(":core:architecture"))
|
implementation(project(":core:architecture"))
|
||||||
//api(project(":core:architecture-reflect"))
|
implementation(project(":bill"))
|
||||||
implementation(project(":core:network"))
|
implementation(project(":StatisticReporter"))
|
||||||
|
|
||||||
implementation(project(":youtube:core"))
|
|
||||||
implementation(project(":youtube:custom-ui"))
|
|
||||||
|
|
||||||
implementation libs.androidx.navigation.fragment.ktx
|
implementation libs.androidx.navigation.fragment.ktx
|
||||||
implementation(libs.startup)
|
implementation(libs.startup)
|
||||||
|
|
@ -83,11 +105,14 @@ dependencies {
|
||||||
implementation(libs.datastore)
|
implementation(libs.datastore)
|
||||||
implementation(libs.protobuf.kotlin.lite)
|
implementation(libs.protobuf.kotlin.lite)
|
||||||
implementation(libs.kotlinx.serialization.json)
|
implementation(libs.kotlinx.serialization.json)
|
||||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
|
||||||
implementation(libs.glide) // ImageLoader在用
|
implementation(libs.glide) // ImageLoader在用
|
||||||
implementation(libs.okhttp.logging)
|
implementation(libs.okhttp.logging)
|
||||||
implementation(libs.retrofit)
|
implementation(libs.retrofit)
|
||||||
implementation(libs.retrofit.kotlin.serialization)
|
implementation(libs.retrofit.kotlin.serialization)
|
||||||
|
// implementation 'com.pierfrancescosoffritti.androidyoutubeplayer:core:13.0.0'
|
||||||
|
// implementation 'com.pierfrancescosoffritti.androidyoutubeplayer:custom-ui:13.0.0'
|
||||||
|
implementation(project(":youtube:core"))
|
||||||
|
implementation(project(":youtube:custom-ui"))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
ext {
|
||||||
|
// AdMob配置
|
||||||
|
admob = [applicationId: "ca-app-pub-3392799053230605~7472226445", // 测试应用ID,请替换为实际的AdMob应用ID
|
||||||
|
adUnitIds : [banner : "ca-app-pub-3392799053230605/2634832736",//"ca-app-pub-3392799053230605/6746479899",//"ca-app-pub-3940256099942544/9214589741", // "ca-app-pub-3392799053230605/6746479899" // 横幅广告测试ID // TODO- use pre test key
|
||||||
|
interstitial: "ca-app-pub-3392799053230605/5069601997", // 插页广告测试ID
|
||||||
|
splash : "ca-app-pub-3392799053230605/5699979777", // 开屏广告测试ID
|
||||||
|
native : "ca-app-pub-3392799053230605/8969442262", // 原生广告测试ID
|
||||||
|
full_native : "ca-app-pub-3392799053230605/6710110437", // 全屏原生广告测试ID
|
||||||
|
rewarded : "ca-app-pub-3392799053230605/9854847207" // 激励广告测试ID
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Pangle配置
|
||||||
|
pangle = [applicationId: "8757571", // Pangle测试应用ID
|
||||||
|
adUnitIds : [splash : "", // 开屏广告测试ID(竖屏)
|
||||||
|
banner : "", // 横幅广告测试ID(320x50)
|
||||||
|
interstitial: "982655945", // 插页广告测试ID(竖屏)
|
||||||
|
native : "", // 原生广告测试ID
|
||||||
|
full_native : "", // 全屏原生广告测试ID
|
||||||
|
rewarded : "982655960" // 激励视频测试ID(竖屏)
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TopOn配置
|
||||||
|
topon = [applicationId: "h1h0ukemtu13ak", // TopOn 应用 ID(需替换为实际值)
|
||||||
|
appKey : "7d3af77b0803cbc641888cb393e8652e", // TopOn 应用密钥(需替换为实际值)
|
||||||
|
adUnitIds : [ interstitial: "n1h0ukemvrnhn1", //"n1h0ukemvrnhn1", // 插页广告位 ID(需替换为实际值) // TODO- if use this alway report error: placementId maybe is null
|
||||||
|
rewarded : "n1h0uken0i262r", // 激励广告位 ID
|
||||||
|
native : "", // 原生广告位 ID(需替换为实际值)
|
||||||
|
splash : "", // 开屏广告位 ID(需替换为实际值)
|
||||||
|
full_native : "", // 全屏原生广告位 ID(需替换为实际值)
|
||||||
|
//banner : "" // 横幅广告位 ID(需替换为实际值)
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 应用版本配置
|
||||||
|
app = [applicationId: "com.viddin.videos.free",
|
||||||
|
compileSdk : 36,
|
||||||
|
minSdk : libs.versions.minSdk.get().toInteger(),
|
||||||
|
targetSdk : 36,
|
||||||
|
versionCode : 1,
|
||||||
|
versionName : "1.0.0"]
|
||||||
|
|
||||||
|
url = [privacyUrl: "https://www.google.com",
|
||||||
|
teamUrl : "https://www.google.com",]
|
||||||
|
|
||||||
|
// 统计归因配置
|
||||||
|
analytics = [adjustAppToken: "sa8ei0td10xs", // Adjust App Token
|
||||||
|
thinkingDataAppId: "097b3fd67217437b83529c35f81a567e", // 数数 SDK APP ID
|
||||||
|
thinkingDataServerUrl: "https://data.tapvicogames.com", // 数数上报域名
|
||||||
|
defaultUserChannel: "paid"] // 默认用户渠道,internal默认paid
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
ext {
|
||||||
|
// AdMob配置 - Play 市场版本
|
||||||
|
admob = [applicationId: "ca-app-pub-3392799053230605~7472226445", // 测试应用ID,请替换为实际的AdMob应用ID
|
||||||
|
adUnitIds : [banner : "ca-app-pub-3392799053230605/2634832736", //"ca-app-pub-3392799053230605/6746479899", // 横幅广告测试ID
|
||||||
|
interstitial: "ca-app-pub-3392799053230605/5069601997", // 插页广告测试ID
|
||||||
|
splash : "ca-app-pub-3392799053230605/5699979777", // 开屏广告测试ID
|
||||||
|
native : "ca-app-pub-3392799053230605/8969442262", // 原生广告测试ID
|
||||||
|
full_native : "ca-app-pub-3392799053230605/6710110437", // 全屏原生广告测试ID
|
||||||
|
rewarded : "ca-app-pub-3392799053230605/9854847207" // 激励广告测试ID
|
||||||
|
]]
|
||||||
|
|
||||||
|
// Pangle配置
|
||||||
|
pangle = [applicationId: "8757571", // Pangle测试应用ID
|
||||||
|
adUnitIds : [splash : "", // 开屏广告测试ID(竖屏)
|
||||||
|
banner : "", // 横幅广告测试ID(320x50)
|
||||||
|
interstitial: "982655945", // 插页广告测试ID(竖屏)
|
||||||
|
native : "", // 原生广告测试ID
|
||||||
|
full_native : "", // 全屏原生广告测试ID
|
||||||
|
rewarded : "982655960" // 激励视频测试ID(竖屏)
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TopOn配置
|
||||||
|
topon = [applicationId: "h1h0ukemtu13ak", // TopOn 应用 ID(需替换为实际值)
|
||||||
|
appKey : "7d3af77b0803cbc641888cb393e8652e", // TopOn 应用密钥(需替换为实际值)
|
||||||
|
adUnitIds : [ interstitial: "n1h0ukemvrnhn1", // 插页广告位 ID(需替换为实际值)
|
||||||
|
rewarded : "n1h0uken0i262r", // 激励广告位 ID
|
||||||
|
native : "", // 原生广告位 ID(需替换为实际值)
|
||||||
|
splash : "", // 开屏广告位 ID(需替换为实际值)
|
||||||
|
full_native : "", // 全屏原生广告位 ID(需替换为实际值)
|
||||||
|
banner : "" // 横幅广告位 ID(需替换为实际值)
|
||||||
|
]]
|
||||||
|
|
||||||
|
// 应用版本配置 - Play 市场版本
|
||||||
|
app = [applicationId: "com.viddin.videos.free",
|
||||||
|
compileSdk : 36,
|
||||||
|
minSdk : libs.versions.minSdk.get().toInteger(),
|
||||||
|
targetSdk : 36,
|
||||||
|
versionCode : 1,
|
||||||
|
versionName : "1.0.0"]
|
||||||
|
|
||||||
|
url = [privacyUrl: "https://alifmd.com/privacy.html",
|
||||||
|
teamUrl : "https://alifmd.com/privacy.html",]
|
||||||
|
|
||||||
|
// 统计归因配置
|
||||||
|
analytics = [adjustAppToken: "sa8ei0td10xs", // Adjust App Token
|
||||||
|
thinkingDataAppId: "097b3fd67217437b83529c35f81a567e", // 数数 SDK APP ID
|
||||||
|
thinkingDataServerUrl: "https://data.tapvicogames.com", // 数数上报域名
|
||||||
|
defaultUserChannel: "paid"] // 默认用户渠道,internal默认paid
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "461028728722",
|
||||||
|
"project_id": "ag965e29930c-2d797-gp",
|
||||||
|
"storage_bucket": "ag965e29930c-2d797-gp.firebasestorage.app"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:461028728722:android:e3c8d4a98e08f4e3f2eb4b",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.viddin.videos.free"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyA4pitzEQhu3VGg-VjOH-bWCEP2POYTDzA"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration_version": "1"
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,204 @@
|
||||||
# Add project specific ProGuard rules here.
|
# ==============================================================================
|
||||||
# You can control the set of applied configuration files using the
|
# 基础配置 (Basic Configuration)
|
||||||
# proguardFiles setting in build.gradle.
|
# ==============================================================================
|
||||||
#
|
# 代码优化次数
|
||||||
# For more details, see
|
-optimizationpasses 5
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
# 不使用混合大小写类名
|
||||||
|
-dontusemixedcaseclassnames
|
||||||
|
# 不忽略非公共库类
|
||||||
|
-dontskipnonpubliclibraryclasses
|
||||||
|
# 打印混淆详情
|
||||||
|
-verbose
|
||||||
|
# 忽略警告
|
||||||
|
-ignorewarnings
|
||||||
|
# 不进行预校验
|
||||||
|
-dontpreverify
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
# ==============================================================================
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
# 属性保留 (Attributes)
|
||||||
# class:
|
# ==============================================================================
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
# 保留泛型签名(避免JSON解析、Kotlin反射等问题)
|
||||||
# public *;
|
-keepattributes Signature
|
||||||
#}
|
# 保留注解
|
||||||
|
-keepattributes *Annotation*
|
||||||
# Uncomment this to preserve the line number information for
|
# 保留异常信息
|
||||||
# debugging stack traces.
|
-keepattributes Exceptions
|
||||||
#-keepattributes SourceFile,LineNumberTable
|
# 保留内部类信息
|
||||||
|
-keepattributes InnerClasses
|
||||||
# If you keep the line number information, uncomment this to
|
# 保留封闭方法信息
|
||||||
# hide the original source file name.
|
-keepattributes EnclosingMethod
|
||||||
|
# 保留源文件和行号(用于Crashlytics堆栈追踪)
|
||||||
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
# 如果需要隐藏源文件名,取消注释下面这行
|
||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# Android 组件 (Android Components)
|
||||||
|
# ==============================================================================
|
||||||
|
-keep public class * extends android.app.Activity
|
||||||
|
-keep public class * extends android.app.Application
|
||||||
|
-keep public class * extends android.app.Service
|
||||||
|
-keep public class * extends android.content.BroadcastReceiver
|
||||||
|
-keep public class * extends android.content.ContentProvider
|
||||||
|
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||||
|
-keep public class * extends android.preference.Preference
|
||||||
|
-keep public class * extends android.view.View
|
||||||
|
|
||||||
|
# 保持 Native 方法
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保持自定义 View 的构造方法
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet);
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保持 Parcelable
|
||||||
|
-keep class * implements android.os.Parcelable {
|
||||||
|
public static final android.os.Parcelable$Creator *;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保持 Serializable
|
||||||
|
-keepclassmembers class * implements java.io.Serializable {
|
||||||
|
static final long serialVersionUID;
|
||||||
|
private static final java.io.ObjectStreamField[] serialPersistentFields;
|
||||||
|
private void writeObject(java.io.ObjectOutputStream);
|
||||||
|
private void readObject(java.io.ObjectInputStream);
|
||||||
|
java.lang.Object writeReplace();
|
||||||
|
java.lang.Object readResolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保持枚举
|
||||||
|
-keepclassmembers enum * {
|
||||||
|
public static **[] values();
|
||||||
|
public static ** valueOf(java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保持 R 文件资源引用
|
||||||
|
-keepclassmembers class **.R$* {
|
||||||
|
public static <fields>;
|
||||||
|
public static final int *;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# Kotlin Coroutines
|
||||||
|
# ==============================================================================
|
||||||
|
-keep class kotlinx.coroutines.** { *; }
|
||||||
|
-keepclassmembers class kotlinx.coroutines.** {
|
||||||
|
volatile <fields>;
|
||||||
|
}
|
||||||
|
# 如果使用 AtomicFU
|
||||||
|
-dontwarn java.util.concurrent.atomic.Atomic*
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# Kotlin Serialization
|
||||||
|
# ==============================================================================
|
||||||
|
-keepattributes *Annotation*, InnerClasses
|
||||||
|
-dontnote kotlinx.serialization.SerializationKt
|
||||||
|
-keep,allowobfuscation,allowshrinking class kotlinx.serialization.* { *; }
|
||||||
|
-keep class * implements kotlinx.serialization.KSerializer { *; }
|
||||||
|
-keepclassmembers class * {
|
||||||
|
@kotlinx.serialization.Serializable <init>(...);
|
||||||
|
@kotlinx.serialization.Serializable <fields>;
|
||||||
|
}
|
||||||
|
-keep @kotlinx.serialization.Serializable class * { *; }
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# 项目特定 (Project Specific)
|
||||||
|
# ==============================================================================
|
||||||
|
# 实体类/Bean (防止 JSON 解析失败)
|
||||||
|
-keep class com.gamedog.vididin.beans.** { *; }
|
||||||
|
-keep class com.gamedog.vididin.manager.taskbeans.** { *; }
|
||||||
|
# 任务配置Bean
|
||||||
|
-keep class com.gamedog.vididin.main.fragments.task.** { *; }
|
||||||
|
# 路由相关
|
||||||
|
-keep class com.gamedog.vididin.router.** { *; }
|
||||||
|
# App 入口
|
||||||
|
-keep class com.viddin.videos.free.VidiDinApp { *; }
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# 第三方库 (Third Party Libraries)
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
# ----------------- Hilt / Dagger -----------------
|
||||||
|
-keep class dagger.hilt.internal.aggregatedroot.** { *; }
|
||||||
|
-keep class hilt_aggregated_deps.** { *; }
|
||||||
|
-keep class * extends android.app.Application { @dagger.hilt.android.AndroidEntryPoint <init>(); }
|
||||||
|
-keepclasseswithmembers class * { @dagger.hilt.android.AndroidEntryPoint <fields>; }
|
||||||
|
-keepclasseswithmembers class * { @dagger.hilt.android.AndroidEntryPoint <methods>; }
|
||||||
|
-keep @dagger.Module class *
|
||||||
|
-keep @dagger.hilt.InstallIn class *
|
||||||
|
-keep @dagger.hilt.EntryPoint class *
|
||||||
|
-keepclassmembers @dagger.hilt.EntryPoint class * { *; }
|
||||||
|
-keep @dagger.hilt.components.SingletonComponent class *
|
||||||
|
-keepclassmembers @dagger.hilt.components.SingletonComponent class * { *; }
|
||||||
|
-keep class * extends dagger.internal.Binding { *; }
|
||||||
|
-keep class * extends dagger.internal.Factory { *; }
|
||||||
|
-keep class * implements dagger.MembersInjector { *; }
|
||||||
|
-keep class * implements dagger.Lazy { *; }
|
||||||
|
|
||||||
|
# ----------------- Gson -----------------
|
||||||
|
-keep class com.google.gson.** { *; }
|
||||||
|
-keep class sun.misc.Unsafe { *; }
|
||||||
|
-keep class com.google.gson.stream.** { *; }
|
||||||
|
-keepclassmembers class * {
|
||||||
|
@com.google.gson.annotations.SerializedName <fields>;
|
||||||
|
}
|
||||||
|
-keep class * implements com.google.gson.TypeAdapterFactory
|
||||||
|
-keep class * implements com.google.gson.JsonSerializer
|
||||||
|
-keep class * implements com.google.gson.JsonDeserializer
|
||||||
|
|
||||||
|
# ----------------- OkHttp3 -----------------
|
||||||
|
-dontwarn okhttp3.**
|
||||||
|
-keep class okhttp3.** { *; }
|
||||||
|
-keep interface okhttp3.** { *; }
|
||||||
|
-dontwarn okio.**
|
||||||
|
|
||||||
|
# ----------------- Retrofit2 -----------------
|
||||||
|
-dontwarn retrofit2.**
|
||||||
|
-keep class retrofit2.** { *; }
|
||||||
|
|
||||||
|
# ----------------- Glide -----------------
|
||||||
|
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||||
|
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
|
||||||
|
**[] $VALUES;
|
||||||
|
public *;
|
||||||
|
}
|
||||||
|
-keep class com.bumptech.glide.** { *; }
|
||||||
|
# Glide Transformations
|
||||||
|
-keep class jp.wasabeef.glide.** { *; }
|
||||||
|
# 相关依赖
|
||||||
|
-keep class com.davemorrissey.** { *; }
|
||||||
|
-keep class com.filippudak.** { *; }
|
||||||
|
|
||||||
|
# ----------------- Lottie -----------------
|
||||||
|
-keep class com.airbnb.lottie.** { *; }
|
||||||
|
|
||||||
|
# ----------------- Room -----------------
|
||||||
|
-dontwarn androidx.room.paging.**
|
||||||
|
|
||||||
|
# ----------------- Tencent X5 / Security -----------------
|
||||||
|
-keep class com.tencent.** { *; }
|
||||||
|
-keep class Decoder.** { *; }
|
||||||
|
-keep class org.bouncycastle.** { *; }
|
||||||
|
|
||||||
|
# ----------------- Alibaba FastJson -----------------
|
||||||
|
-dontwarn com.alibaba.fastjson.**
|
||||||
|
-keep class com.alibaba.fastjson.** { *; }
|
||||||
|
|
||||||
|
# ----------------- JZlib / Apache / Others -----------------
|
||||||
|
-dontwarn com.jcraft.jzlib.**
|
||||||
|
-keep class com.jcraft.jzlib.** { *; }
|
||||||
|
-dontwarn org.apache.**
|
||||||
|
-keep class org.apache.** { *; }
|
||||||
|
-dontwarn com.loopj.**
|
||||||
|
-keep class com.loopj.** { *; }
|
||||||
|
-dontwarn org.jivesoftware.smack.**
|
||||||
|
-dontwarn org.xbill.**
|
||||||
|
-keep class org.xbill.** { *; }
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# 结束 (End)
|
||||||
|
# ==============================================================================
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,20 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.camera"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".VidiDinApp"
|
android:name=".VidiDinApp"
|
||||||
|
|
@ -14,27 +27,54 @@
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:theme="@style/Theme.Architectureandroid">
|
android:theme="@style/Theme.Architectureandroid">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".main.MainActivity"
|
android:name="com.gamedog.vididin.features.splash.SplashActivity"
|
||||||
android:exported="true">
|
android:exported="true"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:theme="@style/Theme.Transparent"
|
||||||
|
android:screenOrientation="portrait">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
|
||||||
<activity android:name=".login.LoginActivity" android:exported="false" />
|
<activity
|
||||||
<activity android:name=".features.benefit.BenefitActivity" android:exported="false" />
|
android:name="com.gamedog.vididin.main.MainActivity"
|
||||||
<activity android:name=".features.zero.ZeroBuyActivity" android:exported="false" />
|
android:screenOrientation="portrait" android:exported="true"
|
||||||
<activity android:name=".features.winrecords.WinRecordsActivity" android:exported="false" />
|
android:launchMode="singleTop" >
|
||||||
<activity android:name=".features.withdraw.WithDrawActivity" android:exported="false" />
|
</activity>
|
||||||
<activity android:name=".features.splash.SplashActivity" android:exported="false" />
|
|
||||||
<activity android:name=".features.version.VersionActivity" android:exported="false" />
|
<activity-alias
|
||||||
<activity android:name=".features.feedback.FeedbackActivity" android:exported="false" />
|
android:name="com.gamedog.vididin.main.MainActivityAlias"
|
||||||
<activity android:name=".features.withdrawrecord.WithdrawRecordActivity" android:exported="false" />
|
android:targetActivity="com.gamedog.vididin.main.MainActivity"
|
||||||
<activity android:name=".features.privacy.PrivacyActivity" android:exported="false" />
|
android:launchMode="singleTop"
|
||||||
|
android:exported="true"
|
||||||
|
android:enabled="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.remax.notification.ACTION_OPEN_APP" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity-alias>
|
||||||
|
|
||||||
|
<activity android:name="com.gamedog.vididin.login.LoginActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.benefit.BenefitActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.zero.ZeroBuyActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.winrecords.WinRecordsActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.withdraw.WithDrawActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.withdraw.WithDrawSubActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.version.VersionActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.feedback.FeedbackActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.withdrawrecord.WithdrawRecordActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.privacy.PrivacyActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.game.GameCenterActivity" android:exported="false" />
|
||||||
|
<activity android:name="com.gamedog.vididin.features.watchad.WatchAdActivity"
|
||||||
|
android:theme="@style/Theme.Transparent"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -46,6 +86,39 @@
|
||||||
android:name="com.gamedog.vididin.router.RouterInitializer"
|
android:name="com.gamedog.vididin.router.RouterInitializer"
|
||||||
android:value="androidx.startup" />
|
android:value="androidx.startup" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name="com.gamedog.vididin.manager.DateChangeReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.DATE_CHANGED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name="com.remax.notification.newUtil.events.AppInstallReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.PACKAGE_ADDED" />
|
||||||
|
<action android:name="android.intent.action.PACKAGE_REPLACED" />
|
||||||
|
<action android:name="android.intent.action.PACKAGE_REMOVED" />
|
||||||
|
<data android:scheme="package" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<receiver android:name="com.remax.notification.newUtil.events.PowerConnectionReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
|
||||||
|
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
@ -4,7 +4,10 @@
|
||||||
"module_name": "任务中心",
|
"module_name": "任务中心",
|
||||||
"page_path": "底部第二个页签",
|
"page_path": "底部第二个页签",
|
||||||
"layout_style": "上下滑动长页面",
|
"layout_style": "上下滑动长页面",
|
||||||
"currency_display": ["金币账户", "巴西雷亚尔现金账户"]
|
"currency_display": [
|
||||||
|
"金币账户",
|
||||||
|
"巴西雷亚尔现金账户"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"task_categories": [
|
"task_categories": [
|
||||||
{
|
{
|
||||||
|
|
@ -50,13 +53,34 @@
|
||||||
"target_action": "用户每日完成签到操作(支持广告补签)",
|
"target_action": "用户每日完成签到操作(支持广告补签)",
|
||||||
"reward_type": "金币",
|
"reward_type": "金币",
|
||||||
"reward_details": [
|
"reward_details": [
|
||||||
{"day": 1, "value": 100},
|
{
|
||||||
{"day": 2, "value": 300},
|
"day": 1,
|
||||||
{"day": 3, "value": 300},
|
"value": 100
|
||||||
{"day": 4, "value": 500},
|
},
|
||||||
{"day": 5, "value": 300},
|
{
|
||||||
{"day": 6, "value": 300},
|
"day": 2,
|
||||||
{"day": 7, "value": 800}
|
"value": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 3,
|
||||||
|
"value": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 4,
|
||||||
|
"value": 500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 5,
|
||||||
|
"value": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 6,
|
||||||
|
"value": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 7,
|
||||||
|
"value": 800
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"support_makeup": true,
|
"support_makeup": true,
|
||||||
"makeup_method": "观看15-30秒激励视频",
|
"makeup_method": "观看15-30秒激励视频",
|
||||||
|
|
@ -78,13 +102,34 @@
|
||||||
"target_action": "用户当日完成签到操作",
|
"target_action": "用户当日完成签到操作",
|
||||||
"reward_type": "金币",
|
"reward_type": "金币",
|
||||||
"reward_details": [
|
"reward_details": [
|
||||||
{"day": 1, "value": 100},
|
{
|
||||||
{"day": 2, "value": 300},
|
"day": 1,
|
||||||
{"day": 3, "value": 300},
|
"value": 100
|
||||||
{"day": 4, "value": 500},
|
},
|
||||||
{"day": 5, "value": 300},
|
{
|
||||||
{"day": 6, "value": 300},
|
"day": 2,
|
||||||
{"day": 7, "value": 500}
|
"value": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 3,
|
||||||
|
"value": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 4,
|
||||||
|
"value": 500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 5,
|
||||||
|
"value": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 6,
|
||||||
|
"value": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 7,
|
||||||
|
"value": 500
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"double_reward_method": "观看15-30秒激励视频",
|
"double_reward_method": "观看15-30秒激励视频",
|
||||||
"support_makeup": true,
|
"support_makeup": true,
|
||||||
|
|
@ -99,9 +144,18 @@
|
||||||
"target_action": "用户累计观看短视频",
|
"target_action": "用户累计观看短视频",
|
||||||
"reward_type": "金币",
|
"reward_type": "金币",
|
||||||
"reward_details": [
|
"reward_details": [
|
||||||
{"target_count": 10, "value": 100},
|
{
|
||||||
{"target_count": 20, "value": 150},
|
"target_count": 10,
|
||||||
{"target_count": 30, "value": 200}
|
"value": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target_count": 20,
|
||||||
|
"value": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target_count": 30,
|
||||||
|
"value": 200
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"reward_stackable": true,
|
"reward_stackable": true,
|
||||||
"is_one_time": false,
|
"is_one_time": false,
|
||||||
|
|
@ -114,9 +168,18 @@
|
||||||
"target_action": "用户累计观看激励视频",
|
"target_action": "用户累计观看激励视频",
|
||||||
"reward_type": "金币",
|
"reward_type": "金币",
|
||||||
"reward_details": [
|
"reward_details": [
|
||||||
{"target_count": 1, "value": 100},
|
{
|
||||||
{"target_count": 5, "value": 150},
|
"target_count": 1,
|
||||||
{"target_count": 10, "value": 200}
|
"value": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target_count": 5,
|
||||||
|
"value": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target_count": 10,
|
||||||
|
"value": 200
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"daily_limit": 10,
|
"daily_limit": 10,
|
||||||
"reward_stackable": true,
|
"reward_stackable": true,
|
||||||
|
|
@ -125,6 +188,104 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"box_task": {
|
||||||
|
"category_id": "bonuses_task",
|
||||||
|
"category_name": "福利宝箱(Prémios únicos)",
|
||||||
|
"valid_period": "每个宝箱持续3天,完成对应任务即可领取现金奖励。",
|
||||||
|
"display_priority": 3,
|
||||||
|
"chests": [
|
||||||
|
{
|
||||||
|
"chest_id": "1",
|
||||||
|
"chest_name": "福利宝箱1",
|
||||||
|
"chest_desc": "完成福利宝箱1的全部任务后,获得R$0.1现金奖励",
|
||||||
|
"duration_days": 3,
|
||||||
|
"reward_type": "货币",
|
||||||
|
"reward_value": 0.1,
|
||||||
|
"is_one_time": true,
|
||||||
|
"status": "active",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"task_id": "chest1_task1",
|
||||||
|
"task_name": "观看1个广告",
|
||||||
|
"required_count": 1,
|
||||||
|
"task_type": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "chest1_task2",
|
||||||
|
"task_name": "观看3个视频",
|
||||||
|
"required_count": 3,
|
||||||
|
"task_type": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "chest1_task3",
|
||||||
|
"task_name": "完成1次签到",
|
||||||
|
"required_count": 1,
|
||||||
|
"task_type": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chest_id": "2",
|
||||||
|
"chest_name": "福利宝箱2",
|
||||||
|
"chest_desc": "完成福利宝箱2的全部任务后,获得R$1现金奖励",
|
||||||
|
"duration_days": 3,
|
||||||
|
"reward_type": "货币",
|
||||||
|
"reward_value": 1,
|
||||||
|
"is_one_time": true,
|
||||||
|
"status": "locked",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"task_id": "chest2_task1",
|
||||||
|
"task_name": "观看15个广告",
|
||||||
|
"required_count": 15,
|
||||||
|
"task_type": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "chest2_task2",
|
||||||
|
"task_name": "观看30个视频",
|
||||||
|
"required_count": 30,
|
||||||
|
"task_type": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "chest2_task3",
|
||||||
|
"task_name": "参与1次0元购",
|
||||||
|
"required_count": 1,
|
||||||
|
"task_type": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chest_id": "3",
|
||||||
|
"chest_name": "福利宝箱3",
|
||||||
|
"chest_desc": "完成福利宝箱3的全部任务后,获得R$2现金奖励",
|
||||||
|
"duration_days": 3,
|
||||||
|
"reward_type": "货币",
|
||||||
|
"reward_value": 2,
|
||||||
|
"is_one_time": true,
|
||||||
|
"status": "locked",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"task_id": "chest3_task1",
|
||||||
|
"task_name": "观看30个广告",
|
||||||
|
"required_count": 30,
|
||||||
|
"task_type": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "chest3_task2",
|
||||||
|
"task_name": "观看50个视频",
|
||||||
|
"required_count": 50,
|
||||||
|
"task_type": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "chest3_task3",
|
||||||
|
"task_name": "参与10次0元购",
|
||||||
|
"required_count": 10,
|
||||||
|
"task_type": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
{
|
||||||
|
"task_module_config": {
|
||||||
|
"basic_info": {
|
||||||
|
"module_name": "任务中心",
|
||||||
|
"page_path": "底部第二个页签",
|
||||||
|
"layout_style": "上下滑动长页面",
|
||||||
|
"currency_display": ["金币账户", "巴西雷亚尔现金账户"]
|
||||||
|
},
|
||||||
|
"task_categories": [
|
||||||
|
{
|
||||||
|
"category_id": "newbie_task",
|
||||||
|
"category_name": "新手任务(Missão Para Iniciantes)",
|
||||||
|
"valid_period": "注册后7天内",
|
||||||
|
"display_priority": 1,
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"task_id": "newbie_first_withdraw",
|
||||||
|
"task_name": "完成第一次提现",
|
||||||
|
"task_desc": "完成首次提现操作(0.1 BRL门槛),即可获得100金币奖励",
|
||||||
|
"target_action": "用户完成首次提现流程(含绑定Pix账户、观看广告)",
|
||||||
|
"reward_type": "金币",
|
||||||
|
"reward_value": 100,
|
||||||
|
"is_one_time": true,
|
||||||
|
"status": "active"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "newbie_push_notify",
|
||||||
|
"task_name": "开启消息推送",
|
||||||
|
"task_desc": "启用APP消息推送权限,实时获取任务更新与奖励通知",
|
||||||
|
"target_action": "用户授权APP系统推送通知",
|
||||||
|
"reward_type": "金币",
|
||||||
|
"reward_value": 300,
|
||||||
|
"is_one_time": true,
|
||||||
|
"status": "active"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "newbie_join_discord",
|
||||||
|
"task_name": "加入Discord社区",
|
||||||
|
"task_desc": "通过APP内链接加入官方Discord社区,获取专属活动与客服支持",
|
||||||
|
"target_action": "用户通过指定链接成功加入Discord社区",
|
||||||
|
"reward_type": "金币",
|
||||||
|
"reward_value": 200,
|
||||||
|
"is_one_time": true,
|
||||||
|
"status": "active"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "newbie_7day_checkin",
|
||||||
|
"task_name": "7日连续签到",
|
||||||
|
"task_desc": "连续7天完成签到,奖励逐级递增,第7天最高可得800金币",
|
||||||
|
"target_action": "用户每日完成签到操作(支持广告补签)",
|
||||||
|
"reward_type": "金币",
|
||||||
|
"reward_details": [
|
||||||
|
{"day": 1, "value": 100},
|
||||||
|
{"day": 2, "value": 300},
|
||||||
|
{"day": 3, "value": 300},
|
||||||
|
{"day": 4, "value": 500},
|
||||||
|
{"day": 5, "value": 300},
|
||||||
|
{"day": 6, "value": 300},
|
||||||
|
{"day": 7, "value": 800}
|
||||||
|
],
|
||||||
|
"support_makeup": true,
|
||||||
|
"makeup_method": "观看15-30秒激励视频",
|
||||||
|
"is_one_time": true,
|
||||||
|
"status": "active"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category_id": "daily_task",
|
||||||
|
"category_name": "日常任务(Missão Diária)",
|
||||||
|
"valid_period": "每日凌晨00:00重置",
|
||||||
|
"display_priority": 2,
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"task_id": "daily_checkin",
|
||||||
|
"task_name": "每日签到",
|
||||||
|
"task_desc": "每日签到可获金币,7天为一周期,奖励循环递增(支持双倍广告奖励)",
|
||||||
|
"target_action": "用户当日完成签到操作",
|
||||||
|
"reward_type": "金币",
|
||||||
|
"reward_details": [
|
||||||
|
{"day": 1, "value": 100},
|
||||||
|
{"day": 2, "value": 300},
|
||||||
|
{"day": 3, "value": 300},
|
||||||
|
{"day": 4, "value": 500},
|
||||||
|
{"day": 5, "value": 300},
|
||||||
|
{"day": 6, "value": 300},
|
||||||
|
{"day": 7, "value": 500}
|
||||||
|
],
|
||||||
|
"double_reward_method": "观看15-30秒激励视频",
|
||||||
|
"support_makeup": true,
|
||||||
|
"makeup_method": "观看15-30秒激励视频",
|
||||||
|
"is_one_time": false,
|
||||||
|
"status": "active"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "daily_video_ladder",
|
||||||
|
"task_name": "阶梯观看视频",
|
||||||
|
"task_desc": "累计观看指定数量短视频,分3档领取奖励(与基础观看收益叠加)",
|
||||||
|
"target_action": "用户累计观看短视频",
|
||||||
|
"reward_type": "金币",
|
||||||
|
"reward_details": [
|
||||||
|
{"target_count": 10, "value": 100},
|
||||||
|
{"target_count": 20, "value": 150},
|
||||||
|
{"target_count": 30, "value": 200}
|
||||||
|
],
|
||||||
|
"reward_stackable": true,
|
||||||
|
"is_one_time": false,
|
||||||
|
"status": "active"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"task_id": "daily_ad_ladder",
|
||||||
|
"task_name": "阶梯观看激励视频",
|
||||||
|
"task_desc": "累计观看指定数量激励视频,分3档领取奖励(每日上限10次)",
|
||||||
|
"target_action": "用户累计观看激励视频",
|
||||||
|
"reward_type": "金币",
|
||||||
|
"reward_details": [
|
||||||
|
{"target_count": 1, "value": 100},
|
||||||
|
{"target_count": 5, "value": 150},
|
||||||
|
{"target_count": 10, "value": 200}
|
||||||
|
],
|
||||||
|
"daily_limit": 10,
|
||||||
|
"reward_stackable": true,
|
||||||
|
"is_one_time": false,
|
||||||
|
"status": "active"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
package com.gamedog.vididin
|
|
||||||
|
|
||||||
object VidiConst {
|
|
||||||
/**
|
|
||||||
* 描述:网络常量
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
const val URL_YOUTUBE_API = "https://www.googleapis.com"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 描述:其他常量
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
const val YOUTUBE_API_KEY = "AIzaSyBm9k2lS_j7Fdd43NEPkcfikJRotup5DMY"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
package com.gamedog.vididin
|
||||||
|
|
||||||
|
object VidiConst {
|
||||||
|
|
||||||
|
// adjust
|
||||||
|
const val GUIDE_INDEX_GIFT: Int = 1
|
||||||
|
const val GUIDE_INDEX_CASH_GOLD: Int = 2
|
||||||
|
const val GUIDE_INDEX_WITHDRAW: Int = 3
|
||||||
|
const val GUIDE_INDEX_ZERO: Int = 4
|
||||||
|
const val GUIDE_INDEX_POP_MENU: Int = 5
|
||||||
|
|
||||||
|
|
||||||
|
// adjust
|
||||||
|
const val ADJUST_TOKEN: String = "sa8ei0td10xs"
|
||||||
|
const val ADJUST_TOKEN_S2: String = "f3cff8c4bba54c6dc08b3401069ae06d"
|
||||||
|
const val ADJUST_WITHDRAW_SUCCESS_EVENT: String = "tjs3fp"
|
||||||
|
const val ADJUST_WITHDRAW_FAILED_EVENT: String = "33jp2j"
|
||||||
|
|
||||||
|
// shushu
|
||||||
|
const val SHUSHU_APP_ID: String = "097b3fd67217437b83529c35f81a567e"
|
||||||
|
const val SHUSHU_SERVER_URL: String = "https://data.tapvicogames.com"//"https://ss.zolnm.com"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const val NEWBIE_GIFT_GOLD_NUM: Long = 100
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Varous type for watching Ad
|
||||||
|
*/
|
||||||
|
const val WATCH_AD_FOR_WITHDRAW_SMALL = 1
|
||||||
|
const val WATCH_AD_FOR_WITHDRAW_BIG = 2
|
||||||
|
const val WATCH_AD_FOR_BOX_TASK = 3
|
||||||
|
const val WATCH_AD_FOR_ZERO_EARN_DIAMOND = 4
|
||||||
|
const val WATCH_AD_FOR_DAILY_WATCH_AD = 5
|
||||||
|
const val WATCH_AD_FOR_DAILY_EARN_GOLD = 6
|
||||||
|
const val WATCH_AD_FOR_CONVERT_GOLD_2_CASH = 7
|
||||||
|
const val WATCH_AD_FOR_DAILY_SIGN_SINGLE = 8
|
||||||
|
const val WATCH_AD_FOR_DAILY_SIGN_DOUBLE = 9
|
||||||
|
const val WATCH_AD_FOR_DAILY_SIGN_COMPLEMENT = 10
|
||||||
|
const val WATCH_AD_FOR_DAILY_EARN_GOLD_POPMENU = 11
|
||||||
|
const val WATCH_AD_FOR_WATCHED_3_VIDEOS = 12
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Withdraw related const
|
||||||
|
*/
|
||||||
|
const val WITHDRAW_MD5KEY = "eonline~#*^%$@!~0702"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zero buy related values
|
||||||
|
*/
|
||||||
|
const val ZERO_GET_PURCHASE_LIST: Int = 0
|
||||||
|
const val ZERO_JOIN_PURCHASE: Int = 10
|
||||||
|
const val ZERO_WITHDRAW_OPERATION: Int = 18
|
||||||
|
const val ZERO_WITHDRAW_RESULT_CHECK: Int = 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const val URL_DISCORD: String = "https://discord.gg/qAZaaN8uaU"
|
||||||
|
const val URL_GAME: String = "https://s.gamifyspace.com/tml?pid=20057&appk=ZPfHlw7v5plM1N2moiiaDzixPszLSxIl&did=%s"
|
||||||
|
const val URL_PRIVACY: String = "https://rsappinc.com/privacy.html"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述:网络常量
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
const val URL_YOUTUBE_API = "https://vd.rsappinc.com"
|
||||||
|
|
||||||
|
const val URL_ZERO_BUY: String = "https://va.rsappinc.com" //"https://rsappinc.com" //
|
||||||
|
|
||||||
|
const val URL_WITHDRAW: String = "https://zz.rsappinc.com" //"https://jpec.3idiotstudio.com"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述:其他常量
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const val YOUTUBE_API_KEY = "AIzaSyBm9k2lS_j7Fdd43NEPkcfikJRotup5DMY"
|
||||||
|
|
||||||
|
const val GOLD_IN_CONFIG: String = "金币"
|
||||||
|
|
||||||
|
const val PER_01CASH_COST_GOLD_NUM = 100
|
||||||
|
const val WATCH_AD_REWARD_GOLD = 200
|
||||||
|
|
||||||
|
const val ZEROBUY_SECRET: String = "efda5260"//"1f04c57a"
|
||||||
|
|
||||||
|
const val DIAMOND_NUM_FOR_ONE_AD = 1
|
||||||
|
const val WITHDRAW_SMALL_NUM = 0.1F
|
||||||
|
const val WITHDRAW_REWARD_AD_REVENUE_PERCENT = 1.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------ Statistics ----------------------------
|
||||||
|
const val STATISTICS_APP_OPEN = "app_open"
|
||||||
|
const val STATISTICS_NOTIFI_CLICK = "Notific_Click"
|
||||||
|
const val STATISTICS_NOTIFI_ENTER = "Notific_Enter"
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
package com.gamedog.vididin
|
|
||||||
|
|
||||||
import com.ama.core.architecture.BaseApp
|
|
||||||
import com.gamedog.vididin.core.login.login.AccountManager
|
|
||||||
import com.gamedog.vididin.manager.TaskManager
|
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
|
||||||
|
|
||||||
|
|
||||||
@HiltAndroidApp
|
|
||||||
class VidiDinApp : BaseApp() {
|
|
||||||
|
|
||||||
init {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate() {
|
|
||||||
super.onCreate()
|
|
||||||
initManagers()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initManagers() {
|
|
||||||
AccountManager.getAccount()
|
|
||||||
TaskManager.instance()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.gamedog.vididin
|
||||||
|
|
||||||
|
object VidiStatisticHelper {
|
||||||
|
|
||||||
|
fun getShowFromStr(watchAdType: Int): String {
|
||||||
|
val fromStr = ""
|
||||||
|
when (watchAdType) {
|
||||||
|
VidiConst.WATCH_AD_FOR_WATCHED_3_VIDEOS -> {
|
||||||
|
return "RV_VideoStream"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_DAILY_EARN_GOLD_POPMENU -> {
|
||||||
|
return "RV_Home_Menu"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_DAILY_WATCH_AD -> {
|
||||||
|
return "RV_Daily_Task"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_DAILY_EARN_GOLD -> {
|
||||||
|
return "RV_Coin"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_CONVERT_GOLD_2_CASH -> {
|
||||||
|
return "RV_Exchange"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_BOX_TASK -> {
|
||||||
|
return "Benefit_Task"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_WITHDRAW_BIG -> {
|
||||||
|
return "RV_Accelerate2"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_WITHDRAW_SMALL -> {
|
||||||
|
return "RV_Accelerate1"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_DAILY_SIGN_SINGLE -> {
|
||||||
|
return "RV_Extra"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_DAILY_SIGN_DOUBLE -> {
|
||||||
|
return "RV_Double"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_DAILY_SIGN_COMPLEMENT -> {
|
||||||
|
return "RV_SupplementarySigning"
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_ZERO_EARN_DIAMOND -> {
|
||||||
|
return "RV_Zero_Diamond"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return fromStr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,9 +1,66 @@
|
||||||
package com.gamedog.vididin
|
package com.gamedog.vididin
|
||||||
|
|
||||||
object VididinEvents {
|
object VididinEvents {
|
||||||
|
|
||||||
const val Event_Sign_State_Changed = 600
|
const val Event_Sign_State_Changed = 600
|
||||||
const val Event_Account_Gold_Changed = 601
|
const val Event_Account_Gold_Changed = 601
|
||||||
const val Event_Account_Cash_Changed = 602
|
const val Event_Account_Cash_Changed = 602
|
||||||
const val Event_Account_Bank_Info_Changed = 603
|
const val EVENT_BANK_INFO_CHANGED = 603
|
||||||
|
const val Event_Account_Diamond_Changed = 604
|
||||||
|
|
||||||
|
|
||||||
|
const val Event_HOME_WATCH_Time_TICK = 700
|
||||||
|
const val Event_Finish_One_Video = 701
|
||||||
|
const val EVENT_FINISHED_ONE_AD = 702
|
||||||
|
const val Event_Finish_One_Sign = 703
|
||||||
|
const val Event_Finish_One_Zerobuy = 704
|
||||||
|
|
||||||
|
const val EVENT_DAILY_WATCHED_VIDEO_NUM_CHANGED = 705
|
||||||
|
const val EVENT_DAILY_WATCHED_AD_NUM_CHANGED = 706
|
||||||
|
|
||||||
|
const val EVENT_BOX_TASK_STATE_CHANGED = 707
|
||||||
|
const val EVENT_NEWBIE_NOTIFY_TASK_CHANGED = 708
|
||||||
|
const val EVENT_NEWBIE_FIRST_WITHDRAW_TASK_CHANGED = 709
|
||||||
|
const val EVENT_NEWBIE_DISCORD_TASK_CHANGED = 710
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const val EVENT_AD_WATCHED_FOR_CONVERT_GOLD_2_CASH = 800
|
||||||
|
const val EVENT_AD_WATCHED_FOR_EARN_GOLD = 801
|
||||||
|
const val EVENT_AD_WATCHED_FOR_DAILY_WATCH_AD = 802
|
||||||
|
const val Event_AD_TASK_TYPE_Withdraw = 803
|
||||||
|
const val Event_AD_TASK_TYPE_Complement = 804
|
||||||
|
const val EVENT_AD_WATCHED_FOR_BOX_TASK = 805
|
||||||
|
const val EVENT_AD_WATCHED_FOR_ZEROBUY_EARN_DIAMOND = 806
|
||||||
|
const val EVENT_AD_WATCHED_FOR_WITHDRAW_SMALL = 807
|
||||||
|
const val EVENT_AD_WATCHED_FOR_WITHDRAW_BIG = 808
|
||||||
|
const val EVENT_AD_WATCHED_FOR_DAILY_SIGN_SINGLE = 809
|
||||||
|
const val EVENT_AD_WATCHED_FOR_DAILY_SIGN_DOUBLE = 810
|
||||||
|
const val EVENT_AD_WATCHED_FOR_DAILY_SIGN_COMPLEMENT = 811
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// UI jump related
|
||||||
|
const val EVENT_JUMP_2_FIRST_WITHDRAW = 900
|
||||||
|
const val EVENT_JUMP_2_VIDEO = 901
|
||||||
|
const val EVENT_JUMP_2_SIGN= 902
|
||||||
|
|
||||||
|
|
||||||
|
const val AD_ACT_SHOWING = 951
|
||||||
|
const val AD_ACT_DESTROY = 952
|
||||||
|
|
||||||
|
|
||||||
|
// Withdraw related
|
||||||
|
const val EVENT_WITHDRAW_SUB_ITEM_PROGRESS_UPDATED = 500
|
||||||
|
const val EVENT_WITHDRAW_SELECTED_SUB_ITEM_CHANGED = 501
|
||||||
|
const val EVENT_WITHDRAW_RESULT_UPDATED = 502
|
||||||
|
const val EVENT_WITHDRAW_ITEM_LIST_CHANGED = 503
|
||||||
|
const val EVENT_WITHDRAW_SMALL_AD_FINISHED = 504
|
||||||
|
|
||||||
|
|
||||||
|
// zero withdraw events
|
||||||
|
const val EVENT_ZERO_WITHDRAW_LIST_CHANGED = 200
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -10,18 +10,18 @@ import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.ama.core.architecture.appBase.adapter.AppNavigatorAdapter
|
import com.ama.core.architecture.appBase.adapter.AppNavigatorAdapter
|
||||||
import com.ama.core.common.util.asSafe
|
import com.ama.core.common.util.asSafe
|
||||||
import com.ama.core.common.util.getDataFromThemeAttr
|
import com.ama.core.common.util.getDataFromThemeAttr
|
||||||
import com.gamedog.vididin.R
|
|
||||||
import com.gamedog.vididin.beans.MainTabsItem
|
import com.gamedog.vididin.beans.MainTabsItem
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabClickAgainListener
|
import com.gamedog.vididin.main.interfaces.OnTabClickAgainListener
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabClickRefreshFinishListener
|
import com.gamedog.vididin.main.interfaces.OnTabClickRefreshFinishListener
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabClickRefreshListener
|
import com.gamedog.vididin.main.interfaces.OnTabClickRefreshListener
|
||||||
|
import com.viddin.videos.free.R
|
||||||
import net.lucode.hackware.magicindicator.MagicIndicator
|
import net.lucode.hackware.magicindicator.MagicIndicator
|
||||||
import net.lucode.hackware.magicindicator.buildins.commonnavigator.CommonNavigator
|
import net.lucode.hackware.magicindicator.buildins.commonnavigator.CommonNavigator
|
||||||
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator
|
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator
|
||||||
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerTitleView
|
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerTitleView
|
||||||
import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.CommonPagerTitleView
|
import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.CommonPagerTitleView
|
||||||
import kotlin.ranges.until
|
import kotlin.ranges.until
|
||||||
import com.gamedog.vididin.databinding.ItemActivityMainTabBinding as ViewBinding
|
import com.viddin.videos.free.databinding.ItemActivityMainTabBinding as ViewBinding
|
||||||
import com.google.android.material.R as materialR
|
import com.google.android.material.R as materialR
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -103,10 +103,10 @@ class MainTabsAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun ViewBinding.onTabClickAgainHandle(index: Int) {
|
private fun ViewBinding.onTabClickAgainHandle(index: Int) {
|
||||||
val currentFragment = mainFragmentStateAdapter.getFragmentByIndex(index)
|
val currentFragment = mainFragmentStateAdapter.getFragmentByIndex(index)
|
||||||
if (currentFragment is OnTabClickRefreshListener) {
|
if (currentFragment is OnTabClickRefreshListener) {
|
||||||
// 刷新 - 展示Loading
|
|
||||||
currentFragment.onTabClickRefresh(object : OnTabClickRefreshFinishListener {
|
currentFragment.onTabClickRefresh(object : OnTabClickRefreshFinishListener {
|
||||||
override fun onTabClickRefreshFinish() {
|
override fun onTabClickRefreshFinish() {
|
||||||
setTabStyle(1)
|
setTabStyle(1)
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ interface YoutubeApi {
|
||||||
): ResYoutubePlayList
|
): ResYoutubePlayList
|
||||||
|
|
||||||
@GET("/youtube/v3/videos")
|
@GET("/youtube/v3/videos")
|
||||||
suspend fun getVideoList(
|
suspend fun getVideoList_old(
|
||||||
@Query("part") part: String= URLEncoder.encode("snippet", "UTF-8"),
|
@Query("part") part: String= URLEncoder.encode("snippet", "UTF-8"),
|
||||||
@Query("key") key: String= VidiConst.YOUTUBE_API_KEY,
|
@Query("key") key: String= VidiConst.YOUTUBE_API_KEY,
|
||||||
@Query("videoDuration") videoDuration: String= "short",
|
@Query("videoDuration") videoDuration: String= "short",
|
||||||
|
|
@ -56,10 +56,9 @@ interface YoutubeApi {
|
||||||
): ResYoutubePlayList
|
): ResYoutubePlayList
|
||||||
|
|
||||||
|
|
||||||
/*
|
@GET("/videos")
|
||||||
https://www.googleapis.com/youtube/v3/videos?part=id&chart=mostPopular®ionCode=BR&maxResults=10&key=AIzaSyBm9k2lS_j7Fdd43NEPkcfikJRotup5DMY
|
suspend fun getVideoList(
|
||||||
https://www.googleapis.com/youtube/v3/videos?part=snippet,statistics&chart=mostPopular®ionCode=BR&maxResults=10&key=AIzaSyBm9k2lS_j7Fdd43NEPkcfikJRotup5DMY
|
@Query("video") video: String? = URLEncoder.encode("", "UTF-8"),
|
||||||
*/
|
): ResYoutubePlayList
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,14 +2,25 @@ package com.gamedog.vididin.beans
|
||||||
|
|
||||||
|
|
||||||
data class Account(
|
data class Account(
|
||||||
|
var userId: Int = 0,
|
||||||
|
var userName: String = "Miguel",
|
||||||
val accountId: String,
|
val accountId: String,
|
||||||
val deviceUUId: String,
|
val deviceUUId: String,
|
||||||
val token: String="",
|
val token: String="",
|
||||||
val createdAt: Long,
|
val createdAt: Long,
|
||||||
|
@Volatile
|
||||||
var goldCount: Long = 0L,
|
var goldCount: Long = 0L,
|
||||||
var cashCount: Float = 0F,
|
@Volatile
|
||||||
|
var cashCount: Double = 0.0,
|
||||||
|
@Volatile
|
||||||
|
var diamondCount: Int = 0,
|
||||||
var bankInfo: BankInfo? = null,
|
var bankInfo: BankInfo? = null,
|
||||||
)
|
val zeroBuyServerSecret: String = "",
|
||||||
|
var rvTimesGold: Int = 0,
|
||||||
|
var rvTimesCash: Int = 0,
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
data class BankInfo(
|
data class BankInfo(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
package com.gamedog.vididin.beans
|
||||||
|
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.DateUtil
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_FAIL
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_ONGOING
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_SUCCESS
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
|
||||||
|
|
||||||
|
// Record 类型
|
||||||
|
const val RECORD_CASH_PLUS_GOLD_CONVERT: Int = 1
|
||||||
|
const val RECORD_CASH_PLUS_BOX_TASK: Int = 2
|
||||||
|
const val RECORD_CASH_PLUS_WITHDRAW_ONGOING: Int = 3
|
||||||
|
const val RECORD_CASH_WITHDRAW: Int = 4
|
||||||
|
const val RECORD_CASH_ZERO_WITHDRAW_SUCCESS: Int = 5
|
||||||
|
|
||||||
|
abstract class BaseRecord {
|
||||||
|
var dateMs: Long = DateUtil.getCurTimeMs()
|
||||||
|
var uuid: String = AndroidUtil.randomUUid()
|
||||||
|
}
|
||||||
|
|
||||||
|
open class RecordCash (var recordType: Int = 0,
|
||||||
|
var amountNum: Double = 0.0,) : BaseRecord() {
|
||||||
|
|
||||||
|
// 提现相关的
|
||||||
|
var payInitItemId: Int = 0
|
||||||
|
var payOutReplyId: String = ""
|
||||||
|
var payOutReplyNo: String = ""
|
||||||
|
var withdrawState: Int = TRANSACTION_STATE_ONGOING // 提现状态 1:提现中,2:提现成功,3:提现失败
|
||||||
|
var withdrawFailType: Int = WithdrawManager.INIT_OK
|
||||||
|
var withdrawItemIndex: Int = -1
|
||||||
|
var withdrawItemLoopIndex: Int = -1
|
||||||
|
var withdrawItemSubIndex: Int = -1
|
||||||
|
var withdrawInitUUID: String = ""
|
||||||
|
var hasShowResultDialog: Boolean = false
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordCashShow: RecordCash() {
|
||||||
|
var title: Int = 0
|
||||||
|
var description: Int = 0
|
||||||
|
var iconRes: Int = 0
|
||||||
|
var textColor: Int = R.color.green_39
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun RecordCash.toShowBean(): RecordCashShow {
|
||||||
|
return RecordCashShow().apply {
|
||||||
|
this@apply.uuid = this@toShowBean.uuid
|
||||||
|
this@apply.dateMs = this@toShowBean.dateMs
|
||||||
|
this@apply.amountNum = this@toShowBean.amountNum
|
||||||
|
this@apply.recordType = this@toShowBean.recordType
|
||||||
|
this@apply.withdrawState = this@toShowBean.withdrawState
|
||||||
|
this@apply.withdrawFailType = this@toShowBean.withdrawFailType
|
||||||
|
|
||||||
|
when (this@apply.recordType) {
|
||||||
|
RECORD_CASH_PLUS_GOLD_CONVERT -> {
|
||||||
|
title = R.string.record_cash_title_convert_from_gold
|
||||||
|
description = R.string.record_cash_descr_convert_from_gold
|
||||||
|
iconRes = R.mipmap.task_gold
|
||||||
|
textColor = R.color.green_39
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_CASH_PLUS_BOX_TASK -> {
|
||||||
|
title = R.string.record_cash_title_box
|
||||||
|
description = R.string.record_cash_descr_box
|
||||||
|
iconRes = R.mipmap.icon_gift
|
||||||
|
textColor = R.color.green_39
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_CASH_PLUS_WITHDRAW_ONGOING -> {
|
||||||
|
title = R.string.record_cash_title_withdraw_ongoing
|
||||||
|
description = R.string.record_cash_descr_withdraw_onging
|
||||||
|
iconRes = R.mipmap.icon_convert_cash
|
||||||
|
textColor = R.color.red_28
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_CASH_WITHDRAW -> {
|
||||||
|
this@apply.amountNum = -this@toShowBean.amountNum
|
||||||
|
when (withdrawState) {
|
||||||
|
TRANSACTION_STATE_ONGOING -> {
|
||||||
|
title = R.string.record_cash_title_withdraw_ongoing
|
||||||
|
description = R.string.record_cash_descr_withdraw_onging
|
||||||
|
iconRes = R.mipmap.icon_withdraw_ongoing
|
||||||
|
textColor = R.color.green_39
|
||||||
|
}
|
||||||
|
|
||||||
|
TRANSACTION_STATE_SUCCESS -> {
|
||||||
|
title = R.string.record_cash_title_withdraw_success
|
||||||
|
description = R.string.record_cash_descr_withdraw_success
|
||||||
|
iconRes = R.mipmap.icon_check
|
||||||
|
textColor = R.color.green_39
|
||||||
|
}
|
||||||
|
|
||||||
|
TRANSACTION_STATE_FAIL -> {
|
||||||
|
title = R.string.record_cash_title_withdraw_failed
|
||||||
|
description = WithdrawManager.instance().getFailHintStrRes(withdrawFailType)
|
||||||
|
iconRes = R.mipmap.icon_fail
|
||||||
|
textColor = R.color.gray3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_CASH_ZERO_WITHDRAW_SUCCESS -> {
|
||||||
|
title = R.string.record_cash_title_zero
|
||||||
|
description = R.string.record_cash_descr_zero
|
||||||
|
iconRes = R.mipmap.icon_zero
|
||||||
|
textColor = R.color.green_39
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
package com.gamedog.vididin.beans
|
||||||
|
|
||||||
|
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import kotlin.Int
|
||||||
|
|
||||||
|
const val RECORD_GOLD_PLUS_WATCH_VIDEO_BY_TIME_DURATION: Int = 1
|
||||||
|
const val RECORD_GOLD_PLUS_WATCH_REWARD_AD: Int = 2
|
||||||
|
const val RECORD_GOLD_PLUS_NEWBIE_GIFT: Int = 3
|
||||||
|
const val RECORD_GOLD_PLUS_TASK_ENABLE_NOTIFY: Int = 4
|
||||||
|
const val RECORD_GOLD_PLUS_TASK_FIRST_WITHDRAW: Int = 5
|
||||||
|
const val RECORD_GOLD_PLUS_TASK_JOIN_DISCORD: Int = 6
|
||||||
|
const val RECORD_GOLD_PLUS_TASK_SIGN: Int = 7
|
||||||
|
const val RECORD_GOLD_PLUS_TASK_DAILY_AD: Int = 8
|
||||||
|
const val RECORD_GOLD_PLUS_TASK_DAILY_VIDEO: Int = 9
|
||||||
|
const val RECORD_GOLD_MINUS_CONVERT_2_CASH: Int = 10
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
open class RecordGold(var recordType: Int = 0, var amountNum: Long = 0): BaseRecord() {
|
||||||
|
var isSuccess: Boolean = false
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordGoldShow: RecordGold() {
|
||||||
|
var title: Int = 0
|
||||||
|
var description: Int = 0
|
||||||
|
var iconRes: Int = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun RecordGold.toShowBean(): RecordGoldShow {
|
||||||
|
return RecordGoldShow().apply {
|
||||||
|
this@apply.uuid = this@toShowBean.uuid
|
||||||
|
this@apply.dateMs = this@toShowBean.dateMs
|
||||||
|
this@apply.isSuccess = this@toShowBean.isSuccess
|
||||||
|
this@apply.amountNum = this@toShowBean.amountNum
|
||||||
|
this@apply.recordType = this@toShowBean.recordType
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
when (this@apply.recordType) {
|
||||||
|
RECORD_GOLD_PLUS_WATCH_VIDEO_BY_TIME_DURATION -> {
|
||||||
|
title = R.string.record_gold_title_watch_video_time_duration
|
||||||
|
description = R.string.record_gold_descr_watch_video_time_duration
|
||||||
|
iconRes = R.mipmap.icon_video_task
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_GOLD_PLUS_WATCH_REWARD_AD -> {
|
||||||
|
title = R.string.record_gold_title_watch_reward_ad
|
||||||
|
description = R.string.record_gold_descr_watch_reward_ad
|
||||||
|
iconRes = R.mipmap.icon_ad
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_GOLD_PLUS_NEWBIE_GIFT -> {
|
||||||
|
title = R.string.record_gold_title_newbie_gift
|
||||||
|
description = R.string.record_gold_descr_newbie_gift
|
||||||
|
iconRes = R.mipmap.icon_gift
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_GOLD_PLUS_TASK_ENABLE_NOTIFY -> {
|
||||||
|
title = R.string.record_gold_title_enable_notify
|
||||||
|
description = R.string.record_gold_descr_enable_notify
|
||||||
|
iconRes = R.mipmap.icon_notify
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_GOLD_PLUS_TASK_FIRST_WITHDRAW -> {
|
||||||
|
title = R.string.record_gold_title_first_withdraw
|
||||||
|
description = R.string.record_gold_descr_first_withdraw
|
||||||
|
iconRes = R.mipmap.icon_dollar
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_GOLD_PLUS_TASK_JOIN_DISCORD -> {
|
||||||
|
title = R.string.record_gold_title_join_discord
|
||||||
|
description = R.string.record_gold_descr_join_discord
|
||||||
|
iconRes = R.mipmap.icon_discord_2
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_GOLD_PLUS_TASK_SIGN -> {
|
||||||
|
title = R.string.record_gold_title_sign
|
||||||
|
description = R.string.record_gold_descr_sign
|
||||||
|
iconRes = R.mipmap.icon_calendar
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_GOLD_PLUS_TASK_DAILY_AD -> {
|
||||||
|
title = R.string.record_gold_title_daily_task_ad
|
||||||
|
description = R.string.record_gold_descr_daily_task_ad
|
||||||
|
iconRes = R.mipmap.icon_ad
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_GOLD_PLUS_TASK_DAILY_VIDEO -> {
|
||||||
|
title = R.string.record_gold_title_daily_task_video
|
||||||
|
description = R.string.record_gold_descr_daily_task_video
|
||||||
|
iconRes = R.mipmap.icon_video_task
|
||||||
|
}
|
||||||
|
|
||||||
|
RECORD_GOLD_MINUS_CONVERT_2_CASH -> {
|
||||||
|
title = R.string.record_gold_title_convert_2_cash
|
||||||
|
description = R.string.record_gold_descr_convert_2_cash
|
||||||
|
iconRes = R.mipmap.icon_convert_cash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.gamedog.vididin.beans
|
||||||
|
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
|
||||||
|
|
||||||
|
open class RecordZero : BaseRecord() {
|
||||||
|
var isSuccess: Boolean = false
|
||||||
|
var amountNum: Double = 0.0
|
||||||
|
var recordType: Int = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordZeroShow: RecordZero() {
|
||||||
|
var title: Int = 0
|
||||||
|
var description: Int = 0
|
||||||
|
var iconRes: Int = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun RecordZero.toShowBean(): RecordZeroShow {
|
||||||
|
return RecordZeroShow().apply {
|
||||||
|
this@apply.uuid = this@toShowBean.uuid
|
||||||
|
this@apply.dateMs = this@toShowBean.dateMs
|
||||||
|
this@apply.isSuccess = this@toShowBean.isSuccess
|
||||||
|
this@apply.amountNum = this@toShowBean.amountNum
|
||||||
|
this@apply.recordType = this@toShowBean.recordType
|
||||||
|
|
||||||
|
when (this@apply.recordType) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.gamedog.vididin.beans
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data class WatchAdNotifyBean<T>(
|
||||||
|
var earnMoneyNum: Double = 0.0,
|
||||||
|
var extraData: T,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
@ -5,92 +5,20 @@ import com.ama.core.model.BaseFragmentStateDiffItem
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class ResYoutubeChannel(
|
|
||||||
val id: String,
|
|
||||||
val name: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ResYoutubePlayList (
|
data class ResYoutubePlayList (
|
||||||
val kind: String,
|
val videos: List<YoutubeVideo>,
|
||||||
val etag: String, // TODO - this is Etag type
|
|
||||||
val nextPageToken: String,
|
|
||||||
val prevPageToken: String,
|
|
||||||
val pageInfo: PageInfo,
|
|
||||||
val items: List<YoutubeVideo>,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class PageInfo(
|
|
||||||
val totalResults: Int,
|
|
||||||
val resultsPerPage: Int,
|
|
||||||
)
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class YoutubeVideo(
|
data class YoutubeVideo(
|
||||||
val kind: String,
|
|
||||||
val etag: String,
|
|
||||||
val id: String,
|
val id: String,
|
||||||
val snippet: Snippet,
|
val channel_title: String,
|
||||||
val status: Status,
|
val description: String,
|
||||||
|
|
||||||
val contentDetails: ContentDetails,
|
|
||||||
val player: Player,
|
|
||||||
val localizations: Localizations,
|
|
||||||
) : BaseFragmentStateDiffItem {
|
) : BaseFragmentStateDiffItem {
|
||||||
override fun getPrimaryKey() = id
|
override fun getPrimaryKey() = id
|
||||||
override fun getItemId() = id.hashCode().toLong()
|
override fun getItemId() = id.hashCode().toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class ContentDetails(
|
|
||||||
val itemCount: Int,
|
|
||||||
)
|
|
||||||
@Serializable
|
|
||||||
data class Player(
|
|
||||||
val embedHtml: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Localizations(
|
|
||||||
val title: String,
|
|
||||||
val description: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Snippet(
|
|
||||||
val publishedAt: String,
|
|
||||||
val channelId: String,
|
|
||||||
val title: String,
|
|
||||||
val description: String,
|
|
||||||
//val thumbnails: Thumbnail,
|
|
||||||
val channelTitle: String,
|
|
||||||
val defaultLanguage: String,
|
|
||||||
val localized: Localized,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Localized(
|
|
||||||
val title: String,
|
|
||||||
val description: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Thumbnail(
|
|
||||||
val standard: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Status(
|
|
||||||
val privacyStatus: String,
|
|
||||||
val podcastStatus: Int,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
package com.gamedog.vididin.beans
|
||||||
|
|
||||||
|
|
||||||
|
import com.ama.core.model.BaseFragmentStateDiffItem
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ResYoutubeChannel(
|
||||||
|
val id: String,
|
||||||
|
val name: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ResYoutubePlayList (
|
||||||
|
val kind: String,
|
||||||
|
val etag: String, // TODO - this is Etag type
|
||||||
|
val nextPageToken: String,
|
||||||
|
val prevPageToken: String,
|
||||||
|
val pageInfo: PageInfo,
|
||||||
|
val items: List<YoutubeVideo>,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class PageInfo(
|
||||||
|
val totalResults: Int,
|
||||||
|
val resultsPerPage: Int,
|
||||||
|
)
|
||||||
|
@Serializable
|
||||||
|
data class YoutubeVideo(
|
||||||
|
val kind: String,
|
||||||
|
val etag: String,
|
||||||
|
val id: String,
|
||||||
|
val snippet: Snippet,
|
||||||
|
val status: Status,
|
||||||
|
|
||||||
|
val contentDetails: ContentDetails,
|
||||||
|
val player: Player,
|
||||||
|
val localizations: Localizations,
|
||||||
|
) : BaseFragmentStateDiffItem {
|
||||||
|
override fun getPrimaryKey() = id
|
||||||
|
override fun getItemId() = id.hashCode().toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ContentDetails(
|
||||||
|
val itemCount: Int,
|
||||||
|
)
|
||||||
|
@Serializable
|
||||||
|
data class Player(
|
||||||
|
val embedHtml: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Localizations(
|
||||||
|
val title: String,
|
||||||
|
val description: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Snippet(
|
||||||
|
val publishedAt: String,
|
||||||
|
val channelId: String,
|
||||||
|
val title: String,
|
||||||
|
val description: String,
|
||||||
|
//val thumbnails: Thumbnail,
|
||||||
|
val channelTitle: String,
|
||||||
|
val defaultLanguage: String,
|
||||||
|
val localized: Localized,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Localized(
|
||||||
|
val title: String,
|
||||||
|
val description: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Thumbnail(
|
||||||
|
val standard: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Status(
|
||||||
|
val privacyStatus: String,
|
||||||
|
val podcastStatus: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.gamedog.vididin.beans
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data class ZeroBuyResp (
|
||||||
|
val code: Int,
|
||||||
|
val message: String,
|
||||||
|
val user_id: Int,
|
||||||
|
val current_purchases : List<ZeroBuyItem>,
|
||||||
|
val finished_purchases : List<ZeroBuyItem>?,
|
||||||
|
val Content: String,
|
||||||
|
var contentObj: ZeroBuyItem?
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
data class ZeroBuyItem (
|
||||||
|
val id:Int = 0,
|
||||||
|
val title: String? = null,
|
||||||
|
val start_time:Long = 0,
|
||||||
|
val end_time:Long = 0,
|
||||||
|
val target_num:Int = 0,
|
||||||
|
val cost:Int = 0,
|
||||||
|
val price: String? = null,
|
||||||
|
val image:Int = 0,
|
||||||
|
val current_users: List<Int>? = null,
|
||||||
|
val winners: List<Int>? = null,
|
||||||
|
/*val redeem_code: String? = null,*/
|
||||||
|
val completed: Boolean = false,
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data class ZeroBuyWithdrawResp (
|
||||||
|
val code: Int,
|
||||||
|
val message: String,
|
||||||
|
val content: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.gamedog.vididin.beans.req
|
||||||
|
|
||||||
|
import com.gamedog.vididin.beans.resp.PbReportDataAdjust
|
||||||
|
import com.gamedog.vididin.beans.resp.PbReportDataShuShu
|
||||||
|
|
||||||
|
|
||||||
|
open class PayInitReq (
|
||||||
|
var platform: String? = null,
|
||||||
|
var deviceid: String? = null,
|
||||||
|
var version: String? = null,
|
||||||
|
var ip: String? = null,
|
||||||
|
var ts: String? = null,
|
||||||
|
var sign: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class PayoutReq(
|
||||||
|
var account: String? = null,
|
||||||
|
var item_id: Int = 0,
|
||||||
|
var amount: String? = null,
|
||||||
|
var additional_remark: String? = null,
|
||||||
|
var uuid: String? = null,
|
||||||
|
var account_type: String? = null,
|
||||||
|
var document_type: String? = null,
|
||||||
|
var document_id: String? = null,
|
||||||
|
var name: String? = null,
|
||||||
|
var clientName: String? = null,
|
||||||
|
var dataAdjust: PbReportDataAdjust = PbReportDataAdjust(),
|
||||||
|
var dataShuShu: PbReportDataShuShu = PbReportDataShuShu(),
|
||||||
|
) : PayInitReq()
|
||||||
|
|
||||||
|
data class PayoutCheckReq(var record_no: String = "") : PayInitReq()
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
package com.gamedog.vididin.beans.resp
|
||||||
|
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_ONGOING
|
||||||
|
|
||||||
|
|
||||||
|
data class WithDrawRespData (
|
||||||
|
var items: MutableList<InitIem?>? = null,
|
||||||
|
var UUID: String? = null,
|
||||||
|
var IP: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
open class BaseReply (
|
||||||
|
var code: Int = 0,
|
||||||
|
var msg: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
data class PayInit(var data: PayInitReply? = null) : BaseReply() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
open class PayInitReply (
|
||||||
|
var uuid: String? = null,
|
||||||
|
var items: List<InitIem?>? = null,
|
||||||
|
var days: Int = 0,
|
||||||
|
var error: Int = 0,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class InitIem (
|
||||||
|
var id: Int = 0,
|
||||||
|
var amount: Float = 0f,
|
||||||
|
var status: Int = 0,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
data class PbReportDataAdjust(
|
||||||
|
var gps_adid: String? = null, // 用户的gaid
|
||||||
|
var android_id: String? = null, // 原始安卓 ID
|
||||||
|
var adid: String? = null, // 与设备关联的 Adjust 标识符
|
||||||
|
var user_agent: String? = null, // 设备的User-Agent。必须进行 URL 编码。
|
||||||
|
var price: String? = null, // 客户端上报的价格 客户端上报的价格,例如0.05
|
||||||
|
var currency: String? = null, // 货币单位 客户端上报的货币,例如
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
data class PbReportDataShuShu(
|
||||||
|
var gps_gaid: String? = null, // 用户的gaid
|
||||||
|
var android_id: String? = null ,// 原始安卓 ID
|
||||||
|
var adid: String? = null, // 与设备关联的 Adjust 标识符
|
||||||
|
var user_agent: String? = null, // 设备的User-Agent。必须进行 URL 编码
|
||||||
|
var price: String? = null, // 客户端上报的价格 客户端上报的价格,例如0.05
|
||||||
|
var currency: String? = null, // 货币单位 客户端上报的货币,例如USD
|
||||||
|
var payment_method: String? = null, // 收款方式 暂时只有一种:pix
|
||||||
|
var payment_type: String? = null, // 账户形式 cpf/cnpj/evp/email/phone
|
||||||
|
var payment_number: String? = null, // 账户号码 收款账号号码
|
||||||
|
var iap_name: String? = null, // 商品名称 游戏侧自定义的提现项目名称,例如:0.1br/50br/100br
|
||||||
|
var gamecoin_number: String? = null, // 提现消耗的虚拟货币数 提现消耗的虚拟货币数量,例如:1500
|
||||||
|
var gamecoin_type: String? = null, // 提现消耗的虚拟货币类型 金币或钞票,例如:coin/money
|
||||||
|
var ss_account_id: String? = null, // 数数账号ID 用户的登录ID(如果需要接入数数请务必传此值)
|
||||||
|
var ss_distinct_id: String? = null, // 数数访客ID 用户在未登录状态下的ID(如果需要接入数数请务必传此值)
|
||||||
|
var ss_super_properties: String? = null, // 数数的公共属性和预制属性 json字符串
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data class PayoutData(
|
||||||
|
var data: PayoutReply? = null
|
||||||
|
) : BaseReply()
|
||||||
|
|
||||||
|
data class PayoutReply (
|
||||||
|
var id: String? = null,
|
||||||
|
var record_no: String = "",
|
||||||
|
var error: Int = 0,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data class PayoutCheckData(var data: PayoutCheck? = null) : BaseReply()
|
||||||
|
|
||||||
|
data class PayoutCheck(
|
||||||
|
var status: Int = 0, // 提现状态 1:提现中,2:提现成功,3:提现失败
|
||||||
|
var error: Int = 0, // 错误码,0成功,1失败,2签名验证失败,3客户端版本过低,4 ts长度错误
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
data class WithdrawRecord (
|
||||||
|
var payOutReplyId: String = "",
|
||||||
|
var payOutReplyNo: String = "",
|
||||||
|
var cashNum: Double = 0.0,
|
||||||
|
var operateMs: Long = 0L,
|
||||||
|
var state: Int = TRANSACTION_STATE_ONGOING, // 提现状态 1:提现中,2:提现成功,3:提现失败
|
||||||
|
var failReason: Int = 0, // TODO - define various fail reasons
|
||||||
|
|
||||||
|
var withdrawItemIndex: Int = 0,
|
||||||
|
var withdrawItemSubIndex: Int = 0,
|
||||||
|
var hasShowResultDialog: Boolean = false
|
||||||
|
)*/
|
||||||
|
|
@ -5,19 +5,27 @@ import com.gamedog.vididin.features.benefit.DefaultBenefitRouter
|
||||||
import com.gamedog.vididin.features.winrecords.DefaultWinRecordRouter
|
import com.gamedog.vididin.features.winrecords.DefaultWinRecordRouter
|
||||||
import com.gamedog.vididin.features.winrecords.WinRecordRouter
|
import com.gamedog.vididin.features.winrecords.WinRecordRouter
|
||||||
import com.gamedog.vididin.features.withdraw.DefaultWithdrawRouter
|
import com.gamedog.vididin.features.withdraw.DefaultWithdrawRouter
|
||||||
|
import com.gamedog.vididin.features.withdraw.DefaultWithdrawSubRouter
|
||||||
import com.gamedog.vididin.features.withdraw.WithdrawRouter
|
import com.gamedog.vididin.features.withdraw.WithdrawRouter
|
||||||
|
import com.gamedog.vididin.features.withdraw.WithdrawSubRouter
|
||||||
import com.gamedog.vididin.features.zero.DefaultZeroBuyRouter
|
import com.gamedog.vididin.features.zero.DefaultZeroBuyRouter
|
||||||
import com.gamedog.vididin.features.zero.ZeroBuyRouter
|
import com.gamedog.vididin.features.zero.ZeroBuyRouter
|
||||||
import com.gamedog.vididin.router.DefaultFeedbackRouter
|
import com.gamedog.vididin.router.DefaultFeedbackRouter
|
||||||
|
import com.gamedog.vididin.router.DefaultGameRouter
|
||||||
|
import com.gamedog.vididin.router.DefaultMainRouter
|
||||||
import com.gamedog.vididin.router.DefaultPrivacyRouter
|
import com.gamedog.vididin.router.DefaultPrivacyRouter
|
||||||
import com.gamedog.vididin.router.DefaultSplashRouter
|
import com.gamedog.vididin.router.DefaultSplashRouter
|
||||||
import com.gamedog.vididin.router.DefaultVersionRouter
|
import com.gamedog.vididin.router.DefaultVersionRouter
|
||||||
|
import com.gamedog.vididin.router.DefaultWatchAdRouter
|
||||||
import com.gamedog.vididin.router.DefaultWithdrawRecordRouter
|
import com.gamedog.vididin.router.DefaultWithdrawRecordRouter
|
||||||
import com.gamedog.vididin.router.IRouterFeedback
|
import com.gamedog.vididin.router.IRouterFeedback
|
||||||
|
import com.gamedog.vididin.router.IRouterGame
|
||||||
import com.gamedog.vididin.router.IRouterPrivacy
|
import com.gamedog.vididin.router.IRouterPrivacy
|
||||||
import com.gamedog.vididin.router.IRouterSplash
|
import com.gamedog.vididin.router.IRouterSplash
|
||||||
import com.gamedog.vididin.router.IRouterVersion
|
import com.gamedog.vididin.router.IRouterVersion
|
||||||
import com.gamedog.vididin.router.IRouterWithdrawRecord
|
import com.gamedog.vididin.router.IRouterWithdrawRecord
|
||||||
|
import com.gamedog.vididin.router.IRouterWatchAd
|
||||||
|
import com.gamedog.vididin.router.MainRouter
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
|
|
@ -51,6 +59,15 @@ object WithdrawModule {
|
||||||
fun provideRouter(): WithdrawRouter = DefaultWithdrawRouter()
|
fun provideRouter(): WithdrawRouter = DefaultWithdrawRouter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
object WithdrawSubModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideRouter(): WithdrawSubRouter = DefaultWithdrawSubRouter()
|
||||||
|
}
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
object WinRecordModule {
|
object WinRecordModule {
|
||||||
|
|
@ -59,6 +76,14 @@ object WinRecordModule {
|
||||||
fun provideRouter(): WinRecordRouter = DefaultWinRecordRouter()
|
fun provideRouter(): WinRecordRouter = DefaultWinRecordRouter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
object MainModule {
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideRouter(): MainRouter = DefaultMainRouter()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
|
|
@ -68,6 +93,14 @@ object PrivacyModule {
|
||||||
fun provideRouter(): IRouterPrivacy = DefaultPrivacyRouter()
|
fun provideRouter(): IRouterPrivacy = DefaultPrivacyRouter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
object PrivacyGame {
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideRouter(): IRouterGame = DefaultGameRouter()
|
||||||
|
}
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
object FeedbackModule {
|
object FeedbackModule {
|
||||||
|
|
@ -99,3 +132,11 @@ object VersionModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideRouter(): IRouterVersion = DefaultVersionRouter()
|
fun provideRouter(): IRouterVersion = DefaultVersionRouter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
object WatchAd {
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideRouter(): IRouterWatchAd = DefaultWatchAdRouter()
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,8 @@ package com.gamedog.vididin.core.network.di
|
||||||
|
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.ama.core.architecture.util.DeviceUtil
|
||||||
|
import com.gamedog.vididin.request.RequestUtil
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
|
@ -24,26 +26,23 @@ class GlobalInterceptor : Interceptor {
|
||||||
val emptyBody = "{}".toRequestBody("application/json;charset=utf-8".toMediaType())
|
val emptyBody = "{}".toRequestBody("application/json;charset=utf-8".toMediaType())
|
||||||
val requestBody = if (bodyStr.isNotBlank()) request.body else emptyBody
|
val requestBody = if (bodyStr.isNotBlank()) request.body else emptyBody
|
||||||
|
|
||||||
|
val timeSec = RequestUtil.getTimestampSec()
|
||||||
|
|
||||||
val headersBuilder = Headers.Builder()
|
val requestBuilder = chain.request().newBuilder()
|
||||||
/*
|
.addHeader("User-Agent", "Android")
|
||||||
.add("authorazation", "Bearer xxxxx")
|
.addHeader("Accept-Language", Locale.getDefault().toLanguageTag())
|
||||||
.add("AUTH_DID", AppUtils.getAndroidID())
|
.addHeader("Content-Type", "application/json")
|
||||||
.add("platform", AppConstant.APP_CLIENT)
|
.addHeader("Accept", "application/json")
|
||||||
.add("Authorization", "Bearer xxx")
|
.addHeader("Accept-Charset", "utf-8")
|
||||||
.add("versionNum", "100")
|
// server real defined
|
||||||
*/
|
.addHeader("ApplicationId", RequestUtil.Request_APPId)
|
||||||
.add("User-Agent", "Android")
|
.addHeader("Timestamp", timeSec.toString())
|
||||||
.add("Accept-Language", Locale.getDefault().toLanguageTag())
|
.addHeader("Sign", RequestUtil.getRequestSign(timeSec))
|
||||||
.add("Content-Type", "application/json")
|
.addHeader("DeviceId", DeviceUtil.generateDeviceId())
|
||||||
.add("Accept", "application/json")
|
.addHeader("authorazation", "Bearer xxxxx")
|
||||||
.add("Accept-Charset", "utf-8")
|
|
||||||
|
|
||||||
|
request = requestBuilder.build()
|
||||||
|
|
||||||
val headers = headersBuilder.build()
|
|
||||||
request = chain.request().newBuilder()
|
|
||||||
.headers(headers)
|
|
||||||
.build()
|
|
||||||
val response = chain.proceed(request)
|
val response = chain.proceed(request)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.gamedog.vididin.core.network.di
|
||||||
|
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.DeviceUtil
|
||||||
|
import com.gamedog.vididin.request.RequestUtil
|
||||||
|
import okhttp3.Headers
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import okhttp3.Response
|
||||||
|
import okhttp3.ResponseBody
|
||||||
|
import okhttp3.ResponseBody.Companion.asResponseBody
|
||||||
|
import okio.Buffer
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalInterceptor2 : Interceptor {
|
||||||
|
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
var request = chain.request()
|
||||||
|
val bodyStr = readBody(chain.request().body)
|
||||||
|
val emptyBody = "{}".toRequestBody("application/json;charset=utf-8".toMediaType())
|
||||||
|
val requestBody = if (bodyStr.isNotBlank()) request.body else emptyBody
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val requestBuilder = chain.request().newBuilder()
|
||||||
|
.addHeader("User-Agent", "Android")
|
||||||
|
.addHeader("Accept-Language", Locale.getDefault().toLanguageTag())
|
||||||
|
.addHeader("Content-Type", "application/json")
|
||||||
|
.addHeader("Accept", "application/json")
|
||||||
|
.addHeader("Accept-Charset", "utf-8")
|
||||||
|
// server real defined
|
||||||
|
.addHeader("ApplicationId", AndroidUtil.getPackageId())
|
||||||
|
.addHeader("DeviceId", DeviceUtil.generateDeviceId())
|
||||||
|
.addHeader("authorazation", "Bearer xxxxx")
|
||||||
|
|
||||||
|
request = requestBuilder.build()
|
||||||
|
|
||||||
|
val response = chain.proceed(request)
|
||||||
|
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
try {
|
||||||
|
val contentStr = clone(response.body)?.string()
|
||||||
|
Log.d("RetroLog" ,
|
||||||
|
"""
|
||||||
|
———————————————— 请求 Start ——————————————————————————————
|
||||||
|
${request.url}
|
||||||
|
******** 请求头 ${request.method} ********:
|
||||||
|
${getRequestHeadersString(request)}
|
||||||
|
******** 请求体(当post等时) ********:
|
||||||
|
${readBody(requestBody)}
|
||||||
|
******** 请求响应 ********:
|
||||||
|
$contentStr
|
||||||
|
———————————————— 请求 End ———————————————————————————————
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.d("RetroLog" , "GlobalInterceptor request.exception : ${e.localizedMessage}}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getRequestHeadersString(request: Request): String {
|
||||||
|
val headers = request.headers
|
||||||
|
val headerCount = headers.size
|
||||||
|
|
||||||
|
val sb = StringBuilder()
|
||||||
|
for (i in 0 until headerCount) {
|
||||||
|
val key = headers.name(i)
|
||||||
|
val value = headers.value(i)
|
||||||
|
sb.append("$key=$value\n")
|
||||||
|
}
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun readBody(body: RequestBody?): String {
|
||||||
|
val buffer = Buffer()
|
||||||
|
body?.writeTo(buffer)
|
||||||
|
return buffer.readUtf8()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun clone(body: ResponseBody?): ResponseBody? {
|
||||||
|
val source = body?.source()
|
||||||
|
if (source?.request(Long.MAX_VALUE) == true) throw IOException("body too long!")
|
||||||
|
val bufferedCopy = source?.buffer?.clone()
|
||||||
|
return bufferedCopy?.asResponseBody(body.contentType(), body.contentLength())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -45,7 +45,6 @@ internal object NetworkModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun providesRetrofit(
|
fun providesRetrofit(
|
||||||
networkJson: Json,
|
|
||||||
okhttpCallFactory: dagger.Lazy<Call.Factory>,
|
okhttpCallFactory: dagger.Lazy<Call.Factory>,
|
||||||
): Retrofit {
|
): Retrofit {
|
||||||
return Retrofit.Builder()
|
return Retrofit.Builder()
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,16 @@ import com.gamedog.vididin.core.router.interfaces.TaskRouter
|
||||||
import com.gamedog.vididin.features.benefit.BenefitRouter
|
import com.gamedog.vididin.features.benefit.BenefitRouter
|
||||||
import com.gamedog.vididin.features.winrecords.WinRecordRouter
|
import com.gamedog.vididin.features.winrecords.WinRecordRouter
|
||||||
import com.gamedog.vididin.features.withdraw.WithdrawRouter
|
import com.gamedog.vididin.features.withdraw.WithdrawRouter
|
||||||
|
import com.gamedog.vididin.features.withdraw.WithdrawSubRouter
|
||||||
import com.gamedog.vididin.features.zero.ZeroBuyRouter
|
import com.gamedog.vididin.features.zero.ZeroBuyRouter
|
||||||
import com.gamedog.vididin.router.IRouterFeedback
|
import com.gamedog.vididin.router.IRouterFeedback
|
||||||
|
import com.gamedog.vididin.router.IRouterGame
|
||||||
import com.gamedog.vididin.router.IRouterPrivacy
|
import com.gamedog.vididin.router.IRouterPrivacy
|
||||||
import com.gamedog.vididin.router.IRouterSplash
|
import com.gamedog.vididin.router.IRouterSplash
|
||||||
import com.gamedog.vididin.router.IRouterVersion
|
import com.gamedog.vididin.router.IRouterVersion
|
||||||
import com.gamedog.vididin.router.IRouterWithdrawRecord
|
import com.gamedog.vididin.router.IRouterWithdrawRecord
|
||||||
|
import com.gamedog.vididin.router.IRouterWatchAd
|
||||||
|
import com.gamedog.vididin.router.MainRouter
|
||||||
import dagger.hilt.EntryPoint
|
import dagger.hilt.EntryPoint
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
|
@ -30,14 +34,18 @@ interface RouterEntryPoint {
|
||||||
fun benefitRouter(): BenefitRouter
|
fun benefitRouter(): BenefitRouter
|
||||||
fun zeroBuyRouter(): ZeroBuyRouter
|
fun zeroBuyRouter(): ZeroBuyRouter
|
||||||
fun withdrawRouter(): WithdrawRouter
|
fun withdrawRouter(): WithdrawRouter
|
||||||
|
fun withdrawSubRouter(): WithdrawSubRouter
|
||||||
fun winRecordBuyRouter(): WinRecordRouter
|
fun winRecordBuyRouter(): WinRecordRouter
|
||||||
|
fun mainRouter(): MainRouter
|
||||||
|
|
||||||
|
|
||||||
fun privacyRouter(): IRouterPrivacy
|
fun privacyRouter(): IRouterPrivacy
|
||||||
|
fun GameRouter(): IRouterGame
|
||||||
fun versionRouter(): IRouterVersion
|
fun versionRouter(): IRouterVersion
|
||||||
fun feedbackRouter(): IRouterFeedback
|
fun feedbackRouter(): IRouterFeedback
|
||||||
fun splashRouter(): IRouterSplash
|
fun splashRouter(): IRouterSplash
|
||||||
fun withdrawRecordRouter(): IRouterWithdrawRecord
|
fun withdrawRecordRouter(): IRouterWithdrawRecord
|
||||||
|
fun watchAdRouter(): IRouterWatchAd
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,35 @@ package com.gamedog.vididin.features.benefit
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.LinearLayout
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import com.ama.core.architecture.appBase.AppViewsActivity
|
import com.ama.core.architecture.appBase.AppViewsActivity
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.ama.core.architecture.util.eventbus.NotifyMan
|
||||||
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.gamedog.vididin.VididinEvents
|
||||||
|
import com.gamedog.vididin.features.benefit.widget.BenefitTaskItemView
|
||||||
|
import com.gamedog.vididin.main.fragments.task.DailySignDialog
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
||||||
|
import com.gamedog.vididin.manager.TaskManager
|
||||||
|
import com.gamedog.vididin.manager.TaskManager.Companion.BOX_SUB_TASK_TYPE_AD
|
||||||
|
import com.gamedog.vididin.manager.TaskManager.Companion.BOX_SUB_TASK_TYPE_VIDEO
|
||||||
|
import com.gamedog.vididin.manager.TaskManager.Companion.BOX_SUB_TASK_TYPE_SIGN
|
||||||
|
import com.gamedog.vididin.manager.TaskManager.Companion.BOX_SUB_TASK_TYPE_ZERO_BUY
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import kotlin.getValue
|
||||||
import com.gamedog.vididin.databinding.ActivityBenefitBinding as ViewBinding
|
import com.gamedog.vididin.manager.taskbeans.BaseTaskState.Companion.STATE_FINISH
|
||||||
|
import com.gamedog.vididin.manager.taskbeans.BaseTaskState.Companion.STATE_CLAIMED
|
||||||
|
import com.gamedog.vididin.manager.taskbeans.BaseTaskState.Companion.STATE_EXPIRED
|
||||||
|
import com.gamedog.vididin.router.Router
|
||||||
|
import com.viddin.videos.free.databinding.ActivityBenefitBinding as ViewBinding
|
||||||
import com.gamedog.vididin.main.MainUiState as UiState
|
import com.gamedog.vididin.main.MainUiState as UiState
|
||||||
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
||||||
|
|
||||||
|
|
@ -16,6 +38,8 @@ import com.gamedog.vididin.main.MainViewModel as ViewModel
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class BenefitActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
class BenefitActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
||||||
|
|
||||||
|
private val mSubTaskViewList = mutableListOf<BenefitTaskItemView>()
|
||||||
|
|
||||||
|
|
||||||
override val mViewModel: ViewModel by viewModels()
|
override val mViewModel: ViewModel by viewModels()
|
||||||
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
||||||
|
|
@ -26,21 +50,35 @@ class BenefitActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnT
|
||||||
|
|
||||||
|
|
||||||
override fun ViewBinding.initViews() {
|
override fun ViewBinding.initViews() {
|
||||||
|
titlebar.setTitleText(R.string.benefit)
|
||||||
taskItem1.setActionFun {
|
initViewsByTaskState()
|
||||||
gotoWatchVideo()
|
|
||||||
}
|
|
||||||
taskItem2.setActionFun {
|
|
||||||
gotoWatchVideo()
|
|
||||||
}
|
|
||||||
taskItem3.setActionFun {
|
|
||||||
gotoWatchVideo()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
val boxStatus = TaskManager.instance().boxTaskStatus()
|
||||||
|
val curSubBoxState = boxStatus.getCurrentBoxState()
|
||||||
|
val subTaskCount = curSubBoxState!!.tasks.size
|
||||||
|
val reward = curSubBoxState.reward_value
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Welfare_Show, mapOf(
|
||||||
|
"total_amount" to reward,
|
||||||
|
"chest_count" to subTaskCount,
|
||||||
|
"task_type" to boxStatus.getCurrentBoxIndex().toString(),
|
||||||
|
"task_progress" to boxStatus.getCurrentBoxTotalProgress(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun ViewBinding.initListeners() {
|
override fun ViewBinding.initListeners() {
|
||||||
|
registerEvents({ data->
|
||||||
|
when (data?.mEventType) {
|
||||||
|
VididinEvents.EVENT_BOX_TASK_STATE_CHANGED -> {
|
||||||
|
updateUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, VididinEvents.EVENT_BOX_TASK_STATE_CHANGED)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initObservers() {
|
override fun ViewBinding.initObservers() {
|
||||||
|
|
@ -56,10 +94,188 @@ class BenefitActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
private fun initViewsByTaskState() {
|
||||||
//TODO("Not yet implemented")
|
initAddSubTaskViews()
|
||||||
|
updateSubTasksUI()
|
||||||
|
updateTopBoxesUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateUI() {
|
||||||
|
updateSubTasksUI()
|
||||||
|
updateTopBoxesUI()
|
||||||
|
binding.counterdownTv.restartTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initAddSubTaskViews() {
|
||||||
|
val taskStateHelper = TaskManager.instance().boxTaskStatus()
|
||||||
|
var subTaskIndex = taskStateHelper.getCurrentBoxIndex()
|
||||||
|
if (subTaskIndex >= 0) {
|
||||||
|
val currentBoxState = taskStateHelper.getStatusBean().boxList[subTaskIndex]
|
||||||
|
currentBoxState.tasks.forEachIndexed { index, subTask ->
|
||||||
|
val separateLine = View(this@BenefitActivity)
|
||||||
|
separateLine.setBackgroundResource(R.color.gray_f2)
|
||||||
|
binding.llSubTaskContainer.addView(separateLine, ViewGroup.LayoutParams.MATCH_PARENT, ResUtil.getPixelSize(R.dimen.dp1))
|
||||||
|
|
||||||
|
val subTaskView = BenefitTaskItemView(this@BenefitActivity)
|
||||||
|
subTaskView.setActionFun { handleActionButClicked(subTask.task_type) }
|
||||||
|
val subViewParam = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
subViewParam.topMargin = ResUtil.getPixelSize(R.dimen.dp10)
|
||||||
|
subViewParam.bottomMargin = ResUtil.getPixelSize(R.dimen.dp10)
|
||||||
|
binding.llSubTaskContainer.addView(subTaskView, subViewParam)
|
||||||
|
|
||||||
|
mSubTaskViewList.add(subTaskView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleActionButClicked(taskType: Int) {
|
||||||
|
when (taskType) {
|
||||||
|
BOX_SUB_TASK_TYPE_AD -> {
|
||||||
|
Router.WatchAd.startActivity(this@BenefitActivity, VidiConst.WATCH_AD_FOR_BOX_TASK)
|
||||||
|
}
|
||||||
|
|
||||||
|
BOX_SUB_TASK_TYPE_SIGN -> {
|
||||||
|
DailySignDialog(this@BenefitActivity).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
BOX_SUB_TASK_TYPE_VIDEO -> {
|
||||||
|
finish()
|
||||||
|
NotifyMan.instance().sendEvent(VididinEvents.EVENT_JUMP_2_VIDEO, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
BOX_SUB_TASK_TYPE_ZERO_BUY -> {
|
||||||
|
Router.ZeroBuy.startActivity(this@BenefitActivity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateSubTasksUI() {
|
||||||
|
val taskStateHelper = TaskManager.instance().boxTaskStatus()
|
||||||
|
val currentBoxIndex = taskStateHelper.getCurrentBoxIndex()
|
||||||
|
val subTaskStateList = taskStateHelper.getStatusBean().boxList[currentBoxIndex].tasks
|
||||||
|
|
||||||
|
if (subTaskStateList.size == mSubTaskViewList.size) {
|
||||||
|
mSubTaskViewList.forEachIndexed { index, view ->
|
||||||
|
view.updateUIByState(subTaskStateList[index], currentBoxIndex,index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateTopBoxesUI() {
|
||||||
|
val taskStateHelper = TaskManager.instance().boxTaskStatus()
|
||||||
|
val boxStateList = taskStateHelper.getStatusBean().boxList
|
||||||
|
|
||||||
|
with (binding) {
|
||||||
|
boxStateList.forEachIndexed { index, curBoxState ->
|
||||||
|
val stateEnum = taskStateHelper.getBoxStateEnum(index)
|
||||||
|
if (index == 0) {
|
||||||
|
ivSubtask1.setImageResource(getIconResByState(stateEnum))
|
||||||
|
tvSubtask1State.setText(getStrResByState(stateEnum))
|
||||||
|
tvSubtask1State.setTextColor(getStrColorByState(stateEnum))
|
||||||
|
|
||||||
|
with (tvSubtask1Reward) {
|
||||||
|
compoundDrawablePadding = if (stateEnum == STATE_CLAIMED) 0 else ResUtil.getPixelSize(R.dimen.dp3)
|
||||||
|
val tvRewardIcon = getRewardTvDrawableRes(stateEnum)
|
||||||
|
setCompoundDrawablesWithIntrinsicBounds(ResUtil.getDrawable(tvRewardIcon), null, null, null)
|
||||||
|
val needShowNum = R.mipmap.icon_check_mark != tvRewardIcon
|
||||||
|
setText(if (needShowNum) { ResUtil.getString(R.string.cash) + " " + curBoxState.reward_value} else "")
|
||||||
|
//setText(ResUtil.getString(R.string.cash) + " " + curBoxState.reward_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == 1) {
|
||||||
|
ivSubtask2.setImageResource(getIconResByState(stateEnum))
|
||||||
|
tvSubtask2State.setText(getStrResByState(stateEnum))
|
||||||
|
tvSubtask2State.setTextColor(getStrColorByState(stateEnum))
|
||||||
|
|
||||||
|
with (tvSubtask2Reward) {
|
||||||
|
compoundDrawablePadding = if (stateEnum == STATE_FINISH || stateEnum == STATE_CLAIMED) 0 else ResUtil.getPixelSize(R.dimen.dp3)
|
||||||
|
val tvRewardIcon = getRewardTvDrawableRes(stateEnum)
|
||||||
|
setCompoundDrawablesWithIntrinsicBounds(ResUtil.getDrawable(tvRewardIcon), null, null, null)
|
||||||
|
val needShowNum = R.mipmap.icon_check_mark != tvRewardIcon
|
||||||
|
setText(if (needShowNum) { ResUtil.getString(R.string.cash) + " " + curBoxState.reward_value} else "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == 2) {
|
||||||
|
ivSubtask3.setImageResource(getIconResByState(stateEnum))
|
||||||
|
tvSubtask3State.setText(getStrResByState(stateEnum))
|
||||||
|
tvSubtask3State.setTextColor(getStrColorByState(stateEnum))
|
||||||
|
|
||||||
|
with (tvSubtask3Reward) {
|
||||||
|
compoundDrawablePadding = if (stateEnum == STATE_FINISH || stateEnum == STATE_CLAIMED) 0 else ResUtil.getPixelSize(R.dimen.dp3)
|
||||||
|
val tvRewardIcon = getRewardTvDrawableRes(stateEnum)
|
||||||
|
setCompoundDrawablesWithIntrinsicBounds(ResUtil.getDrawable(tvRewardIcon), null, null, null)
|
||||||
|
val needShowNum = R.mipmap.icon_check_mark != tvRewardIcon
|
||||||
|
setText(if (needShowNum) { ResUtil.getString(R.string.cash) + " " + curBoxState.reward_value} else "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val couldClaimCashNum = taskStateHelper.getCouldClaimCashNum()
|
||||||
|
with (tvResgatar) {
|
||||||
|
if (couldClaimCashNum > 0) {
|
||||||
|
setBackgroundResource(R.mipmap.bg_but_green_long)
|
||||||
|
isClickable = true
|
||||||
|
} else {
|
||||||
|
setBackgroundResource(R.mipmap.but_bg_grady)
|
||||||
|
isClickable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
setOnClickListener {
|
||||||
|
if (taskStateHelper.executeClaimCash()) {
|
||||||
|
//AndroidUtil.showToast(String.format(ResUtil.getString(R.string.has_claim_box_cash_hint), couldClaimCashNum))
|
||||||
|
AndroidUtil.showCustomToast(String.format(ResUtil.getString(R.string.has_claim_box_cash_hint), couldClaimCashNum))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 总进度条, 奖励金额
|
||||||
|
val totalProgress = taskStateHelper.getCurrentBoxTotalProgress()
|
||||||
|
progressTasks.setProgress(totalProgress)
|
||||||
|
tvProgressNum.text = "($totalProgress%)"
|
||||||
|
tvHintRewardNum.text = buildString {
|
||||||
|
append(ResUtil.getString(R.string.cash))
|
||||||
|
append(" ")
|
||||||
|
append(taskStateHelper.getStatusBean().boxList[taskStateHelper.getCurrentBoxIndex()].reward_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getIconResByState(state: Int): Int {
|
||||||
|
when (state) {
|
||||||
|
STATE_EXPIRED -> return R.mipmap.benefit_item_expired
|
||||||
|
STATE_FINISH, STATE_CLAIMED -> return R.mipmap.benefit_item_finished
|
||||||
|
else -> return R.mipmap.benefit_item_ongoing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getStrResByState(state: Int): Int {
|
||||||
|
when (state) {
|
||||||
|
STATE_EXPIRED -> return R.string.expired
|
||||||
|
STATE_FINISH, STATE_CLAIMED -> return R.string.finished
|
||||||
|
else -> return R.string.ongoing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getStrColorByState(state: Int): Int {
|
||||||
|
when (state) {
|
||||||
|
STATE_EXPIRED -> return R.color.gray_60
|
||||||
|
STATE_FINISH, STATE_CLAIMED -> return R.color.green_39
|
||||||
|
else -> return R.color.red_5c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getRewardTvDrawableRes(state: Int): Int {
|
||||||
|
when (state) {
|
||||||
|
STATE_EXPIRED -> return R.mipmap.icon_cash_s_disable
|
||||||
|
STATE_CLAIMED -> return R.mipmap.icon_check_mark
|
||||||
|
else -> return R.mipmap.icon_cash_s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@ import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
import com.gamedog.vididin.databinding.BenefitTaskItemViewBinding
|
import com.viddin.videos.free.R
|
||||||
|
import com.viddin.videos.free.databinding.BenefitTaskItemViewBinding
|
||||||
|
import com.gamedog.vididin.manager.TaskManager
|
||||||
|
import com.gamedog.vididin.manager.taskbeans.TaskStateBoxSub
|
||||||
|
|
||||||
|
|
||||||
class BenefitTaskItemView @JvmOverloads constructor(
|
class BenefitTaskItemView @JvmOverloads constructor(
|
||||||
|
|
@ -40,11 +43,44 @@ class BenefitTaskItemView @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun setProgressInfo(progress: String) {
|
fun updateUIByState(subTaskState: TaskStateBoxSub, boxIndex: Int, subTaskIndex: Int) {
|
||||||
mBinding.tvProgressInfo.text = progress
|
with (mBinding) {
|
||||||
|
val finishNum = if (subTaskState.finishedNum > subTaskState.required_count) subTaskState.required_count else subTaskState.finishedNum
|
||||||
|
val progressNum: Int = finishNum * 100 / subTaskState.required_count
|
||||||
|
|
||||||
|
var iconRes = R.mipmap.icon_video_task
|
||||||
|
when(subTaskState.task_type) {
|
||||||
|
1 -> { // ad
|
||||||
|
iconRes = R.mipmap.icon_ad
|
||||||
|
}
|
||||||
|
2-> { // video
|
||||||
|
iconRes = R.mipmap.icon_video_task
|
||||||
|
}
|
||||||
|
3 -> { // sign
|
||||||
|
iconRes = R.mipmap.icon_calendar
|
||||||
|
}
|
||||||
|
4-> { // zeroBuy
|
||||||
|
iconRes = R.mipmap.task_act_convi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ivItemIcon.setImageResource(iconRes)
|
||||||
|
tvItemTitle.setText(TaskManager.instance().boxTaskStatus().getSubTaskHintStrRes(boxIndex, subTaskIndex))
|
||||||
|
progressBar.setProgress(progressNum)
|
||||||
|
tvProgressInfo.text = "($finishNum/${subTaskState.required_count})"
|
||||||
|
|
||||||
|
with (tvAction) {
|
||||||
|
if (progressNum < 100) {
|
||||||
|
isClickable = true
|
||||||
|
setBackgroundResource( R.drawable.bg_benefit_item_action_bg)
|
||||||
|
setText(R.string.go_and_do)
|
||||||
|
} else {
|
||||||
|
isClickable = false
|
||||||
|
setBackgroundResource( R.drawable.bg_sub_task_disable)
|
||||||
|
setText(R.string.finished)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.gamedog.vididin.features.benefit.widget
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.CountDownTimer
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import com.ama.core.architecture.util.DateUtil
|
||||||
|
import com.gamedog.vididin.manager.TaskManager
|
||||||
|
import com.viddin.videos.free.databinding.BenefitCountdownTimerViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
class CounterDownTimerView @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||||
|
private lateinit var mTimer: CountDownTimer
|
||||||
|
private var mBinding: BenefitCountdownTimerViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
mBinding = BenefitCountdownTimerViewBinding.inflate(LayoutInflater.from(context), this, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAttachedToWindow() {
|
||||||
|
super.onAttachedToWindow()
|
||||||
|
startTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startTimer() {
|
||||||
|
val startMs = TaskManager.instance().boxTaskStatus().getCurrentBoxStartTimeMs()
|
||||||
|
val totalMs = TaskManager.instance().boxTaskStatus().getCurrentBoxTotalDurationMs()
|
||||||
|
|
||||||
|
val restMs = startMs + totalMs - System.currentTimeMillis()
|
||||||
|
|
||||||
|
mTimer = object : CountDownTimer(restMs, 1000) {
|
||||||
|
override fun onTick(millisUntilFinished: Long) {
|
||||||
|
val resultList = DateUtil.formatMs2HMS(millisUntilFinished)
|
||||||
|
mBinding.tvHour.text = resultList[0].toString()
|
||||||
|
mBinding.tvMin.text = resultList[1].toString()
|
||||||
|
mBinding.tvSecond.text = resultList[2].toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinish() {
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun restartTimer() {
|
||||||
|
if (mTimer != null) {
|
||||||
|
mTimer.cancel()
|
||||||
|
}
|
||||||
|
startTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromWindow() {
|
||||||
|
super.onDetachedFromWindow()
|
||||||
|
if (mTimer != null) {
|
||||||
|
mTimer.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -8,11 +8,14 @@ import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import com.ama.core.architecture.appBase.AppViewsActivity
|
import com.ama.core.architecture.appBase.AppViewsActivity
|
||||||
import com.gamedog.vididin.R
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.viddin.videos.free.R
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import kotlin.getValue
|
||||||
import com.gamedog.vididin.databinding.ActivityFeedbackBinding as ViewBinding
|
import com.viddin.videos.free.databinding.ActivityFeedbackBinding as ViewBinding
|
||||||
import com.gamedog.vididin.main.MainUiState as UiState
|
import com.gamedog.vididin.main.MainUiState as UiState
|
||||||
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
||||||
|
|
||||||
|
|
@ -30,6 +33,14 @@ class FeedbackActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), On
|
||||||
titleBar.setTitleText(R.string.feedback, R.color.black)
|
titleBar.setTitleText(R.string.feedback, R.color.black)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setOnClickBatch(ivDiscord) {
|
||||||
|
when(this) {
|
||||||
|
ivDiscord -> {
|
||||||
|
AndroidUtil.openUrl(VidiConst.URL_DISCORD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initWindowInsets() {
|
override fun ViewBinding.initWindowInsets() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,299 @@
|
||||||
|
package com.gamedog.vididin.features.game
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.webkit.JavascriptInterface
|
||||||
|
import android.webkit.WebResourceRequest
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
|
import androidx.activity.addCallback
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.ama.core.architecture.BaseApp
|
||||||
|
import com.ama.core.architecture.appBase.AppViewsActivity
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import com.gamedog.vididin.main.MainUiState as UiState
|
||||||
|
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
||||||
|
import com.viddin.videos.free.databinding.ActivityGameBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class GameCenterActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
||||||
|
|
||||||
|
override val mViewModel: ViewModel by viewModels()
|
||||||
|
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
||||||
|
override var mEnableBannerAd = false
|
||||||
|
private var mHasSendStatistic: Boolean = false
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
|
override fun ViewBinding.initViews() {
|
||||||
|
showLoading(false)
|
||||||
|
|
||||||
|
with(binding) {
|
||||||
|
titlebar.setBackIconColor(R.color.black)
|
||||||
|
titlebar.setTitleText(R.string.game_center, R.color.black)
|
||||||
|
|
||||||
|
|
||||||
|
onBackPressedDispatcher.addCallback(this@GameCenterActivity) {
|
||||||
|
if (webView.canGoBack()) {
|
||||||
|
webView.goBack()
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
with(webView) {
|
||||||
|
settings.javaScriptEnabled = true
|
||||||
|
webView.addJavascriptInterface(WebAppInterface(this@GameCenterActivity, webView), "com.viddin.videos.free")
|
||||||
|
|
||||||
|
webViewClient = object : WebViewClient() {
|
||||||
|
override fun onPageFinished(view: WebView?, url: String?) {
|
||||||
|
super.onPageFinished(view, url)
|
||||||
|
if (!mHasSendStatistic) {
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_H5_Show)
|
||||||
|
mHasSendStatistic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun shouldOverrideUrlLoading(
|
||||||
|
view: WebView?,
|
||||||
|
request: WebResourceRequest
|
||||||
|
): Boolean {
|
||||||
|
request.url?.let { url ->
|
||||||
|
if (!request.url.toString().startsWith("intent")) {
|
||||||
|
view?.loadUrl(url.toString())
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
handleIntentUrl(url.toString())
|
||||||
|
return true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Deprecated("For API level < 24")
|
||||||
|
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
|
||||||
|
if (!url.isNullOrBlank() && !url.startsWith("intent")) {
|
||||||
|
view?.loadUrl(url)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
loadGameCenterWeb()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private fun loadGameCenterWeb() {
|
||||||
|
var gaid: String? = ""
|
||||||
|
|
||||||
|
showLoading(false)
|
||||||
|
lifecycleScope.launch {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
gaid = AndroidUtil.getGaid()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gaid.isNullOrBlank()) {
|
||||||
|
binding.webView.loadUrl(String.format(VidiConst.URL_GAME, gaid))
|
||||||
|
hideLoading()
|
||||||
|
} else {
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun ViewBinding.initWindowInsets() {
|
||||||
|
setImmerseRootView(contentRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initListeners() {
|
||||||
|
//TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initObservers() {
|
||||||
|
//TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
|
||||||
|
//TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTabIsDarkFont(isDarkFont: Boolean) {
|
||||||
|
//TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleIntentUrl(url: String) {
|
||||||
|
var intent: Intent? = null
|
||||||
|
if (url.startsWith("intent")) {
|
||||||
|
intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intent != null) {
|
||||||
|
if (isHw()) {
|
||||||
|
intent.setPackage(getDefaultBrowser())
|
||||||
|
}
|
||||||
|
intent.addCategory(Intent.CATEGORY_BROWSABLE)
|
||||||
|
intent.setComponent(null)
|
||||||
|
intent.setFlags(FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
}
|
||||||
|
this.startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isHw(): Boolean {
|
||||||
|
return "huawei".equals(Build.MANUFACTURER, ignoreCase = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDefaultBrowser(): String? {
|
||||||
|
var packageName: String? = null
|
||||||
|
var systemApp: String? = null
|
||||||
|
var userApp: String? = null
|
||||||
|
val userAppList: MutableList<String?> = ArrayList<String?>()
|
||||||
|
val context: Context = BaseApp.appContext()
|
||||||
|
val browserIntent = Intent("android.intent.action.VIEW", Uri.parse("https://"))
|
||||||
|
val resolveInfo = context.getPackageManager()
|
||||||
|
.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY)
|
||||||
|
if (resolveInfo != null && resolveInfo.activityInfo != null) {
|
||||||
|
packageName = resolveInfo.activityInfo.packageName
|
||||||
|
}
|
||||||
|
if (packageName == null || packageName == "android") {
|
||||||
|
val lists = context.getPackageManager().queryIntentActivities(browserIntent, 0)
|
||||||
|
for (app in lists) {
|
||||||
|
if ((app.activityInfo.flags and ApplicationInfo.FLAG_SYSTEM) != 0) {
|
||||||
|
systemApp = app.activityInfo.packageName
|
||||||
|
} else {
|
||||||
|
userApp = app.activityInfo.packageName
|
||||||
|
userAppList.add(userApp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (userAppList.contains("com.android.chrome")) {
|
||||||
|
packageName = "com.android.chrome"
|
||||||
|
} else {
|
||||||
|
if (systemApp != null) {
|
||||||
|
packageName = systemApp
|
||||||
|
}
|
||||||
|
if (userApp != null) {
|
||||||
|
packageName = userApp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return packageName
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal fun startActivity(activity: Activity) {
|
||||||
|
activity.startActivity(Intent(activity.applicationContext, GameCenterActivity::class.java))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class WebAppInterface(private val context: Activity, private val webView: WebView) {
|
||||||
|
@JavascriptInterface
|
||||||
|
fun openBrowser(url: String) {
|
||||||
|
try {
|
||||||
|
var intent: Intent? = null
|
||||||
|
if (url.startsWith("intent")) {
|
||||||
|
intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME)
|
||||||
|
} else {
|
||||||
|
intent = Intent("android.intent.action.VIEW", Uri.parse(url))
|
||||||
|
}
|
||||||
|
if (intent != null) {
|
||||||
|
if (isHw()) {
|
||||||
|
intent.setPackage(getDefaultBrowser())
|
||||||
|
}
|
||||||
|
intent.addCategory(Intent.CATEGORY_BROWSABLE)
|
||||||
|
intent.setComponent(null)
|
||||||
|
intent.setFlags(FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
}
|
||||||
|
context.startActivity(intent)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//点击互动广告关闭按钮时调用该方法。
|
||||||
|
@JavascriptInterface
|
||||||
|
fun close() {
|
||||||
|
//TODO close the ad page or activity.
|
||||||
|
}
|
||||||
|
|
||||||
|
//接入Gspace-Fully广告时需实现此方法。该方法用于打开新的Webview页面。
|
||||||
|
@JavascriptInterface
|
||||||
|
fun openWebview(url: String?) {
|
||||||
|
//TODO open a new page to display landingpage.
|
||||||
|
//TODO 使用展示GSpace的Activity新实例打开当前url.
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isHw(): Boolean {
|
||||||
|
return "huawei".equals(Build.MANUFACTURER, ignoreCase = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDefaultBrowser(): String? {
|
||||||
|
var packageName: String? = null
|
||||||
|
var systemApp: String? = null
|
||||||
|
var userApp: String? = null
|
||||||
|
val userAppList: MutableList<String?> = ArrayList<String?>()
|
||||||
|
val context: Context = BaseApp.appContext()
|
||||||
|
val browserIntent = Intent("android.intent.action.VIEW", Uri.parse("https://"))
|
||||||
|
val resolveInfo = context.getPackageManager()
|
||||||
|
.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY)
|
||||||
|
if (resolveInfo != null && resolveInfo.activityInfo != null) {
|
||||||
|
packageName = resolveInfo.activityInfo.packageName
|
||||||
|
}
|
||||||
|
if (packageName == null || packageName == "android") {
|
||||||
|
val lists = context.getPackageManager().queryIntentActivities(browserIntent, 0)
|
||||||
|
for (app in lists) {
|
||||||
|
if ((app.activityInfo.flags and ApplicationInfo.FLAG_SYSTEM) != 0) {
|
||||||
|
systemApp = app.activityInfo.packageName
|
||||||
|
} else {
|
||||||
|
userApp = app.activityInfo.packageName
|
||||||
|
userAppList.add(userApp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (userAppList.contains("com.android.chrome")) {
|
||||||
|
packageName = "com.android.chrome"
|
||||||
|
} else {
|
||||||
|
if (systemApp != null) {
|
||||||
|
packageName = systemApp
|
||||||
|
}
|
||||||
|
if (userApp != null) {
|
||||||
|
packageName = userApp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return packageName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,15 +4,13 @@ import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import androidx.core.view.updatePadding
|
|
||||||
import com.ama.core.architecture.appBase.AppViewsActivity
|
import com.ama.core.architecture.appBase.AppViewsActivity
|
||||||
import com.gamedog.vididin.R
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.viddin.videos.free.R
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import kotlin.getValue
|
||||||
import com.gamedog.vididin.databinding.ActivityPrivacyBinding as ViewBinding
|
import com.viddin.videos.free.databinding.ActivityPrivacyBinding as ViewBinding
|
||||||
import com.gamedog.vididin.main.MainUiState as UiState
|
import com.gamedog.vididin.main.MainUiState as UiState
|
||||||
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
||||||
|
|
||||||
|
|
@ -28,17 +26,14 @@ class PrivacyActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnT
|
||||||
with(binding) {
|
with(binding) {
|
||||||
titlebar.setBackIconColor(R.color.black)
|
titlebar.setBackIconColor(R.color.black)
|
||||||
titlebar.setTitleText(R.string.privacy, R.color.black)
|
titlebar.setTitleText(R.string.privacy, R.color.black)
|
||||||
|
|
||||||
|
webView.loadUrl(VidiConst.URL_PRIVACY)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initWindowInsets() {
|
override fun ViewBinding.initWindowInsets() {
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(contentRoot) { v, insets ->
|
setImmerseRootView(contentRoot)
|
||||||
val systemBars =
|
|
||||||
insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
|
|
||||||
v.updatePadding(top = systemBars.top)
|
|
||||||
insets
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initListeners() {
|
override fun ViewBinding.initListeners() {
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,210 @@
|
||||||
package com.gamedog.vididin.features.splash
|
package com.gamedog.vididin.features.splash
|
||||||
|
|
||||||
|
import android.animation.ObjectAnimator
|
||||||
|
import android.animation.ValueAnimator
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.PersistableBundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.viewModels
|
import android.view.animation.LinearInterpolator
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelActivity
|
||||||
import androidx.core.view.updatePadding
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
import com.ama.core.architecture.appBase.AppViewsActivity
|
|
||||||
import com.gamedog.vididin.R
|
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
||||||
|
import com.gamedog.vididin.router.Router
|
||||||
|
import com.remax.base.report.DataReportManager
|
||||||
|
import com.remax.bill.ads.AdResult
|
||||||
|
import com.remax.bill.ads.PreloadController
|
||||||
|
import com.remax.bill.ads.bidding.AppOpenBiddingInitializer
|
||||||
|
import com.remax.bill.ads.config.AdConfigManager
|
||||||
|
import com.remax.bill.ads.ext.AdShowExt
|
||||||
|
import com.remax.bill.ads.log.AdLogger
|
||||||
|
import com.viddin.videos.free.R
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import kotlinx.coroutines.async
|
||||||
import com.gamedog.vididin.databinding.ActivitySplashBinding as ViewBinding
|
import kotlinx.coroutines.delay
|
||||||
import com.gamedog.vididin.main.MainUiState as UiState
|
import kotlinx.coroutines.launch
|
||||||
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
import kotlin.math.ceil
|
||||||
|
import com.viddin.videos.free.databinding.ActivitySplashBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class SplashActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
class SplashActivity : AppViewsEmptyViewModelActivity<ViewBinding>(), OnTabStyleListener {
|
||||||
|
|
||||||
|
private var mHasGotoMain: Boolean = false
|
||||||
|
private var mStartMs: Long = 0L
|
||||||
|
private var isAdShowSuccess = false
|
||||||
|
private var startTime = 0L
|
||||||
|
|
||||||
override val mViewModel: ViewModel by viewModels()
|
|
||||||
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
||||||
|
|
||||||
override fun ViewBinding.initViews() {
|
override var mEnableBannerAd = false
|
||||||
with(binding) {
|
|
||||||
|
|
||||||
|
override fun ViewBinding.initViews() {
|
||||||
|
startTime = System.currentTimeMillis()
|
||||||
|
|
||||||
|
with(binding) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
mStartMs = System.currentTimeMillis()
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Loading_Start, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Loading_End, mapOf("Time" to (System.currentTimeMillis() - mStartMs)/1000))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initWindowInsets() {
|
override fun ViewBinding.initWindowInsets() {
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(contentRoot) { v, insets ->
|
setImmerseRootView(contentRoot)
|
||||||
val systemBars =
|
|
||||||
insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
|
|
||||||
v.updatePadding(top = systemBars.top)
|
|
||||||
insets
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initListeners() {
|
override fun ViewBinding.initListeners() {
|
||||||
//TODO("Not yet implemented")
|
startJumpTimer()
|
||||||
|
startLoadingAnim()
|
||||||
|
initializeApp()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initObservers() {
|
override fun ViewBinding.initObservers() {
|
||||||
//TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
|
|
||||||
//TODO("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabIsDarkFont(isDarkFont: Boolean) {
|
override fun onTabIsDarkFont(isDarkFont: Boolean) {
|
||||||
//TODO("Not yet implemented")
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startJumpTimer() {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
delay(MAX_SPLASH_TIME)
|
||||||
|
gotoMain(!isAdShowSuccess)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializeApp() {
|
||||||
|
lifecycleScope.launch() {
|
||||||
|
try {
|
||||||
|
val adMobInitDeferred = async { initializeAd() }
|
||||||
|
val adMobResult = adMobInitDeferred.await()
|
||||||
|
|
||||||
|
// 处理AdMob初始化结果
|
||||||
|
when (adMobResult) {
|
||||||
|
is AdResult.Success -> {
|
||||||
|
// 2. 加载开屏广告
|
||||||
|
showAppOpenAd()
|
||||||
|
}
|
||||||
|
|
||||||
|
is AdResult.Failure -> {
|
||||||
|
AdLogger.e("AdMob SDK初始化失败: ${adMobResult.error.message}")
|
||||||
|
// 初始化失败,延迟后直接跳转
|
||||||
|
delayAndJumpToMain(isAdShowSuccess)
|
||||||
|
}
|
||||||
|
|
||||||
|
AdResult.Loading -> {
|
||||||
|
AdLogger.d("AdMob SDK初始化中...")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
AdLogger.e("应用初始化异常", e)
|
||||||
|
delayAndJumpToMain(isAdShowSuccess)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private suspend fun initializeAd(): AdResult<Unit> {
|
||||||
|
return AppOpenBiddingInitializer.initialize(this@SplashActivity, R.mipmap.ic_launcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private suspend fun showAppOpenAd() {
|
||||||
|
when (val result = AdShowExt.showAppOpenAd(this@SplashActivity) { loaded ->
|
||||||
|
PreloadController.preload(this)
|
||||||
|
PreloadController.preloadPangle(this)
|
||||||
|
PreloadController.preloadTopOn(this)
|
||||||
|
DataReportManager.reportData(
|
||||||
|
"loading_page_end", mapOf(
|
||||||
|
"pass_time" to ceil((System.currentTimeMillis() - startTime) / 1000.0).toInt()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
is AdResult.Success -> {
|
||||||
|
isAdShowSuccess = true
|
||||||
|
delayAndJumpToMain(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
is AdResult.Failure -> {
|
||||||
|
AdLogger.e("开屏广告显示失败: ${result.error.message}")
|
||||||
|
// 开屏失败尝试展示插页
|
||||||
|
if (AdConfigManager.shouldShowInterstitialAfterAppOpenFailure()) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
try {
|
||||||
|
when (val interstitialResult = AdShowExt.showInterstitialAd(this@SplashActivity, "splash")) {
|
||||||
|
is AdResult.Success -> {
|
||||||
|
delayAndJumpToMain(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
is AdResult.Failure -> {
|
||||||
|
delayAndJumpToMain(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
AdResult.Loading -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
delayAndJumpToMain(isAdShowSuccess)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
delayAndJumpToMain(isAdShowSuccess)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AdResult.Loading -> {
|
||||||
|
AdLogger.d("开屏广告显示中...")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun delayAndJumpToMain(needShowSplashAd: Boolean) {
|
||||||
|
val elapsedTime = System.currentTimeMillis() - startTime
|
||||||
|
val remainingTime = MIN_SPLASH_TIME - elapsedTime
|
||||||
|
|
||||||
|
if (remainingTime > 0) {
|
||||||
|
delay(remainingTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
gotoMain(needShowSplashAd)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun gotoMain(needShowSplashAd: Boolean) {
|
||||||
|
if (!mHasGotoMain) {
|
||||||
|
mHasGotoMain = true
|
||||||
|
Router.Main.startActivity(this@SplashActivity, needShowSplashAd)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startLoadingAnim() {
|
||||||
|
val imageView = binding.ivAnim
|
||||||
|
ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f).apply {
|
||||||
|
duration = 2000L
|
||||||
|
interpolator = LinearInterpolator()
|
||||||
|
repeatCount = ValueAnimator.INFINITE
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
const val MAX_SPLASH_TIME = 5 * 1000L
|
||||||
|
const val MIN_SPLASH_TIME = 2 * 1000L
|
||||||
|
|
||||||
internal fun startActivity(activity: Activity) {
|
internal fun startActivity(activity: Activity) {
|
||||||
activity.startActivity(Intent(activity.applicationContext, SplashActivity::class.java))
|
activity.startActivity(Intent(activity.applicationContext, SplashActivity::class.java))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,24 @@ import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import androidx.core.view.updatePadding
|
|
||||||
import com.ama.core.architecture.appBase.AppViewsActivity
|
import com.ama.core.architecture.appBase.AppViewsActivity
|
||||||
import com.gamedog.vididin.R
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.SpUtil
|
||||||
|
import com.gamedog.vididin.beans.RecordGold
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.viddin.videos.free.R
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
||||||
|
import com.gamedog.vididin.manager.TestingManager
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import kotlin.getValue
|
||||||
import com.gamedog.vididin.databinding.ActivityVersionBinding as ViewBinding
|
import com.viddin.videos.free.databinding.ActivityVersionBinding as ViewBinding
|
||||||
import com.gamedog.vididin.main.MainUiState as UiState
|
import com.gamedog.vididin.main.MainUiState as UiState
|
||||||
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class VersionActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
class VersionActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
||||||
|
|
||||||
|
|
@ -28,17 +33,63 @@ class VersionActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnT
|
||||||
with(binding) {
|
with(binding) {
|
||||||
titlebar.setBackIconColor(R.color.black)
|
titlebar.setBackIconColor(R.color.black)
|
||||||
titlebar.setTitleText(R.string.version, R.color.black)
|
titlebar.setTitleText(R.string.version, R.color.black)
|
||||||
|
|
||||||
|
tvVersion.text = AndroidUtil.getAppVersionInfo()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// For Testing
|
||||||
|
val shouldShowDebug = false//BuildConfig.DEBUG
|
||||||
|
llTesting.isVisible = shouldShowDebug
|
||||||
|
if (shouldShowDebug) {
|
||||||
|
butCash.setOnClickListener {
|
||||||
|
try {
|
||||||
|
val cashNum: Double = evCash.text.toString().toDouble()
|
||||||
|
AccountManager.adjustCash(cashNum, null)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
butGold.setOnClickListener {
|
||||||
|
try {
|
||||||
|
val goldNum = evGold.text.toString().toLong()
|
||||||
|
AccountManager.adjustGold(goldNum, RecordGold())
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
butDiamond.setOnClickListener {
|
||||||
|
try {
|
||||||
|
val diamondNum = evDiamond.text.toString().toInt()
|
||||||
|
AccountManager.adjustDiamond(diamondNum)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ad
|
||||||
|
checkerRewardAd.isChecked = TestingManager.instance().isRewardAdDisable()
|
||||||
|
checkerNormalAd.isChecked = TestingManager.instance().isNormalAdDisable()
|
||||||
|
|
||||||
|
checkerRewardAd.setOnCheckedChangeListener {_, isChecked ->
|
||||||
|
SpUtil.instance().putBoolean(SpUtil.KEY_TESTING_REWARD_AD_DISABLE, isChecked)
|
||||||
|
}
|
||||||
|
checkerNormalAd.setOnCheckedChangeListener {_, isChecked ->
|
||||||
|
SpUtil.instance().putBoolean(SpUtil.KEY_TESTING_NORMAL_AD_DISABLE, isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initWindowInsets() {
|
override fun ViewBinding.initWindowInsets() {
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(contentRoot) { v, insets ->
|
setImmerseRootView(contentRoot)
|
||||||
val systemBars =
|
|
||||||
insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
|
|
||||||
v.updatePadding(top = systemBars.top)
|
|
||||||
insets
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initListeners() {
|
override fun ViewBinding.initListeners() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,248 @@
|
||||||
|
package com.gamedog.vididin.features.watchad
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.CountDownTimer
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.updatePadding
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelActivity
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.ama.core.architecture.util.eventbus.NotifyMan
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.VidiStatisticHelper
|
||||||
|
import com.gamedog.vididin.VididinEvents
|
||||||
|
import com.gamedog.vididin.beans.WatchAdNotifyBean
|
||||||
|
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
||||||
|
import com.gamedog.vididin.manager.TestingManager
|
||||||
|
import com.gamedog.vididin.manager.WithdrawItem
|
||||||
|
import com.remax.bill.ads.AdResult
|
||||||
|
import com.remax.bill.ads.ext.AdShowExt
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.viddin.videos.free.databinding.ActivityWatchAdBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class WatchAdActivity : AppViewsEmptyViewModelActivity<ViewBinding>(), OnTabStyleListener {
|
||||||
|
|
||||||
|
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
||||||
|
private var mIsLoadSuccess: Boolean = false
|
||||||
|
private var mRewardedDollarNum: Double = 0.0
|
||||||
|
override var mEnableBannerAd = false
|
||||||
|
|
||||||
|
private lateinit var mCountDownTimer: CountDownTimer
|
||||||
|
private var mWatchType: Int = 0
|
||||||
|
private var mExtraJsonStr: String? = null
|
||||||
|
|
||||||
|
override fun ViewBinding.initViews() {
|
||||||
|
with(binding) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initWindowInsets() {
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(contentRoot) { v, insets ->
|
||||||
|
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
|
||||||
|
v.updatePadding(top = systemBars.top)
|
||||||
|
insets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initListeners() {
|
||||||
|
stateCounter()
|
||||||
|
showVideoAd()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun notifyAdWatchFinish() {
|
||||||
|
var notifyEventType = 0
|
||||||
|
var notifyData: NotifyMan.NotifyData<Any> = NotifyMan.NotifyData()
|
||||||
|
var shouldNotifyOneAdWatched = true
|
||||||
|
|
||||||
|
|
||||||
|
when (mWatchType) {
|
||||||
|
VidiConst.WATCH_AD_FOR_WITHDRAW_SMALL -> {
|
||||||
|
shouldNotifyOneAdWatched = true
|
||||||
|
notifyEventType = VididinEvents.EVENT_AD_WATCHED_FOR_WITHDRAW_SMALL
|
||||||
|
|
||||||
|
val extraData = mExtraJsonStr?.let {
|
||||||
|
AndroidUtil.json2Object<Float>(mExtraJsonStr!!)
|
||||||
|
}
|
||||||
|
notifyData.mData = WatchAdNotifyBean(mRewardedDollarNum, extraData)
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_WITHDRAW_BIG -> {
|
||||||
|
shouldNotifyOneAdWatched = true
|
||||||
|
notifyEventType = VididinEvents.EVENT_AD_WATCHED_FOR_WITHDRAW_BIG
|
||||||
|
|
||||||
|
val extraData = mExtraJsonStr?.let {
|
||||||
|
AndroidUtil.json2Object<WithdrawItem>(mExtraJsonStr!!)
|
||||||
|
}
|
||||||
|
notifyData.mData = WatchAdNotifyBean(mRewardedDollarNum, extraData)
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_DAILY_SIGN_SINGLE -> {
|
||||||
|
shouldNotifyOneAdWatched = true
|
||||||
|
notifyEventType = VididinEvents.EVENT_AD_WATCHED_FOR_DAILY_SIGN_SINGLE
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_DAILY_SIGN_DOUBLE-> {
|
||||||
|
shouldNotifyOneAdWatched = true
|
||||||
|
notifyEventType = VididinEvents.EVENT_AD_WATCHED_FOR_DAILY_SIGN_DOUBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_DAILY_SIGN_COMPLEMENT -> {
|
||||||
|
shouldNotifyOneAdWatched = true
|
||||||
|
notifyEventType = VididinEvents.EVENT_AD_WATCHED_FOR_DAILY_SIGN_COMPLEMENT
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_BOX_TASK -> {
|
||||||
|
shouldNotifyOneAdWatched = true
|
||||||
|
notifyEventType = VididinEvents.EVENT_AD_WATCHED_FOR_BOX_TASK
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_ZERO_EARN_DIAMOND -> {
|
||||||
|
shouldNotifyOneAdWatched = false
|
||||||
|
notifyEventType = VididinEvents.EVENT_AD_WATCHED_FOR_ZEROBUY_EARN_DIAMOND
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_WATCHED_3_VIDEOS, VidiConst.WATCH_AD_FOR_DAILY_WATCH_AD -> {
|
||||||
|
shouldNotifyOneAdWatched = true
|
||||||
|
notifyEventType = VididinEvents.EVENT_AD_WATCHED_FOR_DAILY_WATCH_AD
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_DAILY_EARN_GOLD_POPMENU, VidiConst.WATCH_AD_FOR_DAILY_EARN_GOLD -> {
|
||||||
|
shouldNotifyOneAdWatched = true
|
||||||
|
notifyEventType = VididinEvents.EVENT_AD_WATCHED_FOR_EARN_GOLD
|
||||||
|
}
|
||||||
|
|
||||||
|
VidiConst.WATCH_AD_FOR_CONVERT_GOLD_2_CASH -> {
|
||||||
|
shouldNotifyOneAdWatched = true
|
||||||
|
notifyEventType = VididinEvents.EVENT_AD_WATCHED_FOR_CONVERT_GOLD_2_CASH
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NotifyMan.instance().sendEvent(notifyEventType, notifyData)
|
||||||
|
if (shouldNotifyOneAdWatched) {
|
||||||
|
NotifyMan.instance().sendEvent(VididinEvents.EVENT_FINISHED_ONE_AD, NotifyMan.NotifyData(1))
|
||||||
|
}
|
||||||
|
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stateCounter() {
|
||||||
|
mCountDownTimer = object : CountDownTimer(50* 1000, 1000) {
|
||||||
|
override fun onTick(millisUntilFinished: Long) {
|
||||||
|
val secondsRemaining = millisUntilFinished / 1000
|
||||||
|
//binding.tvAdCounter.text = "${secondsRemaining}"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinish() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mCountDownTimer.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readIntent(intent: Intent) {
|
||||||
|
super.readIntent(intent)
|
||||||
|
mWatchType = intent.getIntExtra(KEY_TASK_TYPE, 0)
|
||||||
|
mExtraJsonStr = intent.getStringExtra(KEY_TASK_DATA)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
mCountDownTimer.cancel()
|
||||||
|
|
||||||
|
NotifyMan.instance().sendEvent(VididinEvents.AD_ACT_DESTROY, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
NotifyMan.instance().sendEvent(VididinEvents.AD_ACT_SHOWING, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initObservers() {
|
||||||
|
//TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun onTabIsDarkFont(isDarkFont: Boolean) {
|
||||||
|
//TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun showVideoAd() {
|
||||||
|
if (TestingManager.instance().isRewardAdDisable()) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
delay(2000)
|
||||||
|
mRewardedDollarNum = 0.02
|
||||||
|
notifyAdWatchFinish()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
binding.root.postDelayed({
|
||||||
|
if (!mIsLoadSuccess) {
|
||||||
|
handleLoadFailed()
|
||||||
|
}
|
||||||
|
}, 3000)
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
AndroidUtil.adHintToast(ResUtil.getString(R.string.watch_full_reward_ad_hint))
|
||||||
|
|
||||||
|
when(AdShowExt.showRewardedVideoAd(this@WatchAdActivity,
|
||||||
|
VidiStatisticHelper.getShowFromStr(mWatchType), { rewardedData ->
|
||||||
|
mRewardedDollarNum = rewardedData.rewardNum
|
||||||
|
}, {
|
||||||
|
notifyAdWatchFinish()
|
||||||
|
}, {
|
||||||
|
mIsLoadSuccess = true
|
||||||
|
})) {
|
||||||
|
is AdResult.Success -> {
|
||||||
|
mIsLoadSuccess = true
|
||||||
|
}
|
||||||
|
|
||||||
|
is AdResult.Failure -> {
|
||||||
|
handleLoadFailed()
|
||||||
|
}
|
||||||
|
|
||||||
|
AdResult.Loading -> {
|
||||||
|
val temp = 111
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleLoadFailed() {
|
||||||
|
AndroidUtil.showToast(R.string.ad_load_fail)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val KEY_TASK_TYPE = "KEY_TASK_TYPE"
|
||||||
|
private val KEY_TASK_DATA = "KEY_TASK_DATA"
|
||||||
|
|
||||||
|
internal fun startActivity(activity: Activity, taskType: Int, taskDataJson: String?) {
|
||||||
|
val intent = Intent(activity.applicationContext, WatchAdActivity::class.java)
|
||||||
|
intent.putExtra(KEY_TASK_TYPE, taskType)
|
||||||
|
intent.putExtra(KEY_TASK_DATA, taskDataJson)
|
||||||
|
activity.startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -4,59 +4,118 @@ import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.core.view.updatePadding
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.ama.core.architecture.appBase.AppViewsActivity
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.gamedog.vididin.R
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelActivity
|
||||||
|
import com.ama.core.architecture.util.CommonItemDecoration
|
||||||
|
import com.gamedog.vididin.VididinEvents
|
||||||
|
import com.gamedog.vididin.beans.ZeroBuyResp
|
||||||
|
import com.gamedog.vididin.features.zero.ZeroBuyViewModel
|
||||||
|
import com.gamedog.vididin.features.zero.ZeroRecordAdapter
|
||||||
|
import com.viddin.videos.free.R
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
||||||
|
import com.gamedog.vididin.manager.ZeroManager
|
||||||
|
import com.gamedog.vididin.netbase.Result
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.getValue
|
import kotlin.getValue
|
||||||
import com.gamedog.vididin.databinding.ActivityWinRecordBinding as ViewBinding
|
import com.viddin.videos.free.databinding.ActivityWinRecordBinding as ViewBinding
|
||||||
import com.gamedog.vididin.main.MainUiState as UiState
|
|
||||||
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
|
||||||
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class WinRecordsActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
class WinRecordsActivity : AppViewsEmptyViewModelActivity<ViewBinding>(), OnTabStyleListener {
|
||||||
|
|
||||||
|
private val viewModel: ZeroBuyViewModel by viewModels()
|
||||||
|
private lateinit var mAdapter: ZeroRecordAdapter
|
||||||
|
|
||||||
|
|
||||||
override val mViewModel: ViewModel by viewModels()
|
|
||||||
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
||||||
|
|
||||||
override fun ViewBinding.initViews() {
|
override fun ViewBinding.initViews() {
|
||||||
|
|
||||||
with(binding) {
|
with(binding) {
|
||||||
titlebar.setBackIconColor(R.color.black)
|
titlebar.setBackIconColor(R.color.black)
|
||||||
titlebar.setTitleText(R.string.lottery_record, R.color.black)
|
titlebar.setTitleText(R.string.lottery_record, R.color.black)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
with(recyclerView) {
|
||||||
|
mAdapter = ZeroRecordAdapter({
|
||||||
|
ZeroManager.instance().startWithdrawProcess(this@WinRecordsActivity, it)
|
||||||
|
})
|
||||||
|
adapter = mAdapter
|
||||||
|
layoutManager = LinearLayoutManager(this@WinRecordsActivity, LinearLayoutManager.VERTICAL, false)
|
||||||
|
addItemDecoration(
|
||||||
|
CommonItemDecoration.create(horizontalSpace = 0, verticalSpace = 30)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initWindowInsets() {
|
override fun ViewBinding.initWindowInsets() {
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(contentRoot) { v, insets ->
|
setImmerseRootView(contentRoot)
|
||||||
val systemBars =
|
|
||||||
insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
|
|
||||||
v.updatePadding(top = systemBars.top)
|
|
||||||
insets
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initListeners() {
|
override fun ViewBinding.initListeners() {
|
||||||
//TODO("Not yet implemented")
|
|
||||||
|
registerEvents({ data->
|
||||||
|
when (data?.mEventType) {
|
||||||
|
VididinEvents.EVENT_ZERO_WITHDRAW_LIST_CHANGED -> {
|
||||||
|
mAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, VididinEvents.EVENT_ZERO_WITHDRAW_LIST_CHANGED,)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
requestData()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initObservers() {
|
override fun ViewBinding.initObservers() {
|
||||||
//TODO("Not yet implemented")
|
//TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
|
|
||||||
//TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTabIsDarkFont(isDarkFont: Boolean) {
|
override fun onTabIsDarkFont(isDarkFont: Boolean) {
|
||||||
//TODO("Not yet implemented")
|
//TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun requestData() {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
|
viewModel.ZeroBuyListData.collect { result ->
|
||||||
|
when (result) {
|
||||||
|
is Result.Loading -> { showLoading(false) }
|
||||||
|
is Result.Success -> {
|
||||||
|
hideLoading()
|
||||||
|
updateUIs(result.data)
|
||||||
|
}
|
||||||
|
is Result.Error -> {
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.requestZeroBuyInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateUIs(data: ZeroBuyResp) {
|
||||||
|
val dataList = data.finished_purchases
|
||||||
|
if (dataList.isNullOrEmpty()) {
|
||||||
|
binding.tvNoDataHint.isVisible = true
|
||||||
|
binding.recyclerView.isVisible = false
|
||||||
|
} else {
|
||||||
|
binding.tvNoDataHint.isVisible = false
|
||||||
|
binding.recyclerView.isVisible = true
|
||||||
|
mAdapter.submitList(dataList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
internal fun startActivity(activity: Activity) {
|
internal fun startActivity(activity: Activity) {
|
||||||
|
|
|
||||||
|
|
@ -48,4 +48,12 @@ object BankUtil {
|
||||||
val remainder = sum % 11
|
val remainder = sum % 11
|
||||||
return if (remainder < 2) 0 else 11 - remainder
|
return if (remainder < 2) 0 else 11 - remainder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun executeWithDraw() {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
|
||||||
|
class DefaultWithdrawSubRouter: WithdrawSubRouter {
|
||||||
|
override fun startActivity(activity: Activity, withdrawType: Int) {
|
||||||
|
WithDrawSubActivity.Companion.startActivity(activity, withdrawType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,133 +3,400 @@ package com.gamedog.vididin.features.withdraw
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.viewModels
|
import androidx.core.graphics.toColorInt
|
||||||
import com.ama.core.architecture.appBase.AppViewsActivity
|
import androidx.core.view.isVisible
|
||||||
|
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelActivity
|
||||||
|
import com.ama.core.architecture.highlightpro.HighlightPro
|
||||||
|
import com.ama.core.architecture.highlightpro.parameter.Constraints
|
||||||
|
import com.ama.core.architecture.highlightpro.parameter.HighlightParameter
|
||||||
|
import com.ama.core.architecture.highlightpro.parameter.MarginOffset
|
||||||
|
import com.ama.core.architecture.highlightpro.shape.RectShape
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.ama.core.architecture.util.ResUtil.dp
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
import com.gamedog.vididin.R
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.viddin.videos.free.R
|
||||||
import com.gamedog.vididin.VididinEvents
|
import com.gamedog.vididin.VididinEvents
|
||||||
import com.gamedog.vididin.beans.Account
|
import com.gamedog.vididin.beans.RecordCash
|
||||||
|
import com.gamedog.vididin.beans.WatchAdNotifyBean
|
||||||
import com.gamedog.vididin.core.login.login.AccountManager
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.gamedog.vididin.features.withdraw.dialogs.WithdrawBindBankDialog
|
||||||
|
import com.gamedog.vididin.features.withdraw.dialogs.WithdrawFailDialog
|
||||||
|
import com.gamedog.vididin.features.withdraw.dialogs.WithdrawInfoConfirmDialog
|
||||||
|
import com.gamedog.vididin.features.withdraw.dialogs.WithdrawSuccessDialog
|
||||||
|
import com.gamedog.vididin.features.withdraw.dialogs.WithdrawWatchAdDialog
|
||||||
import com.gamedog.vididin.features.withdraw.widget.WithDrawItemView
|
import com.gamedog.vididin.features.withdraw.widget.WithDrawItemView
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.manager.GuideManager
|
||||||
|
import com.gamedog.vididin.manager.TaskManager
|
||||||
|
import com.gamedog.vididin.manager.WithdrawItem
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.STATE_COULD_WITHDRAW
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.STATE_WITHDRAW_SUCCESS
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_FAIL
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_ONGOING
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_SUCCESS
|
||||||
import com.gamedog.vididin.router.Router
|
import com.gamedog.vididin.router.Router
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import com.viddin.videos.free.databinding.ActivityWithdrawBinding as ViewBinding
|
||||||
import com.gamedog.vididin.databinding.ActivityWithdrawBinding as ViewBinding
|
|
||||||
import com.gamedog.vididin.main.MainUiState as UiState
|
|
||||||
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提现主页面 Activity
|
||||||
|
* 负责展示可提现金额列表、处理提现逻辑、显示提现结果弹窗及新手引导
|
||||||
|
*/
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class WithDrawActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
class WithDrawActivity : AppViewsEmptyViewModelActivity<ViewBinding>() {
|
||||||
|
// 存储提现选项视图的列表
|
||||||
|
private val mItemViewList: MutableList<WithDrawItemView> = mutableListOf()
|
||||||
|
|
||||||
|
|
||||||
override val mViewModel: ViewModel by viewModels()
|
|
||||||
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
||||||
|
|
||||||
private val mItemViewList: MutableList<WithDrawItemView> = mutableListOf()
|
|
||||||
private var mCurSelectedIndex: Int = 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun ViewBinding.initWindowInsets() {
|
override fun ViewBinding.initWindowInsets() {
|
||||||
|
// 设置沉浸式状态栏
|
||||||
setImmerseRootView(contentRoot)
|
setImmerseRootView(contentRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initViews() {
|
override fun ViewBinding.initViews() {
|
||||||
|
// 设置标题栏文字
|
||||||
|
titlebar.setTitleText(R.string.sacar)
|
||||||
|
|
||||||
|
// 初始化提现选项列表
|
||||||
mItemViewList.add(withdraw01)
|
mItemViewList.add(withdraw01)
|
||||||
|
mItemViewList.add(withdraw1)
|
||||||
mItemViewList.add(withdraw10)
|
mItemViewList.add(withdraw10)
|
||||||
mItemViewList.add(withdraw20)
|
mItemViewList.add(withdraw20)
|
||||||
mItemViewList.add(withdraw50)
|
mItemViewList.add(withdraw50)
|
||||||
mItemViewList.add(withdraw100)
|
mItemViewList.add(withdraw100)
|
||||||
mItemViewList.add(withdraw300)
|
mItemViewList.add(withdraw300)
|
||||||
|
|
||||||
withdraw01.setNumAndAction(0, 0.1F,
|
// 为每个提现选项设置金额和点击回调
|
||||||
|
withdraw01.setNumAndAction(0, 0.1,
|
||||||
{ itemIndex->
|
{ itemIndex->
|
||||||
updateUIItemSelectStates(itemIndex)
|
handleGotoWithdraw(itemIndex)
|
||||||
})
|
})
|
||||||
|
|
||||||
withdraw10.setNumAndAction(1, 10F,
|
withdraw1.setNumAndAction(1, 1.0,
|
||||||
{ itemIndex->
|
{ itemIndex->
|
||||||
updateUIItemSelectStates(itemIndex)
|
handleGotoWithdraw(itemIndex)
|
||||||
})
|
})
|
||||||
|
|
||||||
withdraw20.setNumAndAction(2, 20F,
|
withdraw10.setNumAndAction(2, 10.0,
|
||||||
{ itemIndex->
|
{ itemIndex->
|
||||||
updateUIItemSelectStates(itemIndex)
|
handleGotoWithdraw(itemIndex)
|
||||||
})
|
})
|
||||||
|
|
||||||
withdraw50.setNumAndAction(3, 50F,
|
withdraw20.setNumAndAction(3, 20.0,
|
||||||
{ itemIndex->
|
{ itemIndex->
|
||||||
updateUIItemSelectStates(itemIndex)
|
handleGotoWithdraw(itemIndex)
|
||||||
})
|
})
|
||||||
|
|
||||||
withdraw100.setNumAndAction(4, 100F,
|
withdraw50.setNumAndAction(4, 50.0,
|
||||||
{ itemIndex->
|
{ itemIndex->
|
||||||
updateUIItemSelectStates(itemIndex)
|
handleGotoWithdraw(itemIndex)
|
||||||
})
|
})
|
||||||
|
|
||||||
withdraw300.setNumAndAction(5, 300F,
|
withdraw100.setNumAndAction(5, 100.0,
|
||||||
{ itemIndex->
|
{ itemIndex->
|
||||||
updateUIItemSelectStates(itemIndex)
|
handleGotoWithdraw(itemIndex)
|
||||||
})
|
})
|
||||||
|
|
||||||
withdrawPix2.setIconAndText(R.mipmap.pix2, R.string.pix2, {
|
withdraw300.setNumAndAction(6, 300.0,
|
||||||
|
{ itemIndex->
|
||||||
|
handleGotoWithdraw(itemIndex)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 设置提现方式(如 PIX)的图标和点击事件
|
||||||
|
withdrawPix2.setIconAndText(R.mipmap.pix2_big, R.string.pix2, {
|
||||||
|
// 点击显示绑定银行卡对话框
|
||||||
|
WithdrawBindBankDialog(this@WithDrawActivity, null).setWithDrawCashNum(0.0).show()
|
||||||
|
})
|
||||||
|
|
||||||
withdrawPix2.setSelectedState(true)
|
withdrawPix2.setSelectedState(true)
|
||||||
updateUIItemSelectStates(0)
|
|
||||||
|
|
||||||
setOnClickBatch(tvSacar, withdrawRecord) {
|
// 设置点击事件监听
|
||||||
|
setOnClickBatch(withdrawRecord) {
|
||||||
when(this) {
|
when(this) {
|
||||||
tvSacar -> {
|
|
||||||
val hasBindBank = AccountManager.hasValidBankInfo()
|
|
||||||
if (!hasBindBank) {
|
|
||||||
WithdrawBindBankDialog(this@WithDrawActivity).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
withdrawRecord -> {
|
withdrawRecord -> {
|
||||||
|
// 跳转到提现记录页面
|
||||||
Router.WithdrawRecord.startActivity(this@WithDrawActivity)
|
Router.WithdrawRecord.startActivity(this@WithDrawActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新总金额 UI
|
||||||
updateUICashTotal()
|
updateUICashTotal()
|
||||||
|
|
||||||
|
// 判断 0.1 元新人提现是否已完成,若完成则隐藏该选项
|
||||||
|
// TaskManager.instance().newbieFirstWithdrawStatus().getStatusBean().hasWithdrawed
|
||||||
|
if (WithdrawManager.instance().getItemState(0, 0) == STATE_WITHDRAW_SUCCESS
|
||||||
|
|| TaskManager.instance().newbieFirstWithdrawStatus().smallCashHasWithdrawed()) {
|
||||||
|
withdraw01.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateUIItemSelectStates(itemIndex: Int) {
|
// 上报提现页面展示事件
|
||||||
mCurSelectedIndex = itemIndex
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Withdrawal_Show)
|
||||||
mItemViewList.forEachIndexed { index, view ->
|
}
|
||||||
view.setSelectedState(index == mCurSelectedIndex)
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理提现点击逻辑
|
||||||
|
* @param itemIndex 提现选项的索引
|
||||||
|
*/
|
||||||
|
private fun handleGotoWithdraw(itemIndex: Int) {
|
||||||
|
val cashNum = mItemViewList.get(itemIndex).getCashNum()
|
||||||
|
if (cashNum >= 1.0) {
|
||||||
|
// 金额大于等于 1.0,标记开始提现并进入二级提现页面
|
||||||
|
WithdrawManager.instance().setItemStarted(itemIndex)
|
||||||
|
gotoWithdrawSubActivity(itemIndex)
|
||||||
|
} else {
|
||||||
|
// 小额提现(0.1元)逻辑
|
||||||
|
val hasBindBank = AccountManager.hasValidBankInfo()
|
||||||
|
if (!hasBindBank) {
|
||||||
|
// 未绑定银行卡,显示绑定弹窗
|
||||||
|
WithdrawBindBankDialog(this@WithDrawActivity, ::startRealWithdraw ).setWithDrawCashNum(cashNum).show()
|
||||||
|
} else {
|
||||||
|
if (WithdrawManager.instance().getItemState(0, 0) == STATE_COULD_WITHDRAW) {
|
||||||
|
// 已满足提现条件,显示信息确认弹窗
|
||||||
|
WithdrawInfoConfirmDialog(this@WithDrawActivity, ::startRealWithdraw).setWithDrawCashNum(cashNum).show()
|
||||||
|
} else {
|
||||||
|
// 不满足条件(通常是需要看广告),显示看广告提现弹窗
|
||||||
|
WithdrawWatchAdDialog(this@WithDrawActivity, cashNum, ::startRealWithdraw).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 上报点击提现选项事件
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Withdrawal_finsh, mapOf("Withdrawal_Position" to cashNum))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发起真实的提现请求
|
||||||
|
* @param cashNum 提现金额
|
||||||
|
*/
|
||||||
|
private fun startRealWithdraw(cashNum: Double) {
|
||||||
|
// payCashNum: Double, payItemId: Int, paySubItemId: Int, payItemLoopIndex: Int
|
||||||
|
WithdrawManager.instance().startWithdrawReal(cashNum, 0, 0, 1)
|
||||||
|
WithdrawManager.instance().setItemStarted(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新 UI 上的总现金数和已提现成功总额
|
||||||
|
*/
|
||||||
private fun updateUICashTotal() {
|
private fun updateUICashTotal() {
|
||||||
binding.tvCashTotal.text = AccountManager.getCash().toString()
|
binding.tvCashTotal.text = String.format("%.2f", AccountManager.getCash())
|
||||||
|
binding.tvAllCashHasWithdrawed.text = buildString {
|
||||||
|
append(ResUtil.getString(R.string.cash))
|
||||||
|
append(" ")
|
||||||
|
append(WithdrawManager.instance().getHasWithdrawSuccessCashCount())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新提现列表项的 UI 状态(进度、按钮等)
|
||||||
|
*/
|
||||||
|
private fun updateItemListUI() {
|
||||||
|
mItemViewList.forEach {
|
||||||
|
it.updateProgressAndButUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否需要隐藏 0.1 元提现选项
|
||||||
|
if (WithdrawManager.instance().getItemState(0, 0) == STATE_WITHDRAW_SUCCESS
|
||||||
|
|| TaskManager.instance().newbieFirstWithdrawStatus().smallCashHasWithdrawed()) {
|
||||||
|
binding.withdraw01.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun ViewBinding.initListeners() {
|
override fun ViewBinding.initListeners() {
|
||||||
|
// 注册事件总线监听
|
||||||
registerEvents({ data->
|
registerEvents({ data->
|
||||||
|
when (data?.mEventType) {
|
||||||
|
VididinEvents.Event_Account_Cash_Changed -> {
|
||||||
|
// 现金余额发生变化
|
||||||
updateUICashTotal()
|
updateUICashTotal()
|
||||||
}, VididinEvents.Event_Account_Cash_Changed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_AD_WATCHED_FOR_WITHDRAW_SMALL -> {
|
||||||
|
// 小额提现看广告奖励
|
||||||
|
val adNotifyBean = data.mData as WatchAdNotifyBean<Double>
|
||||||
|
WithdrawManager.instance().addAdEarnForSubBean(0, 0,
|
||||||
|
adNotifyBean.earnMoneyNum * VidiConst.WITHDRAW_REWARD_AD_REVENUE_PERCENT)
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_WITHDRAW_RESULT_UPDATED -> {
|
||||||
|
// 提现结果更新
|
||||||
|
try {
|
||||||
|
val record = data.mData as RecordCash
|
||||||
|
if (record.withdrawItemIndex == 0) {
|
||||||
|
// 如果是当前小额提现的结果,显示结果弹窗
|
||||||
|
showTransactionResultDialog(record)
|
||||||
|
}
|
||||||
|
updateUICashTotal()
|
||||||
|
mItemViewList[record.withdrawItemIndex].updateProgressAndButUI()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_WITHDRAW_ITEM_LIST_CHANGED -> {
|
||||||
|
// 提现列表整体发生变化
|
||||||
|
updateItemListUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_BANK_INFO_CHANGED -> {
|
||||||
|
// 银行卡绑定信息变化
|
||||||
|
withdrawPix2.updateBankAccountInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_WITHDRAW_SUB_ITEM_PROGRESS_UPDATED -> {
|
||||||
|
// 二级提现项进度更新
|
||||||
|
updateItemListUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_WITHDRAW_SMALL_AD_FINISHED -> {
|
||||||
|
// 小额提现相关广告观看完成
|
||||||
|
handleGotoWithdraw(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, VididinEvents.Event_Account_Cash_Changed,
|
||||||
|
VididinEvents.EVENT_AD_WATCHED_FOR_WITHDRAW_SMALL,
|
||||||
|
VididinEvents.EVENT_WITHDRAW_RESULT_UPDATED,
|
||||||
|
VididinEvents.EVENT_WITHDRAW_ITEM_LIST_CHANGED,
|
||||||
|
VididinEvents.EVENT_BANK_INFO_CHANGED,
|
||||||
|
VididinEvents.EVENT_WITHDRAW_SUB_ITEM_PROGRESS_UPDATED,
|
||||||
|
VididinEvents.EVENT_WITHDRAW_SMALL_AD_FINISHED)
|
||||||
|
|
||||||
|
// 读取本地提现记录并展示未通知的结果
|
||||||
|
readTransactionsAndShowResult()
|
||||||
|
|
||||||
|
// 检查并展示新手引导
|
||||||
|
if (needShowGuide()) {
|
||||||
|
binding.tvCashTotal.postDelayed({
|
||||||
|
showGuide()
|
||||||
|
}, 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun ViewBinding.initObservers() {
|
override fun ViewBinding.initObservers() {
|
||||||
//TODO("Not yet implemented")
|
//TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
|
/**
|
||||||
//TODO("Not yet implemented")
|
* 显示提现成功弹窗
|
||||||
|
*/
|
||||||
|
private fun showSuccessDialog(cashNum: Double) {
|
||||||
|
WithdrawSuccessDialog(this@WithDrawActivity, cashNum).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabIsDarkFont(isDarkFont: Boolean) {
|
/**
|
||||||
//TODO("Not yet implemented")
|
* 显示提现失败弹窗
|
||||||
|
*/
|
||||||
|
private fun showFailDialog(failHintRes: Int) {
|
||||||
|
WithdrawFailDialog(this@WithDrawActivity, failHintRes).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转到提现二级详情页面
|
||||||
|
*/
|
||||||
|
private fun gotoWithdrawSubActivity(selectedIndex: Int) {
|
||||||
|
Router.WithdrawSub.startActivity(this, selectedIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------ 新增处理逻辑 -------------------------//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取并处理本地提现记录
|
||||||
|
*/
|
||||||
|
private fun readTransactionsAndShowResult() {
|
||||||
|
val recordList = WithdrawManager.instance().getClonedRecordList()
|
||||||
|
recordList.forEach {
|
||||||
|
showTransactionResultDialog(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据提现记录状态显示对应的结果弹窗
|
||||||
|
*/
|
||||||
|
private fun showTransactionResultDialog(record: RecordCash) {
|
||||||
|
// 如果未展示过结果弹窗且提现状态不是“进行中”,则展示结果
|
||||||
|
if (!record.hasShowResultDialog && record.withdrawState != TRANSACTION_STATE_ONGOING) {
|
||||||
|
WithdrawManager.instance().updateRecordHasNotifyState(record.uuid)
|
||||||
|
when (record.withdrawState) {
|
||||||
|
TRANSACTION_STATE_SUCCESS -> {
|
||||||
|
showSuccessDialog(record.amountNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
TRANSACTION_STATE_FAIL -> {
|
||||||
|
showFailDialog(WithdrawManager.instance().getFailHintStrRes(record.withdrawFailType))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否需要显示引导
|
||||||
|
*/
|
||||||
|
private fun needShowGuide(): Boolean {
|
||||||
|
return GuideManager.instance().getCurGuideIndex() == VidiConst.GUIDE_INDEX_CASH_GOLD
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存引导状态,标记当前步骤已完成
|
||||||
|
*/
|
||||||
|
private fun saveGuideState() {
|
||||||
|
GuideManager.instance().setGuideIndex(VidiConst.GUIDE_INDEX_WITHDRAW)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行新手引导展示
|
||||||
|
*/
|
||||||
|
private fun showGuide() {
|
||||||
|
HighlightPro.with(this@WithDrawActivity)
|
||||||
|
.setHighlightParameter {
|
||||||
|
HighlightParameter.Builder()
|
||||||
|
.setHighlightView(mItemViewList.get(0), {
|
||||||
|
})
|
||||||
|
.setTipsViewId(R.layout.guide_step_withdraw)
|
||||||
|
.setHighlightShape(RectShape(10.dp, 10.dp, 10.dp))
|
||||||
|
.setHighlightHorizontalPadding(0.dp)
|
||||||
|
.setConstraints(Constraints.TopToBottomOfHighlight + Constraints.EndToEndOfHighlight)
|
||||||
|
.setMarginOffset(MarginOffset(top = -40.dp.toInt(), end = 0.dp.toInt()))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
.setBackgroundColor("#cc000000".toColorInt())
|
||||||
|
.setOnShowCallback { index ->
|
||||||
|
|
||||||
|
}
|
||||||
|
.setOnDismissCallback {
|
||||||
|
// 引导消失后保存状态并触发点击 0.1 元提现
|
||||||
|
saveGuideState()
|
||||||
|
handleGotoWithdraw(0)
|
||||||
|
}
|
||||||
|
.interceptBackPressed(true)
|
||||||
|
.show()
|
||||||
|
|
||||||
|
// 上报引导埋点
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Guide, mapOf("Guide" to 3))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
/**
|
||||||
|
* 启动 WithDrawActivity
|
||||||
|
*/
|
||||||
internal fun startActivity(activity: Activity) {
|
internal fun startActivity(activity: Activity) {
|
||||||
activity.startActivity(Intent(activity.applicationContext, WithDrawActivity::class.java))
|
activity.startActivity(Intent(activity.applicationContext, WithDrawActivity::class.java))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,276 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.text.Spannable
|
||||||
|
import android.text.SpannableString
|
||||||
|
import android.text.method.ScrollingMovementMethod
|
||||||
|
import android.text.style.ForegroundColorSpan
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelActivity
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.CommonItemDecoration
|
||||||
|
import com.ama.core.architecture.util.DateUtil
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.VididinEvents
|
||||||
|
import com.gamedog.vididin.beans.RecordCash
|
||||||
|
import com.gamedog.vididin.beans.WatchAdNotifyBean
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.gamedog.vididin.features.withdraw.dialogs.WithdrawBindBankDialog
|
||||||
|
import com.gamedog.vididin.features.withdraw.dialogs.WithdrawFailDialog
|
||||||
|
import com.gamedog.vididin.features.withdraw.dialogs.WithdrawInfoConfirmDialog
|
||||||
|
import com.gamedog.vididin.features.withdraw.dialogs.WithdrawSuccessDialog
|
||||||
|
import com.gamedog.vididin.manager.WithdrawItem
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_FAIL
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_ONGOING
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_SUCCESS
|
||||||
|
import com.gamedog.vididin.router.Router
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlin.getValue
|
||||||
|
import com.viddin.videos.free.databinding.ActivityWithdrawSubBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class WithDrawSubActivity : AppViewsEmptyViewModelActivity<ViewBinding>() {
|
||||||
|
private lateinit var mCurItem: WithdrawItem
|
||||||
|
private var mSelectingIndex: Int = 0
|
||||||
|
private var mType: Int = 0
|
||||||
|
private val mAdapter: WithdrawSubAdapter by lazy { WithdrawSubAdapter( { itemIndex ->
|
||||||
|
handleSubItemClicked(itemIndex)
|
||||||
|
}) }
|
||||||
|
|
||||||
|
|
||||||
|
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
||||||
|
|
||||||
|
override fun ViewBinding.initWindowInsets() {
|
||||||
|
setImmerseRootView(contentRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initViews() {
|
||||||
|
mType = intent.getIntExtra(EXTRA_TYPE, 0)
|
||||||
|
titlebar.setTitleText(R.string.title_withdraw_sub)
|
||||||
|
titlebar.setTitleTextSize(17F)
|
||||||
|
recyclerView.layoutManager = LinearLayoutManager(this@WithDrawSubActivity, LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
recyclerView.adapter = mAdapter
|
||||||
|
recyclerView.addItemDecoration(CommonItemDecoration.create(18, 0, false))
|
||||||
|
|
||||||
|
tvHint.movementMethod = ScrollingMovementMethod.getInstance()
|
||||||
|
tvHint.isSelected = true
|
||||||
|
|
||||||
|
val foreColorSpan = ForegroundColorSpan(ResUtil.getColor(R.color.green_39))
|
||||||
|
val ssb = SpannableString(tvTopHint.text).apply {
|
||||||
|
setSpan(foreColorSpan, 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
}
|
||||||
|
tvTopHint.text = ssb
|
||||||
|
|
||||||
|
|
||||||
|
setOnClickBatch(flAction) {
|
||||||
|
when(this) {
|
||||||
|
flAction -> {
|
||||||
|
when (mCurItem.subItemList[mSelectingIndex].withdrawState) {
|
||||||
|
WithdrawManager.STATE_NEED_WATCH_AD -> {
|
||||||
|
gotoWatchAd()
|
||||||
|
sendClickStatistic()
|
||||||
|
}
|
||||||
|
|
||||||
|
WithdrawManager.STATE_COULD_WITHDRAW -> {
|
||||||
|
tryRequestWithdraw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun tryRequestWithdraw() {
|
||||||
|
val subBean = mCurItem.subItemList[mSelectingIndex]
|
||||||
|
if (AccountManager.isBankAccountExist()) {
|
||||||
|
WithdrawInfoConfirmDialog(this@WithDrawSubActivity, { cashNum -> startRealWithdraw(cashNum) }).setWithDrawCashNum(subBean.cashTotal).show()
|
||||||
|
} else {
|
||||||
|
WithdrawBindBankDialog(this@WithDrawSubActivity, { cashNum -> startRealWithdraw(cashNum) }).setWithDrawCashNum(subBean.cashTotal).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun startRealWithdraw(cashNum: Double) {
|
||||||
|
val withdrawItemIndex = mCurItem.index
|
||||||
|
val withdrawSubItemIndex = mCurItem.subItemList[mSelectingIndex].dayIndex
|
||||||
|
WithdrawManager.instance().startWithdrawReal(cashNum, withdrawItemIndex, withdrawSubItemIndex, mCurItem.loopIndex)
|
||||||
|
WithdrawManager.instance().setItemStarted(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun showSuccessDialog(cashNum: Double) {
|
||||||
|
WithdrawSuccessDialog(this, cashNum).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showFailDialog(errorHintRes: Int) {
|
||||||
|
WithdrawFailDialog(this, errorHintRes).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleSubItemClicked(itemIndex: Int) {
|
||||||
|
val mMaxDayIndex = DateUtil.getDaysPassed(mCurItem.startMs)
|
||||||
|
if (itemIndex >= 0 && itemIndex <= mMaxDayIndex) {
|
||||||
|
mSelectingIndex = itemIndex
|
||||||
|
updateUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun gotoWatchAd() {
|
||||||
|
Router.WatchAd.startActivity(this, VidiConst.WATCH_AD_FOR_WITHDRAW_BIG, AndroidUtil.object2Json(mCurItem))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initListeners() {
|
||||||
|
registerEvents({ data->
|
||||||
|
when (data?.mEventType) {
|
||||||
|
VididinEvents.EVENT_AD_WATCHED_FOR_WITHDRAW_BIG -> {
|
||||||
|
handleAdWatched(data.mData as WatchAdNotifyBean<WithdrawItem>)
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_WITHDRAW_SUB_ITEM_PROGRESS_UPDATED -> {
|
||||||
|
if ((data.mData as Int) == mSelectingIndex) {
|
||||||
|
updateProgressUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_WITHDRAW_SELECTED_SUB_ITEM_CHANGED -> {
|
||||||
|
updateUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_WITHDRAW_ITEM_LIST_CHANGED -> {
|
||||||
|
updateUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_WITHDRAW_RESULT_UPDATED -> {
|
||||||
|
try {
|
||||||
|
val record = data.mData as RecordCash
|
||||||
|
if (record.withdrawItemIndex > 0) {
|
||||||
|
showTransactionResultDialog(record)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, VididinEvents.EVENT_AD_WATCHED_FOR_WITHDRAW_BIG,
|
||||||
|
VididinEvents.EVENT_WITHDRAW_SUB_ITEM_PROGRESS_UPDATED,
|
||||||
|
VididinEvents.EVENT_WITHDRAW_SELECTED_SUB_ITEM_CHANGED,
|
||||||
|
VididinEvents.EVENT_WITHDRAW_RESULT_UPDATED,
|
||||||
|
VididinEvents.EVENT_WITHDRAW_ITEM_LIST_CHANGED)
|
||||||
|
|
||||||
|
|
||||||
|
mCurItem = WithdrawManager.instance().getItem(mType)
|
||||||
|
if (mCurItem.startMs <= 0L) {
|
||||||
|
WithdrawManager.instance().startItem(mCurItem)
|
||||||
|
}
|
||||||
|
mSelectingIndex = DateUtil.getDaysPassed(mCurItem.startMs)
|
||||||
|
updateUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showTransactionResultDialog(record: RecordCash) {
|
||||||
|
if (!record.hasShowResultDialog && record.withdrawState != TRANSACTION_STATE_ONGOING) {
|
||||||
|
WithdrawManager.instance().updateRecordHasNotifyState(record.uuid)
|
||||||
|
when (record.withdrawState) {
|
||||||
|
TRANSACTION_STATE_SUCCESS -> {
|
||||||
|
showSuccessDialog(record.amountNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
TRANSACTION_STATE_FAIL -> {
|
||||||
|
showFailDialog(WithdrawManager.instance().getFailHintStrRes(record.withdrawFailType))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleAdWatched(adNotifyBean: WatchAdNotifyBean<WithdrawItem>) {
|
||||||
|
val withdrawItemBean = adNotifyBean.extraData
|
||||||
|
if (WithdrawManager.instance().addAdEarnForSubBean(withdrawItemBean.index,
|
||||||
|
mSelectingIndex, adNotifyBean.earnMoneyNum * VidiConst.WITHDRAW_REWARD_AD_REVENUE_PERCENT)) {
|
||||||
|
updateUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateUI() {
|
||||||
|
with(binding) {
|
||||||
|
mAdapter.mSelectedSubIndex = mSelectingIndex
|
||||||
|
mAdapter.submitList(mCurItem.subItemList)
|
||||||
|
mAdapter.notifyDataSetChanged()
|
||||||
|
recyclerView.scrollToPosition(mSelectingIndex)
|
||||||
|
|
||||||
|
tvCashTotal.text = mCurItem.totalCashNum.toString()
|
||||||
|
progressBar.enableTouch(false)
|
||||||
|
progressBar.setBarColor(forColor = R.color.green_ce)
|
||||||
|
updateProgressUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateProgressUI() {
|
||||||
|
with(binding) {
|
||||||
|
val subBean = mCurItem.subItemList[mSelectingIndex]
|
||||||
|
val curProgress = subBean.currentAdProgress
|
||||||
|
progressBar.setProgress(curProgress)
|
||||||
|
tvProgress.text = "${"%.2f".format(curProgress) }%"
|
||||||
|
|
||||||
|
ivAction.isVisible = curProgress < 100
|
||||||
|
if (curProgress < 100) {
|
||||||
|
tvAction.setText(R.string.withdraw_cash_out)
|
||||||
|
flAction.isClickable = true
|
||||||
|
flAction.alpha = 1F
|
||||||
|
|
||||||
|
sendShowStatistic()
|
||||||
|
} else {
|
||||||
|
var actionText = R.string.withdraw_cash_out
|
||||||
|
when(subBean.withdrawState) {
|
||||||
|
WithdrawManager.STATE_COULD_WITHDRAW -> {
|
||||||
|
actionText = R.string.withdraw_cash_out
|
||||||
|
flAction.isClickable = true
|
||||||
|
flAction.alpha = 1F
|
||||||
|
}
|
||||||
|
|
||||||
|
WithdrawManager.STATE_WITHDRAWING -> {
|
||||||
|
actionText = R.string.pending
|
||||||
|
flAction.isClickable = false
|
||||||
|
flAction.alpha = 0.6F
|
||||||
|
}
|
||||||
|
|
||||||
|
WithdrawManager.STATE_WITHDRAW_SUCCESS -> {
|
||||||
|
actionText = R.string.withdraw_success
|
||||||
|
flAction.isClickable = false
|
||||||
|
flAction.alpha = 0.6F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tvAction.setText(actionText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendShowStatistic() {
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_RV_Button_Show, mapOf("Position" to "RV_Accelerate2"))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendClickStatistic() {
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_RV_Button_Click, mapOf("Position" to "RV_Accelerate2"))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initObservers() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val EXTRA_TYPE = "EXTRA_TYPE"
|
||||||
|
internal fun startActivity(activity: Activity, withdrawType: Int) {
|
||||||
|
activity.startActivity(Intent(activity.applicationContext,
|
||||||
|
WithDrawSubActivity::class.java).apply { putExtra(EXTRA_TYPE, withdrawType) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
package com.gamedog.vididin.features.withdraw
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.text.Editable
|
|
||||||
import android.text.TextWatcher
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
|
||||||
import com.ama.core.architecture.widget.BindingDialog
|
|
||||||
import com.gamedog.vididin.R
|
|
||||||
import com.gamedog.vididin.core.login.login.AccountManager
|
|
||||||
import com.gamedog.vididin.databinding.DialogWithdrawBindingBankBinding as ViewBinding
|
|
||||||
import com.gamedog.vididin.router.Router
|
|
||||||
|
|
||||||
|
|
||||||
class WithdrawBindBankDialog(context: Context) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
build()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun build() {
|
|
||||||
with()
|
|
||||||
setBottom()
|
|
||||||
setMaskValue(0.9f)
|
|
||||||
setCanCancel(false)
|
|
||||||
|
|
||||||
mBinding.run {
|
|
||||||
setOnClickBatch(tvConfirm, ivClose) {
|
|
||||||
when (this) {
|
|
||||||
ivClose -> {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
tvConfirm -> {
|
|
||||||
saveBankAccount(mBinding.tvCpfEdit.text.toString().trim())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tvCpfEdit.addTextChangedListener(object : TextWatcher {
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
checkBankAccountValidation(s.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun beforeTextChanged(
|
|
||||||
s: CharSequence?,
|
|
||||||
start: Int,
|
|
||||||
count: Int,
|
|
||||||
after: Int
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTextChanged(
|
|
||||||
s: CharSequence?,
|
|
||||||
start: Int,
|
|
||||||
before: Int,
|
|
||||||
count: Int
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
checkBankAccountValidation("")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveBankAccount(bankAccount: String) {
|
|
||||||
AccountManager.saveBankAccount(bankAccount)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkBankAccountValidation(bankAccount: String) {
|
|
||||||
// TODO - forTesting- contain "B"
|
|
||||||
if (BankUtil.isValidCpf(bankAccount) || bankAccount.contains("B")) {
|
|
||||||
mBinding.ivState.isVisible = true
|
|
||||||
mBinding.ivState.setImageResource(R.mipmap.icon_success)
|
|
||||||
mBinding.tvConfirm.alpha = 1F
|
|
||||||
mBinding.tvConfirm.isClickable = true
|
|
||||||
} else {
|
|
||||||
mBinding.ivState.isVisible = !bankAccount.isEmpty()
|
|
||||||
mBinding.ivState.setImageResource(R.mipmap.icon_fail)
|
|
||||||
mBinding.tvConfirm.alpha = 0.3F
|
|
||||||
mBinding.tvConfirm.isClickable = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
|
||||||
ownerActivity?.let { Router.Withdraw.startActivity(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDetachedFromWindow() {
|
|
||||||
super.onDetachedFromWindow()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
package com.gamedog.vididin.features.withdraw
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
|
||||||
import com.ama.core.architecture.widget.BindingDialog
|
|
||||||
import com.gamedog.vididin.databinding.DialogWithdrawBindingBankFinishBinding as ViewBinding
|
|
||||||
import com.gamedog.vididin.router.Router
|
|
||||||
|
|
||||||
|
|
||||||
class WithdrawBindBankFinishDialog(context: Context) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
build()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun build() {
|
|
||||||
with()
|
|
||||||
setCenter()
|
|
||||||
setMaskValue(0.8f)
|
|
||||||
setCanCancel(false)
|
|
||||||
|
|
||||||
mBinding.run {
|
|
||||||
setOnClickBatch(tvConfirm, ivClose) {
|
|
||||||
when (this) {
|
|
||||||
tvConfirm, ivClose -> {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
|
||||||
ownerActivity?.let { Router.Withdraw.startActivity(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
package com.gamedog.vididin.features.withdraw
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
|
||||||
import com.ama.core.architecture.widget.BindingDialog
|
|
||||||
import com.gamedog.vididin.databinding.DialogWithdrawFailBinding as ViewBinding
|
|
||||||
import com.gamedog.vididin.router.Router
|
|
||||||
|
|
||||||
|
|
||||||
class WithdrawFailDialog(context: Context) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
build()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun build() {
|
|
||||||
with()
|
|
||||||
setCenter()
|
|
||||||
setMaskValue(0.8f)
|
|
||||||
setCanCancel(false)
|
|
||||||
|
|
||||||
mBinding.run {
|
|
||||||
setOnClickBatch(tvConfirm, ivClose) {
|
|
||||||
when (this) {
|
|
||||||
tvConfirm, ivClose -> {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
|
||||||
ownerActivity?.let { Router.Withdraw.startActivity(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw
|
||||||
|
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.gamedog.vididin.manager.WithdrawSubItem
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.viddin.videos.free.databinding.LayoutItemWithdrawSubBinding as ViewBinding
|
||||||
|
|
||||||
|
class WithdrawSubAdapter(private val selectCallback: (index: Int)->Unit) : ListAdapter<WithdrawSubItem, WithdrawSubAdapter.ViewHolder>(DiffCallback()) {
|
||||||
|
|
||||||
|
var mSelectedSubIndex: Int = 0
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val binding = ViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
return ViewHolder(binding,)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.itemView.rootView.setOnClickListener {
|
||||||
|
selectCallback.invoke(position)
|
||||||
|
}
|
||||||
|
holder.bind(getItem(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inner class ViewHolder(private val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(item: WithdrawSubItem) {
|
||||||
|
with(binding) {
|
||||||
|
tvTitle.text = buildString {
|
||||||
|
append(ResUtil.getString(R.string.cash))
|
||||||
|
append(item.cashTotal)
|
||||||
|
}
|
||||||
|
tvDay.text = buildString {
|
||||||
|
append(ResUtil.getString(R.string.day))
|
||||||
|
append(" ")
|
||||||
|
append(item.dayIndex + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.dayIndex == mSelectedSubIndex) {
|
||||||
|
root.setBackgroundResource(R.drawable.bg_withdraw_sub_selected)
|
||||||
|
root.alpha = 1F
|
||||||
|
ivLefttopChecked.isVisible = true
|
||||||
|
} else {
|
||||||
|
root.setBackgroundResource(R.drawable.bg_withdraw_sub_unselected)
|
||||||
|
root.alpha = 0.7F
|
||||||
|
ivLefttopChecked.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiffCallback : DiffUtil.ItemCallback<WithdrawSubItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: WithdrawSubItem, newItem: WithdrawSubItem): Boolean {
|
||||||
|
return oldItem.dayIndex == newItem.dayIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: WithdrawSubItem, newItem: WithdrawSubItem): Boolean {
|
||||||
|
return newItem == oldItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
|
||||||
|
interface WithdrawSubRouter {
|
||||||
|
fun startActivity(activity: Activity, withdrawType: Int)
|
||||||
|
}
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
package com.gamedog.vididin.features.withdraw
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
|
||||||
import com.ama.core.architecture.widget.BindingDialog
|
|
||||||
import com.gamedog.vididin.databinding.DialogWithdrawSuccessBinding as ViewBinding
|
|
||||||
import com.gamedog.vididin.router.Router
|
|
||||||
|
|
||||||
|
|
||||||
class WithdrawSuccessDialog(context: Context) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
build()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun build() {
|
|
||||||
with()
|
|
||||||
setCenter()
|
|
||||||
setMaskValue(0.8f)
|
|
||||||
setCanCancel(false)
|
|
||||||
|
|
||||||
mBinding.run {
|
|
||||||
setOnClickBatch(tvConfirm, ivClose) {
|
|
||||||
when (this) {
|
|
||||||
tvConfirm, ivClose -> {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
|
||||||
ownerActivity?.let { Router.Withdraw.startActivity(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.DeviceUtil
|
||||||
|
import com.ama.core.architecture.util.MD5Util
|
||||||
|
import com.ama.core.architecture.util.NetUtil
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.beans.req.PayInitReq
|
||||||
|
import com.gamedog.vididin.beans.req.PayoutCheckReq
|
||||||
|
import com.gamedog.vididin.beans.req.PayoutReq
|
||||||
|
import com.gamedog.vididin.beans.resp.PayInit
|
||||||
|
import com.gamedog.vididin.beans.resp.PayoutCheckData
|
||||||
|
import com.gamedog.vididin.beans.resp.PayoutData
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager
|
||||||
|
import com.gamedog.vididin.netbase.NetworkUtil
|
||||||
|
import com.gamedog.vididin.netbase.Result
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class WithdrawViewModel : ViewModel() {
|
||||||
|
private val _InitData = MutableStateFlow<Result<PayInit>>(Result.Loading)
|
||||||
|
val InitData: StateFlow<Result<PayInit>> = _InitData.asStateFlow()
|
||||||
|
|
||||||
|
private val _PayoutResult = MutableStateFlow<Result<PayoutData?>>(Result.Loading)
|
||||||
|
val PayoutResult: StateFlow<Result<PayoutData?>> = _PayoutResult.asStateFlow()
|
||||||
|
|
||||||
|
private val _CheckResult = MutableStateFlow<Result<PayoutCheckData?>>(Result.Loading)
|
||||||
|
val CheckResult: StateFlow<Result<PayoutCheckData?>> = _CheckResult.asStateFlow()
|
||||||
|
|
||||||
|
|
||||||
|
fun withdrawInit() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val requestParam = PayInitReq().applyInitFields()
|
||||||
|
|
||||||
|
_InitData.value = Result.Loading
|
||||||
|
_InitData.value = NetworkUtil.callApi {
|
||||||
|
NetworkUtil.apiservice().withdrawInit(requestParam)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun withdrawPayout(initUUID: String, payItemId: Int, payCashNum: Double) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val requestParam = PayoutReq().applyInitFields().apply {
|
||||||
|
val bankAccount = AccountManager.getAccount().bankInfo?.bankAccount
|
||||||
|
val accountType = "CPF"
|
||||||
|
|
||||||
|
account = bankAccount
|
||||||
|
item_id = payItemId
|
||||||
|
amount = payCashNum.toString()
|
||||||
|
additional_remark = "communnyboneycashmoneyrewardfastrealgame"
|
||||||
|
uuid = initUUID
|
||||||
|
account_type = accountType
|
||||||
|
document_type = accountType
|
||||||
|
document_id = bankAccount
|
||||||
|
name = "CapyBucks"
|
||||||
|
clientName = AndroidUtil.getPackageId()
|
||||||
|
|
||||||
|
|
||||||
|
dataAdjust.gps_adid = "gaid"
|
||||||
|
dataAdjust.android_id = "androidid"
|
||||||
|
dataAdjust.adid = "adid"
|
||||||
|
dataAdjust.user_agent = "GetUerAgent"
|
||||||
|
dataAdjust.price = amount
|
||||||
|
dataAdjust.currency = "USD"
|
||||||
|
|
||||||
|
dataShuShu.gps_gaid = "gaid"
|
||||||
|
dataShuShu.android_id = "androidid"
|
||||||
|
dataShuShu.adid = "adid"
|
||||||
|
dataShuShu.user_agent = "GetUerAgent"
|
||||||
|
dataShuShu.price = amount
|
||||||
|
dataShuShu.currency = "USD"
|
||||||
|
dataShuShu.payment_method = "Pix"
|
||||||
|
dataShuShu.payment_type = accountType
|
||||||
|
dataShuShu.payment_number = account
|
||||||
|
dataShuShu.iap_name = "100br"
|
||||||
|
dataShuShu.gamecoin_number = "100"
|
||||||
|
dataShuShu.gamecoin_type = "gold"
|
||||||
|
dataShuShu.ss_account_id = "GetSSAccountId"
|
||||||
|
dataShuShu.ss_distinct_id = "GetSSDistinctId"
|
||||||
|
dataShuShu.ss_super_properties = "GetSSSuper Properties"
|
||||||
|
}
|
||||||
|
|
||||||
|
_PayoutResult.value = Result.Loading
|
||||||
|
_PayoutResult.value = NetworkUtil.callApi {
|
||||||
|
NetworkUtil.apiservice().withdrawPayout(requestParam)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withdrawCheck(recordNo: String) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val requestParam = PayoutCheckReq().applyInitFields().apply {
|
||||||
|
record_no = recordNo
|
||||||
|
}
|
||||||
|
|
||||||
|
_CheckResult.value = Result.Loading
|
||||||
|
_CheckResult.value = NetworkUtil.callApi {
|
||||||
|
NetworkUtil.apiservice().withdrawCheck(requestParam)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun <T : PayInitReq> T.applyInitFields(): T {
|
||||||
|
return WithdrawManager.instance().applyInitFields(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw.dialogs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.gamedog.vididin.features.withdraw.BankUtil
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.STATE_COULD_WITHDRAW
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.STATE_NEED_WATCH_AD
|
||||||
|
import com.viddin.videos.free.databinding.DialogWithdrawBindingBankBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
class WithdrawBindBankDialog(activity: Activity, private val onConfirmedWithdraw: ((cashNum: Double)->Unit)?) : BindingDialog<ViewBinding>(activity, ViewBinding::inflate) {
|
||||||
|
|
||||||
|
private var mWithdrawCashNum: Double = 0.0
|
||||||
|
private var mWithdrawCashNumStr: String = ""
|
||||||
|
|
||||||
|
init {
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun build() {
|
||||||
|
with()
|
||||||
|
setBottom()
|
||||||
|
setMaskValue(0.9f)
|
||||||
|
setCanCancel(false)
|
||||||
|
|
||||||
|
mBinding.run {
|
||||||
|
setOnClickBatch(tvConfirm, ivClose) {
|
||||||
|
when (this) {
|
||||||
|
ivClose -> {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
tvConfirm -> {
|
||||||
|
saveBankAccount(mBinding.tvCpfEdit.text.toString().trim())
|
||||||
|
if (onConfirmedWithdraw != null) {
|
||||||
|
if (mWithdrawCashNum == 0.1 && WithdrawManager.instance().getItemState(0, 0) == STATE_NEED_WATCH_AD) {
|
||||||
|
WithdrawWatchAdDialog(mActivity, mWithdrawCashNum, onConfirmedWithdraw).show()
|
||||||
|
} else {
|
||||||
|
val dialogBuilder = WithdrawInfoConfirmDialog(mActivity, onConfirmedWithdraw)
|
||||||
|
if (mWithdrawCashNum > 0F) {
|
||||||
|
dialogBuilder.setWithDrawCashNum(mWithdrawCashNum)
|
||||||
|
} else {
|
||||||
|
dialogBuilder.setWithDrawCashNumStr(mWithdrawCashNumStr)
|
||||||
|
}
|
||||||
|
dialogBuilder.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tvCpfEdit.addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun afterTextChanged(s: Editable?) {
|
||||||
|
checkBankAccountValidation(s.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun beforeTextChanged(
|
||||||
|
s: CharSequence?,
|
||||||
|
start: Int,
|
||||||
|
count: Int,
|
||||||
|
after: Int
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(
|
||||||
|
s: CharSequence?,
|
||||||
|
start: Int,
|
||||||
|
before: Int,
|
||||||
|
count: Int
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
AccountManager.getAccount().bankInfo?.bankAccount.also { tvCpfEdit.setText(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
checkBankAccountValidation(mBinding.tvCpfEdit.text.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveBankAccount(bankAccount: String) {
|
||||||
|
AccountManager.saveBankAccount(bankAccount)
|
||||||
|
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Withdrawal_Info, mapOf("Info_Type" to "CPF", "Withdrawal_Account" to bankAccount))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkBankAccountValidation(bankAccount: String) {
|
||||||
|
if (BankUtil.isValidCpf(bankAccount) || (bankAccount.trim().length == 11)) {
|
||||||
|
mBinding.ivState.isVisible = true
|
||||||
|
mBinding.ivState.setImageResource(R.mipmap.icon_success)
|
||||||
|
mBinding.tvConfirm.alpha = 1F
|
||||||
|
mBinding.tvConfirm.isClickable = true
|
||||||
|
} else {
|
||||||
|
mBinding.ivState.isVisible = !bankAccount.isEmpty()
|
||||||
|
mBinding.ivState.setImageResource(R.mipmap.icon_fail)
|
||||||
|
mBinding.tvConfirm.alpha = 0.3F
|
||||||
|
mBinding.tvConfirm.isClickable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
override fun onDetachedFromWindow() {
|
||||||
|
super.onDetachedFromWindow()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun setWithDrawCashNum(withdrawNum: Double): WithdrawBindBankDialog {
|
||||||
|
mWithdrawCashNum = withdrawNum
|
||||||
|
|
||||||
|
if (mWithdrawCashNum == 0.0) {
|
||||||
|
mBinding.tvConfirm.text = ResUtil.getString(R.string.confirm)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setWithDrawCashNumStr(withdrawNumStr: String): WithdrawBindBankDialog {
|
||||||
|
mWithdrawCashNumStr = withdrawNumStr
|
||||||
|
|
||||||
|
if (mWithdrawCashNum == 0.0) {
|
||||||
|
mBinding.tvConfirm.text = ResUtil.getString(R.string.confirm)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw.dialogs
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
|
import com.viddin.videos.free.databinding.DialogWithdrawFailBinding as ViewBinding
|
||||||
|
import com.gamedog.vididin.router.Router
|
||||||
|
|
||||||
|
|
||||||
|
class WithdrawFailDialog(context: Activity, private val errorHintRes: Int) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun build() {
|
||||||
|
with()
|
||||||
|
setCenter()
|
||||||
|
setMaskValue(0.8f)
|
||||||
|
setCanCancel(false)
|
||||||
|
|
||||||
|
mBinding.run {
|
||||||
|
setOnClickBatch(tvActionFeedback, tvActionConfirm, ivClose) {
|
||||||
|
when (this) {
|
||||||
|
ivClose -> {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
tvActionFeedback -> {
|
||||||
|
gotoFeedback()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
tvActionConfirm -> {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//tvReason.setText(errorHintRes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun gotoFeedback() {
|
||||||
|
Router.Feedback.startActivity(mActivity)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw.dialogs
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.viddin.videos.free.databinding.DialogWithdrawInfoConfirmBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
class WithdrawInfoConfirmDialog(context: Activity, private val onConfirmed: (cashNum: Double)->Unit) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
||||||
|
|
||||||
|
private var mWithdrawCashNum: Double = 0.0
|
||||||
|
private var mWithdrawCashNumStr: String = ""
|
||||||
|
|
||||||
|
init {
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun build() {
|
||||||
|
with()
|
||||||
|
setCenter()
|
||||||
|
setMaskValue(0.8f)
|
||||||
|
setCanCancel(false)
|
||||||
|
|
||||||
|
mBinding.run {
|
||||||
|
setOnClickBatch(tvActionAlter, tvActionApply, ivClose) {
|
||||||
|
when (this) {
|
||||||
|
ivClose -> {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
tvActionAlter -> {
|
||||||
|
val dialogBuilder = WithdrawBindBankDialog(activity = mActivity, onConfirmed)
|
||||||
|
if (!mWithdrawCashNumStr.isEmpty()) {
|
||||||
|
dialogBuilder.setWithDrawCashNumStr(mWithdrawCashNumStr).show()
|
||||||
|
} else {
|
||||||
|
dialogBuilder.setWithDrawCashNum(mWithdrawCashNum).show()
|
||||||
|
}
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
tvActionApply -> {
|
||||||
|
onConfirmed.invoke(mWithdrawCashNum)
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Withdrawal_Apply,
|
||||||
|
mapOf("Withdrawal_Position" to mWithdrawCashNum,
|
||||||
|
"Withdrawal_Day" to 1))
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun setWithDrawCashNum(withdrawNum: Double): WithdrawInfoConfirmDialog {
|
||||||
|
mWithdrawCashNum = withdrawNum
|
||||||
|
|
||||||
|
mBinding.tvCashNum.text = buildString {
|
||||||
|
append(ResUtil.getString(R.string.cash))
|
||||||
|
append(" ")
|
||||||
|
append(mWithdrawCashNum)
|
||||||
|
}
|
||||||
|
mBinding.tvCpfAccount.text = AccountManager.getBankInfo()?.bankAccount
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setWithDrawCashNumStr(withdrawNumStr: String): WithdrawInfoConfirmDialog {
|
||||||
|
mWithdrawCashNumStr = withdrawNumStr
|
||||||
|
|
||||||
|
mBinding.tvCashNum.text = buildString {
|
||||||
|
append(mWithdrawCashNumStr)
|
||||||
|
}
|
||||||
|
mBinding.tvCpfAccount.text = AccountManager.getBankInfo()?.bankAccount
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw.dialogs
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.viddin.videos.free.databinding.DialogWithdrawSuccessBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
class WithdrawSuccessDialog(context: Activity, private val mCashNum: Double = 0.0, private val cashNumStr: String = "") : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun build() {
|
||||||
|
with()
|
||||||
|
setCenter()
|
||||||
|
setMaskValue(0.8f)
|
||||||
|
setCanCancel(false)
|
||||||
|
|
||||||
|
mBinding.run {
|
||||||
|
setOnClickBatch(flAction, ivClose) {
|
||||||
|
when (this) {
|
||||||
|
ivClose -> {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
flAction -> {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCashNum > 0F) {
|
||||||
|
tvCashNum.text = ResUtil.getString(R.string.cash) + " " + mCashNum.toString()
|
||||||
|
} else {
|
||||||
|
tvCashNum.text = cashNumStr
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw.dialogs
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager
|
||||||
|
import com.gamedog.vididin.router.Router
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.viddin.videos.free.databinding.DialogWithdrawWatchAdBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
class WithdrawWatchAdDialog(context: Activity, private var mWithdrawCashNum: Double, private val onConfirmed: (cashNum: Double)->Unit) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun build() {
|
||||||
|
with()
|
||||||
|
setCenter()
|
||||||
|
setMaskValue(0.8f)
|
||||||
|
setCanCancel(false)
|
||||||
|
|
||||||
|
mBinding.run {
|
||||||
|
progressBar.setBarColor(R.color.blue_ba, R.color.blue_ff)
|
||||||
|
|
||||||
|
val subItem = WithdrawManager.instance().getItem(0).subItemList[0]
|
||||||
|
val progress = ((subItem.hasEarnMoneyByAd / subItem.cashTotal) * 100)
|
||||||
|
progressBar.setProgress(progress.toInt())
|
||||||
|
tvProgress.text = "%.2f".format(progress) + "%"
|
||||||
|
|
||||||
|
setOnClickBatch(flAction, ivClose) {
|
||||||
|
when (this) {
|
||||||
|
ivClose -> {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
flAction -> {
|
||||||
|
gotoWatchVideo()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun gotoWatchVideo() {
|
||||||
|
Router.WatchAd.startActivity(mActivity, VidiConst.WATCH_AD_FOR_WITHDRAW_SMALL, AndroidUtil.object2Json(mWithdrawCashNum))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.gamedog.vididin.features.withdraw.widget
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.viddin.videos.free.databinding.WithdrawItemBankViewBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
class WithDrawItemBankView @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||||
|
private var mItemIndex: Int = 0
|
||||||
|
private var mIsSelected = false
|
||||||
|
private var mBinding: ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
mBinding = ViewBinding.inflate(LayoutInflater.from(context), this, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateBankAccountInfo() {
|
||||||
|
with(mBinding) {
|
||||||
|
if (AccountManager.isBankAccountExist()) {
|
||||||
|
bankContainer.isVisible = true
|
||||||
|
tvBankHint.isVisible = false
|
||||||
|
AccountManager.getBankInfo()?.bankAccount?.let {
|
||||||
|
tvBankAccount.text = it
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bankContainer.isVisible = false
|
||||||
|
tvBankHint.isVisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAttachedToWindow() {
|
||||||
|
super.onAttachedToWindow()
|
||||||
|
updateBankAccountInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For withdraw number in top area
|
||||||
|
*/
|
||||||
|
fun setAction(itemIndex: Int, clickAction: (Int)->Unit) {
|
||||||
|
mItemIndex = itemIndex
|
||||||
|
mBinding.root.setOnClickListener {
|
||||||
|
clickAction.invoke(mItemIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For bank item in bottom area
|
||||||
|
*/
|
||||||
|
fun setIconAndText(iconRes: Int, textRes: Int, clickAction: ()->Unit) {
|
||||||
|
mBinding.tvWithdrawNum.text = ResUtil.getString(textRes)
|
||||||
|
mBinding.ivItemIcon.setImageResource(iconRes)
|
||||||
|
mBinding.root.setOnClickListener {
|
||||||
|
clickAction.invoke()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSelectedState(isSelected: Boolean) {
|
||||||
|
mIsSelected = isSelected
|
||||||
|
mBinding.root.setBackgroundResource(if (mIsSelected) R.drawable.withdraw_item_bg_selected else R.drawable.withdraw_item_bg_unselected)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
package com.gamedog.vididin.features.withdraw.widget
|
package com.gamedog.vididin.features.withdraw.widget
|
||||||
|
|
||||||
|
import android.accounts.AccountManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import com.ama.core.architecture.util.ResUtil
|
import com.ama.core.architecture.util.ResUtil
|
||||||
import com.gamedog.vididin.R
|
import com.ama.core.architecture.util.SpUtil
|
||||||
import com.gamedog.vididin.databinding.WithdrawItemViewBinding as ViewBinding
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.gamedog.statisticreporter.adjust.SpHelper.Companion.KEY_USER_FROM_TYPE
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.STATE_WITHDRAWING
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.viddin.videos.free.databinding.WithdrawItemViewBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
class WithDrawItemView @JvmOverloads constructor(
|
class WithDrawItemView @JvmOverloads constructor(
|
||||||
|
|
@ -15,8 +21,7 @@ class WithDrawItemView @JvmOverloads constructor(
|
||||||
defStyleAttr: Int = 0
|
defStyleAttr: Int = 0
|
||||||
) : LinearLayout(context, attrs, defStyleAttr) {
|
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||||
private var mItemIndex: Int = 0
|
private var mItemIndex: Int = 0
|
||||||
private var mIsSelected = false
|
private var mCashNum: Double = 0.0
|
||||||
private var mCashNum: Float = 0F
|
|
||||||
private var mBinding: ViewBinding
|
private var mBinding: ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -28,30 +33,50 @@ class WithDrawItemView @JvmOverloads constructor(
|
||||||
/**
|
/**
|
||||||
* For withdraw number in top area
|
* For withdraw number in top area
|
||||||
*/
|
*/
|
||||||
fun setNumAndAction(itemIndex: Int, cashNum: Float, clickAction: (Int)->Unit) {
|
fun setNumAndAction(itemIndex: Int, cashNum: Double, clickAction: (Int)->Unit) {
|
||||||
mItemIndex = itemIndex
|
mItemIndex = itemIndex
|
||||||
mCashNum = cashNum
|
mCashNum = cashNum
|
||||||
mBinding.tvWithdrawNum.text = cashNum.toString()
|
mBinding.tvWithdrawNum.text = ResUtil.getString(R.string.cash) + " " +
|
||||||
mBinding.root.setOnClickListener {
|
if (cashNum.toString().endsWith(".0")) cashNum.toString().substring(0, cashNum.toString().indexOf(".0")) else cashNum.toString()
|
||||||
|
|
||||||
|
setOnClickBatch(mBinding.tvSacar) {
|
||||||
|
when (this) {
|
||||||
|
mBinding.tvSacar-> {
|
||||||
clickAction.invoke(mItemIndex)
|
clickAction.invoke(mItemIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For bank item in bottom area
|
|
||||||
*/
|
|
||||||
fun setIconAndText(iconRes: Int, textRes: Int, clickAction: ()->Unit) {
|
|
||||||
mBinding.tvWithdrawNum.text = ResUtil.getString(textRes)
|
|
||||||
mBinding.ivItemIcon.setImageResource(iconRes)
|
|
||||||
mBinding.root.setOnClickListener {
|
|
||||||
clickAction.invoke()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSelectedState(isSelected: Boolean) {
|
updateProgressAndButUI()
|
||||||
mIsSelected = isSelected
|
}
|
||||||
mBinding.root.setBackgroundResource(if (mIsSelected) R.drawable.withdraw_item_bg_selected else R.drawable.withdraw_item_bg_unselected)
|
|
||||||
|
|
||||||
|
fun getCashNum(): Double {
|
||||||
|
return mCashNum
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateProgressAndButUI() {
|
||||||
|
var itemProgress = WithdrawManager.instance().getItemProgress(mItemIndex) * 100
|
||||||
|
|
||||||
|
/*if (mItemIndex == 0 && SpUtil.instance().getInt(KEY_USER_FROM_TYPE) == 2 && itemProgress > 0) {
|
||||||
|
itemProgress = 100.0
|
||||||
|
}*/
|
||||||
|
|
||||||
|
with(mBinding) {
|
||||||
|
progressBar.setProgress(itemProgress.toInt())
|
||||||
|
tvProgress.text = String.format("%.2f", itemProgress) + ResUtil.getString(R.string.percent)
|
||||||
|
|
||||||
|
var is01Withdrawing = false
|
||||||
|
if (mItemIndex == 0) {
|
||||||
|
is01Withdrawing = WithdrawManager.instance().getItemState(mItemIndex, 0) == STATE_WITHDRAWING
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// update ui
|
||||||
|
val canClickable: Boolean = itemProgress >= 100F && !is01Withdrawing
|
||||||
|
tvSacar.isClickable = canClickable
|
||||||
|
tvSacar.alpha = if (canClickable) 1F else 0.5F
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.gamedog.vididin.features.withdrawrecord
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.beans.RECORD_CASH_PLUS_GOLD_CONVERT
|
||||||
|
import com.gamedog.vididin.beans.RecordCashShow
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import com.viddin.videos.free.databinding.FragmentWithdrawRecordCashItemBinding as ViewBinding
|
||||||
|
|
||||||
|
class RecordCashRvAdapter : ListAdapter<RecordCashShow, RecordCashRvAdapter.ViewHolder>(DiffCallback()) {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val binding = ViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
return ViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(getItem(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ViewHolder(private val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(data: RecordCashShow) {
|
||||||
|
binding.tvDate.text = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(data.dateMs)
|
||||||
|
binding.tvTitle.text = ResUtil.getString(data.title)
|
||||||
|
binding.ivType.setImageResource(data.iconRes)
|
||||||
|
|
||||||
|
binding.tvAmount.text = (if (data.amountNum < 0) "-" else "+") + ResUtil.getString(R.string.cash) + " " + String.format("%.2f", Math.abs(data.amountNum))
|
||||||
|
binding.tvAmount.setTextColor(ResUtil.getColor(data.textColor))
|
||||||
|
|
||||||
|
if (data.recordType == RECORD_CASH_PLUS_GOLD_CONVERT) {
|
||||||
|
binding.tvDescription.text = String.format(ResUtil.getString(data.description), Math.abs(data.amountNum *10 * VidiConst.PER_01CASH_COST_GOLD_NUM).toInt())
|
||||||
|
} else {
|
||||||
|
binding.tvDescription.text = ResUtil.getString(data.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiffCallback : DiffUtil.ItemCallback<RecordCashShow>() {
|
||||||
|
override fun areItemsTheSame(oldItem: RecordCashShow, newItem: RecordCashShow): Boolean {
|
||||||
|
return oldItem.uuid == newItem.uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: RecordCashShow, newItem: RecordCashShow): Boolean {
|
||||||
|
return oldItem.uuid == newItem.uuid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.gamedog.vididin.features.withdrawrecord
|
||||||
|
|
||||||
|
|
||||||
|
import com.ama.core.architecture.appBase.vm.AppViewModel
|
||||||
|
import com.gamedog.vididin.beans.RecordCash
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import javax.inject.Inject
|
||||||
|
import com.gamedog.vididin.features.withdrawrecord.RecordCashUiState as UiState
|
||||||
|
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class RecordCashViewModel @Inject constructor() : AppViewModel<UiState>() {
|
||||||
|
override val uiStateInitialValue: UiState = UiState()
|
||||||
|
override val uiStateFlow: Flow<UiState> = flowOf()
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data class RecordCashUiState(
|
||||||
|
val mRecordList: MutableList<RecordCash> = mutableListOf()
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.gamedog.vididin.features.withdrawrecord
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.gamedog.vididin.beans.RECORD_GOLD_MINUS_CONVERT_2_CASH
|
||||||
|
import com.gamedog.vididin.beans.RecordGoldShow
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import com.viddin.videos.free.databinding.FragmentWithdrawRecordGoldItemBinding as ViewBinding
|
||||||
|
|
||||||
|
class RecordGoldRvAdapter : ListAdapter<RecordGoldShow, RecordGoldRvAdapter.ViewHolder>(DiffCallback()) {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val binding = ViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
return ViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(getItem(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ViewHolder(private val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(data: RecordGoldShow) {
|
||||||
|
binding.tvDate.text = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(data.dateMs)
|
||||||
|
binding.tvTitle.text = ResUtil.getString(data.title)
|
||||||
|
binding.tvAmount.text = (if(data.amountNum > 0) "+" else "") + data.amountNum.toString()
|
||||||
|
binding.ivType.setImageResource(data.iconRes)
|
||||||
|
if (data.recordType == RECORD_GOLD_MINUS_CONVERT_2_CASH) {
|
||||||
|
binding.tvDescription.text = String.format(ResUtil.getString(data.description), Math.abs(data.amountNum))
|
||||||
|
} else {
|
||||||
|
binding.tvDescription.text = ResUtil.getString(data.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiffCallback : DiffUtil.ItemCallback<RecordGoldShow>() {
|
||||||
|
override fun areItemsTheSame(oldItem: RecordGoldShow, newItem: RecordGoldShow): Boolean {
|
||||||
|
return oldItem.uuid == newItem.uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: RecordGoldShow, newItem: RecordGoldShow): Boolean {
|
||||||
|
return oldItem.uuid == newItem.uuid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.gamedog.vididin.features.withdrawrecord
|
||||||
|
|
||||||
|
|
||||||
|
import com.ama.core.architecture.appBase.vm.AppViewModel
|
||||||
|
import com.gamedog.vididin.beans.RecordGold
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import javax.inject.Inject
|
||||||
|
import com.gamedog.vididin.features.withdrawrecord.RecordGoldUiState as UiState
|
||||||
|
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class RecordGoldViewModel @Inject constructor() : AppViewModel<UiState>() {
|
||||||
|
override val uiStateInitialValue: UiState = UiState()
|
||||||
|
override val uiStateFlow: Flow<UiState> = flowOf()
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data class RecordGoldUiState(
|
||||||
|
val mRecordList: MutableList<RecordGold> = mutableListOf()
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.gamedog.vididin.features.withdrawrecord
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
import com.gamedog.vididin.features.withdrawrecord.fragments.CashRecordFragment
|
||||||
|
import com.gamedog.vididin.features.withdrawrecord.fragments.GoldRecordFragment
|
||||||
|
|
||||||
|
class ViewPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = 2
|
||||||
|
|
||||||
|
override fun createFragment(position: Int): Fragment {
|
||||||
|
return when (position) {
|
||||||
|
0 -> CashRecordFragment()
|
||||||
|
1 -> GoldRecordFragment()
|
||||||
|
else -> throw IllegalArgumentException("Invalid position: $position")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,15 +4,16 @@ import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.core.view.ViewCompat
|
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import androidx.core.view.updatePadding
|
|
||||||
import com.ama.core.architecture.appBase.AppViewsActivity
|
import com.ama.core.architecture.appBase.AppViewsActivity
|
||||||
import com.gamedog.vididin.R
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.viddin.videos.free.R
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
||||||
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import kotlin.getValue
|
||||||
import com.gamedog.vididin.databinding.ActivityWithdrawRecordBinding as ViewBinding
|
import com.viddin.videos.free.databinding.ActivityWithdrawRecordBinding as ViewBinding
|
||||||
import com.gamedog.vididin.main.MainUiState as UiState
|
import com.gamedog.vididin.main.MainUiState as UiState
|
||||||
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
||||||
|
|
||||||
|
|
@ -26,19 +27,21 @@ class WithdrawRecordActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>
|
||||||
override fun ViewBinding.initViews() {
|
override fun ViewBinding.initViews() {
|
||||||
|
|
||||||
with(binding) {
|
with(binding) {
|
||||||
titlebar.setBackIconColor(R.color.black)
|
setupViewPager()
|
||||||
titlebar.setTitleText(R.string.title_cash_record, R.color.black)
|
|
||||||
|
setOnClickBatch(ivBack) {
|
||||||
|
when (this) {
|
||||||
|
ivBack -> {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initWindowInsets() {
|
override fun ViewBinding.initWindowInsets() {
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(contentRoot) { v, insets ->
|
setImmerseRootView(binding.root)
|
||||||
val systemBars =
|
|
||||||
insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
|
|
||||||
v.updatePadding(top = systemBars.top)
|
|
||||||
insets
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initListeners() {
|
override fun ViewBinding.initListeners() {
|
||||||
|
|
@ -58,6 +61,36 @@ class WithdrawRecordActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun setupViewPager() {
|
||||||
|
val adapter = ViewPagerAdapter(this)
|
||||||
|
binding.viewPager.adapter = adapter
|
||||||
|
|
||||||
|
with (binding.tabLayout) {
|
||||||
|
addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener {
|
||||||
|
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||||
|
setTabTextColors(ResUtil.getColor(R.color.black),
|
||||||
|
ResUtil.getColor(if (selectedTabPosition == 0) R.color.green_39 else R.color.yellow_0b))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTabUnselected(tab: TabLayout.Tab?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTabReselected(tab: TabLayout.Tab?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
|
||||||
|
tab.text = when (position) {
|
||||||
|
0 -> ResUtil.getString(R.string.record_cash_title)
|
||||||
|
1 -> ResUtil.getString(R.string.record_gold_title)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}.attach()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
internal fun startActivity(activity: Activity) {
|
internal fun startActivity(activity: Activity) {
|
||||||
activity.startActivity(Intent(activity.applicationContext, WithdrawRecordActivity::class.java))
|
activity.startActivity(Intent(activity.applicationContext, WithdrawRecordActivity::class.java))
|
||||||
|
|
@ -65,3 +98,8 @@ class WithdrawRecordActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
package com.gamedog.vididin.features.withdrawrecord.fragments
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.ama.core.architecture.appBase.AppViewsFragment
|
||||||
|
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.ama.core.architecture.util.setStatusBarDarkFont
|
||||||
|
import com.gamedog.vididin.features.withdrawrecord.RecordCashRvAdapter
|
||||||
|
import com.gamedog.vididin.manager.RecordsManager
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlin.getValue
|
||||||
|
import com.viddin.videos.free.databinding.FragmentWithdrawRecordCashBinding as ViewBinding
|
||||||
|
import com.gamedog.vididin.features.withdrawrecord.RecordCashUiState as UiState
|
||||||
|
import com.gamedog.vididin.features.withdrawrecord.RecordCashViewModel as ViewModel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class CashRecordFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(),
|
||||||
|
OnFragmentBackgroundListener {
|
||||||
|
private lateinit var mAdapter: RecordCashRvAdapter
|
||||||
|
override val mViewModel: ViewModel by viewModels()
|
||||||
|
override var isBackgroundBright: Boolean = true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private var isStatusBarDarkFont = false
|
||||||
|
|
||||||
|
override fun inflateViewBinding(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
) = ViewBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
|
override fun ViewBinding.initWindowInsets() {
|
||||||
|
binding?.root?.let { setImmerseRootView(it) }
|
||||||
|
isStatusBarDarkFont = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initViews() {
|
||||||
|
setupRecyclerView()
|
||||||
|
|
||||||
|
tvCashNum.text = buildString {
|
||||||
|
append(ResUtil.getString(R.string.cash))
|
||||||
|
append(" ")
|
||||||
|
append(WithdrawManager.instance().getHasWithdrawSuccessCashCount())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initListeners() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initObservers() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
setStatusBarDarkFont(isDarkFont = isStatusBarDarkFont)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun setupRecyclerView() {
|
||||||
|
mAdapter = RecordCashRvAdapter()
|
||||||
|
binding?.recyclerView?.adapter = mAdapter
|
||||||
|
binding?.recyclerView?.layoutManager = LinearLayoutManager(requireContext())
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
mAdapter.submitList(RecordsManager.instance().getCashRecords())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal fun newInstance() = CashRecordFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.gamedog.vididin.features.withdrawrecord.fragments
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.ama.core.architecture.appBase.AppViewsFragment
|
||||||
|
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
|
||||||
|
import com.ama.core.architecture.util.setStatusBarDarkFont
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.gamedog.vididin.features.withdrawrecord.RecordGoldRvAdapter
|
||||||
|
import com.gamedog.vididin.manager.RecordsManager
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlin.getValue
|
||||||
|
import com.viddin.videos.free.databinding.FragmentWithdrawRecordGoldBinding as ViewBinding
|
||||||
|
import com.gamedog.vididin.features.withdrawrecord.RecordGoldUiState as UiState
|
||||||
|
import com.gamedog.vididin.features.withdrawrecord.RecordGoldViewModel as ViewModel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class GoldRecordFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(),
|
||||||
|
OnFragmentBackgroundListener {
|
||||||
|
private lateinit var mAdapter: RecordGoldRvAdapter
|
||||||
|
override val mViewModel: ViewModel by viewModels()
|
||||||
|
override var isBackgroundBright: Boolean = true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private var isStatusBarDarkFont = false
|
||||||
|
|
||||||
|
override fun inflateViewBinding(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
) = ViewBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
|
override fun ViewBinding.initWindowInsets() {
|
||||||
|
binding?.root?.let { setImmerseRootView(it) }
|
||||||
|
isStatusBarDarkFont = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initViews() {
|
||||||
|
setupRecyclerView()
|
||||||
|
tvGoldNum.text = AccountManager.getGold().toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initListeners() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.initObservers() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
setStatusBarDarkFont(isDarkFont = isStatusBarDarkFont)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun setupRecyclerView() {
|
||||||
|
mAdapter = RecordGoldRvAdapter()
|
||||||
|
binding?.recyclerView?.adapter = mAdapter
|
||||||
|
binding?.recyclerView?.layoutManager = LinearLayoutManager(requireContext())
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
mAdapter.submitList(RecordsManager.instance().getGoldRecords())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
internal fun newInstance() = CashRecordFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,86 +4,242 @@ import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.core.view.updatePadding
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.ama.core.architecture.appBase.AppViewsActivity
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelActivity
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.CommonItemDecoration
|
||||||
|
import com.ama.core.architecture.util.SpUtil
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
import com.gamedog.vididin.R
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.VididinEvents
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.gamedog.vididin.beans.ZeroBuyItem
|
||||||
|
import com.gamedog.vididin.beans.ZeroBuyResp
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.gamedog.vididin.features.withdraw.dialogs.WithdrawSuccessDialog
|
||||||
|
import com.gamedog.vididin.features.zero.dialogs.ZeroBuyNotWinDialog
|
||||||
|
import com.gamedog.vididin.features.zero.dialogs.ZeroBuyRulesDialog
|
||||||
|
import com.gamedog.vididin.features.zero.dialogs.ZeroBuyWinDialog
|
||||||
|
import com.gamedog.vididin.manager.ZeroManager
|
||||||
import com.gamedog.vididin.router.Router
|
import com.gamedog.vididin.router.Router
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import kotlinx.coroutines.launch
|
||||||
import com.gamedog.vididin.databinding.ActivityZerobuyBinding as ViewBinding
|
import com.gamedog.vididin.netbase.Result
|
||||||
import com.gamedog.vididin.main.MainUiState as UiState
|
import kotlin.collections.contains
|
||||||
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
import com.viddin.videos.free.databinding.ActivityZerobuyBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class ZeroBuyActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
class ZeroBuyActivity : AppViewsEmptyViewModelActivity<ViewBinding>() {
|
||||||
|
private val viewModel: ZeroBuyViewModel by viewModels()
|
||||||
|
private lateinit var mAdapter: ZeroItemAdapter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override val mViewModel: ViewModel by viewModels()
|
|
||||||
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
||||||
|
|
||||||
override fun ViewBinding.initViews() {
|
override fun ViewBinding.initViews() {
|
||||||
binding.run {
|
binding.run {
|
||||||
setOnClickBatch(tvZeroGoldNum, tvZeroLotteryList) {
|
setOnClickBatch(tvZeroGoldNum, tvZeroLotteryList, llDiamondAd) {
|
||||||
when (this) {
|
when (this) {
|
||||||
tvZeroGoldNum -> {
|
tvZeroGoldNum -> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tvZeroLotteryList -> {
|
tvZeroLotteryList -> {
|
||||||
gotoLotteryRecords()
|
gotoLotteryRecords()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llDiamondAd -> {
|
||||||
|
gotoEarnDiamond()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateUIDiamondNum()
|
||||||
|
|
||||||
titlebar.setTitleText(R.string.zero_buy)
|
titlebar.setTitleText(R.string.zero_buy)
|
||||||
titlebar.addRightIcon(R.mipmap.icon_question_mark, {
|
titlebar.addRightIcon(R.mipmap.icon_question_mark, {
|
||||||
showHintInfo()
|
showHintInfo()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
with(recyclerView) {
|
||||||
|
mAdapter = ZeroItemAdapter({ itemId, diamondCost->
|
||||||
|
|
||||||
|
if (AccountManager.getDiamond() >= diamondCost) {
|
||||||
|
requestParticipateActivity(itemId)
|
||||||
|
} else {
|
||||||
|
AndroidUtil.showToast(R.string.dont_enought_diamond)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
adapter = mAdapter
|
||||||
|
layoutManager = GridLayoutManager(this@ZeroBuyActivity, 2)
|
||||||
|
addItemDecoration(
|
||||||
|
CommonItemDecoration.create(horizontalSpace = 45, verticalSpace = 45)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZeroBuyRulesDialog(this@ZeroBuyActivity).show()
|
StatisticUtil.reportEvents(StatisticUtil.KEY_lottery_Show)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun ViewBinding.initWindowInsets() {
|
override fun ViewBinding.initWindowInsets() {
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(contentRoot) { v, insets ->
|
setImmerseRootView(contentRoot)
|
||||||
val systemBars =
|
|
||||||
insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
|
|
||||||
v.updatePadding(top = systemBars.top)
|
|
||||||
insets
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showHintInfo() {
|
private fun showHintInfo() {
|
||||||
//TODO("Not yet implemented")
|
ZeroBuyRulesDialog(this@ZeroBuyActivity).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initListeners() {
|
override fun ViewBinding.initListeners() {
|
||||||
//TODO("Not yet implemented")
|
registerEvents({ data->
|
||||||
|
when (data?.mEventType) {
|
||||||
|
VididinEvents.Event_Account_Diamond_Changed -> {
|
||||||
|
updateUIDiamondNum()
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_ZERO_WITHDRAW_LIST_CHANGED -> {
|
||||||
|
checkPreWithdrawWaitNotifyResult()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, VididinEvents.Event_Account_Diamond_Changed,
|
||||||
|
VididinEvents.EVENT_ZERO_WITHDRAW_LIST_CHANGED)
|
||||||
|
|
||||||
|
requestData()
|
||||||
|
|
||||||
|
checkPreWithdrawWaitNotifyResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkPreWithdrawWaitNotifyResult() {
|
||||||
|
val waitNotifyList = ZeroManager.instance().getWaitNotifyResultList()
|
||||||
|
|
||||||
|
waitNotifyList.forEach {
|
||||||
|
WithdrawSuccessDialog(this, cashNumStr = it.winCashNumStr).show()
|
||||||
|
ZeroManager.instance().updateHasNotifyValue(it.purchase_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateUIDiamondNum() {
|
||||||
|
binding.tvZeroGoldNum.text = AccountManager.getDiamond().toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initObservers() {
|
override fun ViewBinding.initObservers() {
|
||||||
//TODO("Not yet implemented")
|
//TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
|
|
||||||
//TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTabIsDarkFont(isDarkFont: Boolean) {
|
|
||||||
//TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun gotoLotteryRecords() {
|
private fun gotoLotteryRecords() {
|
||||||
Router.WinRecord.startActivity(this)
|
Router.WinRecord.startActivity(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun gotoEarnDiamond() {
|
||||||
|
Router.WatchAd.startActivity(this, VidiConst.WATCH_AD_FOR_ZERO_EARN_DIAMOND)
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------- start -----------------------------
|
||||||
|
|
||||||
|
|
||||||
|
private fun requestData() {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
viewModel.ZeroBuyListData.collect { result ->
|
||||||
|
when (result) {
|
||||||
|
is Result.Loading -> { showLoading(false) }
|
||||||
|
is Result.Success -> {
|
||||||
|
hideLoading()
|
||||||
|
updateUIs(result.data)
|
||||||
|
}
|
||||||
|
is Result.Error -> {
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.requestZeroBuyInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun requestParticipateActivity(itemId: Int) {
|
||||||
|
val joinedItemIds: List<Int> = SpUtil.instance().getList<Int>(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS)
|
||||||
|
if (!joinedItemIds.contains(AccountManager.getAccount()?.userId)) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
viewModel.ZeroBuyJoinResult.collect { result ->
|
||||||
|
when (result) {
|
||||||
|
is Result.Loading -> { }
|
||||||
|
is Result.Success -> {
|
||||||
|
result.data?.let {
|
||||||
|
AccountManager.adjustDiamond(-1 * it.cost)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateItemUI(result.data)
|
||||||
|
}
|
||||||
|
is Result.Error -> { AndroidUtil.showToast(R.string.has_join_failed_zerobuy) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.requestJoinZeroBuy(itemId)
|
||||||
|
} else {
|
||||||
|
AndroidUtil.showToast(R.string.has_joined_zerobuy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun updateUIs(data: ZeroBuyResp) {
|
||||||
|
mAdapter.submitList(data.current_purchases)
|
||||||
|
showCompletePurchasesInfo(data.finished_purchases)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showCompletePurchasesInfo(finishedList: List<ZeroBuyItem>?) {
|
||||||
|
finishedList?.let {
|
||||||
|
val userId = AccountManager.getAccount().userId
|
||||||
|
val joinedIdList = SpUtil.instance().getList<Int>(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS)
|
||||||
|
val hasNotifiedIdList: MutableList<Int> = SpUtil.instance().getList<Int>(SpUtil.KEY_ZEROBUY_HAS_NOTIFY_IDS).toMutableList()
|
||||||
|
it.forEach { item->
|
||||||
|
if (joinedIdList.contains(item.id) && !hasNotifiedIdList.contains(item.id)) {
|
||||||
|
hasNotifiedIdList.add(item.id)
|
||||||
|
|
||||||
|
item.winners?.let {
|
||||||
|
if (it.contains(userId)) {
|
||||||
|
ZeroBuyWinDialog(this@ZeroBuyActivity, item).show()
|
||||||
|
} else {
|
||||||
|
ZeroBuyNotWinDialog(this@ZeroBuyActivity, item).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SpUtil.instance().putList(SpUtil.KEY_ZEROBUY_HAS_NOTIFY_IDS, hasNotifiedIdList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateItemUI(joinedItem: ZeroBuyItem?) {
|
||||||
|
if (joinedItem == null) {
|
||||||
|
mAdapter.notifyDataSetChanged()
|
||||||
|
} else {
|
||||||
|
val currentList = mAdapter.currentList.toMutableList()
|
||||||
|
val indexToUpdate = currentList.indexOfFirst { it.id == joinedItem?.id }
|
||||||
|
if (indexToUpdate != -1) {
|
||||||
|
currentList.removeAt(indexToUpdate)
|
||||||
|
currentList.add(indexToUpdate, joinedItem)
|
||||||
|
mAdapter.submitList(currentList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------- end -----------------------------
|
||||||
companion object {
|
companion object {
|
||||||
internal fun startActivity(activity: Activity) {
|
internal fun startActivity(activity: Activity) {
|
||||||
activity.startActivity(Intent(activity.applicationContext, ZeroBuyActivity::class.java))
|
activity.startActivity(Intent(activity.applicationContext, ZeroBuyActivity::class.java))
|
||||||
|
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
package com.gamedog.vididin.features.zero
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
|
||||||
import com.ama.core.architecture.widget.BindingDialog
|
|
||||||
import com.gamedog.vididin.databinding.DialogZeroBuyFailBinding as ViewBinding
|
|
||||||
import com.gamedog.vididin.router.Router
|
|
||||||
|
|
||||||
|
|
||||||
class ZeroBuyFailDialog(context: Context) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
build()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun build() {
|
|
||||||
with()
|
|
||||||
setCenter()
|
|
||||||
setMaskValue(0.8f)
|
|
||||||
setCanCancel(false)
|
|
||||||
|
|
||||||
mBinding.run {
|
|
||||||
setOnClickBatch(tvConfirm, ivClose) {
|
|
||||||
when (this) {
|
|
||||||
tvConfirm, ivClose -> {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
|
||||||
ownerActivity?.let { Router.Withdraw.startActivity(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
package com.gamedog.vididin.features.zero
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
|
import com.ama.core.architecture.util.DeviceUtil
|
||||||
|
import com.ama.core.architecture.util.SpUtil
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.VidiConst.ZERO_GET_PURCHASE_LIST
|
||||||
|
import com.gamedog.vididin.VidiConst.ZERO_JOIN_PURCHASE
|
||||||
|
import com.gamedog.vididin.beans.ZeroBuyItem
|
||||||
|
import com.gamedog.vididin.beans.ZeroBuyResp
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.gamedog.vididin.netbase.NetworkUtil
|
||||||
|
import com.gamedog.vididin.netbase.Result
|
||||||
|
import com.gamedog.vididin.request.RequestUtil
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
|
||||||
|
class ZeroBuyViewModel : ViewModel() {
|
||||||
|
private val CODE_HAS_JOINED_BEFORE: Int = 10003
|
||||||
|
private val _ZeroBuyListData = MutableStateFlow<Result<ZeroBuyResp>>(Result.Loading)
|
||||||
|
val ZeroBuyListData: StateFlow<Result<ZeroBuyResp>> = _ZeroBuyListData.asStateFlow()
|
||||||
|
|
||||||
|
private val _ZeroBuyJoinResult = MutableStateFlow<Result<ZeroBuyItem?>>(Result.Loading)
|
||||||
|
val ZeroBuyJoinResult: StateFlow<Result<ZeroBuyItem?>> = _ZeroBuyJoinResult.asStateFlow()
|
||||||
|
|
||||||
|
|
||||||
|
fun requestJoinZeroBuy(itemId: Int) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_ZeroBuyJoinResult.value = Result.Loading
|
||||||
|
|
||||||
|
val operationVal = ZERO_JOIN_PURCHASE
|
||||||
|
val curTimeSec = System.currentTimeMillis()/1000
|
||||||
|
val signStr = RequestUtil.getZeroBuyRequestSign(curTimeSec, operationVal)
|
||||||
|
val requestHeaders = mapOf("Operation" to operationVal.toString(), "Timestamp" to curTimeSec.toString(), "Sign" to signStr)
|
||||||
|
val requestParams: MutableMap<String, String> = mutableMapOf("app_id" to AndroidUtil.getPackageId(), "device_id" to DeviceUtil.generateDeviceId())
|
||||||
|
val userId = AccountManager.getAccount()?.userId?: 0
|
||||||
|
if (userId > 0) {
|
||||||
|
requestParams.put("user_id", userId.toString())
|
||||||
|
}
|
||||||
|
val joinZeroBuyItemIds = SpUtil.instance().getList<Int>(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS)
|
||||||
|
requestParams.put("activity_id", itemId.toString())
|
||||||
|
|
||||||
|
val jsonObj = JSONObject().apply {
|
||||||
|
put("app_id",AndroidUtil.getPackageId())
|
||||||
|
put("device_id",DeviceUtil.generateDeviceId())
|
||||||
|
put("activity_id", itemId)
|
||||||
|
put("purchase_ids", JSONArray(joinZeroBuyItemIds))
|
||||||
|
if (userId > 0) {
|
||||||
|
put("user_id", userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val result = NetworkUtil.postJsonGeneric<ZeroBuyResp>("${VidiConst.URL_ZERO_BUY}/any", jsonObj.toString(), requestHeaders)
|
||||||
|
when (result) {
|
||||||
|
is Result.Success -> {
|
||||||
|
val respObj = result.data
|
||||||
|
|
||||||
|
if (respObj.code == CODE_HAS_JOINED_BEFORE || respObj.code == 0) {
|
||||||
|
// save
|
||||||
|
val joinedActivityList = SpUtil.instance().getList<Int>(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS).toMutableList()
|
||||||
|
if (!joinedActivityList.contains(itemId)) {
|
||||||
|
joinedActivityList.add(itemId)
|
||||||
|
SpUtil.instance().putList(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS, joinedActivityList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// flow set
|
||||||
|
val joinItem = respObj.current_purchases?.firstOrNull()
|
||||||
|
if (joinItem != null) {
|
||||||
|
_ZeroBuyJoinResult.value = Result.Success(joinItem)
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ZeroBuyJoinResult.value = Result.Error(Throwable("empty response or code error: ${respObj.code}"))
|
||||||
|
}
|
||||||
|
is Result.Error -> {
|
||||||
|
_ZeroBuyJoinResult.value = Result.Error(result.exception, result.message)
|
||||||
|
}
|
||||||
|
else -> { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestZeroBuyInfo() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_ZeroBuyListData.value = Result.Loading
|
||||||
|
|
||||||
|
val operationVal = ZERO_GET_PURCHASE_LIST
|
||||||
|
val curTimeSec = System.currentTimeMillis()/1000
|
||||||
|
val signStr = RequestUtil.getZeroBuyRequestSign(curTimeSec, operationVal)
|
||||||
|
val requestHeaders = mapOf("Operation" to operationVal.toString(), "Timestamp" to curTimeSec.toString(), "Sign" to signStr)
|
||||||
|
val requestParams: MutableMap<String, String> = mutableMapOf("app_id" to AndroidUtil.getPackageId(), "device_id" to DeviceUtil.generateDeviceId())
|
||||||
|
val userId = AccountManager.getAccount()?.userId?: 0
|
||||||
|
if (userId > 0) {
|
||||||
|
requestParams.put("user_id", userId.toString())
|
||||||
|
}
|
||||||
|
val joinZeroBuyItemIds = SpUtil.instance().getList<Int>(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS)
|
||||||
|
|
||||||
|
val jsonObj = JSONObject().apply {
|
||||||
|
put("app_id",AndroidUtil.getPackageId())
|
||||||
|
put("device_id",DeviceUtil.generateDeviceId())
|
||||||
|
put("purchase_ids", JSONArray(joinZeroBuyItemIds))
|
||||||
|
if (userId > 0) {
|
||||||
|
put("user_id", userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val result = NetworkUtil.postJsonGeneric<ZeroBuyResp>("${VidiConst.URL_ZERO_BUY}/any", jsonObj.toString(), requestHeaders)
|
||||||
|
when (result) {
|
||||||
|
is Result.Success -> {
|
||||||
|
val respObj = result.data
|
||||||
|
|
||||||
|
if (userId <= 0) {
|
||||||
|
respObj.user_id.let { id ->
|
||||||
|
AccountManager.saveUserIdInfo(id)
|
||||||
|
saveHasJoinedZeroIds(id, respObj.current_purchases)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ZeroBuyListData.value = Result.Success(respObj)
|
||||||
|
}
|
||||||
|
is Result.Error -> {
|
||||||
|
_ZeroBuyListData.value = Result.Error(result.exception, result.message)
|
||||||
|
AndroidUtil.showToast(R.string.net_error)
|
||||||
|
}
|
||||||
|
else -> { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveHasJoinedZeroIds(userId: Int, currentPurchases: List<ZeroBuyItem>?) {
|
||||||
|
val joinZeroBuyItemIds = SpUtil.instance().getList<Int>(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS)?.toMutableList() ?: mutableListOf()
|
||||||
|
currentPurchases?.forEach { zero ->
|
||||||
|
zero.current_users?.let {
|
||||||
|
if (it.contains(userId) && !joinZeroBuyItemIds.contains(zero.id)) {
|
||||||
|
joinZeroBuyItemIds.add(zero.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SpUtil.instance().putList(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS, joinZeroBuyItemIds)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
package com.gamedog.vididin.features.zero
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
|
||||||
import com.ama.core.architecture.widget.BindingDialog
|
|
||||||
import com.gamedog.vididin.databinding.DialogZeroBuyWinBinding as ViewBinding
|
|
||||||
import com.gamedog.vididin.router.Router
|
|
||||||
|
|
||||||
|
|
||||||
class ZeroBuyWinDialog(context: Context) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
|
||||||
|
|
||||||
init {
|
|
||||||
build()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun build() {
|
|
||||||
with()
|
|
||||||
setCenter()
|
|
||||||
setMaskValue(0.8f)
|
|
||||||
setCanCancel(false)
|
|
||||||
|
|
||||||
mBinding.run {
|
|
||||||
setOnClickBatch(tvConfirm, ivClose) {
|
|
||||||
when (this) {
|
|
||||||
tvConfirm, ivClose -> {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
|
||||||
ownerActivity?.let { Router.Withdraw.startActivity(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
package com.gamedog.vididin.features.zero
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.CountDownTimer
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.ama.core.architecture.util.SpUtil
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.gamedog.vididin.beans.ZeroBuyItem
|
||||||
|
import com.viddin.videos.free.databinding.LayoutItemZerobuyBinding as ViewBinding
|
||||||
|
|
||||||
|
class ZeroItemAdapter(private val joinCallback: (itemId: Int, diamondCost: Int)->Unit) : ListAdapter<ZeroBuyItem, ZeroItemAdapter.ViewHolder>(DiffCallback()) {
|
||||||
|
|
||||||
|
private val mBgResList = listOf<Int>(R.mipmap.zero_bg_item_sub1, R.mipmap.zero_bg_item_sub2, R.mipmap.zero_bg_item_sub3, R.mipmap.zero_bg_item_sub4)
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val binding = ViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
return ViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(getItem(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getJoinedIdList(): List<Int> {
|
||||||
|
return SpUtil.instance().getList<Int>(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startCountDownTimer(targetTimeMs: Long) {
|
||||||
|
val countDownDuration = targetTimeMs - System.currentTimeMillis()
|
||||||
|
|
||||||
|
val mCountDownTimer = object : CountDownTimer(countDownDuration, 1000) {
|
||||||
|
override fun onTick(millisUntilFinished: Long) {
|
||||||
|
val joinedIds = getJoinedIdList()
|
||||||
|
|
||||||
|
currentList.forEach { item->
|
||||||
|
if (joinedIds.contains(item.id) && !item.completed) {
|
||||||
|
var remainSec = (item.end_time - System.currentTimeMillis()) / 1000
|
||||||
|
//item.mCountDownTimeStr =
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*long totalSeconds = millisUntilFinished / 1000;
|
||||||
|
long minutes = totalSeconds / 60;
|
||||||
|
long seconds = totalSeconds % 60;
|
||||||
|
String timeText = String . format ("%02d:%02d", minutes, seconds);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinish() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mCountDownTimer.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun submitList(list: List<ZeroBuyItem>?) {
|
||||||
|
val sortedList = list?.sortedByDescending { it.start_time }
|
||||||
|
super.submitList(sortedList)
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ViewHolder(private val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(item: ZeroBuyItem) {
|
||||||
|
binding.tvTitle.text = item.title
|
||||||
|
binding.tvJoinedNum.text = item.current_users?.size.toString()
|
||||||
|
binding.tvPeopleTotal.text = "/${item.target_num}"
|
||||||
|
binding.tvJoinGoldNum.text = item.cost.toString()
|
||||||
|
binding.ivBgType.setImageResource(mBgResList[item.image])
|
||||||
|
binding.tvRewardCashNum.text = item.price
|
||||||
|
|
||||||
|
with(binding) {
|
||||||
|
setOnClickBatch(flBottomBut) {
|
||||||
|
when (this) {
|
||||||
|
flBottomBut-> {
|
||||||
|
joinCallback(item.id, item.cost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// judge state
|
||||||
|
val joinedIds = getJoinedIdList()
|
||||||
|
val hasJoined = joinedIds.contains(item.id)
|
||||||
|
val hasCompleted = item.completed
|
||||||
|
flBottomBut.isVisible = !hasJoined
|
||||||
|
tvParticipateAlready.isVisible = hasJoined
|
||||||
|
//tvRemainTime.isVisible = hasJoined && !hasCompleted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiffCallback : DiffUtil.ItemCallback<ZeroBuyItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: ZeroBuyItem, newItem: ZeroBuyItem): Boolean {
|
||||||
|
return oldItem.id == newItem.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: ZeroBuyItem, newItem: ZeroBuyItem): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
package com.gamedog.vididin.features.zero
|
||||||
|
|
||||||
|
|
||||||
|
import android.text.SpannableString
|
||||||
|
import android.text.Spanned
|
||||||
|
import android.text.style.UnderlineSpan
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.gamedog.vididin.beans.ZeroBuyItem
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_FAIL
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_ONGOING
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_SUCCESS
|
||||||
|
import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_UNSTART
|
||||||
|
import com.gamedog.vididin.manager.ZeroManager
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import com.viddin.videos.free.databinding.ZeroRecordWinBinding as ViewBinding
|
||||||
|
|
||||||
|
class ZeroRecordAdapter(private val onWithdrawCallback: (ZeroBuyItem)-> Unit) : ListAdapter<ZeroBuyItem, ZeroRecordAdapter.ViewHolder>(DiffCallback()) {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val binding = ViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
return ViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(getItem(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun submitList(list: List<ZeroBuyItem?>?) {
|
||||||
|
val sortedList = list?.sortedByDescending { it?.start_time }
|
||||||
|
super.submitList(sortedList)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isWinItem(item: ZeroBuyItem): Boolean {
|
||||||
|
val winerIds = item.winners
|
||||||
|
return winerIds?.contains(AccountManager.getAccount().userId) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ViewHolder(private val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(item: ZeroBuyItem) {
|
||||||
|
val isWinItem = isWinItem(item)
|
||||||
|
|
||||||
|
with(binding) {
|
||||||
|
tvDateWin.text = SimpleDateFormat("yyyy/MM/dd").format(item.start_time * 1000)
|
||||||
|
rlBg.setBackgroundResource(if (isWinItem) R.drawable.bg_records_win else R.drawable.bg_records_lost)
|
||||||
|
ivLeftWin.setImageResource(if (isWinItem) R.mipmap.record_win else R.mipmap.record_lost)
|
||||||
|
tvTitleWin.text = ResUtil.getString(if (isWinItem) R.string.record_win_item_title else R.string.record_lost_item_title)
|
||||||
|
tvDescWin.text = item.title
|
||||||
|
llRightWin.isVisible = isWinItem
|
||||||
|
llRightLost.isVisible = !isWinItem
|
||||||
|
|
||||||
|
if (isWinItem) {
|
||||||
|
val withdrawBean = ZeroManager.instance().getZeroWithdrawItem(item)
|
||||||
|
when (withdrawBean?.withdrawState) {
|
||||||
|
TRANSACTION_STATE_UNSTART -> {
|
||||||
|
llRightWin.isClickable = true
|
||||||
|
tvWinRightBottom.text = SpannableString(ResUtil.getString(R.string.zero_win_state_withdrarw_unstart)).apply {
|
||||||
|
setSpan(
|
||||||
|
UnderlineSpan(),
|
||||||
|
0,
|
||||||
|
this.length,
|
||||||
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRANSACTION_STATE_FAIL -> {
|
||||||
|
llRightWin.isClickable = true
|
||||||
|
tvWinRightBottom.text = SpannableString(ResUtil.getString(R.string.zero_win_state_failed)).apply {
|
||||||
|
setSpan(
|
||||||
|
UnderlineSpan(),
|
||||||
|
0,
|
||||||
|
this.length,
|
||||||
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRANSACTION_STATE_ONGOING -> {
|
||||||
|
llRightWin.isClickable = false
|
||||||
|
tvWinRightBottom.text = ResUtil.getString(R.string.zero_win_state_withdrarw_ongoing)
|
||||||
|
}
|
||||||
|
|
||||||
|
TRANSACTION_STATE_SUCCESS -> {
|
||||||
|
llRightWin.isClickable = false
|
||||||
|
tvWinRightBottom.text = ResUtil.getString(R.string.zero_win_state_withdrarw_success)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llRightWin.setOnClickListener {
|
||||||
|
onWithdrawCallback(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiffCallback : DiffUtil.ItemCallback<ZeroBuyItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: ZeroBuyItem, newItem: ZeroBuyItem): Boolean {
|
||||||
|
return oldItem.id == newItem.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: ZeroBuyItem, newItem: ZeroBuyItem): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
package com.gamedog.vididin.features.zero
|
package com.gamedog.vididin.features.zero.dialogs
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context
|
import android.app.Activity
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
import com.ama.core.architecture.widget.BindingDialog
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
import com.gamedog.vididin.databinding.DialogZeroBuyRuleBinding as ViewBinding
|
import com.viddin.videos.free.databinding.DialogZeroBuyFailBinding as ViewBinding
|
||||||
import com.gamedog.vididin.router.Router
|
import com.gamedog.vididin.router.Router
|
||||||
|
|
||||||
|
|
||||||
class ZeroBuyRulesDialog(context: Context) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
class ZeroBuyFailDialog(context: Activity) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
build()
|
build()
|
||||||
|
|
@ -33,7 +33,7 @@ class ZeroBuyRulesDialog(context: Context) : BindingDialog<ViewBinding>(context,
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
private fun gotoWatchVideo() {
|
||||||
ownerActivity?.let { Router.Withdraw.startActivity(it) }
|
Router.Withdraw.startActivity(mActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.gamedog.vididin.features.zero.dialogs
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
|
import com.gamedog.vididin.beans.ZeroBuyItem
|
||||||
|
import com.viddin.videos.free.databinding.DialogZeroBuyNotWinBinding as ViewBinding
|
||||||
|
import com.gamedog.vididin.router.Router
|
||||||
|
|
||||||
|
|
||||||
|
class ZeroBuyNotWinDialog(context: Activity, private val item: ZeroBuyItem) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun build() {
|
||||||
|
with()
|
||||||
|
setCenter()
|
||||||
|
setMaskValue(0.8f)
|
||||||
|
setCanCancel(false)
|
||||||
|
|
||||||
|
mBinding.run {
|
||||||
|
setOnClickBatch(ivClose) {
|
||||||
|
when (this) {
|
||||||
|
ivClose -> {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tvTitleSub.text = item.title + " - " + item.price
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
package com.gamedog.vididin.features.zero
|
package com.gamedog.vididin.features.zero.dialogs
|
||||||
|
|
||||||
|
|
||||||
import android.content.Context
|
import android.app.Activity
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
import com.ama.core.architecture.widget.BindingDialog
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
import com.gamedog.vididin.databinding.DialogZeroBuyNotWinBinding as ViewBinding
|
import com.viddin.videos.free.databinding.DialogZeroBuyRuleBinding as ViewBinding
|
||||||
import com.gamedog.vididin.router.Router
|
import com.gamedog.vididin.router.Router
|
||||||
|
|
||||||
|
|
||||||
class ZeroBuyNotWinDialog(context: Context) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
class ZeroBuyRulesDialog(context: Activity) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
build()
|
build()
|
||||||
|
|
@ -33,7 +33,7 @@ class ZeroBuyNotWinDialog(context: Context) : BindingDialog<ViewBinding>(context
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
private fun gotoWatchVideo() {
|
||||||
ownerActivity?.let { Router.Withdraw.startActivity(it) }
|
Router.Withdraw.startActivity(mActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.gamedog.vididin.features.zero.dialogs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
|
import com.gamedog.vididin.beans.ZeroBuyItem
|
||||||
|
import com.gamedog.vididin.manager.ZeroManager
|
||||||
|
import com.viddin.videos.free.databinding.DialogZeroBuyWinBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
class ZeroBuyWinDialog(context: Activity, private val item: ZeroBuyItem) : BindingDialog<ViewBinding>(context, ViewBinding::inflate) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun build() {
|
||||||
|
with()
|
||||||
|
setCenter()
|
||||||
|
setMaskValue(0.8f)
|
||||||
|
setCanCancel(false)
|
||||||
|
|
||||||
|
mBinding.run {
|
||||||
|
setOnClickBatch(ivClose, rlAction) {
|
||||||
|
when (this) {
|
||||||
|
ivClose -> {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
rlAction -> {
|
||||||
|
handleWithdraw(item)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tvTitleSub.text = item.title
|
||||||
|
tvPurchaseReward.text = item.price
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleWithdraw(item: ZeroBuyItem) {
|
||||||
|
ZeroManager.instance().addWinWithdrawItem(item)
|
||||||
|
ZeroManager.instance().startWithdrawProcess(mActivity, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,17 +1,40 @@
|
||||||
package com.gamedog.vididin.core.login.login
|
package com.gamedog.vididin.core.login.login
|
||||||
|
|
||||||
|
import com.ama.core.architecture.BaseApp
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
import com.ama.core.architecture.util.DateUtil
|
import com.ama.core.architecture.util.DateUtil
|
||||||
import com.ama.core.architecture.util.DeviceUtil
|
import com.ama.core.architecture.util.DeviceUtil
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
import com.ama.core.architecture.util.SpUtil
|
import com.ama.core.architecture.util.SpUtil
|
||||||
import com.ama.core.architecture.util.eventbus.NotifyMan
|
import com.ama.core.architecture.util.eventbus.NotifyMan
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
import com.gamedog.vididin.VididinEvents
|
import com.gamedog.vididin.VididinEvents
|
||||||
import com.gamedog.vididin.beans.Account
|
import com.gamedog.vididin.beans.Account
|
||||||
import com.gamedog.vididin.beans.BankInfo
|
import com.gamedog.vididin.beans.BankInfo
|
||||||
|
import com.gamedog.vididin.beans.RECORD_CASH_PLUS_GOLD_CONVERT
|
||||||
|
import com.gamedog.vididin.beans.RECORD_GOLD_MINUS_CONVERT_2_CASH
|
||||||
|
import com.gamedog.vididin.beans.RecordCash
|
||||||
|
import com.gamedog.vididin.beans.RecordGold
|
||||||
|
import com.gamedog.vididin.manager.RecordsManager
|
||||||
|
import com.remax.notification.service.NotificationKeepAliveService
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
|
||||||
object AccountManager {
|
object AccountManager {
|
||||||
|
|
||||||
private val mAccount: Account? by lazy {
|
init {
|
||||||
|
NotifyMan.instance().register(object: NotifyMan.ICallback(true) {
|
||||||
|
override fun onEvent(data: NotifyMan.NotifyData<*>?) {
|
||||||
|
when (data?.mEventType) {
|
||||||
|
VididinEvents.EVENT_AD_WATCHED_FOR_ZEROBUY_EARN_DIAMOND -> {
|
||||||
|
adjustDiamond(VidiConst.DIAMOND_NUM_FOR_ONE_AD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, VididinEvents.EVENT_AD_WATCHED_FOR_ZEROBUY_EARN_DIAMOND)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mAccount: Account by lazy {
|
||||||
var account = SpUtil.instance().getObject<Account>(SpUtil.KEY_ACCOUNT)
|
var account = SpUtil.instance().getObject<Account>(SpUtil.KEY_ACCOUNT)
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
val deviceUUId = DeviceUtil.generateDeviceId()
|
val deviceUUId = DeviceUtil.generateDeviceId()
|
||||||
|
|
@ -27,29 +50,89 @@ object AccountManager {
|
||||||
SpUtil.instance().putObject(SpUtil.KEY_ACCOUNT, mAccount)
|
SpUtil.instance().putObject(SpUtil.KEY_ACCOUNT, mAccount)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAccount() : Account? {
|
|
||||||
|
fun updateUserName(userName: String) {
|
||||||
|
mAccount.userName = userName
|
||||||
|
saveAccountInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------- 3个数值相关属性 增减 start --------------------------//
|
||||||
|
fun getAccount() : Account {
|
||||||
return mAccount
|
return mAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGold(): Long {
|
fun getGold(): Long {
|
||||||
return mAccount?.goldCount ?: 0L
|
return mAccount.goldCount
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCash(): Float {
|
fun getGoldRVTimes(): Int {
|
||||||
return mAccount?.cashCount ?: 0F
|
return mAccount.rvTimesGold
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addGold(newGold: Int) {
|
fun adjustGold(adjustNum: Long, recordBean: RecordGold, isEarnByRv: Boolean = false): Boolean {
|
||||||
mAccount?.goldCount += newGold
|
if (adjustNum < 0L && Math.abs(adjustNum) > getGold()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mAccount.goldCount += adjustNum
|
||||||
|
if (isEarnByRv) {
|
||||||
|
mAccount.rvTimesGold++
|
||||||
|
}
|
||||||
saveAccountInfo()
|
saveAccountInfo()
|
||||||
NotifyMan.instance().sendEvent(VididinEvents.Event_Account_Gold_Changed, null)
|
NotifyMan.instance().sendEvent(VididinEvents.Event_Account_Gold_Changed, null)
|
||||||
|
RecordsManager.instance().appendGoldRecord(recordBean)
|
||||||
|
updateResidentNotification()
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addCash(newCash: Float) {
|
private fun updateResidentNotification() {
|
||||||
mAccount?.cashCount += newCash
|
NotificationKeepAliveService.updateNotification(BaseApp.appContext())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getCash(): Double {
|
||||||
|
return mAccount.cashCount
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCashRVTimes(): Int {
|
||||||
|
return mAccount.rvTimesCash
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun adjustCash(adjustNum: Double, recordBean: RecordCash? = null, isEarnByRv: Boolean = false): Boolean {
|
||||||
|
if (adjustNum < 0L && Math.abs(adjustNum) > getCash()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mAccount.cashCount += adjustNum
|
||||||
|
if (isEarnByRv) {
|
||||||
|
mAccount.rvTimesCash++
|
||||||
|
}
|
||||||
saveAccountInfo()
|
saveAccountInfo()
|
||||||
NotifyMan.instance().sendEvent(VididinEvents.Event_Account_Cash_Changed, null)
|
NotifyMan.instance().sendEvent(VididinEvents.Event_Account_Cash_Changed, null)
|
||||||
|
recordBean?.let {
|
||||||
|
RecordsManager.instance().appendCashRecord(recordBean)
|
||||||
}
|
}
|
||||||
|
updateResidentNotification()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDiamond(): Int {
|
||||||
|
return mAccount.diamondCount
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun adjustDiamond(adjustNum: Int): Boolean {
|
||||||
|
if (adjustNum < 0L && Math.abs(adjustNum) > getDiamond()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
mAccount.diamondCount += adjustNum
|
||||||
|
saveAccountInfo()
|
||||||
|
NotifyMan.instance().sendEvent(VididinEvents.Event_Account_Diamond_Changed, null)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------- 3个数值相关属性 增减 End --------------------------//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun getBankInfo(): BankInfo? {
|
fun getBankInfo(): BankInfo? {
|
||||||
return mAccount?.bankInfo
|
return mAccount?.bankInfo
|
||||||
|
|
@ -62,14 +145,51 @@ object AccountManager {
|
||||||
|
|
||||||
fun saveBankAccount(bankAccount: String?) {
|
fun saveBankAccount(bankAccount: String?) {
|
||||||
if (bankAccount.isNullOrEmpty()) {
|
if (bankAccount.isNullOrEmpty()) {
|
||||||
mAccount?.bankInfo = null
|
mAccount.bankInfo = null
|
||||||
} else {
|
} else {
|
||||||
mAccount?.bankInfo = BankInfo(bankAccount=bankAccount)
|
mAccount.bankInfo = BankInfo(bankAccount=bankAccount)
|
||||||
}
|
}
|
||||||
saveAccountInfo()
|
saveAccountInfo()
|
||||||
NotifyMan.instance().sendEvent(
|
NotifyMan.instance().sendEvent(
|
||||||
VididinEvents.Event_Account_Bank_Info_Changed, NotifyMan.NotifyData(bankAccount))
|
VididinEvents.EVENT_BANK_INFO_CHANGED, NotifyMan.NotifyData(bankAccount))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun convertGold2Cash(): Boolean {
|
||||||
|
try {
|
||||||
|
val couldCovertCashTotal = getGold().div(VidiConst.PER_01CASH_COST_GOLD_NUM) ?: 0
|
||||||
|
if (couldCovertCashTotal > 0) {
|
||||||
|
val costGoldNum = couldCovertCashTotal * VidiConst.PER_01CASH_COST_GOLD_NUM
|
||||||
|
if (getGold() >= costGoldNum) {
|
||||||
|
adjustGold(-1L * costGoldNum.toInt(), RecordGold(RECORD_GOLD_MINUS_CONVERT_2_CASH, -1L * costGoldNum.toInt()))
|
||||||
|
val adjustCashNum = couldCovertCashTotal * 0.1
|
||||||
|
adjustCash(adjustCashNum, RecordCash(RECORD_CASH_PLUS_GOLD_CONVERT, adjustCashNum.toDouble()), true)
|
||||||
|
AndroidUtil.showCustomToast(String.format(ResUtil.getString(R.string.has_claim_box_cash_hint), adjustCashNum))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AndroidUtil.showToast(ResUtil.getString(R.string.not_enough_gold))
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveUserIdInfo(userId: Int) {
|
||||||
|
mAccount?.let {
|
||||||
|
it.userId = userId
|
||||||
|
saveAccountInfo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isBankAccountExist(): Boolean {
|
||||||
|
return !mAccount?.bankInfo?.bankAccount.isNullOrEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import android.view.LayoutInflater
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelActivity
|
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelActivity
|
||||||
import com.gamedog.vididin.databinding.VididinappFeatureLoginActivityLoginBinding as ViewBinding
|
import com.viddin.videos.free.databinding.VididinappFeatureLoginActivityLoginBinding as ViewBinding
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.jvm.java
|
import kotlin.jvm.java
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,29 @@
|
||||||
package com.gamedog.vididin.main
|
package com.gamedog.vididin.main
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.widget.FrameLayout
|
||||||
|
import androidx.core.graphics.toColorInt
|
||||||
|
import com.ama.core.architecture.highlightpro.HighlightPro
|
||||||
|
import com.ama.core.architecture.highlightpro.parameter.Constraints
|
||||||
|
import com.ama.core.architecture.highlightpro.parameter.HighlightParameter
|
||||||
|
import com.ama.core.architecture.highlightpro.parameter.MarginOffset
|
||||||
|
import com.ama.core.architecture.highlightpro.shape.RectShape
|
||||||
|
import com.ama.core.architecture.util.ResUtil.dp
|
||||||
|
import com.ama.core.architecture.util.SpUtil
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
import com.ama.core.architecture.widget.BindingDialog
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
import com.gamedog.vididin.databinding.DialogBeginnerGiftBinding
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
import com.gamedog.vididin.router.Router
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.VidiConst.GUIDE_INDEX_GIFT
|
||||||
|
import com.gamedog.vididin.beans.RECORD_GOLD_PLUS_NEWBIE_GIFT
|
||||||
|
import com.gamedog.vididin.beans.RecordGold
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.gamedog.vididin.manager.GuideManager
|
||||||
|
import com.viddin.videos.free.R
|
||||||
|
import com.viddin.videos.free.databinding.DialogBeginnerGiftBinding
|
||||||
|
|
||||||
|
|
||||||
class BeginnerGiftDialog(context: Context) : BindingDialog<DialogBeginnerGiftBinding>(context, DialogBeginnerGiftBinding::inflate) {
|
class BeginnerGiftDialog(activity: Activity) : BindingDialog<DialogBeginnerGiftBinding>(activity, DialogBeginnerGiftBinding::inflate) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
build()
|
build()
|
||||||
|
|
@ -25,16 +40,55 @@ class BeginnerGiftDialog(context: Context) : BindingDialog<DialogBeginnerGiftBin
|
||||||
setOnClickBatch(tvAction) {
|
setOnClickBatch(tvAction) {
|
||||||
when (this) {
|
when (this) {
|
||||||
tvAction -> {
|
tvAction -> {
|
||||||
gotoWatchVideo()
|
handleClickEvent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showGuide()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleClickEvent() {
|
||||||
|
if (mActivity is MainActivity) {
|
||||||
|
(mActivity as MainActivity).switchTab(1)
|
||||||
|
}
|
||||||
|
if (!SpUtil.instance().getBoolean(SpUtil.KEY_GUIDE_HAS_GOT_NEWBIE_GOLD)) {
|
||||||
|
AccountManager.adjustGold(VidiConst.NEWBIE_GIFT_GOLD_NUM, RecordGold(RECORD_GOLD_PLUS_NEWBIE_GIFT, VidiConst.NEWBIE_GIFT_GOLD_NUM))
|
||||||
|
SpUtil.instance().putBoolean(SpUtil.KEY_GUIDE_HAS_GOT_NEWBIE_GOLD, true)
|
||||||
|
}
|
||||||
|
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
|
||||||
ownerActivity?.let { Router.Withdraw.startActivity(it) }
|
private fun showGuide() {
|
||||||
|
HighlightPro.with(window?.decorView as FrameLayout)
|
||||||
|
.setHighlightParameter {
|
||||||
|
HighlightParameter.Builder()
|
||||||
|
.setHighlightView(mBinding.tvAction, {
|
||||||
|
val temp = 111
|
||||||
|
})
|
||||||
|
.setTipsViewId(R.layout.guide_step_withdraw)
|
||||||
|
.setHighlightShape(RectShape(22.dp, 22.dp, 22.dp))
|
||||||
|
.setHighlightHorizontalPadding(0.dp)
|
||||||
|
.setConstraints(Constraints.TopToBottomOfHighlight + Constraints.EndToEndOfHighlight)
|
||||||
|
.setMarginOffset(MarginOffset(top = -22.dp.toInt(), end = -10.dp.toInt()))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
.setBackgroundColor("#00000000".toColorInt())
|
||||||
|
.setOnShowCallback { index ->
|
||||||
|
|
||||||
|
}
|
||||||
|
.setOnDismissCallback {
|
||||||
|
GuideManager.instance().setGuideIndex(GUIDE_INDEX_GIFT)
|
||||||
|
handleClickEvent()
|
||||||
|
}
|
||||||
|
.interceptBackPressed(true)
|
||||||
|
.show()
|
||||||
|
|
||||||
|
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Guide, mapOf("Guide" to 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,61 +1,91 @@
|
||||||
package com.gamedog.vididin.main
|
package com.gamedog.vididin.main
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import com.ama.core.common.util.asSafe
|
import android.content.BroadcastReceiver
|
||||||
import androidx.core.view.ViewCompat
|
import android.content.ComponentName
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import android.content.Intent
|
||||||
import androidx.fragment.app.Fragment
|
import android.content.IntentFilter
|
||||||
import androidx.fragment.app.FragmentManager
|
import android.content.pm.PackageManager
|
||||||
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
|
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.ama.core.architecture.appBase.AppViewsActivity
|
import com.ama.core.architecture.appBase.AppViewsActivity
|
||||||
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
|
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
|
||||||
import com.ama.core.architecture.ext.toast
|
import com.ama.core.architecture.ext.toast
|
||||||
|
import com.ama.core.architecture.util.DateUtil
|
||||||
import com.ama.core.architecture.util.bindViewPager2
|
import com.ama.core.architecture.util.bindViewPager2
|
||||||
import com.ama.core.architecture.util.setCommonNavigator
|
import com.ama.core.architecture.util.setCommonNavigator
|
||||||
import com.ama.core.architecture.util.setDataOrAdapter
|
import com.ama.core.architecture.util.setDataOrAdapter
|
||||||
import com.gamedog.vididin.R
|
import com.ama.core.common.util.asSafe
|
||||||
|
import com.blankj.utilcode.util.ActivityUtils
|
||||||
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.VidiConst.GUIDE_INDEX_GIFT
|
||||||
|
import com.gamedog.vididin.VidiConst.GUIDE_INDEX_ZERO
|
||||||
|
import com.gamedog.vididin.VididinEvents
|
||||||
import com.gamedog.vididin.adapter.MainTabsAdapter
|
import com.gamedog.vididin.adapter.MainTabsAdapter
|
||||||
import com.gamedog.vididin.adapter.MainViewPagerAdapter
|
import com.gamedog.vididin.adapter.MainViewPagerAdapter
|
||||||
|
import com.gamedog.vididin.main.fragments.task.DailySignSuccessDialog
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
||||||
|
import com.gamedog.vididin.manager.DateChangeReceiver
|
||||||
|
import com.gamedog.vididin.manager.GuideManager
|
||||||
|
import com.gamedog.vididin.manager.NotificationController
|
||||||
|
import com.gamedog.vididin.router.Router
|
||||||
|
import com.remax.base.report.DataReportManager
|
||||||
|
import com.remax.base.utils.ActivityLauncher
|
||||||
|
import com.remax.bill.ads.AdResult
|
||||||
|
import com.remax.bill.ads.PreloadController
|
||||||
|
import com.remax.bill.ads.ext.AdShowExt
|
||||||
|
import com.remax.bill.ads.log.AdLogger
|
||||||
|
import com.remax.notification.builder.LANDING_NOTIFICATION_ACTION
|
||||||
|
import com.remax.notification.builder.LANDING_NOTIFICATION_CONTENT
|
||||||
|
import com.remax.notification.builder.LANDING_NOTIFICATION_FROM
|
||||||
|
import com.remax.notification.builder.LANDING_NOTIFICATION_TITLE
|
||||||
|
import com.remax.notification.check.NotificationCheckController
|
||||||
|
import com.remax.notification.config.PushContent
|
||||||
|
import com.remax.notification.controller.NotificationLandingController
|
||||||
|
import com.remax.notification.newUtil.events.AppInstallReceiver
|
||||||
|
import com.remax.notification.newUtil.events.PowerConnectionReceiver
|
||||||
|
import com.remax.notification.service.NotificationKeepAliveServiceManager
|
||||||
|
import com.viddin.videos.free.R
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import kotlinx.coroutines.launch
|
||||||
import com.gamedog.vididin.databinding.ActivityMainBinding as ViewBinding
|
import kotlin.math.ceil
|
||||||
import com.gamedog.vididin.main.MainUiState as UiState
|
import com.gamedog.vididin.main.MainUiState as UiState
|
||||||
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
import com.gamedog.vididin.main.MainViewModel as ViewModel
|
||||||
|
import com.viddin.videos.free.databinding.ActivityMainBinding as ViewBinding
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
class MainActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
|
||||||
|
|
||||||
|
private lateinit var mAppInstallReceiver: AppInstallReceiver
|
||||||
|
private lateinit var mPowerReceiver: BroadcastReceiver
|
||||||
|
private lateinit var activityLauncher: ActivityLauncher
|
||||||
override val mViewModel: ViewModel by viewModels()
|
override val mViewModel: ViewModel by viewModels()
|
||||||
private lateinit var navigatorAdapter: MainTabsAdapter
|
private lateinit var navigatorAdapter: MainTabsAdapter
|
||||||
private val fragmentStateAdapter by lazy { MainViewPagerAdapter(this) }
|
private val fragmentStateAdapter by lazy { MainViewPagerAdapter(this) }
|
||||||
|
private lateinit var mDateChangeReceiver: DateChangeReceiver
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
|
||||||
|
|
||||||
override fun ViewBinding.initWindowInsets() {
|
override fun ViewBinding.initWindowInsets() {
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(magicIndicator) { v, insets ->
|
setImmerseRootView(flForImmerse)
|
||||||
val systemBars =
|
|
||||||
insets.getInsets(WindowInsetsCompat.Type.navigationBars() or WindowInsetsCompat.Type.displayCutout())
|
|
||||||
v.setPadding(
|
|
||||||
systemBars.left,
|
|
||||||
36,
|
|
||||||
systemBars.right,
|
|
||||||
systemBars.bottom + 36
|
|
||||||
)
|
|
||||||
insets
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun ViewBinding.initViews() {
|
override fun ViewBinding.initViews() {
|
||||||
content.foreground.alpha = 0
|
onAdShowingStateChanged(false)
|
||||||
|
|
||||||
|
activityLauncher = ActivityLauncher(this@MainActivity)
|
||||||
|
|
||||||
navigatorAdapter = MainTabsAdapter(
|
navigatorAdapter = MainTabsAdapter(
|
||||||
this@MainActivity, viewPager2, fragmentStateAdapter, magicIndicator
|
this@MainActivity, viewPager2, fragmentStateAdapter, magicIndicator
|
||||||
)
|
)
|
||||||
|
|
@ -67,10 +97,21 @@ class MainActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabS
|
||||||
viewPager2.offscreenPageLimit
|
viewPager2.offscreenPageLimit
|
||||||
|
|
||||||
|
|
||||||
|
if (GuideManager.instance().getCurGuideIndex() < GUIDE_INDEX_GIFT) {
|
||||||
BeginnerGiftDialog(this@MainActivity).show()
|
BeginnerGiftDialog(this@MainActivity).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (intent.getBooleanExtra(EXTRA_NEED_SHOW_SPLASH_AD, false)) {
|
||||||
|
showSplashAd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initListeners() {
|
override fun ViewBinding.initListeners() {
|
||||||
|
mDateChangeReceiver = DateChangeReceiver()
|
||||||
|
val filter = IntentFilter(Intent.ACTION_DATE_CHANGED)
|
||||||
|
registerReceiver(mDateChangeReceiver, filter)
|
||||||
|
registerReceivers()
|
||||||
|
|
||||||
onBackPressedDispatcher.addCallback(this@MainActivity) {
|
onBackPressedDispatcher.addCallback(this@MainActivity) {
|
||||||
if (mViewModel.canBack) {
|
if (mViewModel.canBack) {
|
||||||
finish()
|
finish()
|
||||||
|
|
@ -97,10 +138,34 @@ class MainActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabS
|
||||||
onTabIsDarkFont(isBackgroundBright)
|
onTabIsDarkFont(isBackgroundBright)
|
||||||
}
|
}
|
||||||
}, false)
|
}, false)
|
||||||
|
|
||||||
|
registerEvents( { data->
|
||||||
|
when (data?.mEventType) {
|
||||||
|
VididinEvents.EVENT_AD_WATCHED_FOR_EARN_GOLD-> {
|
||||||
|
DailySignSuccessDialog(this@MainActivity).initData(VidiConst.WATCH_AD_REWARD_GOLD.toInt(), false).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_JUMP_2_VIDEO-> {
|
||||||
|
switchTab(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.AD_ACT_SHOWING-> {
|
||||||
|
onAdShowingStateChanged(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.AD_ACT_DESTROY-> {
|
||||||
|
onAdShowingStateChanged(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, VididinEvents.EVENT_AD_WATCHED_FOR_EARN_GOLD, VididinEvents.EVENT_JUMP_2_VIDEO,
|
||||||
|
VididinEvents.AD_ACT_SHOWING, VididinEvents.AD_ACT_DESTROY)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initObservers() {
|
override fun ViewBinding.initObservers() {
|
||||||
|
checkNotifyPermissionAndStartService()
|
||||||
|
handleNotificationAction()
|
||||||
|
reportStatistics(intent, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -112,9 +177,244 @@ class MainActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabS
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Home_Show)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
unregisterReceiver(mDateChangeReceiver)
|
||||||
|
unregisterReceivers()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabIsDarkFont(isDarkFont: Boolean) {
|
override fun onTabIsDarkFont(isDarkFont: Boolean) {
|
||||||
navigatorAdapter.setIsDarkFont(isDarkFont)
|
navigatorAdapter.setIsDarkFont(isDarkFont)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(intent: Intent) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
setIntent(intent)
|
||||||
|
handleNotificationAction()
|
||||||
|
reportStatistics(intent, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun onAdShowingStateChanged(isAdShowing: Boolean) {
|
||||||
|
val newState = if (isAdShowing) {
|
||||||
|
PackageManager.COMPONENT_ENABLED_STATE_DISABLED
|
||||||
|
} else {
|
||||||
|
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
packageManager.setComponentEnabledSetting(
|
||||||
|
ComponentName(this, "com.gamedog.vididin.main.MainActivityAlias"),
|
||||||
|
newState,
|
||||||
|
PackageManager.DONT_KILL_APP
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun switchTab(itemIndex: Int) {
|
||||||
|
binding.viewPager2.setCurrentItem(itemIndex, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleNotificationAction() {
|
||||||
|
if (NotificationLandingController.isFromNotification(intent)) {
|
||||||
|
val notificationAction = intent.getIntExtra(LANDING_NOTIFICATION_ACTION, -1)
|
||||||
|
when (notificationAction) {
|
||||||
|
PushContent.ACTION_TYPE_GAME -> {
|
||||||
|
Router.Game.startActivity(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
PushContent.ACTION_TYPE_GOLD -> {
|
||||||
|
switchTab(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
PushContent.ACTION_TYPE_WITHDRAW -> {
|
||||||
|
Router.Withdraw.startActivity(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
PushContent.ACTION_TYPE_BOX -> {
|
||||||
|
Router.Benefit.startActivity(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NotificationLandingController.clearNotificationParameters(intent)
|
||||||
|
|
||||||
|
sendNotificationClickStatistics(notificationAction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showSplashAd() {
|
||||||
|
val startTime = DateUtil.getCurTimeMs()
|
||||||
|
lifecycleScope.launch {
|
||||||
|
when (val result = AdShowExt.showAppOpenAd(this@MainActivity) { loaded ->
|
||||||
|
PreloadController.preload(this@MainActivity)
|
||||||
|
PreloadController.preloadPangle(this@MainActivity)
|
||||||
|
PreloadController.preloadTopOn(this@MainActivity)
|
||||||
|
DataReportManager.reportData(
|
||||||
|
"loading_page_end", mapOf(
|
||||||
|
"pass_time" to ceil((System.currentTimeMillis() - startTime) / 1000.0).toInt()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
is AdResult.Success -> {
|
||||||
|
AdLogger.e("开屏广告显示成功 in MainAct")
|
||||||
|
}
|
||||||
|
|
||||||
|
is AdResult.Failure -> {
|
||||||
|
AdLogger.e("开屏广告显示失败 in MainAct: ${result.error.message} ")
|
||||||
|
}
|
||||||
|
|
||||||
|
AdResult.Loading -> {
|
||||||
|
AdLogger.d("开屏广告显示中... in MainAct")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendNotificationClickStatistics(notificationAction: Int) {
|
||||||
|
var pushType = 1
|
||||||
|
if (notificationAction == PushContent.ACTION_TYPE_GAME
|
||||||
|
|| notificationAction == PushContent.ACTION_TYPE_GOLD
|
||||||
|
|| notificationAction == PushContent.ACTION_TYPE_WITHDRAW
|
||||||
|
|| notificationAction == PushContent.ACTION_TYPE_BOX ) {
|
||||||
|
pushType = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Push_Click, mapOf(
|
||||||
|
"Push_Position" to pushType,
|
||||||
|
"Push_Type" to pushType
|
||||||
|
))
|
||||||
|
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Push_EnterGame, mapOf(
|
||||||
|
"Push_Position" to pushType,
|
||||||
|
"Push_Type" to pushType
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkNotifyPermissionAndStartService() {
|
||||||
|
if (GuideManager.instance().getCurGuideIndex() > GUIDE_INDEX_ZERO) {
|
||||||
|
NotificationController.requestNotificationPermissionAsAsync(
|
||||||
|
context = this,
|
||||||
|
lifecycleScope = lifecycleScope,
|
||||||
|
activityLauncher = activityLauncher!!,
|
||||||
|
position = "Appstart",
|
||||||
|
onGrantedOnlyUnauthorized = { isGranted->
|
||||||
|
if(isGranted){
|
||||||
|
NotificationKeepAliveServiceManager.startKeepAliveService(this)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun reportStatistics(intent: Intent, isFromNewIntent: Boolean) {
|
||||||
|
// AppOpen
|
||||||
|
DataReportManager.reportData(
|
||||||
|
VidiConst.STATISTICS_APP_OPEN,
|
||||||
|
mapOf(
|
||||||
|
"type" to if (ActivityUtils.isActivityExistsInStack(MainActivity::class.java)) "hot_open" else "cold_open",
|
||||||
|
"position" to if (intent.hasExtra(LANDING_NOTIFICATION_FROM)) intent.getStringExtra(
|
||||||
|
LANDING_NOTIFICATION_FROM).orEmpty().ifBlank { "other" } else "other"
|
||||||
|
))
|
||||||
|
|
||||||
|
// Notific_Click
|
||||||
|
if (intent.hasExtra(LANDING_NOTIFICATION_FROM)) {
|
||||||
|
val notifyFrom = intent.getStringExtra(LANDING_NOTIFICATION_FROM).orEmpty()
|
||||||
|
|
||||||
|
DataReportManager.reportData(
|
||||||
|
VidiConst.STATISTICS_NOTIFI_CLICK, mapOf(
|
||||||
|
"Notific_Type" to when (notifyFrom) {
|
||||||
|
NotificationCheckController.NotificationType.UNLOCK.string -> 1
|
||||||
|
NotificationCheckController.NotificationType.BACKGROUND.string -> 1
|
||||||
|
NotificationCheckController.NotificationType.FIXTIMEPOINT.string -> 1
|
||||||
|
NotificationCheckController.NotificationType.KEEPALIVE.string -> 1
|
||||||
|
NotificationCheckController.NotificationType.FCM.string -> 3
|
||||||
|
NotificationCheckController.NotificationType.RESIDENT.string -> 4
|
||||||
|
else -> 4
|
||||||
|
},
|
||||||
|
"Notific_Position" to when (intent.getStringExtra(LANDING_NOTIFICATION_FROM).orEmpty()) {
|
||||||
|
NotificationCheckController.NotificationType.RESIDENT.string -> 2
|
||||||
|
else -> 1
|
||||||
|
},
|
||||||
|
"Notific_Priority" to when (intent.getStringExtra(LANDING_NOTIFICATION_FROM).orEmpty()) {
|
||||||
|
NotificationCheckController.NotificationType.RESIDENT.string -> "PRIORITY_DEFAULT"
|
||||||
|
else -> "PRIORITY_MAX"
|
||||||
|
},
|
||||||
|
"event_id" to when (intent.getStringExtra(LANDING_NOTIFICATION_FROM).orEmpty()) {
|
||||||
|
NotificationCheckController.NotificationType.RESIDENT.string -> "permanent"
|
||||||
|
else -> "customer_general_style"
|
||||||
|
},
|
||||||
|
"title" to intent.getStringExtra(LANDING_NOTIFICATION_TITLE).orEmpty(),
|
||||||
|
"text" to intent.getStringExtra(LANDING_NOTIFICATION_CONTENT).orEmpty(),
|
||||||
|
"from_background" to /*!ActivityUtils.isActivityExistsInStack(HomeActivity::class.java)*/isFromNewIntent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
DataReportManager.reportData(
|
||||||
|
VidiConst.STATISTICS_NOTIFI_ENTER, mapOf(
|
||||||
|
"Notific_Type" to when (intent.getStringExtra(LANDING_NOTIFICATION_FROM).orEmpty()) {
|
||||||
|
NotificationCheckController.NotificationType.UNLOCK.string -> 1
|
||||||
|
NotificationCheckController.NotificationType.BACKGROUND.string -> 1
|
||||||
|
NotificationCheckController.NotificationType.FIXTIMEPOINT.string -> 1
|
||||||
|
NotificationCheckController.NotificationType.KEEPALIVE.string -> 1
|
||||||
|
NotificationCheckController.NotificationType.FCM.string -> 3
|
||||||
|
NotificationCheckController.NotificationType.RESIDENT.string -> 4
|
||||||
|
else -> 4
|
||||||
|
},
|
||||||
|
"Notific_Position" to when (intent.getStringExtra(LANDING_NOTIFICATION_FROM).orEmpty()) {
|
||||||
|
NotificationCheckController.NotificationType.RESIDENT.string -> 2
|
||||||
|
else -> 1
|
||||||
|
},
|
||||||
|
"Notific_Priority" to when (intent.getStringExtra(LANDING_NOTIFICATION_FROM).orEmpty()) {
|
||||||
|
NotificationCheckController.NotificationType.RESIDENT.string -> "PRIORITY_DEFAULT"
|
||||||
|
else -> "PRIORITY_MAX"
|
||||||
|
},
|
||||||
|
"event_id" to when (intent.getStringExtra(LANDING_NOTIFICATION_FROM).orEmpty()) {
|
||||||
|
NotificationCheckController.NotificationType.RESIDENT.string -> "permanent"
|
||||||
|
else -> "customer_general_style"
|
||||||
|
},
|
||||||
|
"title" to intent.getStringExtra(LANDING_NOTIFICATION_TITLE).orEmpty(),
|
||||||
|
"text" to intent.getStringExtra(LANDING_NOTIFICATION_CONTENT).orEmpty(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun registerReceivers() {
|
||||||
|
mPowerReceiver = PowerConnectionReceiver()
|
||||||
|
val filter1 = IntentFilter().apply {
|
||||||
|
addAction(Intent.ACTION_POWER_CONNECTED)
|
||||||
|
addAction(Intent.ACTION_POWER_DISCONNECTED)
|
||||||
|
}
|
||||||
|
registerReceiver(mPowerReceiver, filter1)
|
||||||
|
|
||||||
|
mAppInstallReceiver = AppInstallReceiver()
|
||||||
|
val filter2 = IntentFilter().apply {
|
||||||
|
addAction(Intent.ACTION_PACKAGE_ADDED)
|
||||||
|
addAction(Intent.ACTION_PACKAGE_REPLACED)
|
||||||
|
addAction(Intent.ACTION_PACKAGE_REMOVED)
|
||||||
|
addDataScheme("package")
|
||||||
|
}
|
||||||
|
registerReceiver(mAppInstallReceiver, filter2)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun unregisterReceivers() {
|
||||||
|
unregisterReceiver(mPowerReceiver)
|
||||||
|
unregisterReceiver(mAppInstallReceiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val EXTRA_NEED_SHOW_SPLASH_AD = "EXTRA_NEED_SHOW_SPLASH_AD"
|
||||||
|
|
||||||
|
internal fun startActivity(activity: Activity, needShowSplashAd: Boolean) {
|
||||||
|
val intent = Intent(activity.applicationContext, MainActivity::class.java).apply {
|
||||||
|
putExtra(EXTRA_NEED_SHOW_SPLASH_AD, needShowSplashAd)
|
||||||
|
}
|
||||||
|
activity.startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package com.gamedog.vididin.main
|
package com.gamedog.vididin.main
|
||||||
|
|
||||||
|
|
||||||
import android.util.TimeUtils
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.ama.core.architecture.appBase.vm.AppViewModel
|
import com.ama.core.architecture.appBase.vm.AppViewModel
|
||||||
import com.gamedog.vididin.R
|
import com.viddin.videos.free.R
|
||||||
import com.gamedog.vididin.beans.MainTabsItem
|
import com.gamedog.vididin.beans.MainTabsItem
|
||||||
import com.gamedog.vididin.repository.MainRepository
|
import com.gamedog.vididin.repository.MainRepository
|
||||||
import com.gamedog.vididin.repository.MainTabType
|
import com.gamedog.vididin.repository.MainTabType
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
package com.gamedog.vididin.main
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
|
import com.ama.core.architecture.widget.BindingDialog
|
||||||
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
|
import com.gamedog.vididin.VidiStatisticHelper
|
||||||
|
import com.viddin.videos.free.databinding.DialogWatchVideoBinding
|
||||||
|
import com.gamedog.vididin.router.Router
|
||||||
|
|
||||||
|
|
||||||
|
class WatchAdDialog(context: Activity, private val mWatchAdType: Int, statisticType: Int, private val mGoldNum: Int? = 0,
|
||||||
|
private val mTaskDataJson: String? = "")
|
||||||
|
: BindingDialog<DialogWatchVideoBinding>(context, DialogWatchVideoBinding::inflate) {
|
||||||
|
|
||||||
|
private var mOnClosed: (() -> Unit)? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
build()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun build() {
|
||||||
|
with()
|
||||||
|
setCenter()
|
||||||
|
setMaskValue(0.93f)
|
||||||
|
setCanCancel(false)
|
||||||
|
|
||||||
|
mBinding.run {
|
||||||
|
setOnClickBatch(flAction, ivClose) {
|
||||||
|
when (this) {
|
||||||
|
ivClose -> {
|
||||||
|
mOnClosed?.invoke()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
flAction -> {
|
||||||
|
gotoWatchVideo()
|
||||||
|
|
||||||
|
sendClickStatistic()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mGoldNum?.let {
|
||||||
|
tvGoldNum.text = "+$mGoldNum"
|
||||||
|
}
|
||||||
|
if (mGoldNum == null) {
|
||||||
|
tvGoldNum.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sendShowStatistic()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun sendShowStatistic() {
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_RV_Button_Show, mapOf("Position" to VidiStatisticHelper.getShowFromStr(mWatchAdType)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendClickStatistic() {
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_RV_Button_Click, mapOf("Position" to VidiStatisticHelper.getShowFromStr(mWatchAdType)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun gotoWatchVideo() {
|
||||||
|
Router.WatchAd.startActivity(mActivity, mWatchAdType, mTaskDataJson)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun setOnCloseListener(onClose: ()->Unit) {
|
||||||
|
mOnClosed = onClose
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val FROM_WATCH_5VIDEOS: Int = 1
|
||||||
|
val FROM_TASK_FRAGMENT_ICON: Int = 2
|
||||||
|
/*val FROM_SIGN_AD_FOR_DOUBLE: Int = 3
|
||||||
|
val FROM_SIGN_AD_FOR_EXTRA: Int = 4
|
||||||
|
val FROM_SIGN_AD_FOR_SUPPLEMENT: Int = 5
|
||||||
|
val FROM_WITHDRAW_PROGRESS: Int = 6*/
|
||||||
|
val FROM_DIALY_TASKS: Int = 7
|
||||||
|
val FROM_CONVERT_GOLD_TO_CASH: Int = 8
|
||||||
|
val FROM_HOME_MENU: Int = 9
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*1每观看5个视频后,插入一条激励视频广告。用户可选择观看完15-30秒广告以获得大额金币奖励。
|
||||||
|
2"看视频获得金币奖励
|
||||||
|
3"签到页面观看视频获得双倍奖励
|
||||||
|
4签到页面观看视频获得额外奖励
|
||||||
|
5签到页面观看视频进行补签
|
||||||
|
6观看视频加速小额进度提现
|
||||||
|
7观看视频加速大额进度提现
|
||||||
|
8观看视频,可以金币兑换现金*/
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
package com.gamedog.vididin.main
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
|
||||||
import com.ama.core.architecture.widget.BindingDialog
|
|
||||||
import com.gamedog.vididin.databinding.DialogWatchVideoBinding
|
|
||||||
import com.gamedog.vididin.main.fragments.task.RewardDetail
|
|
||||||
|
|
||||||
|
|
||||||
class WatchVideoDialog(context: Context) : BindingDialog<DialogWatchVideoBinding>(context, DialogWatchVideoBinding::inflate) {
|
|
||||||
private lateinit var mDataList: List<RewardDetail>
|
|
||||||
|
|
||||||
init {
|
|
||||||
build()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun build() {
|
|
||||||
with()
|
|
||||||
setCenter()
|
|
||||||
setMaskValue(0.93f)
|
|
||||||
setCanCancel(false)
|
|
||||||
|
|
||||||
mBinding.run {
|
|
||||||
setOnClickBatch(flAction, ivClose) {
|
|
||||||
when (this) {
|
|
||||||
ivClose -> {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
flAction -> {
|
|
||||||
gotoWatchVideo()
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun gotoWatchVideo() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package com.gamedog.vididin.main.fragments
|
package com.gamedog.vididin.main.fragments
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.graphics.toColorInt
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updatePadding
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
|
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
|
||||||
|
|
@ -13,16 +13,39 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.ama.core.architecture.appBase.AppViewsFragment
|
import com.ama.core.architecture.appBase.AppViewsFragment
|
||||||
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
|
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
|
||||||
|
import com.ama.core.architecture.highlightpro.HighlightPro
|
||||||
|
import com.ama.core.architecture.highlightpro.parameter.Constraints
|
||||||
|
import com.ama.core.architecture.highlightpro.parameter.HighlightParameter
|
||||||
|
import com.ama.core.architecture.highlightpro.parameter.MarginOffset
|
||||||
|
import com.ama.core.architecture.highlightpro.shape.OvalShape
|
||||||
|
import com.ama.core.architecture.util.ResUtil
|
||||||
|
import com.ama.core.architecture.util.ResUtil.dp
|
||||||
import com.ama.core.architecture.util.setStatusBarDarkFont
|
import com.ama.core.architecture.util.setStatusBarDarkFont
|
||||||
import com.ama.core.common.util.asSafe
|
import com.ama.core.common.widget.PopMenuView
|
||||||
|
import com.gamedog.statisticreporter.StatisticUtil
|
||||||
|
import com.gamedog.vididin.VidiConst
|
||||||
|
import com.gamedog.vididin.VididinEvents
|
||||||
|
import com.gamedog.vididin.beans.RECORD_GOLD_PLUS_WATCH_VIDEO_BY_TIME_DURATION
|
||||||
|
import com.gamedog.vididin.beans.RecordGold
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
|
import com.gamedog.vididin.main.WatchAdDialog
|
||||||
import com.gamedog.vididin.main.fragments.home.HomeFragmentStateAdapter
|
import com.gamedog.vididin.main.fragments.home.HomeFragmentStateAdapter
|
||||||
import com.gamedog.vididin.main.fragments.home.fragment.HomeItemFragment
|
import com.gamedog.vididin.main.fragments.home.fragment.HomeItemFragment
|
||||||
import com.gamedog.vididin.main.interfaces.OnSwitchTabListener
|
import com.gamedog.vididin.main.interfaces.OnSwitchTabListener
|
||||||
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
|
import com.gamedog.vididin.manager.GuideManager
|
||||||
|
import com.gamedog.vididin.manager.TaskManager
|
||||||
|
import com.gamedog.vididin.manager.TestingManager
|
||||||
|
import com.gamedog.vididin.router.Router
|
||||||
|
import com.gamedog.vididin.youtubestatistic.RewardConst
|
||||||
|
import com.gamedog.vididin.youtubestatistic.RewardConst.Companion.Check_Interval_MS
|
||||||
|
import com.remax.bill.ads.AdResult
|
||||||
|
import com.remax.bill.ads.ext.AdShowExt
|
||||||
|
import com.remax.notification.BuildConfig
|
||||||
|
import com.viddin.videos.free.R
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.getValue
|
import kotlin.getValue
|
||||||
import com.gamedog.vididin.databinding.VididinappFeatureHomeFragmentHomeBinding as ViewBinding
|
import com.viddin.videos.free.databinding.VididinappFeatureHomeFragmentHomeBinding as ViewBinding
|
||||||
import com.gamedog.vididin.main.fragments.home.YoutubeViewModel as ViewModel
|
import com.gamedog.vididin.main.fragments.home.YoutubeViewModel as ViewModel
|
||||||
import com.gamedog.vididin.main.fragments.home.YoutubeUiState as UiState
|
import com.gamedog.vididin.main.fragments.home.YoutubeUiState as UiState
|
||||||
|
|
||||||
|
|
@ -30,9 +53,16 @@ import com.gamedog.vididin.main.fragments.home.YoutubeUiState as UiState
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class HomeFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(), OnSwitchTabListener, OnFragmentBackgroundListener {
|
class HomeFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(), OnSwitchTabListener, OnFragmentBackgroundListener {
|
||||||
|
private var mWatchedVideoTotal = 0
|
||||||
|
private var mSwipedVideoTotal = 0
|
||||||
|
private var mLastShowedRewardedAd = true
|
||||||
|
|
||||||
|
override val isLazyInit = false
|
||||||
|
private var mHasShowGuide: Boolean = false
|
||||||
|
private var mTotalMs: Long = 0L
|
||||||
override val mViewModel: ViewModel by viewModels()
|
override val mViewModel: ViewModel by viewModels()
|
||||||
override var isBackgroundBright: Boolean = true
|
override var isBackgroundBright: Boolean = true
|
||||||
|
private var isStatusBarDarkFont = false
|
||||||
|
|
||||||
private val mViewPagerAdapter by lazy { HomeFragmentStateAdapter(this) }
|
private val mViewPagerAdapter by lazy { HomeFragmentStateAdapter(this) }
|
||||||
|
|
||||||
|
|
@ -42,32 +72,219 @@ class HomeFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(), OnSwit
|
||||||
) = ViewBinding.inflate(inflater, container, false)
|
) = ViewBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
override fun ViewBinding.initWindowInsets() {
|
override fun ViewBinding.initWindowInsets() {
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(viewPager2) { v, insets ->
|
/*ViewCompat.setOnApplyWindowInsetsListener(viewPager2) { v, insets ->
|
||||||
val systemBars =
|
val systemBars =
|
||||||
insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
|
insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
|
||||||
v.updatePadding(top = systemBars.top)
|
v.updatePadding(top = systemBars.top)
|
||||||
insets
|
insets
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initViews() {
|
override fun ViewBinding.initViews() {
|
||||||
viewPager2.setPageTransformer { _, _ -> }
|
viewPager2.setPageTransformer { _, _ -> }
|
||||||
viewPager2.offscreenPageLimit = 1
|
viewPager2.offscreenPageLimit = 3
|
||||||
viewPager2.adapter = mViewPagerAdapter
|
viewPager2.adapter = mViewPagerAdapter
|
||||||
|
|
||||||
|
|
||||||
|
popMenu.setMenuList(
|
||||||
|
mutableListOf(
|
||||||
|
PopMenuView.MenuItem(R.mipmap.home_menu_1, 0, 0) {
|
||||||
|
Router.Benefit.startActivity(requireActivity())
|
||||||
|
},
|
||||||
|
PopMenuView.MenuItem(R.mipmap.home_menu_2,R.mipmap.icon_gold_ss_new, 0) {
|
||||||
|
WatchAdDialog(requireActivity(), VidiConst.WATCH_AD_FOR_DAILY_EARN_GOLD_POPMENU, WatchAdDialog.FROM_HOME_MENU,null).show()
|
||||||
|
},
|
||||||
|
PopMenuView.MenuItem(R.mipmap.home_menu_3,0, 0) {
|
||||||
|
Router.Game.startActivity(requireActivity())
|
||||||
|
},
|
||||||
|
PopMenuView.MenuItem(R.mipmap.home_menu_4,0, 0) {
|
||||||
|
Router.ZeroBuy.startActivity(requireActivity())
|
||||||
|
}
|
||||||
|
))
|
||||||
|
|
||||||
|
updatePopMenuTexts()
|
||||||
|
|
||||||
|
registerEvents({ data->
|
||||||
|
when (data?.mEventType) {
|
||||||
|
VididinEvents.Event_HOME_WATCH_Time_TICK -> {
|
||||||
|
handleWatchTimeTick()
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.Event_Finish_One_Video -> {
|
||||||
|
handleEventOneVideoWatched()
|
||||||
|
}
|
||||||
|
|
||||||
|
VididinEvents.EVENT_BOX_TASK_STATE_CHANGED -> {
|
||||||
|
updatePopMenuTexts()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, VididinEvents.Event_HOME_WATCH_Time_TICK, VididinEvents.Event_Finish_One_Video, VididinEvents.EVENT_BOX_TASK_STATE_CHANGED)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updatePopMenuTexts() {
|
||||||
|
for (index in 0..3) {
|
||||||
|
var textStr = ""
|
||||||
|
when (index) {
|
||||||
|
3 -> {
|
||||||
|
textStr = TaskManager.instance().boxTaskStatus().getLeftValidBoxTotalDurationStr()
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> {
|
||||||
|
textStr = VidiConst.WATCH_AD_REWARD_GOLD.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> {
|
||||||
|
textStr = ResUtil.getString(R.string.game_discord)
|
||||||
|
}
|
||||||
|
|
||||||
|
0 -> {
|
||||||
|
textStr = ResUtil.getString(R.string.zero_buy_tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding?.popMenu?.setMenuText(index, textStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun showGuide() {
|
||||||
|
HighlightPro.with(this@HomeFragment)
|
||||||
|
.setHighlightParameter {
|
||||||
|
HighlightParameter.Builder()
|
||||||
|
.setHighlightView(binding?.popMenu!!, {
|
||||||
|
})
|
||||||
|
.setTipsViewId(R.layout.guide_step_popmnue)
|
||||||
|
.setHighlightShape(OvalShape(binding?.popMenu?.measuredWidth!!.toFloat()/2))
|
||||||
|
.setHighlightHorizontalPadding(0.dp)
|
||||||
|
.setConstraints(Constraints.TopToBottomOfHighlight + Constraints.EndToEndOfHighlight)
|
||||||
|
.setMarginOffset(MarginOffset(top = -20.dp.toInt(), end = 20.dp.toInt()))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
.setBackgroundColor("#cc000000".toColorInt())
|
||||||
|
.setOnShowCallback { index ->
|
||||||
|
|
||||||
|
}
|
||||||
|
.setOnDismissCallback {
|
||||||
|
saveGuideState()
|
||||||
|
binding?.popMenu!!.toggleMenu()
|
||||||
|
}
|
||||||
|
.interceptBackPressed(true)
|
||||||
|
.show()
|
||||||
|
|
||||||
|
StatisticUtil.reportEvents(StatisticUtil.KEY_Guide, mapOf("Guide" to 5))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveGuideState() {
|
||||||
|
GuideManager.instance().setGuideIndex(VidiConst.GUIDE_INDEX_POP_MENU)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleEventOneVideoWatched() {
|
||||||
|
mWatchedVideoTotal++
|
||||||
|
|
||||||
|
if (mWatchedVideoTotal % VIDEO_NUM_GAP_FOR_AD_WATCHED == 0) {
|
||||||
|
if (mLastShowedRewardedAd) {
|
||||||
|
showInterstitialAd {}
|
||||||
|
} else {
|
||||||
|
handleShouldShowAdDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset state
|
||||||
|
mLastShowedRewardedAd = !mLastShowedRewardedAd
|
||||||
|
mWatchedVideoTotal = 0
|
||||||
|
mSwipedVideoTotal = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleEventOneVideoSwiped() {
|
||||||
|
mSwipedVideoTotal ++
|
||||||
|
|
||||||
|
if (mSwipedVideoTotal % VIDEO_NUM_GAP_FOR_AD_SWIPED == 0) {
|
||||||
|
if (mLastShowedRewardedAd) {
|
||||||
|
showInterstitialAd {}
|
||||||
|
} else {
|
||||||
|
handleShouldShowAdDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset state
|
||||||
|
mLastShowedRewardedAd = !mLastShowedRewardedAd
|
||||||
|
mWatchedVideoTotal = 0
|
||||||
|
mSwipedVideoTotal = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleWatchTimeTick() {
|
||||||
|
mTotalMs += Check_Interval_MS
|
||||||
|
|
||||||
|
if (mTotalMs < RewardConst.HOME_WATCH_DURATION) {
|
||||||
|
binding?.dragIconView?.setProgress(mTotalMs * 100/RewardConst.HOME_WATCH_DURATION)
|
||||||
|
} else {
|
||||||
|
mTotalMs = 0L
|
||||||
|
binding?.dragIconView?.setProgress(mTotalMs * 100/ RewardConst.HOME_WATCH_DURATION)
|
||||||
|
val goldNum = RewardConst.HOME_WATCH_REWARD_NUM.toLong()
|
||||||
|
AccountManager.adjustGold(goldNum, RecordGold(RECORD_GOLD_PLUS_WATCH_VIDEO_BY_TIME_DURATION, goldNum))
|
||||||
|
binding?.dragIconView?.showRewardGoldAnim()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initListeners() {
|
override fun ViewBinding.initListeners() {
|
||||||
viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
super.onPageSelected(position)
|
super.onPageSelected(position)
|
||||||
setHomeTabStyle(mViewPagerAdapter.getFragmentByIndex(position))
|
val fragment = mViewPagerAdapter.getFragmentByIndex(position)
|
||||||
val curFragment: HomeItemFragment = mViewPagerAdapter.getFragmentByIndex(position) as HomeItemFragment
|
if (fragment != null) {
|
||||||
curFragment.loadVideo()
|
setHomeTabStyle(fragment)
|
||||||
|
val curFragment: HomeItemFragment = fragment as HomeItemFragment
|
||||||
|
curFragment.playVideo()
|
||||||
|
|
||||||
|
handleEventOneVideoSwiped()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preload next N videos and keep previous N videos
|
||||||
|
val preloadCount = 3
|
||||||
|
for (i in 1..preloadCount) {
|
||||||
|
// Next N
|
||||||
|
val nextPos = position + i
|
||||||
|
if (nextPos < mViewPagerAdapter.itemCount) {
|
||||||
|
val nextFragment = mViewPagerAdapter.getFragmentByIndex(nextPos)
|
||||||
|
if (nextFragment != null && nextFragment is HomeItemFragment) {
|
||||||
|
nextFragment.preloadVideo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev N (Keep them ready for playback)
|
||||||
|
val prevPos = position - i
|
||||||
|
if (prevPos >= 0) {
|
||||||
|
val prevFragment = mViewPagerAdapter.getFragmentByIndex(prevPos)
|
||||||
|
if (prevFragment != null && prevFragment is HomeItemFragment) {
|
||||||
|
prevFragment.preloadVideo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release players outside of the window (position - preloadCount - 1)
|
||||||
|
val releasePosBefore = position - preloadCount - 1
|
||||||
|
if (releasePosBefore >= 0) {
|
||||||
|
val prevFragment = mViewPagerAdapter.getFragmentByIndex(releasePosBefore)
|
||||||
|
if (prevFragment != null && prevFragment is HomeItemFragment) {
|
||||||
|
prevFragment.releasePlayer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release players outside of the window (position + preloadCount + 1)
|
||||||
|
val releasePosAfter = position + preloadCount + 1
|
||||||
|
if (releasePosAfter < mViewPagerAdapter.itemCount) {
|
||||||
|
val nextFragment = mViewPagerAdapter.getFragmentByIndex(releasePosAfter)
|
||||||
|
if (nextFragment != null && nextFragment is HomeItemFragment) {
|
||||||
|
nextFragment.releasePlayer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// load more
|
// load more
|
||||||
if (mViewPagerAdapter.itemCount > 0 && position == mViewPagerAdapter.itemCount - 2) {
|
if (mViewPagerAdapter.itemCount > 0 && position >= mViewPagerAdapter.itemCount - 3) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
mViewModel.loadVideoPage()
|
mViewModel.loadVideoList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -81,9 +298,10 @@ class HomeFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(), OnSwit
|
||||||
FragmentLifecycleCallbacks() {
|
FragmentLifecycleCallbacks() {
|
||||||
override fun onFragmentResumed(fm: FragmentManager, fra: Fragment) {
|
override fun onFragmentResumed(fm: FragmentManager, fra: Fragment) {
|
||||||
super.onFragmentResumed(fm, fra)
|
super.onFragmentResumed(fm, fra)
|
||||||
setHomeTabStyle(fra)
|
|
||||||
}
|
}
|
||||||
}, false)
|
}, false)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initObservers() {
|
override fun ViewBinding.initObservers() {
|
||||||
|
|
@ -91,13 +309,22 @@ class HomeFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(), OnSwit
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
|
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
|
||||||
mViewPagerAdapter.submitList(uiState.playLists)
|
mViewPagerAdapter.submitList(uiState.playLists?.toList())
|
||||||
//viewPager2.setDataOrAdapter(uiState.playLists, 1) { mViewPagerAdapter }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
setStatusBarDarkFont(isDarkFont = isBackgroundBright)
|
setStatusBarDarkFont(isDarkFont = isStatusBarDarkFont)
|
||||||
|
|
||||||
|
if (!mHasShowGuide) {
|
||||||
|
val guideStateValue = GuideManager.instance().getCurGuideIndex()
|
||||||
|
if (binding?.popMenu?.isVisible == true && guideStateValue == VidiConst.GUIDE_INDEX_ZERO) {
|
||||||
|
binding?.popMenu?.postDelayed({
|
||||||
|
showGuide()
|
||||||
|
mHasShowGuide = true
|
||||||
|
}, 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
|
@ -113,13 +340,50 @@ class HomeFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(), OnSwit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun showInterstitialAd(callback: () -> Unit) {
|
||||||
|
if (TestingManager.instance().isNormalAdDisable()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
try {
|
||||||
|
when (val result = AdShowExt.showInterstitialAd(requireActivity(), "RV_VideoStream")) {
|
||||||
|
is AdResult.Success -> {
|
||||||
|
callback.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
is AdResult.Failure -> {
|
||||||
|
callback.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
AdResult.Loading -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
callback.invoke()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleShouldShowAdDialog() {
|
||||||
|
val adDialog = WatchAdDialog(requireActivity(), VidiConst.WATCH_AD_FOR_WATCHED_3_VIDEOS,
|
||||||
|
WatchAdDialog.FROM_WATCH_5VIDEOS,null)
|
||||||
|
adDialog.setOnCloseListener {
|
||||||
|
showInterstitialAd {}
|
||||||
|
}
|
||||||
|
adDialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
private fun setHomeTabStyle(f: Fragment?) {
|
private fun setHomeTabStyle(f: Fragment?) {
|
||||||
isBackgroundBright = f.asSafe<OnFragmentBackgroundListener>()?.isBackgroundBright ?: return
|
/*isBackgroundBright = f.asSafe<OnFragmentBackgroundListener>()?.isBackgroundBright ?: return
|
||||||
activity.asSafe<OnTabStyleListener>()?.onTabIsDarkFont(isBackgroundBright)
|
activity.asSafe<OnTabStyleListener>()?.onTabIsDarkFont(isBackgroundBright)*/
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
const val VIDEO_NUM_GAP_FOR_AD_WATCHED = 3
|
||||||
|
const val VIDEO_NUM_GAP_FOR_AD_SWIPED = 5
|
||||||
|
|
||||||
internal fun newInstance() = HomeFragment()
|
internal fun newInstance() = HomeFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,26 @@ package com.gamedog.vididin.main.fragments
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.ama.core.architecture.appBase.AppViewsFragment
|
import com.ama.core.architecture.appBase.AppViewsFragment
|
||||||
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
|
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
|
||||||
|
import com.ama.core.architecture.util.AndroidUtil
|
||||||
import com.ama.core.architecture.util.setOnClickBatch
|
import com.ama.core.architecture.util.setOnClickBatch
|
||||||
import com.ama.core.architecture.util.setStatusBarDarkFont
|
import com.ama.core.architecture.util.setStatusBarDarkFont
|
||||||
import com.ama.core.common.util.dp
|
import com.ama.core.common.util.dp
|
||||||
|
import com.gamedog.vididin.core.login.login.AccountManager
|
||||||
import com.gamedog.vididin.router.Router
|
import com.gamedog.vididin.router.Router
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.getValue
|
import kotlin.getValue
|
||||||
import com.gamedog.vididin.databinding.VididinappFeatureMineFragmentMineBinding as ViewBinding
|
import com.viddin.videos.free.databinding.VididinappFeatureMineFragmentMineBinding as ViewBinding
|
||||||
import com.gamedog.vididin.main.fragments.mine.MineUiState as UiState
|
import com.gamedog.vididin.main.fragments.mine.MineUiState as UiState
|
||||||
import com.gamedog.vididin.main.fragments.mine.MineViewModel as ViewModel
|
import com.gamedog.vididin.main.fragments.mine.MineViewModel as ViewModel
|
||||||
|
|
||||||
|
|
@ -28,9 +33,6 @@ class MineFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(),
|
||||||
OnFragmentBackgroundListener {
|
OnFragmentBackgroundListener {
|
||||||
override val mViewModel: ViewModel by viewModels()
|
override val mViewModel: ViewModel by viewModels()
|
||||||
override var isBackgroundBright: Boolean = true
|
override var isBackgroundBright: Boolean = true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private var isStatusBarDarkFont = false
|
private var isStatusBarDarkFont = false
|
||||||
|
|
||||||
override fun inflateViewBinding(
|
override fun inflateViewBinding(
|
||||||
|
|
@ -48,7 +50,7 @@ class MineFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(),
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ViewBinding.initViews() {
|
override fun ViewBinding.initViews() {
|
||||||
setOnClickBatch(rlPrivacy, rlVersion, rlFeedback) {
|
setOnClickBatch(rlPrivacy, rlVersion, rlFeedback, ivEditName, ivSaveName) {
|
||||||
when (this) {
|
when (this) {
|
||||||
rlPrivacy -> {
|
rlPrivacy -> {
|
||||||
Router.Privacy.startActivity(requireActivity())
|
Router.Privacy.startActivity(requireActivity())
|
||||||
|
|
@ -59,6 +61,65 @@ class MineFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(),
|
||||||
rlFeedback -> {
|
rlFeedback -> {
|
||||||
Router.Feedback.startActivity(requireActivity())
|
Router.Feedback.startActivity(requireActivity())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ivEditName -> {
|
||||||
|
switchNameEditState(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
ivSaveName -> {
|
||||||
|
switchNameEditState(false)
|
||||||
|
AndroidUtil.hideKeyboard(ivSaveName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nameEditRoot.isVisible = false
|
||||||
|
nameNormalRoot.isVisible = true
|
||||||
|
|
||||||
|
var name = AccountManager.getAccount().userName
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
name = "Miguel"
|
||||||
|
AccountManager.updateUserName(name)
|
||||||
|
}
|
||||||
|
tvAccountName.text = name
|
||||||
|
|
||||||
|
etAccountName.addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun afterTextChanged(s: Editable?) {
|
||||||
|
tvNameCharactCount.setText("(${s?.length}/15)")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun beforeTextChanged(
|
||||||
|
s: CharSequence?,
|
||||||
|
start: Int,
|
||||||
|
count: Int,
|
||||||
|
after: Int
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(
|
||||||
|
s: CharSequence?,
|
||||||
|
start: Int,
|
||||||
|
before: Int,
|
||||||
|
count: Int
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun switchNameEditState(isEnterEdit: Boolean) {
|
||||||
|
binding?.let {
|
||||||
|
with(it) {
|
||||||
|
nameEditRoot.isVisible = isEnterEdit
|
||||||
|
nameNormalRoot.isVisible = !isEnterEdit
|
||||||
|
if (isEnterEdit) {
|
||||||
|
etAccountName.setText(tvAccountName.text.toString().trim())
|
||||||
|
} else {
|
||||||
|
val newName = etAccountName.text.toString().trim()
|
||||||
|
if (newName.isNotEmpty()) {
|
||||||
|
tvAccountName.setText(newName)
|
||||||
|
AccountManager.updateUserName(newName)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue