Compare commits
1501
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e668cfb2a3 | ||
|
|
857b63a356 | ||
|
|
0c03406774 | ||
|
|
ac3cb847f4 | ||
|
|
05ed60b86d | ||
|
|
020ec70221 | ||
|
|
478825e708 | ||
|
|
6ce0e630db | ||
|
|
6e538f44b5 | ||
|
|
bd3bec2a31 | ||
|
|
cf25e39485 | ||
|
|
1f87d7a403 | ||
|
|
10da74285c | ||
|
|
3a2607274f | ||
|
|
6cbe7caec1 | ||
|
|
452b4aa667 | ||
|
|
c4d77e40f4 | ||
|
|
3c9a787a77 | ||
|
|
d400da3ab9 | ||
|
|
ded67ac699 | ||
|
|
2c3d78b0b4 | ||
|
|
ed9701a04b | ||
|
|
9af33a4a01 | ||
|
|
481abbc3d8 | ||
|
|
d9065c3073 | ||
|
|
46295e5216 | ||
|
|
5eeff2f08d | ||
|
|
341a368656 | ||
|
|
f9657af36c | ||
|
|
5bead1b88f | ||
|
|
c4d915e60d | ||
|
|
834f70b585 | ||
|
|
a5243e6839 | ||
|
|
03487678ac | ||
|
|
c482e82ebe | ||
|
|
14ecc21937 | ||
|
|
65aa04a7e3 | ||
|
|
d8e1ce12f7 | ||
|
|
9a84b5b87d | ||
|
|
0a42040188 | ||
|
|
8e66f75baf | ||
|
|
72e1371fe0 | ||
|
|
e9c8170ee4 | ||
|
|
330793f8bc | ||
|
|
45015c571f | ||
|
|
b6fcf0330d | ||
|
|
cc95856e47 | ||
|
|
cbab131610 | ||
|
|
879c218f0c | ||
|
|
ef0e2caabf | ||
|
|
d4ab0a1366 | ||
|
|
9cbc45dea3 | ||
|
|
b6133da808 | ||
|
|
59fb11dbaa | ||
|
|
3de88254f6 | ||
|
|
306338992e | ||
|
|
370ee53bde | ||
|
|
ccc61ebb92 | ||
|
|
522cac34b0 | ||
|
|
282c2e3ed7 | ||
|
|
97453703e1 | ||
|
|
dfeff9903d | ||
|
|
208e601f08 | ||
|
|
e9d63463c5 | ||
|
|
c86a1533e4 | ||
|
|
a1332043a1 | ||
|
|
86e41aef7f | ||
|
|
a1937420e8 | ||
|
|
f5383a58e1 | ||
|
|
3476e4eed4 | ||
|
|
9f01927bd1 | ||
|
|
be2b7c99fc | ||
|
|
d4410a1b85 | ||
|
|
1e16a43b1e | ||
|
|
5b70beceeb | ||
|
|
e8dea04d5d | ||
|
|
1dc000f8f5 | ||
|
|
7d3c4ce4a6 | ||
|
|
92159a9242 | ||
|
|
b49813e2b1 | ||
|
|
c977cd5bdf | ||
|
|
9bd5cafc2d | ||
|
|
b96fbc5a5f | ||
|
|
433801a9d0 | ||
|
|
ed115442dc | ||
|
|
3dd4e4df38 | ||
|
|
8925e85bb4 | ||
|
|
3c90940695 | ||
|
|
d2e9968829 | ||
|
|
c7e5c57248 | ||
|
|
7c820b7207 | ||
|
|
0fbdccbecc | ||
|
|
61d63d574b | ||
|
|
c5a0d7d05c | ||
|
|
d07bf40dc3 | ||
|
|
d365cd9068 | ||
|
|
d8a7b451c0 | ||
|
|
6ea4822f41 | ||
|
|
28ab01cbff | ||
|
|
cc16f4727f | ||
|
|
244bae71e2 | ||
|
|
79c2fc9010 | ||
|
|
66951fa826 | ||
|
|
e9047274b3 | ||
|
|
ac364f1ae2 | ||
|
|
5f57558c52 | ||
|
|
01f956477b | ||
|
|
3c8b394a4b | ||
|
|
c525427594 | ||
|
|
f5037dced3 | ||
|
|
8a83052941 | ||
|
|
274e1bd0df | ||
|
|
0bcbf2b4f8 | ||
|
|
32daac436e | ||
|
|
a7d8e7294f | ||
|
|
820ca12c3e | ||
|
|
38aa6c1905 | ||
|
|
f3cda292e0 | ||
|
|
91bd29cf93 | ||
|
|
75c98b98dd | ||
|
|
186a807d54 | ||
|
|
cc6e3c2dd8 | ||
|
|
48ba199613 | ||
|
|
9a9a73e89a | ||
|
|
df3b374f3a | ||
|
|
a6f52af5d1 | ||
|
|
5c26dd8ea4 | ||
|
|
fa12e8f7e0 | ||
|
|
14cf129435 | ||
|
|
3a7a05e630 | ||
|
|
073c80d1b0 | ||
|
|
e05fe77fb4 | ||
|
|
b0856d6232 | ||
|
|
b86128ac66 | ||
|
|
0cdccd6a54 | ||
|
|
3e9058002b | ||
|
|
829a333d7f | ||
|
|
76775f0ad4 | ||
|
|
42984efe25 | ||
|
|
086210718c | ||
|
|
7656468636 | ||
|
|
bc1f11da61 | ||
|
|
448a169bc3 | ||
|
|
63075ca216 | ||
|
|
27cacc03a2 | ||
|
|
4876a881d2 | ||
|
|
2002db57d9 | ||
|
|
fef7082e66 | ||
|
|
0aad1ef358 | ||
|
|
4dc7223629 | ||
|
|
d8f5b5e910 | ||
|
|
9fbb2fada4 | ||
|
|
3d5c832cec | ||
|
|
a31d75ea41 | ||
|
|
bc467ac335 | ||
|
|
efa28aa3d6 | ||
|
|
aee5f38fb5 | ||
|
|
9dd3a26bab | ||
|
|
a4612a127d | ||
|
|
f49bc4d05d | ||
|
|
7a21f11b64 | ||
|
|
0ca4ba2697 | ||
|
|
4775715b66 | ||
|
|
09333dc64d | ||
|
|
c481d5fca9 | ||
|
|
91bfea9917 | ||
|
|
be65e6816d | ||
|
|
042595f238 | ||
|
|
1f2200c584 | ||
|
|
174151b52b | ||
|
|
52b58dc79b | ||
|
|
7fed263a0e | ||
|
|
de92e4670c | ||
|
|
79fd0350e4 | ||
|
|
4806bb89eb | ||
|
|
4f760b5a4d | ||
|
|
0cdbf9ce99 | ||
|
|
f19a4275de | ||
|
|
a7bde644a4 | ||
|
|
7e36bbf83e | ||
|
|
e461b4654e | ||
|
|
0a7338bf89 | ||
|
|
8d7f2dfee8 | ||
|
|
c1197e461b | ||
|
|
bf5bc08671 | ||
|
|
7baaf08167 | ||
|
|
437bef3d03 | ||
|
|
0d75bec938 | ||
|
|
024079c4bc | ||
|
|
0af00ab7d1 | ||
|
|
ed53f509ee | ||
|
|
2011901666 | ||
|
|
6b90aedae8 | ||
|
|
b75ce047df | ||
|
|
4db73ff3d1 | ||
|
|
bfd258ba54 | ||
|
|
4a092f0920 | ||
|
|
e499d98050 | ||
|
|
186c1f80e6 | ||
|
|
7299c9e33a | ||
|
|
59c8be9ac2 | ||
|
|
4d0573ffe5 | ||
|
|
eb2c4c02d2 | ||
|
|
83d13dce1e | ||
|
|
fe2fd354fd | ||
|
|
55dbb029c0 | ||
|
|
16fd8925ff | ||
|
|
3df51d0685 | ||
|
|
661302d90f | ||
|
|
9bc87a1d79 | ||
|
|
2c8dd6e89a | ||
|
|
94667ac741 | ||
|
|
91fe8a8fb4 | ||
|
|
3a354b359a | ||
|
|
cc3456758e | ||
|
|
09443d6ec1 | ||
|
|
c2dc772905 | ||
|
|
ca27776aaf | ||
|
|
9915e8d2df | ||
|
|
3b6cdacf96 | ||
|
|
5c79dbe1c2 | ||
|
|
c7621c44d5 | ||
|
|
f83e97404a | ||
|
|
89997317bf | ||
|
|
f704d54178 | ||
|
|
c87be6c9b8 | ||
|
|
3577e3b70c | ||
|
|
4ae5ea8e57 | ||
|
|
000bd5e7d3 | ||
|
|
b967e72a04 | ||
|
|
4d3e8d4354 | ||
|
|
cc66af3e3a | ||
|
|
0d51b40676 | ||
|
|
f82ef2f64e | ||
|
|
054f03480e | ||
|
|
646329f93b | ||
|
|
114b46ccee | ||
|
|
3f7b9eb796 | ||
|
|
0715c0cfcf | ||
|
|
a3d8a9ba70 | ||
|
|
a51a146780 | ||
|
|
8d05973848 | ||
|
|
c2c3ea68fa | ||
|
|
2b553d263c | ||
|
|
8e40da9fb4 | ||
|
|
265d3afbff | ||
|
|
d6b744533b | ||
|
|
858fced1aa | ||
|
|
df1d411ae0 | ||
|
|
a01d12b012 | ||
|
|
2904616d67 | ||
|
|
8bde61b059 | ||
|
|
61eac6feca | ||
|
|
05eec57058 | ||
|
|
1f29f2ddc5 | ||
|
|
c2a1a4bb5f | ||
|
|
fbff3eadde | ||
|
|
5e01ebcff6 | ||
|
|
7c8a76616c | ||
|
|
ffe0955ef1 | ||
|
|
465d52df67 | ||
|
|
f4ca7c9e66 | ||
|
|
57e69b0d98 | ||
|
|
57b19369a0 | ||
|
|
a799828de0 | ||
|
|
4019219293 | ||
|
|
e6ad306e24 | ||
|
|
5d6c001dfb | ||
|
|
5ff1e0a0a6 | ||
|
|
1f2b1b1180 | ||
|
|
09048a7a21 | ||
|
|
cb7862a0e2 | ||
|
|
2e2e890875 | ||
|
|
1cd23341e2 | ||
|
|
271b1cdfee | ||
|
|
f85dac2ff8 | ||
|
|
bc06512250 | ||
|
|
992b29894e | ||
|
|
a94af3a4db | ||
|
|
9e67ded6bd | ||
|
|
924a34b458 | ||
|
|
24607e1ea5 | ||
|
|
f73b880b6d | ||
|
|
8e260a9de4 | ||
|
|
a53a9eaeaa | ||
|
|
de045f749a | ||
|
|
88390f0fc9 | ||
|
|
fde1628fac | ||
|
|
c6721841ac | ||
|
|
fdeaa05360 | ||
|
|
dfa77311f2 | ||
|
|
d0197142cd | ||
|
|
57e241ab7d | ||
|
|
8257393909 | ||
|
|
50b97aac8a | ||
|
|
9542317b23 | ||
|
|
6166b29b29 | ||
|
|
de595c93f4 | ||
|
|
7ee1331263 | ||
|
|
7596b4117a | ||
|
|
0cc0299215 | ||
|
|
8b6ef6d3af | ||
|
|
a7e0f2ae2b | ||
|
|
1d71def416 | ||
|
|
c38e0aa61e | ||
|
|
18799ce11c | ||
|
|
9496da151a | ||
|
|
b4e34e34b1 | ||
|
|
5cec11c6dd | ||
|
|
cd6f975e56 | ||
|
|
a285bf4270 | ||
|
|
de73c6216b | ||
|
|
344c418412 | ||
|
|
129ae95121 | ||
|
|
5464053fa0 | ||
|
|
78cd5cac9a | ||
|
|
f7fab596ba | ||
|
|
8036fc332b | ||
|
|
c1cb5c23ae | ||
|
|
85afaa5057 | ||
|
|
dbb25fbabd | ||
|
|
f1ed0fc221 | ||
|
|
d75a339a02 | ||
|
|
b64b17038d | ||
|
|
6fd15a05ff | ||
|
|
e5b5bf9d48 | ||
|
|
0d991138c0 | ||
|
|
c58e511040 | ||
|
|
5264a397a0 | ||
|
|
a067a35040 | ||
|
|
c2fe5e6c3c | ||
|
|
dbee2a5a42 | ||
|
|
7c232b70ed | ||
|
|
104ca05772 | ||
|
|
8761d23bda | ||
|
|
ad5eca635a | ||
|
|
81203ef531 | ||
|
|
6c86b49e97 | ||
|
|
743356af01 | ||
|
|
ad8f2b5b5a | ||
|
|
036cf4846c | ||
|
|
3058c220a8 | ||
|
|
7f97394861 | ||
|
|
6531a21fb4 | ||
|
|
d439469f39 | ||
|
|
3366d28e7e | ||
|
|
8ec891d0bc | ||
|
|
39b08702d5 | ||
|
|
bb318aeeb1 | ||
|
|
b90b27e8ce | ||
|
|
6621f7c2a2 | ||
|
|
9b03299c7b | ||
|
|
108e212c56 | ||
|
|
a9343c6777 | ||
|
|
f923db90ea | ||
|
|
a03505f27f | ||
|
|
e5a0e9617b | ||
|
|
b9126aa184 | ||
|
|
e0d27dd97c | ||
|
|
613a101c82 | ||
|
|
5d49fc586b | ||
|
|
43fe0577cd | ||
|
|
e1beef2e29 | ||
|
|
6208c966d0 | ||
|
|
0803e73949 | ||
|
|
636341b4f2 | ||
|
|
e7b8dd56fe | ||
|
|
576ce7d6b0 | ||
|
|
add56248e1 | ||
|
|
e74001e17e | ||
|
|
90a539d361 | ||
|
|
48f6b35abe | ||
|
|
ed2645e3ff | ||
|
|
5beea5d273 | ||
|
|
cdc8d2eaf2 | ||
|
|
842130628e | ||
|
|
bdb9dc670c | ||
|
|
ab26bab35d | ||
|
|
32b3a035a8 | ||
|
|
6ffcbe8329 | ||
|
|
c44aea13d6 | ||
|
|
ca3d1e9585 | ||
|
|
ce4bb21782 | ||
|
|
05a9e9a12c | ||
|
|
fa5716d651 | ||
|
|
9e2f3bb048 | ||
|
|
c7971c9860 | ||
|
|
91aef33725 | ||
|
|
9d3e7c53de | ||
|
|
32c5aa9ac2 | ||
|
|
81c4e1c019 | ||
|
|
e32c3ec74b | ||
|
|
a4125653cf | ||
|
|
3fea0e9c40 | ||
|
|
3c3b51d6ab | ||
|
|
c9c5c96d63 | ||
|
|
9e21dee290 | ||
|
|
2a91238b4f | ||
|
|
c341e493f8 | ||
|
|
e4d740061d | ||
|
|
e6325c74d8 | ||
|
|
f96f2cb7d7 | ||
|
|
e703adb168 | ||
|
|
0482f75172 | ||
|
|
ae2b9e0cce | ||
|
|
eaed8fc752 | ||
|
|
6db84cbc12 | ||
|
|
f871e63002 | ||
|
|
db41faee3e | ||
|
|
189d699d48 | ||
|
|
905158bb07 | ||
|
|
f3b6b3c1b0 | ||
|
|
a08782de4e | ||
|
|
519722d613 | ||
|
|
0fcbffab26 | ||
|
|
3aaca80da1 | ||
|
|
30d6ccbd9a | ||
|
|
b889015368 | ||
|
|
cd7f3f8b52 | ||
|
|
1d3463df0c | ||
|
|
4b57fa9414 | ||
|
|
60ac497e6d | ||
|
|
9d3099f816 | ||
|
|
f8192c7169 | ||
|
|
a0c02b2fd1 | ||
|
|
3f2e0c9b98 | ||
|
|
df8c86fe4c | ||
|
|
2a9ea90df5 | ||
|
|
008a24bfff | ||
|
|
aa40bbb390 | ||
|
|
5484766ef1 | ||
|
|
4782401f0a | ||
|
|
b36a3bfbdb | ||
|
|
0255cfb1b9 | ||
|
|
7fc842c9ef | ||
|
|
764b68d47f | ||
|
|
8615faff4a | ||
|
|
126154fc9b | ||
|
|
ba05c831cc | ||
|
|
ec2df87e42 | ||
|
|
3f11a14d92 | ||
|
|
e963080385 | ||
|
|
0284dec33a | ||
|
|
23286a21f0 | ||
|
|
8d376d9e5a | ||
|
|
4e48faec16 | ||
|
|
ce731b1832 | ||
|
|
666c562092 | ||
|
|
64a8552647 | ||
|
|
4f5cbe426a | ||
|
|
e0b06449ec | ||
|
|
5635cd4139 | ||
|
|
64d62b10a1 | ||
|
|
4bb31d492a | ||
|
|
1a3cf8695d | ||
|
|
f85fe81881 | ||
|
|
1251dd1d2d | ||
|
|
5295e465e9 | ||
|
|
06d5b1a779 | ||
|
|
7f30e66c0c | ||
|
|
c18a3dde9e | ||
|
|
d55361fd72 | ||
|
|
6961bc073a | ||
|
|
63d1c1a3b0 | ||
|
|
e1b6f8d66f | ||
|
|
4cc6bfabd0 | ||
|
|
b95edec916 | ||
|
|
802f639633 | ||
|
|
8756cd1f20 | ||
|
|
8a90602328 | ||
|
|
8122c92bbf | ||
|
|
6f607e9ae8 | ||
|
|
3e53455a05 | ||
|
|
dd0f238701 | ||
|
|
07ddb66264 | ||
|
|
600a9da953 | ||
|
|
4fef230a06 | ||
|
|
d14dec88bc | ||
|
|
2d73131863 | ||
|
|
6e216830d1 | ||
|
|
f90ae6bade | ||
|
|
2b6012b1e7 | ||
|
|
b4a45a17c7 | ||
|
|
ded283df35 | ||
|
|
8767540164 | ||
|
|
86a5c60f7f | ||
|
|
fb8e327856 | ||
|
|
1d964762ca | ||
|
|
344b30aa62 | ||
|
|
4a2d2b23f2 | ||
|
|
d776693aea | ||
|
|
a06d129c8d | ||
|
|
aaf2f9c6c9 | ||
|
|
a0b1adbfe9 | ||
|
|
5fbabfbe23 | ||
|
|
0093463fae | ||
|
|
42645a5414 | ||
|
|
9e572d7844 | ||
|
|
5af63e0adf | ||
|
|
900dbcfe0a | ||
|
|
ba430052de | ||
|
|
e3e06d1638 | ||
|
|
a81ebed663 | ||
|
|
69a4cfa715 | ||
|
|
920883ada1 | ||
|
|
21d9c13fdf | ||
|
|
41c5f57ccc | ||
|
|
09bf8e26ce | ||
|
|
2aa7862fe1 | ||
|
|
21c0ccd9fc | ||
|
|
22795bab81 | ||
|
|
aa95b368f8 | ||
|
|
9ae1c0c1bb | ||
|
|
4be234632c | ||
|
|
c155e560ba | ||
|
|
00d37e3721 | ||
|
|
f92dd71d35 | ||
|
|
4c4a3ae11c | ||
|
|
474f9f0197 | ||
|
|
7e09e6d4e6 | ||
|
|
aee76ba2ff | ||
|
|
b92fa69628 | ||
|
|
398b6fc37b | ||
|
|
d127a84b07 | ||
|
|
454cea3556 | ||
|
|
95916b4289 | ||
|
|
90816b5c67 | ||
|
|
5cb5d06993 | ||
|
|
7c1ac4b267 | ||
|
|
f0da269968 | ||
|
|
c145b64441 | ||
|
|
2fb021ad05 | ||
|
|
2ad5ab7a87 | ||
|
|
1981bc9d14 | ||
|
|
95fd69c5da | ||
|
|
c60cce5467 | ||
|
|
1a3f18cbc2 | ||
|
|
2035d513f1 | ||
|
|
f4031ead02 | ||
|
|
3849569794 | ||
|
|
37b7783b40 | ||
|
|
9f2f6d6f60 | ||
|
|
8059743e0b | ||
|
|
586a82a15f | ||
|
|
2c1beedf8b | ||
|
|
eba922871f | ||
|
|
484510da77 | ||
|
|
337aa7493e | ||
|
|
ddf046cd20 | ||
|
|
1ed9f871c3 | ||
|
|
083d96707c | ||
|
|
1c5316ba4e | ||
|
|
5503caed79 | ||
|
|
10e0bd50da | ||
|
|
1f11530d04 | ||
|
|
2864056186 | ||
|
|
95b5fca205 | ||
|
|
8876a66449 | ||
|
|
7432fe7aba | ||
|
|
41a1d29c4b | ||
|
|
c4630042c7 | ||
|
|
1bb10807c4 | ||
|
|
16f4178e36 | ||
|
|
7f8100660a | ||
|
|
421d080ec7 | ||
|
|
274a1b9fa8 | ||
|
|
381a759c4b | ||
|
|
03c5f83a42 | ||
|
|
08bb1e1174 | ||
|
|
f394bdfec5 | ||
|
|
7fec602f34 | ||
|
|
19c9dd102f | ||
|
|
1f9aca7399 | ||
|
|
d38038f848 | ||
|
|
8ab5cdd860 | ||
|
|
2f30d070ec | ||
|
|
401fc44e91 | ||
|
|
028b3aad59 | ||
|
|
8a7c21c549 | ||
|
|
918967f502 | ||
|
|
95636ad4f4 | ||
|
|
561afe8765 | ||
|
|
929e481b3d | ||
|
|
69266ed31f | ||
|
|
742e0c46b3 | ||
|
|
319f3c421a | ||
|
|
3b5eb3cd10 | ||
|
|
55f71bfd8b | ||
|
|
1ac755a98b | ||
|
|
00d0b9d237 | ||
|
|
edd04586ea | ||
|
|
98b1cf8db3 | ||
|
|
d20296d4b8 | ||
|
|
7c8627f9f6 | ||
|
|
2e2be2fe4a | ||
|
|
673d5fe16c | ||
|
|
4a949e7d45 | ||
|
|
39391a4ace | ||
|
|
9a9552c369 | ||
|
|
6b9f80284c | ||
|
|
15dd2b2fde | ||
|
|
4b2a537e3b | ||
|
|
a94ca687eb | ||
|
|
06f0864cc3 | ||
|
|
1ddc2f6b14 | ||
|
|
ad6c350e69 | ||
|
|
dadbc37189 | ||
|
|
d646a0cd19 | ||
|
|
ae145691c5 | ||
|
|
a6cbf35350 | ||
|
|
aba12ad48a | ||
|
|
32ebf0e4f4 | ||
|
|
099de74ac1 | ||
|
|
dd490abf69 | ||
|
|
3468b9352e | ||
|
|
af0efb7184 | ||
|
|
592d25bf6d | ||
|
|
a53f1d7299 | ||
|
|
ea3707cebd | ||
|
|
b2ba9774bc | ||
|
|
7205c78839 | ||
|
|
26672cfbc2 | ||
|
|
941335ec02 | ||
|
|
8bbf0ebb1f | ||
|
|
9d16d4e57e | ||
|
|
cece5a2a55 | ||
|
|
fb907d68a4 | ||
|
|
dac2e10a52 | ||
|
|
0e472e985b | ||
|
|
e349193afb | ||
|
|
066beb14f1 | ||
|
|
15f8af1e3e | ||
|
|
599ee3dfab | ||
|
|
9d005cd2e0 | ||
|
|
c8747ea957 | ||
|
|
6bc33dbb31 | ||
|
|
303fe83ff9 | ||
|
|
cb122bb6c8 | ||
|
|
bb73aaa580 | ||
|
|
7e7730e825 | ||
|
|
8f291b058f | ||
|
|
0f9ab88e68 | ||
|
|
36c244be15 | ||
|
|
71d4cd09fc | ||
|
|
037f1809e8 | ||
|
|
3513844ca5 | ||
|
|
2e180d2c9c | ||
|
|
fd3eae0283 | ||
|
|
048a835b2b | ||
|
|
e144390d4f | ||
|
|
320892cdf5 | ||
|
|
1716aa51dd | ||
|
|
7157a0c664 | ||
|
|
34787ffb5b | ||
|
|
d44b363d1d | ||
|
|
3972ceba5b | ||
|
|
505a2d4553 | ||
|
|
84da0b422a | ||
|
|
ab19f6b71a | ||
|
|
9c8f962e5f | ||
|
|
ad706355cd | ||
|
|
efac38a871 | ||
|
|
049940f3bb | ||
|
|
5f68809d9c | ||
|
|
930792f983 | ||
|
|
5e7eb51127 | ||
|
|
99a387f9a0 | ||
|
|
679960045a | ||
|
|
1dc1436082 | ||
|
|
2ba602ae9f | ||
|
|
98aa6ef0f8 | ||
|
|
b8f5b0179a | ||
|
|
877670bb84 | ||
|
|
5859b93612 | ||
|
|
0f33dfc395 | ||
|
|
0330b8ad8e | ||
|
|
7d85d61eb5 | ||
|
|
28ee64fc30 | ||
|
|
19bc27059d | ||
|
|
457822de7d | ||
|
|
4c5d83fccc | ||
|
|
92c9ea2222 | ||
|
|
e6b7ea8c2c | ||
|
|
81bc85a0aa | ||
|
|
f9b02b1cce | ||
|
|
2cb6321776 | ||
|
|
bbf0ada834 | ||
|
|
8c63ff69c7 | ||
|
|
94c72eb490 | ||
|
|
d1f2a78a48 | ||
|
|
2983afcda5 | ||
|
|
fe87a5dd64 | ||
|
|
9daa346e31 | ||
|
|
816683ac8a | ||
|
|
b90fd41bf2 | ||
|
|
991f1f9eb8 | ||
|
|
2ae9df03e1 | ||
|
|
665e2dda05 | ||
|
|
a5134f1cd5 | ||
|
|
3680ff44a2 | ||
|
|
34ae44016d | ||
|
|
a0ebc913d1 | ||
|
|
1afa317e7b | ||
|
|
84c194d318 | ||
|
|
56cd2b2d39 | ||
|
|
b001517a63 | ||
|
|
cd389af2bd | ||
|
|
69a2f03656 | ||
|
|
047b547449 | ||
|
|
0912f57184 | ||
|
|
568f69db60 | ||
|
|
511c16771d | ||
|
|
321273c54a | ||
|
|
f6e0a7edb4 | ||
|
|
dd9b2a8a58 | ||
|
|
77f80883ae | ||
|
|
ec5b8b3455 | ||
|
|
cd611afbd3 | ||
|
|
943c612581 | ||
|
|
2ed8082df2 | ||
|
|
4806d97e29 | ||
|
|
c603c9844a | ||
|
|
a3b1220f18 | ||
|
|
18582c535a | ||
|
|
d002d05b2a | ||
|
|
c198a14e0c | ||
|
|
deda04cbf8 | ||
|
|
021e85d5b8 | ||
|
|
0921485959 | ||
|
|
82aacf32b7 | ||
|
|
e7b0ae0225 | ||
|
|
2fb7778717 | ||
|
|
a993993773 | ||
|
|
6f49e35b22 | ||
|
|
ea277c303f | ||
|
|
a7652e4e71 | ||
|
|
5cb7306613 | ||
|
|
1ddecb47af | ||
|
|
ac2c972b9b | ||
|
|
86798ffb59 | ||
|
|
a85a7d84b2 | ||
|
|
1ed90da1b8 | ||
|
|
a2b231f365 | ||
|
|
a618b2cc5b | ||
|
|
4e4c287111 | ||
|
|
060f24b6c6 | ||
|
|
d3840bf9fd | ||
|
|
ba216cb06b | ||
|
|
917f5b565f | ||
|
|
938c6ff633 | ||
|
|
56bf382618 | ||
|
|
eb3cc75a98 | ||
|
|
f3e3cdf79a | ||
|
|
ad808263d1 | ||
|
|
53616c8bc6 | ||
|
|
466105d69c | ||
|
|
64c9cff0bb | ||
|
|
8fbbf8b6be | ||
|
|
6c0d5619e4 | ||
|
|
c3c41f9d2e | ||
|
|
a154138fb5 | ||
|
|
0bf6821a4b | ||
|
|
470ac9dd4d | ||
|
|
b68b10f776 | ||
|
|
c06f2588a8 | ||
|
|
f6ade7a059 | ||
|
|
08d7851de3 | ||
|
|
78902110eb | ||
|
|
b7b9de4ba4 | ||
|
|
83014931dc | ||
|
|
46edd53cb6 | ||
|
|
87b1251f5a | ||
|
|
4ce73d9e55 | ||
|
|
4541ef61c1 | ||
|
|
4f3f26e3f5 | ||
|
|
1f235bfc4a | ||
|
|
548a029db2 | ||
|
|
6d1b964239 | ||
|
|
487cb6c076 | ||
|
|
5a372f6c60 | ||
|
|
81f954d25a | ||
|
|
ec3248f5c3 | ||
|
|
c959d5e5d6 | ||
|
|
49798694b2 | ||
|
|
3879555297 | ||
|
|
fc11e2d055 | ||
|
|
4905e8fed0 | ||
|
|
9a02f2a7c3 | ||
|
|
03014f245c | ||
|
|
13f247467c | ||
|
|
5116f507c5 | ||
|
|
228e6ea282 | ||
|
|
7663d4cee2 | ||
|
|
4e003d355e | ||
|
|
75982656b1 | ||
|
|
2f12cb188f | ||
|
|
46cd9c0582 | ||
|
|
8be76aa871 | ||
|
|
9d9c02bec5 | ||
|
|
30faa329e9 | ||
|
|
0a9322741c | ||
|
|
f68cc4a6bd | ||
|
|
0717fd960e | ||
|
|
0dcb2b8fd7 | ||
|
|
2581b5a1a2 | ||
|
|
36cd21f7f6 | ||
|
|
e09a6291fe | ||
|
|
f800dffb5f | ||
|
|
86ba91a77e | ||
|
|
6aade65b4b | ||
|
|
ba1aeeb4b1 | ||
|
|
4467abc181 | ||
|
|
75960a7631 | ||
|
|
8209aa6fdf | ||
|
|
38bcd40ad6 | ||
|
|
dbc358d0a0 | ||
|
|
dcb2244498 | ||
|
|
e3b6bd8219 | ||
|
|
07f1f62fb7 | ||
|
|
89f94df42b | ||
|
|
b3197aa921 | ||
|
|
cfc2c67efc | ||
|
|
d3b1e6e075 | ||
|
|
b221a8d55d | ||
|
|
9cc6d4f8e0 | ||
|
|
1a0a24df45 | ||
|
|
f74b2b1acf | ||
|
|
c7b5b7d6ca | ||
|
|
215d747dad | ||
|
|
c10b3e5619 | ||
|
|
f03d4892a2 | ||
|
|
6c84540a5d | ||
|
|
664e1fe428 | ||
|
|
328b2caecb | ||
|
|
0799757097 | ||
|
|
8c9fee306f | ||
|
|
c23624ab11 | ||
|
|
ea4315274b | ||
|
|
947183ff02 | ||
|
|
dbe80696d6 | ||
|
|
1296ab56a7 | ||
|
|
bda751e692 | ||
|
|
5135cfa347 | ||
|
|
c450ef7f87 | ||
|
|
bd470aba41 | ||
|
|
3435531cb2 | ||
|
|
e784f8a27b | ||
|
|
96e9579bbf | ||
|
|
36432e0c80 | ||
|
|
b58a918f27 | ||
|
|
e8753831b6 | ||
|
|
7068600d3d | ||
|
|
b9443f0d78 | ||
|
|
3ca54043d8 | ||
|
|
e672a6dcf4 | ||
|
|
453d90827b | ||
|
|
13f68a3b12 | ||
|
|
07a26092ae | ||
|
|
57b6ba04b3 | ||
|
|
cf744757b6 | ||
|
|
59afe0a412 | ||
|
|
488eb7c0ea | ||
|
|
2a7af94f10 | ||
|
|
1922863723 | ||
|
|
1259231653 | ||
|
|
ba8d3c42a1 | ||
|
|
ab851d3600 | ||
|
|
b80213a017 | ||
|
|
8cb4bb0a55 | ||
|
|
58cddd18e2 | ||
|
|
67c0a3eed4 | ||
|
|
e7c7dae411 | ||
|
|
f66d2af98a | ||
|
|
dc3e6293ee | ||
|
|
05397f69d0 | ||
|
|
9f341eb485 | ||
|
|
e944f5bdf5 | ||
|
|
a0a34d138f | ||
|
|
4b55279c84 | ||
|
|
b5a7852f2e | ||
|
|
b675834a6f | ||
|
|
09e509e48f | ||
|
|
e2b6a3a75e | ||
|
|
dc4c31d66a | ||
|
|
abeb31f4f0 | ||
|
|
c7b91b62e6 | ||
|
|
648369b7cd | ||
|
|
3f834cc83b | ||
|
|
4dd5f13b3a | ||
|
|
faea96a786 | ||
|
|
7882968a05 | ||
|
|
d6595f54f1 | ||
|
|
6f1ba0ca9f | ||
|
|
daee7c8665 | ||
|
|
dd591ee78b | ||
|
|
f72ff25ebe | ||
|
|
04cf3b1b8a | ||
|
|
0cd82deaa6 | ||
|
|
826b566540 | ||
|
|
a2018f85b4 | ||
|
|
f48e05badb | ||
|
|
21ad47b45b | ||
|
|
ea54706e8b | ||
|
|
db6c23d511 | ||
|
|
d06396a51d | ||
|
|
bc5cc9b6f6 | ||
|
|
b05d6fb22b | ||
|
|
3144dd07e8 | ||
|
|
247627fe08 | ||
|
|
32668111e1 | ||
|
|
c3848fdbba | ||
|
|
834367ea65 | ||
|
|
7f9e5aa11e | ||
|
|
5554b5197a | ||
|
|
a0e504a834 | ||
|
|
f5d4892ba6 | ||
|
|
32e807e130 | ||
|
|
d7ff759cde | ||
|
|
fc4f8056c5 | ||
|
|
7b073523fa | ||
|
|
7205be3749 | ||
|
|
e1915e19a3 | ||
|
|
4da341ccf8 | ||
|
|
6ef958a606 | ||
|
|
a5811047d9 | ||
|
|
75e562e92f | ||
|
|
75d537f36a | ||
|
|
b68812109c | ||
|
|
44d0f31f93 | ||
|
|
b5d5b87779 | ||
|
|
cf180f5146 | ||
|
|
430c1686c0 | ||
|
|
d1d4bb1f5b | ||
|
|
03561407a3 | ||
|
|
a9c2c6945b | ||
|
|
6ae59e0557 | ||
|
|
b1c2c785f3 | ||
|
|
aa0c2a7093 | ||
|
|
987379b7a2 | ||
|
|
7ee38e27d3 | ||
|
|
60be976861 | ||
|
|
14e1c736b3 | ||
|
|
fc6945a72d | ||
|
|
b73e8b5c99 | ||
|
|
7fad5f2db8 | ||
|
|
6119610d7f | ||
|
|
401685c1b6 | ||
|
|
bf0f78b391 | ||
|
|
0f40e271db | ||
|
|
990a392b83 | ||
|
|
9e1d0077f6 | ||
|
|
68c3619f7f | ||
|
|
0419316f32 | ||
|
|
fb8252eebe | ||
|
|
8a7763c356 | ||
|
|
6187eecac5 | ||
|
|
4d3f262d59 | ||
|
|
95feb481a9 | ||
|
|
1a42c24dab | ||
|
|
833e02bfb2 | ||
|
|
705d6bf639 | ||
|
|
1186cd4a8d | ||
|
|
4b19b59b3a | ||
|
|
066a1ed161 | ||
|
|
cc9a826f1d | ||
|
|
8dd7b2d368 | ||
|
|
d82609304a | ||
|
|
831ba0a774 | ||
|
|
15fe52d83f | ||
|
|
bce20b9ad6 | ||
|
|
291273aef5 | ||
|
|
8248418fe2 | ||
|
|
99629f0a3e | ||
|
|
9405ee352d | ||
|
|
4dd055b9b1 | ||
|
|
7769a76bea | ||
|
|
27b8b57625 | ||
|
|
682ed1c8c5 | ||
|
|
f6c30a4953 | ||
|
|
4c352713ca | ||
|
|
20efb909ae | ||
|
|
fc6f528541 | ||
|
|
1d97000bef | ||
|
|
ade116fa03 | ||
|
|
ec40c99c95 | ||
|
|
ab66804d87 | ||
|
|
126d8c7926 | ||
|
|
b936327eec | ||
|
|
7499aadec6 | ||
|
|
ed5f82cbd2 | ||
|
|
596b71ce56 | ||
|
|
af6aaf341e | ||
|
|
4f51cdec0a | ||
|
|
e4f68f4024 | ||
|
|
b2f78987f7 | ||
|
|
a567d044c6 | ||
|
|
5e6fff7b8d | ||
|
|
f4766d0a11 | ||
|
|
5b95b17703 | ||
|
|
534e33ee46 | ||
|
|
3d0b8cf0a2 | ||
|
|
764f026ab9 | ||
|
|
056fdc3b2c | ||
|
|
d4641d88c0 | ||
|
|
6a82aee5cc | ||
|
|
ffa64a0125 | ||
|
|
856eafe8de | ||
|
|
94a6b5aa96 | ||
|
|
42b02add89 | ||
|
|
034bf2dd2c | ||
|
|
0eccfbf5ea | ||
|
|
23c3bd8852 | ||
|
|
037444d813 | ||
|
|
44de228f9f | ||
|
|
7b25221fee | ||
|
|
363afa251a | ||
|
|
052e3114bf | ||
|
|
d73c5133d3 | ||
|
|
8d0b63ad72 | ||
|
|
5766d03767 | ||
|
|
7ee2f8ab46 | ||
|
|
1840c76a26 | ||
|
|
51e8219306 | ||
|
|
82d16c6a0c | ||
|
|
da087054cc | ||
|
|
5781df15d3 | ||
|
|
4c1cb174b8 | ||
|
|
fa1ef6dfa5 | ||
|
|
1389a39bea | ||
|
|
0491afacec | ||
|
|
de62447522 | ||
|
|
3ba9b8c4e4 | ||
|
|
c1760a48ca | ||
|
|
32b854baf8 | ||
|
|
5b91699c69 | ||
|
|
1f42bb9ec6 | ||
|
|
8330f7fe89 | ||
|
|
74bbb9eed9 | ||
|
|
78960e7827 | ||
|
|
3dfe10fc87 | ||
|
|
807c3b95c4 | ||
|
|
4f408e4cfa | ||
|
|
0d0caa9d83 | ||
|
|
d33e382b49 | ||
|
|
20b7e77be2 | ||
|
|
3652e8c593 | ||
|
|
755268de6b | ||
|
|
4473e68f7e | ||
|
|
65aac426b2 | ||
|
|
a186fd35be | ||
|
|
c651074d91 | ||
|
|
34335d723a | ||
|
|
6cd0cd4730 | ||
|
|
3125ba2f8a | ||
|
|
638ddd0518 | ||
|
|
429f8214b0 | ||
|
|
bdd5c80504 | ||
|
|
c11d763760 | ||
|
|
d2df533c1d | ||
|
|
db3944b8d6 | ||
|
|
0d0e5fdd37 | ||
|
|
2273d2f346 | ||
|
|
7df03fd5e6 | ||
|
|
7dd30d5169 | ||
|
|
c7820e2571 | ||
|
|
cf058d65fd | ||
|
|
3eabe1f659 | ||
|
|
f442f089bf | ||
|
|
82abf48b18 | ||
|
|
7729614f8b | ||
|
|
9b86678daf | ||
|
|
9d356e7d9d | ||
|
|
6ac6819d5d | ||
|
|
e859baf6e5 | ||
|
|
ac137e1fb6 | ||
|
|
997d861f83 | ||
|
|
91cde36777 | ||
|
|
ebf7a4070c | ||
|
|
c63a31ddd8 | ||
|
|
8a0000b678 | ||
|
|
2fc79dbdb8 | ||
|
|
037ea45448 | ||
|
|
e389f7d353 | ||
|
|
6cdba67118 | ||
|
|
3bb32dfd44 | ||
|
|
d7d3ef7549 | ||
|
|
95a029ab6f | ||
|
|
f284a96587 | ||
|
|
ca91b16647 | ||
|
|
35e5a97266 | ||
|
|
6678a361ba | ||
|
|
1e8bd2afc7 | ||
|
|
ad5f658423 | ||
|
|
24e81159f3 | ||
|
|
b6e60e3461 | ||
|
|
203b4b166b | ||
|
|
d586eea977 | ||
|
|
d33e25f95d | ||
|
|
b9508d9be4 | ||
|
|
5b39f797b1 | ||
|
|
6ceb91e8b6 | ||
|
|
94259ce68c | ||
|
|
0f035ebc13 | ||
|
|
dc605a7292 | ||
|
|
15ef4b5419 | ||
|
|
fc6cf416dc | ||
|
|
0a28430c5a | ||
|
|
3207290d77 | ||
|
|
b0fa321606 | ||
|
|
2bffa59a10 | ||
|
|
7f080970e4 | ||
|
|
f1c2527ca3 | ||
|
|
33d210af7f | ||
|
|
d7378e4674 | ||
|
|
8e40b622f7 | ||
|
|
92e4c55cb5 | ||
|
|
f498e7af73 | ||
|
|
bacf196a31 | ||
|
|
2f4603af26 | ||
|
|
203a7d00f2 | ||
|
|
f8c351cd0b | ||
|
|
93ab8d368b | ||
|
|
e38d93fa2b | ||
|
|
59518fa4ce | ||
|
|
c7b7ccfb8b | ||
|
|
e0f9ac1ea3 | ||
|
|
2fa9f76d16 | ||
|
|
7eceb08e8c | ||
|
|
41f558c34c | ||
|
|
dd5963b172 | ||
|
|
c1e3a03412 | ||
|
|
ffd60ded27 | ||
|
|
b5e02b04b7 | ||
|
|
4077621891 | ||
|
|
2d2a835bbe | ||
|
|
526c2a3b8a | ||
|
|
0bee2560d5 | ||
|
|
c4796fb9c7 | ||
|
|
504aa22064 | ||
|
|
7882532361 | ||
|
|
f4786f0479 | ||
|
|
2dc814eacb | ||
|
|
289d82e5bc | ||
|
|
1157d96589 | ||
|
|
e1044a288d | ||
|
|
2cba8fd9ef | ||
|
|
1d9285d371 | ||
|
|
f8d342ba93 | ||
|
|
eae02f4f4a | ||
|
|
f8c397e57f | ||
|
|
87c53c8a42 | ||
|
|
8615d33da9 | ||
|
|
59702a47f0 | ||
|
|
cd69714985 | ||
|
|
f4e51b79fd | ||
|
|
b6fde08278 | ||
|
|
4773f7faef | ||
|
|
33e4637b60 | ||
|
|
e676c5c4f1 | ||
|
|
58741f88f6 | ||
|
|
12077ba07a | ||
|
|
748cb47b4b | ||
|
|
c0470012eb | ||
|
|
cf3eacc14f | ||
|
|
083dc40ad9 | ||
|
|
72001373b9 | ||
|
|
1eb33b6cc5 | ||
|
|
908047fbe2 | ||
|
|
2ac791344a | ||
|
|
0b28a4d20b | ||
|
|
62fbdab39a | ||
|
|
282c82282e | ||
|
|
4b7eeed21c | ||
|
|
d6d50bdc41 | ||
|
|
3be46106a1 | ||
|
|
ea2cda888d | ||
|
|
1d59d4c5ed | ||
|
|
be47db75aa | ||
|
|
41b81641ce | ||
|
|
1faebbb490 | ||
|
|
7036c3e613 | ||
|
|
aa1fece7b5 | ||
|
|
896b420c28 | ||
|
|
ac4fe43aef | ||
|
|
98e5bfb2bb | ||
|
|
ae722e689e | ||
|
|
3abff8cad1 | ||
|
|
155fa80c95 | ||
|
|
a5a2179399 | ||
|
|
8aee5a78a4 | ||
|
|
06ce8a7e6f | ||
|
|
1cc4d7624a | ||
|
|
dd817960e1 | ||
|
|
92e0f3b55b | ||
|
|
03bdf92ae2 | ||
|
|
5492d69445 | ||
|
|
83779a1698 | ||
|
|
49c70e8162 | ||
|
|
654ba13dea | ||
|
|
e4c0b7be6c | ||
|
|
0ee809a721 | ||
|
|
683e17bee4 | ||
|
|
b9d35c2343 | ||
|
|
6b6c69fb19 | ||
|
|
960980022f | ||
|
|
f72da4bec1 | ||
|
|
08e35a811f | ||
|
|
a34c41870c | ||
|
|
25428464b7 | ||
|
|
97c65f9585 | ||
|
|
302fa7e6af | ||
|
|
ab067f242b | ||
|
|
30e5ff6f64 | ||
|
|
2838dc5e7e | ||
|
|
6f4f073ed3 | ||
|
|
564eb85575 | ||
|
|
a6de8e0be4 | ||
|
|
abc87c0254 | ||
|
|
aec302d7f2 | ||
|
|
d27d9227bc | ||
|
|
a1c23aeaaa | ||
|
|
6b05544716 | ||
|
|
161ea1d318 | ||
|
|
f500f34e78 | ||
|
|
e3716b759a | ||
|
|
abc37de666 | ||
|
|
e09994cd30 | ||
|
|
e1dfd9bd99 | ||
|
|
b4ac86ef35 | ||
|
|
3e40286e5d | ||
|
|
4a2d307410 | ||
|
|
878d68a655 | ||
|
|
a56c92f87f | ||
|
|
9095629f96 | ||
|
|
8755c2df34 | ||
|
|
888a1af9b4 | ||
|
|
e0450d3835 | ||
|
|
4e56fdf5aa | ||
|
|
c332d5c97f | ||
|
|
2977a19532 | ||
|
|
a9365a8ba8 | ||
|
|
a6ddcdb759 | ||
|
|
d9dccd53f0 | ||
|
|
3b2f964961 | ||
|
|
2d8bd820a5 | ||
|
|
56a979970c | ||
|
|
836676eb18 | ||
|
|
86a013b619 | ||
|
|
e57a76790f | ||
|
|
b4cec48bbb | ||
|
|
96676721c9 | ||
|
|
eeb8785d42 | ||
|
|
993a1a7f86 | ||
|
|
0b6f29dc70 | ||
|
|
26007f97f3 | ||
|
|
5a55cca59d | ||
|
|
cb425fd18e | ||
|
|
5889dc675e | ||
|
|
df8e7e4b54 | ||
|
|
e07d253a5e | ||
|
|
81f4e6503a | ||
|
|
d7ff250faf | ||
|
|
1d12a5f171 | ||
|
|
485d3d884a | ||
|
|
e78754e39e | ||
|
|
0b6c11f0d0 | ||
|
|
d25604ed66 | ||
|
|
4f3167064c | ||
|
|
f0d4bec116 | ||
|
|
76a1872f74 | ||
|
|
1158cb4aeb | ||
|
|
41ab384e1f | ||
|
|
3839e721db | ||
|
|
d1b84461e6 | ||
|
|
3c79cb3ef5 | ||
|
|
ea7641278a | ||
|
|
23032e8409 | ||
|
|
1d687a01c1 | ||
|
|
0b751964fa | ||
|
|
59eb43c33f | ||
|
|
dfdb056e07 | ||
|
|
cd38eba184 | ||
|
|
a4063b978f | ||
|
|
af51775844 | ||
|
|
f4039abae3 | ||
|
|
1b64f46588 | ||
|
|
ad40368639 | ||
|
|
d15159d9b0 | ||
|
|
c837f6eacc | ||
|
|
14b884daf7 | ||
|
|
63ca14bbe6 | ||
|
|
2605566f90 | ||
|
|
0bcd59d5ba | ||
|
|
a9744bb577 | ||
|
|
9b4dae4af5 | ||
|
|
319d657ab4 | ||
|
|
d9896257c5 | ||
|
|
b5d5e85ee2 | ||
|
|
9dcaddd7fd | ||
|
|
d1bec2e815 | ||
|
|
96d7f28db9 | ||
|
|
90c4ca88e0 | ||
|
|
942fe202d7 | ||
|
|
e17f888598 | ||
|
|
b089c7d7f9 | ||
|
|
afc2a5b258 | ||
|
|
1f0adb7510 | ||
|
|
aba62966b0 | ||
|
|
aaff05685c | ||
|
|
9c1bbab253 | ||
|
|
def1c699e0 | ||
|
|
e6639a63b7 | ||
|
|
1b14761e9e | ||
|
|
07a070a4fe | ||
|
|
8b13fcfd68 | ||
|
|
4088ea68fa | ||
|
|
2e95ed13ce | ||
|
|
f79091bc9c | ||
|
|
ebfc19c1f7 | ||
|
|
bdb8f3cf6f | ||
|
|
4b998f2b97 | ||
|
|
aa1d254a49 | ||
|
|
897b3300e6 | ||
|
|
9c6c9489ff | ||
|
|
6d147b081e | ||
|
|
78432057ca | ||
|
|
21b0ed8925 | ||
|
|
1040e50b32 | ||
|
|
3806a05f4a | ||
|
|
82d45915c6 | ||
|
|
80e5145742 | ||
|
|
f1b7a52f0c | ||
|
|
924952128f | ||
|
|
2fcd04a55f | ||
|
|
deb6e86854 | ||
|
|
086fa37e86 | ||
|
|
e87ecf2f4f | ||
|
|
3dc01dd945 | ||
|
|
da21999192 | ||
|
|
161efaeb52 | ||
|
|
1759fbe8d5 | ||
|
|
b1525266a8 | ||
|
|
28ede39c26 | ||
|
|
6b25eb37ba | ||
|
|
e12dcdf86a | ||
|
|
4bab1490ae | ||
|
|
2374785ae7 | ||
|
|
b338da4359 | ||
|
|
d808f453d9 | ||
|
|
b869f713eb | ||
|
|
2f9cf4751d | ||
|
|
6c7e796e17 | ||
|
|
ff40c7e576 | ||
|
|
0ccc8b2607 | ||
|
|
8febcfdfb7 | ||
|
|
9d05d077b5 | ||
|
|
63ad926078 | ||
|
|
e241848426 | ||
|
|
a82b652bc1 | ||
|
|
e59aecdc75 | ||
|
|
e56ba6b41a | ||
|
|
cfd12483ae | ||
|
|
fd18837f1b | ||
|
|
4f3e37349d | ||
|
|
20653847f4 | ||
|
|
3e294a3ba4 | ||
|
|
20ca6f96f9 | ||
|
|
70a30a5f33 | ||
|
|
b9f170e668 | ||
|
|
809dfbe338 | ||
|
|
af25a82eca | ||
|
|
50b1fcadb4 | ||
|
|
aefe1b2f07 | ||
|
|
28bc30bd83 | ||
|
|
0aeffcd79d | ||
|
|
f3863811bd | ||
|
|
e4aab2fd15 | ||
|
|
5f72a6b855 | ||
|
|
31a0444409 | ||
|
|
4522935545 | ||
|
|
67c13bd416 | ||
|
|
28d5af5fa0 | ||
|
|
15d7e71e7f | ||
|
|
49bac975d2 | ||
|
|
3878c9a1e2 | ||
|
|
a5053c4418 | ||
|
|
4cb844dea8 | ||
|
|
04afad2fd3 | ||
|
|
149efe3199 | ||
|
|
6f05867563 | ||
|
|
4442fd3265 | ||
|
|
6e49856474 | ||
|
|
cc379b71de | ||
|
|
c2a1bb4a5a | ||
|
|
cc58c33e37 | ||
|
|
012f03f7e7 | ||
|
|
28a7a3c389 | ||
|
|
6417279d65 | ||
|
|
07db680ad3 | ||
|
|
d7c97b6589 | ||
|
|
af12289d7e | ||
|
|
afeafba67d | ||
|
|
f56e49da5c | ||
|
|
d233897c73 | ||
|
|
273f1c3d07 | ||
|
|
d34812b77b | ||
|
|
375a60bafc | ||
|
|
156bd57461 | ||
|
|
dacc1b8eeb | ||
|
|
b3bb023852 | ||
|
|
8ca8272bc4 | ||
|
|
fc36f7ad77 | ||
|
|
496bdf5b54 | ||
|
|
877d625945 | ||
|
|
458710e9f0 | ||
|
|
fa6e7e44a0 | ||
|
|
bc12220d7a | ||
|
|
9d7b879e1f | ||
|
|
e4ff8a169b | ||
|
|
5a62aea978 | ||
|
|
b4d9de74c3 | ||
|
|
aa37d8b4b3 | ||
|
|
e334bc6440 | ||
|
|
9f6b9923b0 | ||
|
|
85415ae7fc | ||
|
|
f5382e9649 | ||
|
|
3ca786b820 | ||
|
|
c13908f096 | ||
|
|
d11de94e0b | ||
|
|
e2c10f7e87 | ||
|
|
b05c717981 | ||
|
|
38db5dfee4 | ||
|
|
151eeb5ec1 | ||
|
|
0d150765b8 | ||
|
|
cd6ee3048c | ||
|
|
0ed9e62283 | ||
|
|
fdb89fbf64 | ||
|
|
3fd11831f6 | ||
|
|
cd81fc8b38 | ||
|
|
b512b7d5f7 | ||
|
|
883cb34bdb | ||
|
|
c683947d20 | ||
|
|
483204a811 | ||
|
|
0b5b7bcae2 | ||
|
|
e1d517f9c2 | ||
|
|
b80b869823 | ||
|
|
386a6cbb6c | ||
|
|
9ce4c0ee90 | ||
|
|
1351b5ff90 | ||
|
|
84960a6107 | ||
|
|
5d3fdc0abd | ||
|
|
0d491f0d41 | ||
|
|
955ae91110 | ||
|
|
85fa63d2a1 | ||
|
|
6d8f02435e | ||
|
|
fc0600dfd8 | ||
|
|
1494579353 | ||
|
|
834d7e1da1 | ||
|
|
08b64834cf | ||
|
|
8265c5adec | ||
|
|
be4f2398a9 | ||
|
|
b8f2d36f5e | ||
|
|
49a2526528 | ||
|
|
a755d3d55e | ||
|
|
41a6ddb62a | ||
|
|
e32acd17ba | ||
|
|
0de0add858 | ||
|
|
9a90ca4c53 | ||
|
|
86b1fa6276 | ||
|
|
08d5fb50a7 | ||
|
|
6fca7c7940 | ||
|
|
fad14b26b6 | ||
|
|
d33fe6e185 | ||
|
|
a1db85e50f | ||
|
|
e67f1a649c | ||
|
|
e88fe21802 | ||
|
|
21875b8dd5 | ||
|
|
8f4c6a5b32 | ||
|
|
ba696abe0c | ||
|
|
7f32d8d136 | ||
|
|
e0af365ef3 | ||
|
|
caa85cef49 | ||
|
|
0cb6902519 | ||
|
|
7226473dcb | ||
|
|
222fdf51b5 | ||
|
|
381ba0f69a | ||
|
|
e4170b5f16 | ||
|
|
81294ac9be | ||
|
|
5ae0110153 | ||
|
|
930c2ef9bb | ||
|
|
f109fb33d0 | ||
|
|
eae4f99b34 | ||
|
|
241f0bec43 | ||
|
|
01ea68560f | ||
|
|
03ae42c98a | ||
|
|
ab060b0981 | ||
|
|
89ef96f2b4 | ||
|
|
b7a1af9f64 | ||
|
|
102db1f46d | ||
|
|
cc35404c7f | ||
|
|
c07fccf607 |
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Заготовка для репорта багов
|
||||
title: Ошибка обновлении ленты новостей
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Опишите сам баг**
|
||||
При обновлении новостей вылезает ошибка
|
||||
|
||||
**Опишите действия для воспроизведения ошибки**
|
||||
1. Обновил ленту интересных новостей
|
||||
2. Пролистал до конца страницы
|
||||
|
||||
**Опишите ожидаемый результат**
|
||||
Интересная лента должна прогружать результаты
|
||||
|
||||
**Скриншот ошибки**
|
||||
|
||||
**Информация об устройстве:**
|
||||
- Устройство: Samsung Galaxy J1 Mini
|
||||
- OS: Android 9 | OneUi 3.0
|
||||
- Коммит: fa12e8f (В О Приложении написана версия коммита)
|
||||
|
||||
**Дополнительная информация о баге или мыслях почему оно может происходить (если есть)**
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Предложение функции
|
||||
title: Улучшение голосовых сообщений
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Опишите вашу идею максимально подробно и понятно**
|
||||
Необходима функция улучшения голосовых сообщений. Она значительно улучшит запись голосовых сообщений и собеседнику будет лучше слышно меня
|
||||
|
||||
**Опишите возможное решение/реализацию функции (если понимаете как это можно реализовать на Java/C++)**
|
||||
|
||||
**Остальные мысли о предложенной функции**
|
||||
@@ -4,11 +4,15 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
+2
-1
@@ -28,4 +28,5 @@ smali2/build/resources.zip
|
||||
/smali/VTLite.apk.cache/
|
||||
smali/build/resources.zip
|
||||
smali/assets/version.properties
|
||||
smali/assets/version.properties
|
||||
*.keystore
|
||||
gradle.properties
|
||||
|
||||
@@ -1,99 +1,193 @@
|
||||
# VTosters Lite
|
||||
<p align="center">
|
||||
<a href="https://vtosters.app/">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.discordapp.com/attachments/918864618116481029/1002916719595106344/VT_Fill_Logo_Dark.svg">
|
||||
<img src="https://cdn.discordapp.com/attachments/918864618116481029/1002916719381201036/VT_Fill_Logo_Light.svg">
|
||||
</picture>
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
<a href="https://t.me/s/vtosters">
|
||||
<img src="https://img.shields.io/badge/-Telegram-blue?style=for-the-badge&logo=telegram&color=2AABEE"/>
|
||||
</a>
|
||||
<a href="https://vk.com/vtosters_official">
|
||||
<img src="https://img.shields.io/badge/-VK-blue?style=for-the-badge&logo=vk&color=0077FF"/>
|
||||
</a>
|
||||
<a href="https://discord.gg/j9CAt3uYXj">
|
||||
<img src="https://img.shields.io/badge/-Discord-blue?style=for-the-badge&logo=discord&color=5865F2&logoColor=FFFFFF"/>
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://github.com/vtosters/lite/issues">
|
||||
<img src="https://img.shields.io/github/issues/vtosters/lite?style=flat-square"/>
|
||||
</a>
|
||||
<a href="https://github.com/vtosters/lite/network/members">
|
||||
<img src="https://img.shields.io/github/forks/vtosters/lite?style=flat-square"/>
|
||||
</a>
|
||||
<a href="https://github.com/vtosters/lite/stargazers">
|
||||
<img src="https://img.shields.io/github/stars/vtosters/lite?style=flat-square"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
ВТостерс Lite - это модифицированный клиент (декомпиляция) официального ВКонтакте основанный на версии 5.56.1 (4838)
|
||||
**ВТостерс Lite** — это модифицированный клиент официального ВКонтакте, основанный на версии **5.56.1 (4838)**
|
||||
|
||||
О найденных багах сообщать в [issues](https://github.com/vtosters/lite/issues), просьба не плодить дубликаты, воспользуйтесь поиском перед созданием нового issue
|
||||
* Вы можете предложить свои идеи/сообщить о багах в [Issues](https://github.com/vtosters/lite/issues)
|
||||
|
||||
Скачивать самые актуальные версии можно с [Actions](https://github.com/vtosters/lite/actions)
|
||||
* Скачивать самые актуальные версии можно с [Actions](https://github.com/vtosters/lite/actions)
|
||||
<sup><sub>(могут содержать баги)</sub></sup>
|
||||
|
||||
Стабильные сборки находятся в [Releases](https://github.com/vtosters/lite/releases)
|
||||
* Стабильные сборки находятся в [Releases](https://github.com/vtosters/lite/releases)
|
||||
|
||||
Зеркало на нашем [Git](https://git.maki.su/gdlbo/lite)
|
||||
Зеркало на нашем [<img src="https://git.maki.su/assets/img/logo.svg" align="center" width="20" height="20"/> Git](https://git.maki.su/gdlbo/lite)
|
||||
|
||||
Зеркало на [Github](https://github.com/vtosters/lite)
|
||||
### Быстрая навигация
|
||||
|
||||
* [Функционал](#функционал)
|
||||
* [Отладка приложения](#отладка-приложения)
|
||||
* [Разработка](#разработка)
|
||||
* [Всё необходимое для сборки и компиляции](#всё-необходимое-для-сборки-и-компиляции)
|
||||
* [Необходимые зависимости](#необходимые-зависимости)
|
||||
* [Linux/macOS](#linuxmacos)
|
||||
* [Windows](#windows)
|
||||
|
||||
|
||||
## Функционал
|
||||
|
||||
* Лента
|
||||
* Блокировка рекламы в ленте
|
||||
* Блокировка постов через фильтры
|
||||
* Возможность отключить рекомендации от ВК
|
||||
* Редактор докбара
|
||||
* Редактор элементов Superapp
|
||||
* Медиа контент
|
||||
* Округление дат
|
||||
* 1 января в 4:20
|
||||
* 1 января в 4:20:00
|
||||
* 1 января 2000 в 4:20:00
|
||||
* Округление чисел
|
||||
* Сокращение постов **(Показать полностью)**
|
||||
* Результаты опросов без участия
|
||||
* Возможность указывать папку для загрузки фото/видео/музыки/всего
|
||||
* Интеграция с <a href="https://www.last.fm/">LAST.FM</a> (а также возможность скробблинга)
|
||||
* Новый раздел музыки
|
||||
* Возможность скачивать видео
|
||||
* Возможность найти фотографию через поисковые системы
|
||||
* Интеграция с <a href="https://vkx.app/">VK X</a>
|
||||
* Сообщения
|
||||
* Обои в сообщениях
|
||||
* Возможность выключения кнопки записи голосовых сообщений
|
||||
* Возможность скрыть блок рекомендаций в сообщениях
|
||||
* Режим **VK Me**
|
||||
* Возможность вернуть вкладку уведомлений
|
||||
* Встроенный переводчик текста для сообщений
|
||||
* Возможность выбрать язык перевода
|
||||
* Автоматический перевод ваших сообщений на выбранный язык
|
||||
* Альтернативный дизайн эмодзи меню
|
||||
* Возможность использовать системные эмодзи
|
||||
* Активность
|
||||
* Возможность видеть удаленные сообщения
|
||||
* Функционал, позволяющий оставаться в «оффлайне» (принудительный оффлайн/не отправлять статус онлайна и т.п.)
|
||||
* Нечиталка/неписалка для ЛС/бесед/ботов/групп
|
||||
* Возможность отключить информацию о том, что вы просмотрели историю/прослушали голосовое сообщение
|
||||
* Возможность видеть онлайн пользователей, если у вас скрыт онлайн через VK Messenger
|
||||
* Отключить уведомление о том, что вы сделали скриншот в беседе
|
||||
* Отключение редиректа через away.php
|
||||
* Отключение отправки метрики
|
||||
* Внешний вид
|
||||
* **Milkshake** тема (дизайн новых версий ВК)
|
||||
* Название заголовков в докбаре
|
||||
* Возможность использовать акцент для иконок
|
||||
* Возможность отключить счётчики в докбаре
|
||||
* Смена иконки приложения (содержит много уникальных иконок для донатеров)
|
||||
* Возможность покрасить панель навигации, веб-страницы
|
||||
* Telegram Стикеры
|
||||
* Возможность загружать свои стикерпаки из Telegram во ВКонтакте
|
||||
* Интерфейс
|
||||
* Возможность отключить блок историй наверху ленты
|
||||
* Возможность отключить боковую камеру в разделе «Новости»
|
||||
* Возможность отключить блок «Что у вас нового?» в разделе «Новости»
|
||||
* Возможность показывать лайки у постов справа
|
||||
* Возможность менять стартовый раздел при запуске приложения
|
||||
* Анимации фрагментов
|
||||
* Возможность изменять размер закругления картинок (аватарок и прочего)
|
||||
* Возможность отключить редизайн видеопостов
|
||||
* Возможность отключить блок миниаппов/VK Pay/Superapp
|
||||
* Возможность отключить сокращение названий разделов в меню
|
||||
* Возможность скрыть блок рекомендаций друзей в разделе «Друзья»
|
||||
* Возможность скрыть подписи в настройках
|
||||
* Прокси
|
||||
* Возможность использовать **HTTP/HTTPS/SOCKS** прокси, менять домены **API/OAuth/Static**
|
||||
* Другое
|
||||
* Очистка кеша приложения (**всё/стикеры/изображения/видео/сообщения/WebView**)
|
||||
* Автоочистка кеша при достижении указанного вами значения (**100/500 MB, 1/2/5 GB**)
|
||||
* Функционал для **дебага приложения/бэкап возможности/верификации VTosters**
|
||||
|
||||
А также:
|
||||
* Галочки, которые видны только пользователям приложения **ВТостерс Lite** (подробнее тут: [vtosters.app](https://vtosters.app) ➝ Пожертвования)
|
||||
* Оптимизация приложения VK (удаление ненужных библиотек, которые встроены в оригинальный VK)
|
||||
|
||||
И многое другое!
|
||||
|
||||
## Отладка приложения
|
||||
|
||||
Для отладки с помощью Android Studio необходимо пройти в `/smali/AndroidManifest.xml`
|
||||
```
|
||||
android:debuggable="false" -> android:debuggable="true"
|
||||
```
|
||||
Для отладки с помощью <a href="#"><img src="https://i.imgur.com/cPvvFDP.png" align="center" width="20" height="23"/></a> Android Studio необходимо пройти в `/smali/AndroidManifest.xml` и изменить значение `android:debuggable`:
|
||||
|
||||
Для дополнительной отладки ответов, доп логов и подмены данных для дебаг приложения необходимо включить **Режим разработчика**
|
||||
```
|
||||
Настройки -> О приложении -> Для разработчиков -> Режим разработчика
|
||||
```
|
||||
`android:debuggable="false"` ➝ `android:debuggable="true"`
|
||||
|
||||
Для просмотра трафика необходимо отключить функцию **SSL Pinning**
|
||||
Настройки, необходимые для **отладки** вне Android Studio, находятся по этой ссылке: [vk.com/vt/debug](https://vk.com/vt/debug)
|
||||
|
||||
```
|
||||
Настройки -> О приложении -> Для разработчиков -> SSL Pinning
|
||||
```
|
||||
* Для дополнительной отладки ответов и логов необходимо включить **[Режим разработчика]**
|
||||
|
||||
Для логгирования внутренних запросов к API необходимо включить функции **Логгирование API**
|
||||
* Для просмотра SSL-трафика необходимо **отключить** функцию **[SSL Pinning]**
|
||||
|
||||
(Работает только при использовании внутреннего логгера!)
|
||||
* Для логгирования внутренних запросов к API необходимо включить функцию **[Логгирование API]** <sup>(работает только при использовании внутреннего логгера!)</sup>
|
||||
|
||||
```
|
||||
Настройки -> О приложении -> Для разработчиков -> Логгирование API
|
||||
```
|
||||
* Для использования внутреннего логгера необходимо включить функцию **[Запись логов в файл]**
|
||||
|
||||
Для использования внутреннего логгера необходимо включить функции **Запись логов в файл**
|
||||
```
|
||||
Настройки -> О приложении -> Для разработчиков -> Запись логов в файл
|
||||
```
|
||||
Сразу после нажатия на запись аппа начнет записывать **все действия** в файлы по пути
|
||||
```
|
||||
/VK/logs/com.vtosters.lite
|
||||
```
|
||||
При следующем открытии аппы она автоматически запакует эти файлы и отправит вам в **Документы** ВК
|
||||
Сразу после нажатия на запись приложение начнет записывать **все ваши действия** по пути `/Download/VK/logs/com.vtosters.lite/`
|
||||
|
||||
Позже архив можно будет скачать и работать с файлами логов которые находятся в нем
|
||||
При следующем открытии приложения оно автоматически сохранит логи и отправит вам в [**Документы** ВК](https://vk.com/docs), откуда вы можете скачать архив логов и работать с ними.
|
||||
|
||||
## Разработка
|
||||
|
||||
Для понимания декомпилированного кода требуется использовать **Dex to Java** декомпилятор [jadx](https://github.com/skylot/jadx) или же сторонние варианты как [Fernflower](https://github.com/fesh0r/fernflower)
|
||||
Для понимания работы декомпилированного кода требуется использовать **Dex to Java** декомпилятор [jadx](https://github.com/skylot/jadx) или же сторонние варианты как [Fernflower](https://github.com/fesh0r/fernflower)
|
||||
|
||||
Рекомендуется установка **Android Debug Bridge** в систему ([Гайд как это сделать](https://technastic.com/system-wide-adb-fastboot-windows-10))
|
||||
При нахождении решения каких-либо проблем ждем вас в [Pull Requests](https://github.com/vtosters/lite/pulls)
|
||||
|
||||
Для индексации декомпилированного кода в Studio используется [dex2jar](https://github.com/pxb1988/dex2jar)
|
||||
* Рекомендуется установка **ADB** в систему ([гайд](https://technastic.com/system-wide-adb-fastboot-windows-10))
|
||||
|
||||
Сгенерированные библиотеки из дексов находятся в `/app/libs`
|
||||
* Для индексации декомпилированного кода в Studio используется [dex2jar](https://github.com/pxb1988/dex2jar)
|
||||
|
||||
При чистой перекомпиляции дексов в jar может сломаться некоторая индексация файлов, исправляйте ручками что попадется (К примеру какие-то функции в дексах изменены с **private** на **public**)
|
||||
Сгенерированные библиотеки из .dex файлов находятся в `/app/libs`
|
||||
|
||||
При чистой перекомпиляции .dex в .jar может сломаться некоторая индексация файлов, исправляйте ручками что попадется (К примеру какие-то функции в дексах изменены с **private** на **public**)
|
||||
|
||||
Для сборки декомпилированного кода и ресурсов используется [Apktool](https://github.com/iBotPeaches/Apktool)
|
||||
|
||||
А при нахождении решения каких-либо проблем ждем вас в [Pull Requests](https://github.com/vtosters/lite/pulls)
|
||||
|
||||
### Всё необходимое для сборки и компиляции
|
||||
|
||||
`Не меняйте packagename во избежание проблем с приложением`
|
||||
```diff
|
||||
- Не меняйте имя пакета во избежание проблем с приложением
|
||||
|
||||
`Некоторые функции связанные с музыкой не будут работать в пересобранном приложении`
|
||||
- Некоторые функции, связанные с музыкой не будут работать в пересобранном приложении
|
||||
```
|
||||
|
||||
Весь декомпилированный код клиента находится в `/smali`
|
||||
* Весь декомпилированный код клиента находится в `/smali`
|
||||
|
||||
Весь исходный код модификации находится в `/app`
|
||||
* Весь исходный код модификации находится в `/app`
|
||||
|
||||
Все необходимые скрипты/жарники для компиляции APK, его подписывании и не только находятся в `/scripts`
|
||||
* Все необходимые скрипты/.jar файлы для компиляции APK, его подписывании и не только находятся в `/scripts`
|
||||
|
||||
### Необходимые зависимости
|
||||
Требуется установленная **Java** >11 версии
|
||||
<a href="https://www.oracle.com/java/technologies/downloads/"><img src="https://i.imgur.com/z8ZN19a.png" align="center" width="20" height="23"/> **JDK**</a> >11 версии
|
||||
|
||||
Требуется установленная **Android Studio**
|
||||
<a href="https://developer.android.com/studio"><img src="https://i.imgur.com/cPvvFDP.png" align="center" width="20" height="23"/> **Android Studio**</a>
|
||||
|
||||
### Linux/macOS
|
||||
```
|
||||
./build.sh
|
||||
```
|
||||
|
||||

|
||||
Для сборки используется файл `./build.sh`
|
||||
|
||||
<img src="https://i.imgur.com/8BMX8lG.png" width="550" height="368"/>
|
||||
|
||||
### Windows
|
||||
```
|
||||
build.bat
|
||||
```
|
||||
Для сборки используется файл `build.bat`
|
||||
|
||||

|
||||
<img src="https://i.imgur.com/iZSUKJ6.png" width="550" height="368"/>
|
||||
|
||||
+3
-5
@@ -69,16 +69,15 @@ task exportDex {
|
||||
|
||||
android {
|
||||
compileSdkVersion 32
|
||||
buildToolsVersion '32.0.0'
|
||||
buildToolsVersion '33.0.0'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "ru.vtosters.lite.utils.lite"
|
||||
minSdkVersion 24
|
||||
minSdk 22
|
||||
targetSdkVersion 32
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
multiDexEnabled true
|
||||
multiDexEnabled false
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
@@ -89,7 +88,6 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "androidx.multidex:multidex:2.0.1"
|
||||
implementation 'com.google.android.material:material:1.6.1'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.3'
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
ea0425fab4379ae5f7e9db05a22d4b7afd709560
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
3b92d8876dd59d5afc60a53bb23b103cede6a194
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
b26e21ded459fd6a5748e46f9c0a39d5b6b7f939
|
||||
@@ -5,7 +5,7 @@ package bruhcollective.itaysonlab.libvkx;
|
||||
|
||||
// Works only with original signature of VT
|
||||
|
||||
public interface ILibVkxService extends android.os.IInterface{
|
||||
public interface ILibVkxService extends android.os.IInterface {
|
||||
void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException;
|
||||
|
||||
int getUserId() throws android.os.RemoteException;
|
||||
@@ -24,42 +24,42 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
/**
|
||||
* Default implementation for ILibVkxService.
|
||||
*/
|
||||
class Default implements ILibVkxService{
|
||||
class Default implements ILibVkxService {
|
||||
// Starts playback. playbackContext can be "other" if you don't sure what it is
|
||||
|
||||
@Override
|
||||
public void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException{
|
||||
public void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException {
|
||||
}
|
||||
// A UserID. CHECK FOR THIS TO BE EQUAL BEFORE SENDING ANYTHING TO SERVICE!
|
||||
|
||||
@Override
|
||||
public int getUserId() throws android.os.RemoteException{
|
||||
public int getUserId() throws android.os.RemoteException {
|
||||
return 0;
|
||||
}
|
||||
// Cache add/remove
|
||||
|
||||
@Override
|
||||
public void addTrackToCache(int track_id, int owner_id, String access_key) throws android.os.RemoteException{
|
||||
public void addTrackToCache(int track_id, int owner_id, String access_key) throws android.os.RemoteException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTrackFromCache(int track_id, int owner_id) throws android.os.RemoteException{
|
||||
public void deleteTrackFromCache(int track_id, int owner_id) throws android.os.RemoteException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrackCached(int track_id, int owner_id) throws android.os.RemoteException{
|
||||
public boolean isTrackCached(int track_id, int owner_id) throws android.os.RemoteException {
|
||||
return false;
|
||||
}
|
||||
// Get a list of cached tracks. The response is close to VK's original response (an audio list)
|
||||
// Also, the items in the list are JSON ones.
|
||||
|
||||
@Override
|
||||
public java.util.List<String> getCache() throws android.os.RemoteException{
|
||||
public java.util.List<String> getCache() throws android.os.RemoteException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public android.os.IBinder asBinder(){
|
||||
public android.os.IBinder asBinder() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
/**
|
||||
* Local-side IPC implementation stub class.
|
||||
*/
|
||||
abstract class Stub extends android.os.Binder implements ILibVkxService{
|
||||
abstract class Stub extends android.os.Binder implements ILibVkxService {
|
||||
static final int TRANSACTION_play = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
|
||||
static final int TRANSACTION_getUserId = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
|
||||
static final int TRANSACTION_addTrackToCache = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
|
||||
@@ -81,7 +81,7 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
/**
|
||||
* Construct the stub at attach it to the interface.
|
||||
*/
|
||||
public Stub(){
|
||||
public Stub() {
|
||||
this.attachInterface(this, DESCRIPTOR);
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
* Cast an IBinder object into an bruhcollective.itaysonlab.libvkx.ILibVkxService interface,
|
||||
* generating a proxy if needed.
|
||||
*/
|
||||
public static ILibVkxService asInterface(android.os.IBinder obj){
|
||||
public static ILibVkxService asInterface(android.os.IBinder obj) {
|
||||
if ((obj == null)) {
|
||||
return null;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
return new Proxy(obj);
|
||||
}
|
||||
|
||||
public static boolean setDefaultImpl(ILibVkxService impl){
|
||||
public static boolean setDefaultImpl(ILibVkxService impl) {
|
||||
if (Proxy.sDefaultImpl == null && impl != null) {
|
||||
Proxy.sDefaultImpl = impl;
|
||||
return true;
|
||||
@@ -108,19 +108,19 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ILibVkxService getDefaultImpl(){
|
||||
public static ILibVkxService getDefaultImpl() {
|
||||
return Proxy.sDefaultImpl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public android.os.IBinder asBinder(){
|
||||
public android.os.IBinder asBinder() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{
|
||||
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
|
||||
String descriptor = DESCRIPTOR;
|
||||
switch(code) {
|
||||
switch (code) {
|
||||
case INTERFACE_TRANSACTION: {
|
||||
reply.writeString(descriptor);
|
||||
return true;
|
||||
@@ -190,27 +190,27 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
}
|
||||
}
|
||||
|
||||
private static class Proxy implements ILibVkxService{
|
||||
private static class Proxy implements ILibVkxService {
|
||||
public static ILibVkxService sDefaultImpl;
|
||||
private final android.os.IBinder mRemote;
|
||||
|
||||
Proxy(android.os.IBinder remote){
|
||||
Proxy(android.os.IBinder remote) {
|
||||
mRemote = remote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public android.os.IBinder asBinder(){
|
||||
public android.os.IBinder asBinder() {
|
||||
return mRemote;
|
||||
}
|
||||
// Starts playback. playbackContext can be "other" if you don't sure what it is
|
||||
|
||||
public String getInterfaceDescriptor(){
|
||||
public String getInterfaceDescriptor() {
|
||||
return DESCRIPTOR;
|
||||
}
|
||||
// A UserID. CHECK FOR THIS TO BE EQUAL BEFORE SENDING ANYTHING TO SERVICE!
|
||||
|
||||
@Override
|
||||
public void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException{
|
||||
public void play(java.util.List<String> audio_ids, int index, String playbackContext) throws android.os.RemoteException {
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
@@ -232,7 +232,7 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
// Cache add/remove
|
||||
|
||||
@Override
|
||||
public int getUserId() throws android.os.RemoteException{
|
||||
public int getUserId() throws android.os.RemoteException {
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
int _result;
|
||||
@@ -252,7 +252,7 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTrackToCache(int track_id, int owner_id, String access_key) throws android.os.RemoteException{
|
||||
public void addTrackToCache(int track_id, int owner_id, String access_key) throws android.os.RemoteException {
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
@@ -273,7 +273,7 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTrackFromCache(int track_id, int owner_id) throws android.os.RemoteException{
|
||||
public void deleteTrackFromCache(int track_id, int owner_id) throws android.os.RemoteException {
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
try {
|
||||
@@ -295,7 +295,7 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
// Also, the items in the list are JSON ones.
|
||||
|
||||
@Override
|
||||
public boolean isTrackCached(int track_id, int owner_id) throws android.os.RemoteException{
|
||||
public boolean isTrackCached(int track_id, int owner_id) throws android.os.RemoteException {
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
boolean _result;
|
||||
@@ -317,7 +317,7 @@ public interface ILibVkxService extends android.os.IInterface{
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.List<String> getCache() throws android.os.RemoteException{
|
||||
public java.util.List<String> getCache() throws android.os.RemoteException {
|
||||
android.os.Parcel _data = android.os.Parcel.obtain();
|
||||
android.os.Parcel _reply = android.os.Parcel.obtain();
|
||||
java.util.List<String> _result;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package bruhcollective.itaysonlab.libvkx.client;
|
||||
|
||||
public class ClientConstants{
|
||||
public class ClientConstants {
|
||||
public final static String ACTION = "bruhcollective.itaysonlab.libvkx.LIBVKX_SERVICE";
|
||||
public final static String PACKAGE = "ua.itaysonlab.vkx";
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package bruhcollective.itaysonlab.libvkx.client;
|
||||
|
||||
import static ru.vtosters.lite.utils.Globals.getContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.vk.dto.music.MusicTrack;
|
||||
import com.vk.music.common.MusicPlaybackLaunchContext;
|
||||
@@ -15,47 +15,46 @@ import java.util.List;
|
||||
|
||||
import bruhcollective.itaysonlab.libvkx.ILibVkxService;
|
||||
|
||||
public class LibVKXClient{
|
||||
public class LibVKXClient {
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private static LibVKXClientImpl impl;
|
||||
|
||||
public static LibVKXClientImpl getInstance(Context context){
|
||||
public static LibVKXClientImpl getInstance(Context context) {
|
||||
if (impl == null) {
|
||||
impl = new LibVKXClientImpl(context);
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
public static LibVKXClientImpl getInstance(){
|
||||
public static LibVKXClientImpl getInstance() {
|
||||
LibVKXClientImpl libVKXClientImpl = impl;
|
||||
return libVKXClientImpl == null ? getInstance(getContext()) : libVKXClientImpl;
|
||||
return libVKXClientImpl == null ? getInstance(getGlobalContext()) : libVKXClientImpl;
|
||||
}
|
||||
|
||||
public static boolean isVkxInstalled(){
|
||||
public static boolean isVkxInstalled() {
|
||||
try {
|
||||
getContext().getPackageManager().getPackageInfo("ua.itaysonlab.vkx", 0);
|
||||
getGlobalContext().getPackageManager().getPackageInfo("ua.itaysonlab.vkx", 0);
|
||||
return true;
|
||||
} catch (Exception unused) {
|
||||
return false;
|
||||
}
|
||||
} // VKX check
|
||||
|
||||
public static boolean isIntegrationEnabled(){
|
||||
public static boolean isIntegrationEnabled() {
|
||||
return getBoolValue("libvkx_integration", false) && isVkxInstalled();
|
||||
}
|
||||
|
||||
public static boolean play(MusicTrack musicTrack, List<MusicTrack> list, MusicPlaybackLaunchContext playerRefer){
|
||||
public static boolean play(MusicTrack musicTrack, List<MusicTrack> list, MusicPlaybackLaunchContext playerRefer) {
|
||||
if (!isIntegrationEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.d("LibVKXClient", "playing: " + musicTrack.toString());
|
||||
|
||||
LibVKXClientImpl.LibVKXAction action = iLibVkxService -> LibVKXClient.lambdaplay(list, musicTrack, iLibVkxService);
|
||||
|
||||
return getInstance().runOnService(action);
|
||||
}
|
||||
|
||||
public static void lambdaplay(List<MusicTrack> list, MusicTrack musicTrack, ILibVkxService iLibVkxService){
|
||||
public static void lambdaplay(List<MusicTrack> list, MusicTrack musicTrack, ILibVkxService iLibVkxService) {
|
||||
int indexOf = list.indexOf(musicTrack);
|
||||
var ids = new ArrayList<String>();
|
||||
for (var track : list) {
|
||||
@@ -64,7 +63,7 @@ public class LibVKXClient{
|
||||
if (indexOf == -1) {
|
||||
indexOf = 0;
|
||||
}
|
||||
Log.d("LibVKXClient", "tracks: " + ids.toString());
|
||||
|
||||
try {
|
||||
iLibVkxService.play(ids, indexOf, "");
|
||||
} catch (RemoteException e) {
|
||||
@@ -72,7 +71,7 @@ public class LibVKXClient{
|
||||
}
|
||||
}
|
||||
|
||||
private static String asId(MusicTrack musicTrack){
|
||||
private static String asId(MusicTrack musicTrack) {
|
||||
String str = musicTrack.e + "_" + musicTrack.d;
|
||||
if (musicTrack.O == null || musicTrack.O.equals("")) {
|
||||
return str;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package bruhcollective.itaysonlab.libvkx.client;
|
||||
|
||||
import static ru.vtosters.lite.utils.Globals.getUserId;
|
||||
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserId;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -15,7 +15,7 @@ import java.util.List;
|
||||
|
||||
import bruhcollective.itaysonlab.libvkx.ILibVkxService;
|
||||
|
||||
public class LibVKXClientImpl{
|
||||
public class LibVKXClientImpl {
|
||||
private ILibVkxService serviceInstance;
|
||||
private PackageManager pm;
|
||||
private Context ctx;
|
||||
@@ -23,15 +23,15 @@ public class LibVKXClientImpl{
|
||||
|
||||
private boolean isBindFailed = false;
|
||||
|
||||
private LibVKXClientImpl(){
|
||||
private LibVKXClientImpl() {
|
||||
}
|
||||
|
||||
public LibVKXClientImpl(Context ctx){
|
||||
public LibVKXClientImpl(Context ctx) {
|
||||
this.ctx = ctx;
|
||||
this.pm = ctx.getPackageManager();
|
||||
}
|
||||
|
||||
public void finish(){
|
||||
public void finish() {
|
||||
if (cn != null) {
|
||||
ctx.unbindService(cn);
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class LibVKXClientImpl{
|
||||
serviceInstance = null;
|
||||
}
|
||||
|
||||
public <T> T runOnServiceSync(LibVKXActionGeneric<T> action){
|
||||
public <T> T runOnServiceSync(LibVKXActionGeneric<T> action) {
|
||||
if (serviceInstance != null) {
|
||||
return action.run(serviceInstance);
|
||||
} else {
|
||||
@@ -49,7 +49,7 @@ public class LibVKXClientImpl{
|
||||
|
||||
// true - action is ran
|
||||
// false - action is failed, should fallback to default UI/UX
|
||||
public boolean runOnService(LibVKXAction action){
|
||||
public boolean runOnService(LibVKXAction action) {
|
||||
if (serviceInstance != null) {
|
||||
try {
|
||||
if (serviceInstance.getUserId() != getUserId()) return false;
|
||||
@@ -64,12 +64,12 @@ public class LibVKXClientImpl{
|
||||
}
|
||||
}
|
||||
|
||||
private boolean requestServiceInit(LibVKXAction runAfterBind){
|
||||
private boolean requestServiceInit(LibVKXAction runAfterBind) {
|
||||
if (!verifyBindActuality()) return false;
|
||||
|
||||
cn = new ServiceConnection(){
|
||||
cn = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service){
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
serviceInstance = ILibVkxService.Stub.asInterface(service);
|
||||
if (serviceInstance == null) {
|
||||
// op mycopok...
|
||||
@@ -85,7 +85,7 @@ public class LibVKXClientImpl{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name){
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
serviceInstance = null;
|
||||
}
|
||||
};
|
||||
@@ -94,16 +94,16 @@ public class LibVKXClientImpl{
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean verifyBindActuality(){
|
||||
private boolean verifyBindActuality() {
|
||||
if (!checkIfAppExists()) return false; // no need
|
||||
return !isBindFailed;
|
||||
}
|
||||
|
||||
private Intent getIntent(){
|
||||
private Intent getIntent() {
|
||||
return new Intent(ClientConstants.ACTION).setPackage(ClientConstants.PACKAGE);
|
||||
}
|
||||
|
||||
private boolean checkIfAppExists(){
|
||||
private boolean checkIfAppExists() {
|
||||
List<ResolveInfo> resolveInfos = pm.queryIntentServices(getIntent(), 0);
|
||||
if (resolveInfos == null || resolveInfos.isEmpty()) return false;
|
||||
|
||||
@@ -114,14 +114,14 @@ public class LibVKXClientImpl{
|
||||
return false;
|
||||
}
|
||||
|
||||
public interface LibVKXAction{
|
||||
public interface LibVKXAction {
|
||||
void run(ILibVkxService service);
|
||||
}
|
||||
|
||||
public interface LibVKXActionGeneric<T>{
|
||||
public interface LibVKXActionGeneric<T> {
|
||||
T run(ILibVkxService service);
|
||||
|
||||
default T defaultValue(){
|
||||
default T defaultValue() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,35 +3,35 @@ package com.aefyr.tsg.g2;
|
||||
/**
|
||||
* Created by Aefyr on 19.05.2018.
|
||||
*/
|
||||
public abstract class CustomStickersEventsListener implements TelegramStickersService.StickersEventsListener{
|
||||
public abstract class CustomStickersEventsListener implements TelegramStickersService.StickersEventsListener {
|
||||
|
||||
@Override
|
||||
public void onPackAdded(TelegramStickersPack pack, int atIndex){
|
||||
public void onPackAdded(TelegramStickersPack pack, int atIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackChanged(TelegramStickersPack pack, int atIndex){
|
||||
public void onPackChanged(TelegramStickersPack pack, int atIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackRemoved(TelegramStickersPack pack, int atIndex){
|
||||
public void onPackRemoved(TelegramStickersPack pack, int atIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackDownloadError(TelegramStickersPack pack, Exception error){
|
||||
public void onPackDownloadError(TelegramStickersPack pack, Exception error) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivePacksListChanged(){
|
||||
public void onActivePacksListChanged() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInactivePacksListChanged(){
|
||||
public void onInactivePacksListChanged() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.io.File;
|
||||
/**
|
||||
* Created by Aefyr on 20.05.2018.
|
||||
*/
|
||||
public abstract class CustomStickersPack{
|
||||
public abstract class CustomStickersPack {
|
||||
|
||||
public abstract File folder();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.aefyr.tsg.g2;
|
||||
|
||||
import static ru.vtosters.lite.utils.Globals.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
@@ -16,11 +16,12 @@ import com.aefyr.tsg.g2.stickersgrabber.TelegramStickersGrabber;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
/**
|
||||
* Created by Aefyr on 20.05.2018.
|
||||
*/
|
||||
public class NotificationsHelper{
|
||||
public class NotificationsHelper {
|
||||
private static final int NOTIFICATION_ID_BASE = 3921337;
|
||||
private static final String NOTIFICATION_CHANNEL_ID = "tgss_chan_v5";
|
||||
private static final int MAX_UPDATE_NOTIFICATIONS_PER_SECOND = 3;
|
||||
@@ -31,7 +32,7 @@ public class NotificationsHelper{
|
||||
private final AtomicLong lastNotificationTime = new AtomicLong(0);
|
||||
private int currentNotificationN = 0;
|
||||
|
||||
public NotificationsHelper(Context c){
|
||||
public NotificationsHelper(Context c) {
|
||||
this.c = c;
|
||||
manager = NotificationManagerCompat.from(c);
|
||||
|
||||
@@ -39,31 +40,31 @@ public class NotificationsHelper{
|
||||
downloadingPacksNotificationsIds = new HashMap<>();
|
||||
|
||||
if (oreo()) {
|
||||
NotificationChannel notificationChan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Сервис стикеров Telegram в VTosters", NotificationManager.IMPORTANCE_HIGH);
|
||||
NotificationChannel notificationChan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, AndroidUtils.getString("telegram_stickers_service"), NotificationManager.IMPORTANCE_HIGH);
|
||||
((NotificationManager) c.getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(notificationChan);
|
||||
}
|
||||
}
|
||||
|
||||
public void packStartedDownloading(TelegramStickersPack pack){
|
||||
public void packStartedDownloading(TelegramStickersPack pack) {
|
||||
int notificationId = NOTIFICATION_ID_BASE + currentNotificationN++;
|
||||
downloadingPacksNotificationsIds.put(pack, notificationId);
|
||||
|
||||
Notification.Builder builder = commonBuilder();
|
||||
builder.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + ": загрузка" : pack.title + ": обновление");
|
||||
builder.setContentText("Получение информации");
|
||||
builder.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + AndroidUtils.getString("telegram_stickers_downloading") : pack.title + AndroidUtils.getString("telegram_stickers_updating"));
|
||||
builder.setContentText(AndroidUtils.getString("telegram_stickers_gettinginfo"));
|
||||
builder.setOngoing(true);
|
||||
|
||||
manager.notify(notificationId, builder.build());
|
||||
}
|
||||
|
||||
public void packDownloadUpdated(TelegramStickersPack pack, int downloadProgress){
|
||||
public void packDownloadUpdated(TelegramStickersPack pack, int downloadProgress) {
|
||||
if (System.currentTimeMillis() - lastNotificationTime.get() < MIN_TIME_BETWEEN_UPDATE_NOTIFICATIONS)
|
||||
return;
|
||||
|
||||
lastNotificationTime.set(System.currentTimeMillis());
|
||||
|
||||
Notification.Builder builder = commonBuilder();
|
||||
builder.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + ": загрузка" : pack.title + ": обновление");
|
||||
builder.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + AndroidUtils.getString("telegram_stickers_downloading") : pack.title + AndroidUtils.getString("telegram_stickers_updating"));
|
||||
builder.setContentText(downloadProgress + "/" + pack.stickersCount);
|
||||
builder.setProgress(pack.stickersCount, downloadProgress, false);
|
||||
builder.setOngoing(true);
|
||||
@@ -73,17 +74,17 @@ public class NotificationsHelper{
|
||||
manager.notify(downloadingPacksNotificationsIds.get(pack), builder.build());
|
||||
}
|
||||
|
||||
public void packDoneDownloading(TelegramStickersPack pack, boolean success, boolean wasUpdate, @Nullable Exception e){
|
||||
public void packDoneDownloading(TelegramStickersPack pack, boolean success, boolean wasUpdate, @Nullable Exception e) {
|
||||
Notification.Builder builder = commonBuilder();
|
||||
builder.setProgress(0, 0, false);
|
||||
builder.setOngoing(false);
|
||||
builder.setContentTitle("Сервис стикеров Telegram в VTosters");
|
||||
builder.setContentTitle(AndroidUtils.getString("telegram_stickers_service"));
|
||||
|
||||
String text;
|
||||
if (success)
|
||||
text = wasUpdate ? pack.title + " успешно обновлен" : pack.title + " успешно загружен";
|
||||
text = wasUpdate ? pack.title + AndroidUtils.getString("telegram_stickers_updated") : pack.title + AndroidUtils.getString("telegram_stickers_downloaded");
|
||||
else
|
||||
text = wasUpdate ? pack.title + ": ошибка при обновлении" : pack.title + ": ошибка при загрузке";
|
||||
text = wasUpdate ? pack.title + AndroidUtils.getString("telegram_stickers_error_update") : pack.title + AndroidUtils.getString("telegram_stickers_error_download");
|
||||
|
||||
if (e instanceof TelegramStickersGrabber.TSGException) {
|
||||
text = pack.title + ": " + e.getMessage();
|
||||
@@ -94,11 +95,11 @@ public class NotificationsHelper{
|
||||
manager.notify(downloadingPacksNotificationsIds.remove(pack), builder.build());
|
||||
}
|
||||
|
||||
public void removePackNotification(TelegramStickersPack pack){
|
||||
public void removePackNotification(TelegramStickersPack pack) {
|
||||
manager.cancel(downloadingPacksNotificationsIds.remove(pack));
|
||||
}
|
||||
|
||||
private Notification.Builder commonBuilder(){
|
||||
private Notification.Builder commonBuilder() {
|
||||
var builder = new Notification.Builder(c).setPriority(Notification.PRIORITY_MAX).setSmallIcon(getIdentifier("ic_download_24", "drawable"));
|
||||
if (oreo()) {
|
||||
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
|
||||
@@ -107,7 +108,7 @@ public class NotificationsHelper{
|
||||
return builder;
|
||||
}
|
||||
|
||||
private boolean oreo(){
|
||||
private boolean oreo() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,17 +8,17 @@ import java.io.File;
|
||||
/**
|
||||
* Created by Aefyr on 20.05.2018.
|
||||
*/
|
||||
class PackDeletionTask extends AsyncTask<Void, Void, Boolean>{
|
||||
class PackDeletionTask extends AsyncTask<Void, Void, Boolean> {
|
||||
private static final String TAG = "TGSSAnnihilator";
|
||||
|
||||
private final TelegramStickersPack pack;
|
||||
|
||||
PackDeletionTask(TelegramStickersPack pack){
|
||||
PackDeletionTask(TelegramStickersPack pack) {
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids){
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
boolean success = true;
|
||||
|
||||
for (File f : pack.folder.listFiles()) {
|
||||
@@ -31,7 +31,7 @@ class PackDeletionTask extends AsyncTask<Void, Void, Boolean>{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean aBoolean){
|
||||
protected void onPostExecute(Boolean aBoolean) {
|
||||
Log.d(TAG, String.format("Attempted deleting pack %s, success?%s", pack.id, aBoolean));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import java.util.List;
|
||||
/**
|
||||
* Created by Aefyr on 18.05.2018.
|
||||
*/
|
||||
public class TelegramStickersPack extends CustomStickersPack{
|
||||
public class TelegramStickersPack extends CustomStickersPack {
|
||||
|
||||
public static final int UNKNOWN = -1;
|
||||
public static final int DOWNLOADED = 0;
|
||||
@@ -35,12 +35,12 @@ public class TelegramStickersPack extends CustomStickersPack{
|
||||
|
||||
public HashMap<String, List<Integer>> emojis = new HashMap<>();
|
||||
|
||||
public TelegramStickersPack(String id){
|
||||
public TelegramStickersPack(String id) {
|
||||
this.id = id.toLowerCase();
|
||||
title = id;
|
||||
}
|
||||
|
||||
public JSONObject encodeEmojis() throws JSONException{
|
||||
public JSONObject encodeEmojis() throws JSONException {
|
||||
JSONObject obj = new JSONObject();
|
||||
for (HashMap.Entry<String, List<Integer>> en : emojis.entrySet()) {
|
||||
JSONArray arr = new JSONArray();
|
||||
@@ -51,9 +51,9 @@ public class TelegramStickersPack extends CustomStickersPack{
|
||||
return obj;
|
||||
}
|
||||
|
||||
public void loadEmojis(JSONObject obj) throws JSONException{
|
||||
public void loadEmojis(JSONObject obj) throws JSONException {
|
||||
Iterator<String> it = obj.keys();
|
||||
while(it.hasNext()) {
|
||||
while (it.hasNext()) {
|
||||
String key = it.next();
|
||||
//emojis.put(key, obj.getInt(key));
|
||||
List<Integer> list = emojis.get(key);
|
||||
@@ -65,7 +65,7 @@ public class TelegramStickersPack extends CustomStickersPack{
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap getIcon(int targetMaxSideSize){
|
||||
public Bitmap getIcon(int targetMaxSideSize) {
|
||||
if (state != DOWNLOADED && state != UPDATING)
|
||||
throw new IllegalStateException("Unable to get an icon of a pack that hasn't been downloaded yet");
|
||||
|
||||
@@ -74,7 +74,7 @@ public class TelegramStickersPack extends CustomStickersPack{
|
||||
return getScaledBitmap(icon, targetMaxSideSize);
|
||||
}
|
||||
|
||||
private Bitmap getScaledBitmap(File bitmapFile, int targetMaxSideSize){
|
||||
private Bitmap getScaledBitmap(File bitmapFile, int targetMaxSideSize) {
|
||||
BitmapFactory.Options op = new BitmapFactory.Options();
|
||||
op.inJustDecodeBounds = true;
|
||||
op.inPreferredConfig = Bitmap.Config.ARGB_8888;
|
||||
@@ -100,46 +100,46 @@ public class TelegramStickersPack extends CustomStickersPack{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj){
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof TelegramStickersPack && ((TelegramStickersPack) obj).id.equalsIgnoreCase(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(){
|
||||
public int hashCode() {
|
||||
return id.toLowerCase().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File folder(){
|
||||
public File folder() {
|
||||
return folder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int stickersCount(){
|
||||
public int stickersCount() {
|
||||
return stickersCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name(){
|
||||
public String name() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap getIconBitmap(){
|
||||
public Bitmap getIconBitmap() {
|
||||
return getIcon(128);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap getStickerBitmap(int index){
|
||||
public Bitmap getStickerBitmap(int index) {
|
||||
return BitmapFactory.decodeFile(new File(folder, String.format("%03d.png", index + 1)).getAbsolutePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStickerFile(int index){
|
||||
public File getStickerFile(int index) {
|
||||
return new File(folder, String.format("%03d.png", index + 1));
|
||||
}
|
||||
|
||||
public Bitmap getStickerBitmap(int index, int maxSize){
|
||||
public Bitmap getStickerBitmap(int index, int maxSize) {
|
||||
return getScaledBitmap(new File(folder, String.format("%03d.png", index + 1)), maxSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.aefyr.tsg.g2;
|
||||
|
||||
import static ru.vtosters.lite.utils.Globals.getContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -24,7 +24,7 @@ import ru.vtosters.lite.ui.fragments.tgstickers.StickersFragment;
|
||||
/**
|
||||
* Created by Aefyr on 19.05.2018.
|
||||
*/
|
||||
public class TelegramStickersService{
|
||||
public class TelegramStickersService {
|
||||
private static final String TAG = "TGStickersService";
|
||||
private static TelegramStickersService instance;
|
||||
|
||||
@@ -46,7 +46,7 @@ public class TelegramStickersService{
|
||||
private final NotificationsHelper notificationsHelper;
|
||||
private boolean ready = false;
|
||||
|
||||
private TelegramStickersService(Context context){
|
||||
private TelegramStickersService(Context context) {
|
||||
instance = this;
|
||||
|
||||
this.c = context.getApplicationContext();
|
||||
@@ -67,15 +67,15 @@ public class TelegramStickersService{
|
||||
updatePacks(true);
|
||||
}
|
||||
|
||||
public static TelegramStickersService getInstance(Context c){
|
||||
public static TelegramStickersService getInstance(Context c) {
|
||||
return instance == null ? new TelegramStickersService(c) : instance;
|
||||
}
|
||||
|
||||
private void updatePacks(final boolean notify){
|
||||
private void updatePacks(final boolean notify) {
|
||||
packs.clear();
|
||||
dbHelper.getAllPacks(new TelegramStickersDbHelper.PacksLoadingListener(){
|
||||
dbHelper.getAllPacks(new TelegramStickersDbHelper.PacksLoadingListener() {
|
||||
@Override
|
||||
public void onPackLoaded(final TelegramStickersPack pack){
|
||||
public void onPackLoaded(final TelegramStickersPack pack) {
|
||||
runOnUiThread(() -> {
|
||||
packs.add(pack);
|
||||
|
||||
@@ -89,7 +89,7 @@ public class TelegramStickersService{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllPacksLoaded(ArrayList<TelegramStickersPack> packs){
|
||||
public void onAllPacksLoaded(ArrayList<TelegramStickersPack> packs) {
|
||||
ready = true;
|
||||
|
||||
if (notify) {
|
||||
@@ -98,22 +98,22 @@ public class TelegramStickersService{
|
||||
}
|
||||
|
||||
Log.d(TAG, String.format("Packs list loaded, running %d queued tasks...", queuedTasks.size()));
|
||||
while(!queuedTasks.isEmpty())
|
||||
while (!queuedTasks.isEmpty())
|
||||
queuedTasks.remove(0).run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addStickersEventsListener(StickersEventsListener listener){
|
||||
public void addStickersEventsListener(StickersEventsListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeStickersEventsListener(StickersEventsListener listener){
|
||||
public void removeStickersEventsListener(StickersEventsListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
private void notifyPackAdded(TelegramStickersPack pack, int atIndex){
|
||||
getContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
private void notifyPackAdded(TelegramStickersPack pack, int atIndex) {
|
||||
getGlobalContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
if (listeners.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -122,8 +122,8 @@ public class TelegramStickersService{
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyPackChanged(TelegramStickersPack pack, int atIndex){
|
||||
getContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
private void notifyPackChanged(TelegramStickersPack pack, int atIndex) {
|
||||
getGlobalContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
if (listeners.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -132,8 +132,8 @@ public class TelegramStickersService{
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyPackRemoved(TelegramStickersPack pack, int atIndex){
|
||||
getContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
private void notifyPackRemoved(TelegramStickersPack pack, int atIndex) {
|
||||
getGlobalContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
if (listeners.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -142,8 +142,8 @@ public class TelegramStickersService{
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyPackDownloadError(TelegramStickersPack pack, Exception error){
|
||||
getContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
private void notifyPackDownloadError(TelegramStickersPack pack, Exception error) {
|
||||
getGlobalContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
if (listeners.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -152,8 +152,8 @@ public class TelegramStickersService{
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyActivePacksListChanged(){
|
||||
getContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
private void notifyActivePacksListChanged() {
|
||||
getGlobalContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
if (listeners.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -162,8 +162,8 @@ public class TelegramStickersService{
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyInactivePacksListChanged(){
|
||||
getContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
private void notifyInactivePacksListChanged() {
|
||||
getGlobalContext().sendBroadcast(new Intent(StickersFragment.ACTION_RELOAD));
|
||||
if (listeners.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -172,27 +172,27 @@ public class TelegramStickersService{
|
||||
}
|
||||
}
|
||||
|
||||
public void setBotKey(String botKey){
|
||||
public void setBotKey(String botKey) {
|
||||
grabber.setBotApiKey(botKey);
|
||||
}
|
||||
|
||||
public ArrayList<TelegramStickersPack> getPacksListReference(){
|
||||
public ArrayList<TelegramStickersPack> getPacksListReference() {
|
||||
return packs;
|
||||
}
|
||||
|
||||
public ArrayList<TelegramStickersPack> getActivePacksListReference(){
|
||||
public ArrayList<TelegramStickersPack> getActivePacksListReference() {
|
||||
return activePacks;
|
||||
}
|
||||
|
||||
public ArrayList<TelegramStickersPack> getInactivePacksListReference(){
|
||||
public ArrayList<TelegramStickersPack> getInactivePacksListReference() {
|
||||
return inactivePacks;
|
||||
}
|
||||
|
||||
public boolean isDoneLoading(){
|
||||
public boolean isDoneLoading() {
|
||||
return ready;
|
||||
}
|
||||
|
||||
public boolean requestPackDownload(final String id, File packFolder){
|
||||
public boolean requestPackDownload(final String id, File packFolder) {
|
||||
if (currentlyDownloading.contains(id)) {
|
||||
Log.e(TAG, String.format("Got request to download pack %s which is already downloading", id));
|
||||
return false;
|
||||
@@ -228,9 +228,9 @@ public class TelegramStickersService{
|
||||
notificationsHelper.packStartedDownloading(newPack);
|
||||
|
||||
grabber.enableProxy();
|
||||
grabber.grabPack(id, packFolder, pack.version, new TelegramStickersGrabber.PackDownloadListener(){
|
||||
grabber.grabPack(id, packFolder, pack.version, new TelegramStickersGrabber.PackDownloadListener() {
|
||||
@Override
|
||||
public void onPackDownloaded(TelegramStickersPackInfo packInfo, boolean newVersionFound){
|
||||
public void onPackDownloaded(TelegramStickersPackInfo packInfo, boolean newVersionFound) {
|
||||
|
||||
runOnUiThread(() -> {
|
||||
newPack.state = TelegramStickersPack.DOWNLOADED;
|
||||
@@ -250,7 +250,7 @@ public class TelegramStickersService{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackDownloadError(final Exception e){
|
||||
public void onPackDownloadError(final Exception e) {
|
||||
runOnUiThread(() -> {
|
||||
Log.e(TAG, "Error while downloading pack " + newPack.id);
|
||||
e.printStackTrace();
|
||||
@@ -271,7 +271,7 @@ public class TelegramStickersService{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGotPackInfo(final TelegramStickersPackInfo packInfo){
|
||||
public void onGotPackInfo(final TelegramStickersPackInfo packInfo) {
|
||||
runOnUiThread(() -> {
|
||||
newPack.title = packInfo.title;
|
||||
newPack.stickersCount = packInfo.stickersCount;
|
||||
@@ -283,7 +283,7 @@ public class TelegramStickersService{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStickerDownloaded(String pack, File sticker, String boundEmoji, int stickerIndex, int downloadedStickersCount, int totalStickersCount){
|
||||
public void onStickerDownloaded(String pack, File sticker, String boundEmoji, int stickerIndex, int downloadedStickersCount, int totalStickersCount) {
|
||||
stickerIndex--;
|
||||
|
||||
List<Integer> list = newPack.emojis.get(boundEmoji);
|
||||
@@ -298,7 +298,7 @@ public class TelegramStickersService{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setPackEnabled(final TelegramStickersPack pack, final boolean enabled, final boolean notify){
|
||||
public void setPackEnabled(final TelegramStickersPack pack, final boolean enabled, final boolean notify) {
|
||||
if (!ready) {
|
||||
queuedTasks.add(() -> setPackEnabled(pack, enabled, notify));
|
||||
return;
|
||||
@@ -324,7 +324,7 @@ public class TelegramStickersService{
|
||||
}
|
||||
}
|
||||
|
||||
public void deletePack(final TelegramStickersPack pack){
|
||||
public void deletePack(final TelegramStickersPack pack) {
|
||||
if (!ready) {
|
||||
queuedTasks.add(() -> deletePack(pack));
|
||||
return;
|
||||
@@ -350,11 +350,11 @@ public class TelegramStickersService{
|
||||
new PackDeletionTask(pack).executeOnExecutor(executor);
|
||||
}
|
||||
|
||||
private void runOnUiThread(Runnable r){
|
||||
private void runOnUiThread(Runnable r) {
|
||||
uiThreadHandler.post(r);
|
||||
}
|
||||
|
||||
private void syncPack(final TelegramStickersPack pack){
|
||||
private void syncPack(final TelegramStickersPack pack) {
|
||||
if (!ready) {
|
||||
queuedTasks.add(() -> syncPack(pack));
|
||||
return;
|
||||
@@ -363,7 +363,7 @@ public class TelegramStickersService{
|
||||
Log.d(TAG, "Sync=" + dbHelper.syncPack(pack));
|
||||
}
|
||||
|
||||
public void swap(TelegramStickersPack p1, TelegramStickersPack p2){
|
||||
public void swap(TelegramStickersPack p1, TelegramStickersPack p2) {
|
||||
int i1 = p1.index;
|
||||
int i2 = p2.index;
|
||||
p1.index = i2;
|
||||
@@ -383,7 +383,7 @@ public class TelegramStickersService{
|
||||
getPacksListReference().set(li1, p2);
|
||||
}
|
||||
|
||||
interface StickersEventsListener{
|
||||
interface StickersEventsListener {
|
||||
void onPackAdded(TelegramStickersPack pack, int atIndex);
|
||||
|
||||
void onPackRemoved(TelegramStickersPack pack, int atIndex);
|
||||
|
||||
@@ -5,16 +5,16 @@ import android.provider.BaseColumns;
|
||||
/**
|
||||
* Created by Aefyr on 19.05.2018.
|
||||
*/
|
||||
public final class TelegramStickersContract{
|
||||
public final class TelegramStickersContract {
|
||||
|
||||
public static final String SQL_CREATE_ENTRIES = String.format("CREATE TABLE %s (%s INTEGER PRIMARY KEY, %s INTEGER AUTO_INCREMENT, %s TEXT, %s TEXT, %s TEXT, %s INTEGER, %s INTEGER, %s TEXT, %s TEXT)",
|
||||
StickersTableEntry.TABLE_NAME, StickersTableEntry._ID, StickersTableEntry.COLUMN_NAME_INDEX, StickersTableEntry.COLUMN_NAME_ID, StickersTableEntry.COLUMN_NAME_NAME,
|
||||
StickersTableEntry.COLUMN_NAME_FOLDER, StickersTableEntry.COLUMN_NAME_STICKERS_COUNT, StickersTableEntry.COLUMN_NAME_ENABLED, StickersTableEntry.COLUMN_NAME_VERSION, StickersTableEntry.COLUMN_NAME_EMOJIS);
|
||||
|
||||
private TelegramStickersContract(){
|
||||
private TelegramStickersContract() {
|
||||
}
|
||||
|
||||
public static class StickersTableEntry implements BaseColumns{
|
||||
public static class StickersTableEntry implements BaseColumns {
|
||||
public static final String TABLE_NAME = "packs";
|
||||
|
||||
public static final String COLUMN_NAME_ID = "id";
|
||||
|
||||
@@ -20,35 +20,35 @@ import java.util.ArrayList;
|
||||
/**
|
||||
* Created by Aefyr on 19.05.2018.
|
||||
*/
|
||||
public class TelegramStickersDbHelper extends SQLiteOpenHelper{
|
||||
public class TelegramStickersDbHelper extends SQLiteOpenHelper {
|
||||
private static final int DB_VERSION = 2;
|
||||
private static final String DB_NAME = "TelegramStickers.db";
|
||||
|
||||
private SQLiteDatabase writableDb;
|
||||
private SQLiteDatabase readableDb;
|
||||
|
||||
public TelegramStickersDbHelper(Context context){
|
||||
public TelegramStickersDbHelper(Context context) {
|
||||
super(context, DB_NAME, null, DB_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db){
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(TelegramStickersContract.SQL_CREATE_ENTRIES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion == 1 && newVersion == 2) {
|
||||
db.execSQL(String.format("ALTER TABLE %s ADD COLUMN %s TEXT", TelegramStickersContract.StickersTableEntry.TABLE_NAME, TelegramStickersContract.StickersTableEntry.COLUMN_NAME_EMOJIS));
|
||||
}
|
||||
}
|
||||
|
||||
public void loadDatabases(){
|
||||
public void loadDatabases() {
|
||||
writableDb = getWritableDatabase();
|
||||
readableDb = getReadableDatabase();
|
||||
}
|
||||
|
||||
public boolean syncPack(TelegramStickersPack pack){
|
||||
public boolean syncPack(TelegramStickersPack pack) {
|
||||
ContentValues sqlPack = new ContentValues();
|
||||
sqlPack.put(TelegramStickersContract.StickersTableEntry.COLUMN_NAME_ID, pack.id);
|
||||
sqlPack.put(TelegramStickersContract.StickersTableEntry.COLUMN_NAME_NAME, pack.title);
|
||||
@@ -77,7 +77,7 @@ public class TelegramStickersDbHelper extends SQLiteOpenHelper{
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getNewIndex(){
|
||||
private int getNewIndex() {
|
||||
Cursor c = readableDb.rawQuery("SELECT MAX(" + TelegramStickersContract.StickersTableEntry.COLUMN_NAME_INDEX + ") FROM " + TelegramStickersContract.StickersTableEntry.TABLE_NAME, new String[0]);
|
||||
c.moveToLast();
|
||||
int max;
|
||||
@@ -91,30 +91,30 @@ public class TelegramStickersDbHelper extends SQLiteOpenHelper{
|
||||
return max + 1;
|
||||
}
|
||||
|
||||
public boolean deletePack(TelegramStickersPack pack){
|
||||
public boolean deletePack(TelegramStickersPack pack) {
|
||||
return writableDb.delete(TelegramStickersContract.StickersTableEntry.TABLE_NAME, TelegramStickersContract.StickersTableEntry.COLUMN_NAME_ID + "='" + pack.id + "'", null) == 1;
|
||||
}
|
||||
|
||||
public void getAllPacks(PacksLoadingListener listener){
|
||||
public void getAllPacks(PacksLoadingListener listener) {
|
||||
new PacksLoadingTask(listener).execute();
|
||||
}
|
||||
|
||||
public interface PacksLoadingListener{
|
||||
public interface PacksLoadingListener {
|
||||
void onPackLoaded(TelegramStickersPack pack);
|
||||
|
||||
void onAllPacksLoaded(ArrayList<TelegramStickersPack> packs);
|
||||
}
|
||||
|
||||
private class PacksLoadingTask extends AsyncTask<Void, Void, ArrayList<TelegramStickersPack>>{
|
||||
private class PacksLoadingTask extends AsyncTask<Void, Void, ArrayList<TelegramStickersPack>> {
|
||||
|
||||
PacksLoadingListener listener;
|
||||
|
||||
PacksLoadingTask(PacksLoadingListener listener){
|
||||
PacksLoadingTask(PacksLoadingListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArrayList<TelegramStickersPack> doInBackground(Void... voids){
|
||||
protected ArrayList<TelegramStickersPack> doInBackground(Void... voids) {
|
||||
if (readableDb == null)
|
||||
loadDatabases();
|
||||
|
||||
@@ -125,7 +125,7 @@ public class TelegramStickersDbHelper extends SQLiteOpenHelper{
|
||||
|
||||
ArrayList<TelegramStickersPack> packs = new ArrayList<>(cursor.getCount() + 8);
|
||||
|
||||
while(cursor.moveToNext()) {
|
||||
while (cursor.moveToNext()) {
|
||||
Log.d("DB", "PACK LOADED");
|
||||
String id = cursor.getString(cursor.getColumnIndexOrThrow(TelegramStickersContract.StickersTableEntry.COLUMN_NAME_ID));
|
||||
String name = cursor.getString(cursor.getColumnIndexOrThrow(TelegramStickersContract.StickersTableEntry.COLUMN_NAME_NAME));
|
||||
@@ -160,7 +160,7 @@ public class TelegramStickersDbHelper extends SQLiteOpenHelper{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(ArrayList<TelegramStickersPack> packs){
|
||||
protected void onPostExecute(ArrayList<TelegramStickersPack> packs) {
|
||||
listener.onAllPacksLoaded(packs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import ru.vtosters.lite.net.NetResponse;
|
||||
/**
|
||||
* Created by Aefyr on 11.05.2018.
|
||||
*/
|
||||
public class TelegramStickersGrabber{
|
||||
public class TelegramStickersGrabber {
|
||||
private static final String TAG = "TSG";
|
||||
public static String REAL_TG_IP = null;
|
||||
public static String PROXY_IP = null;
|
||||
@@ -51,7 +51,7 @@ public class TelegramStickersGrabber{
|
||||
private static String GET_FILE_URL;
|
||||
private static String BOT_API_BASE_FILE_URL;
|
||||
|
||||
static{
|
||||
static {
|
||||
updateURLs();
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class TelegramStickersGrabber{
|
||||
private String botApiKey = "";
|
||||
private NetClient httpClient;
|
||||
|
||||
public TelegramStickersGrabber(String botApiKey){
|
||||
public TelegramStickersGrabber(String botApiKey) {
|
||||
this.botApiKey = botApiKey;
|
||||
httpClient = new NetClient.Builder().connectTimeout(5, TimeUnit.SECONDS).build();
|
||||
uiThreadHandler = new Handler(Looper.getMainLooper());
|
||||
@@ -73,7 +73,7 @@ public class TelegramStickersGrabber{
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateURLs(){
|
||||
public static void updateURLs() {
|
||||
BOT_API_BASE_FILE_URL = "https://api.telegram.org/file/bot%s/%s";
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ public class TelegramStickersGrabber{
|
||||
GET_FILE_URL = BOT_API_BASE_URL + "getFile?file_id=%s";
|
||||
}
|
||||
|
||||
public static boolean isTelegramBlocked(){
|
||||
public static boolean isTelegramBlocked() {
|
||||
NetClient client = new NetClient.Builder().connectTimeout(5, TimeUnit.SECONDS).build();
|
||||
try {
|
||||
if (PROXY_IP != null) {
|
||||
@@ -112,14 +112,14 @@ public class TelegramStickersGrabber{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resetProxy(){
|
||||
public void resetProxy() {
|
||||
httpClient = new NetClient.Builder().connectTimeout(5, TimeUnit.SECONDS).build();
|
||||
}
|
||||
|
||||
public void enableProxy(){
|
||||
Thread kostil = new Thread(){
|
||||
public void enableProxy() {
|
||||
Thread kostil = new Thread() {
|
||||
@Override
|
||||
public void run(){
|
||||
public void run() {
|
||||
try {
|
||||
if (PROXY_IP != null) {
|
||||
Socket socket = new Socket(PROXY_IP, PROXY_PORT);
|
||||
@@ -150,41 +150,41 @@ public class TelegramStickersGrabber{
|
||||
}
|
||||
}
|
||||
|
||||
public void grabPack(String id, File packFolder, String installedVersion, final PackDownloadListener listener){
|
||||
public void grabPack(String id, File packFolder, String installedVersion, final PackDownloadListener listener) {
|
||||
getPackInfo(id, packFolder, installedVersion, listener);
|
||||
}
|
||||
|
||||
public void setBotApiKey(String key){
|
||||
public void setBotApiKey(String key) {
|
||||
botApiKey = key;
|
||||
}
|
||||
|
||||
public void checkKey(final KeyCheckListener listener){
|
||||
public void checkKey(final KeyCheckListener listener) {
|
||||
Log.d(TAG, "Checking key: " + botApiKey);
|
||||
NetRequest request = new NetRequest.Builder().get().url(String.format(BOT_API_BASE_URL + "getMe", botApiKey)).build();
|
||||
httpClient.newCall(request).enqueue(new NetCallback(){
|
||||
httpClient.newCall(request).enqueue(new NetCallback() {
|
||||
@Override
|
||||
public void onFailure(NetCall call, IOException e){
|
||||
public void onFailure(NetCall call, IOException e) {
|
||||
e.printStackTrace();
|
||||
runOnUiThread(listener::onNetError);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(NetCall call, final NetResponse response) throws IOException{
|
||||
public void onResponse(NetCall call, final NetResponse response) throws IOException {
|
||||
runOnUiThread(() -> listener.onKeyChecked(response.code() == 200));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void getPackInfo(final String packName, final File packFolder, final String installedVersion, final PackDownloadListener listener){
|
||||
private void getPackInfo(final String packName, final File packFolder, final String installedVersion, final PackDownloadListener listener) {
|
||||
NetRequest packInfoRequest = new NetRequest.Builder().get().url(String.format(GET_STICKER_SET_URL, botApiKey, packName)).build();
|
||||
httpClient.newCall(packInfoRequest).enqueue(new NetCallback(){
|
||||
httpClient.newCall(packInfoRequest).enqueue(new NetCallback() {
|
||||
@Override
|
||||
public void onFailure(NetCall call, IOException e){
|
||||
public void onFailure(NetCall call, IOException e) {
|
||||
listener.onPackDownloadError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(NetCall call, NetResponse response) throws IOException{
|
||||
public void onResponse(NetCall call, NetResponse response) throws IOException {
|
||||
if (!response.isSuccessful()) {
|
||||
if (response.getData() != null)
|
||||
listener.onPackDownloadError(new TSGException(response.getDataString() + "\nURL: " + call.request().url()));
|
||||
@@ -246,7 +246,7 @@ public class TelegramStickersGrabber{
|
||||
});
|
||||
}
|
||||
|
||||
private void getPack(final StickerSet set, final File packFolder, final TelegramStickersPackInfo packInfo, final PackDownloadListener listener){
|
||||
private void getPack(final StickerSet set, final File packFolder, final TelegramStickersPackInfo packInfo, final PackDownloadListener listener) {
|
||||
final GoalCounter downloadedStickers = new GoalCounter(set.stickers.size(), () -> {
|
||||
Log.d(TAG, String.format("Pack %s has been downloaded to %s", set.id, packFolder.getAbsolutePath()));
|
||||
|
||||
@@ -262,9 +262,9 @@ public class TelegramStickersGrabber{
|
||||
final int stickerIndex = i + 1;
|
||||
|
||||
AtomicBoolean sync = new AtomicBoolean();
|
||||
httpClient.newCall(fileInfoRequest).enqueue(new NetCallback(){
|
||||
httpClient.newCall(fileInfoRequest).enqueue(new NetCallback() {
|
||||
@Override
|
||||
public void onFailure(NetCall call, IOException e){
|
||||
public void onFailure(NetCall call, IOException e) {
|
||||
if (deathFlag.up())
|
||||
return;
|
||||
|
||||
@@ -275,7 +275,7 @@ public class TelegramStickersGrabber{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(NetCall call, NetResponse response) throws IOException{
|
||||
public void onResponse(NetCall call, NetResponse response) throws IOException {
|
||||
if (deathFlag.up())
|
||||
return;
|
||||
|
||||
@@ -305,9 +305,9 @@ public class TelegramStickersGrabber{
|
||||
|
||||
NetRequest fileDownloadRequest = new NetRequest.Builder().get().url(String.format(BOT_API_BASE_FILE_URL, botApiKey, filePath)).build();
|
||||
|
||||
httpClient.newCall(fileDownloadRequest).enqueue(new NetCallback(){
|
||||
httpClient.newCall(fileDownloadRequest).enqueue(new NetCallback() {
|
||||
@Override
|
||||
public void onFailure(NetCall call, IOException e){
|
||||
public void onFailure(NetCall call, IOException e) {
|
||||
if (deathFlag.up())
|
||||
return;
|
||||
|
||||
@@ -318,7 +318,7 @@ public class TelegramStickersGrabber{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(NetCall call, NetResponse response) throws IOException{
|
||||
public void onResponse(NetCall call, NetResponse response) throws IOException {
|
||||
if (deathFlag.up())
|
||||
return;
|
||||
|
||||
@@ -407,7 +407,7 @@ public class TelegramStickersGrabber{
|
||||
}
|
||||
});
|
||||
|
||||
while(!sync.get())
|
||||
while (!sync.get())
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e1) {
|
||||
@@ -415,11 +415,11 @@ public class TelegramStickersGrabber{
|
||||
}
|
||||
}
|
||||
|
||||
private void runOnUiThread(Runnable r){
|
||||
private void runOnUiThread(Runnable r) {
|
||||
uiThreadHandler.post(r);
|
||||
}
|
||||
|
||||
public interface PackDownloadListener{
|
||||
public interface PackDownloadListener {
|
||||
void onPackDownloaded(TelegramStickersPackInfo pack, boolean newVersionFound);
|
||||
|
||||
void onPackDownloadError(Exception e);
|
||||
@@ -429,27 +429,27 @@ public class TelegramStickersGrabber{
|
||||
void onStickerDownloaded(String pack, File sticker, String boundEmoji, int stickerIndex, int downloadedStickersCount, int totalStickerCount);
|
||||
}
|
||||
|
||||
public interface KeyCheckListener{
|
||||
public interface KeyCheckListener {
|
||||
void onKeyChecked(boolean ok);
|
||||
|
||||
void onNetError();
|
||||
}
|
||||
|
||||
public class TSGException extends Exception{
|
||||
public class TSGException extends Exception {
|
||||
private static final long serialVersionUID = 7866915509988422944L;
|
||||
|
||||
private TSGException(String message){
|
||||
private TSGException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
private class StickerSet{
|
||||
private class StickerSet {
|
||||
String id;
|
||||
String name;
|
||||
String version;
|
||||
ArrayList<Sticker> stickers;
|
||||
|
||||
StickerSet(String id, String name, String version, ArrayList<Sticker> stickers){
|
||||
StickerSet(String id, String name, String version, ArrayList<Sticker> stickers) {
|
||||
this.name = name;
|
||||
this.stickers = stickers;
|
||||
this.id = id;
|
||||
@@ -457,22 +457,22 @@ public class TelegramStickersGrabber{
|
||||
}
|
||||
}
|
||||
|
||||
private class Sticker{
|
||||
private class Sticker {
|
||||
String emoji;
|
||||
String fileId;
|
||||
|
||||
Sticker(String fileId, String emoji){
|
||||
Sticker(String fileId, String emoji) {
|
||||
this.fileId = fileId;
|
||||
this.emoji = emoji;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj){
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Sticker && ((Sticker) obj).fileId.equals(fileId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(){
|
||||
public int hashCode() {
|
||||
return (17 * emoji.hashCode()) << 32 + fileId.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@ package com.aefyr.tsg.g2.stickersgrabber;
|
||||
/**
|
||||
* Created by Aefyr on 22.05.2018.
|
||||
*/
|
||||
public class TelegramStickersPackInfo{
|
||||
public class TelegramStickersPackInfo {
|
||||
public String id;
|
||||
public String title;
|
||||
public String version;
|
||||
public int stickersCount;
|
||||
|
||||
TelegramStickersPackInfo(String id, String title, int stickersCount, String version){
|
||||
TelegramStickersPackInfo(String id, String title, int stickersCount, String version) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.version = version;
|
||||
|
||||
@@ -3,18 +3,18 @@ package com.aefyr.tsg.g2.stickersgrabber.util;
|
||||
/**
|
||||
* Created by Aefyr on 11.05.2018.
|
||||
*/
|
||||
public class Flag{
|
||||
public class Flag {
|
||||
private boolean up = false;
|
||||
|
||||
public synchronized boolean up(){
|
||||
public synchronized boolean up() {
|
||||
return up;
|
||||
}
|
||||
|
||||
public synchronized void raise(){
|
||||
public synchronized void raise() {
|
||||
up = true;
|
||||
}
|
||||
|
||||
public synchronized void lower(){
|
||||
public synchronized void lower() {
|
||||
up = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,34 +5,34 @@ import android.util.Log;
|
||||
/**
|
||||
* Created by Aefyr on 11.05.2018.
|
||||
*/
|
||||
public class GoalCounter{
|
||||
public class GoalCounter {
|
||||
|
||||
private final int goal;
|
||||
private final OnGoalReachListener listener;
|
||||
private int i = 0;
|
||||
|
||||
public GoalCounter(int goal, OnGoalReachListener listener){
|
||||
public GoalCounter(int goal, OnGoalReachListener listener) {
|
||||
this.goal = goal;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public synchronized void increase(){
|
||||
public synchronized void increase() {
|
||||
if (++i == goal)
|
||||
listener.onGoalReached();
|
||||
|
||||
Log.d("COUNTER", "G=" + goal + ", I=" + i);
|
||||
}
|
||||
|
||||
public synchronized void increase(int delta){
|
||||
public synchronized void increase(int delta) {
|
||||
if ((i += delta) == goal)
|
||||
listener.onGoalReached();
|
||||
}
|
||||
|
||||
public synchronized int value(){
|
||||
public synchronized int value() {
|
||||
return i;
|
||||
}
|
||||
|
||||
public interface OnGoalReachListener{
|
||||
public interface OnGoalReachListener {
|
||||
void onGoalReached();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,60 +8,60 @@ import com.arthenica.smartexception.java.Exceptions;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import ru.vtosters.lite.utils.Globals;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class NativeLoader{
|
||||
public class NativeLoader {
|
||||
static final String[] FFMPEG_LIBRARIES = {"avutil", "swscale", "swresample", "avcodec", "avformat", "avfilter", "avdevice"};
|
||||
|
||||
private static void loadLibrary(String libraryName){
|
||||
String path = Globals.getContext().getFilesDir() + "/lib" + libraryName + ".so";
|
||||
private static void loadLibrary(String libraryName) {
|
||||
String path = AndroidUtils.getGlobalContext().getFilesDir() + "/lib" + libraryName + ".so";
|
||||
System.load(path);
|
||||
}
|
||||
|
||||
private static List<String> loadExternalLibraries(){
|
||||
private static List<String> loadExternalLibraries() {
|
||||
// return Packages.getExternalLibraries();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static String loadNativeAbi(){
|
||||
private static String loadNativeAbi() {
|
||||
// return AbiDetect.getNativeAbi();
|
||||
return Abi.ABI_ARMV7A_NEON.getName();
|
||||
}
|
||||
|
||||
static String loadAbi(){
|
||||
static String loadAbi() {
|
||||
// return AbiDetect.getAbi();
|
||||
return Abi.ABI_ARMV7A_NEON.getName();
|
||||
}
|
||||
|
||||
static String loadPackageName(){
|
||||
static String loadPackageName() {
|
||||
return Packages.getPackageName();
|
||||
}
|
||||
|
||||
static String loadVersion(){
|
||||
static String loadVersion() {
|
||||
return FFmpegKitConfig.getVersion();
|
||||
}
|
||||
|
||||
static boolean loadIsLTSBuild(){
|
||||
static boolean loadIsLTSBuild() {
|
||||
return AbiDetect.isNativeLTSBuild();
|
||||
}
|
||||
|
||||
static int loadLogLevel(){
|
||||
static int loadLogLevel() {
|
||||
return FFmpegKitConfig.getNativeLogLevel();
|
||||
}
|
||||
|
||||
static String loadBuildDate(){
|
||||
static String loadBuildDate() {
|
||||
return FFmpegKitConfig.getBuildDate();
|
||||
}
|
||||
|
||||
static void enableRedirection(){
|
||||
static void enableRedirection() {
|
||||
FFmpegKitConfig.enableRedirection();
|
||||
}
|
||||
|
||||
static void loadFFmpegKitAbiDetect(){
|
||||
static void loadFFmpegKitAbiDetect() {
|
||||
loadLibrary("ffmpegkit_abidetect");
|
||||
}
|
||||
|
||||
static boolean loadFFmpeg(){
|
||||
static boolean loadFFmpeg() {
|
||||
boolean nativeFFmpegLoaded = false;
|
||||
boolean nativeFFmpegTriedAndFailed = false;
|
||||
|
||||
@@ -85,7 +85,7 @@ public class NativeLoader{
|
||||
return nativeFFmpegTriedAndFailed;
|
||||
}
|
||||
|
||||
static void loadFFmpegKit(boolean nativeFFmpegTriedAndFailed){
|
||||
static void loadFFmpegKit(boolean nativeFFmpegTriedAndFailed) {
|
||||
boolean nativeFFmpegKitLoaded = false;
|
||||
if (!nativeFFmpegTriedAndFailed && "arm-v7a".equals(loadNativeAbi())) {
|
||||
try {
|
||||
@@ -102,7 +102,7 @@ public class NativeLoader{
|
||||
}
|
||||
|
||||
|
||||
static String getDeviceDebugInformation(){
|
||||
static String getDeviceDebugInformation() {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append("brand: ");
|
||||
stringBuilder.append(Build.BRAND);
|
||||
|
||||
@@ -43,7 +43,7 @@ import java.util.Set;
|
||||
* @author Taner Sener
|
||||
* @since 0.1.0
|
||||
*/
|
||||
public abstract class AbstractExceptions{
|
||||
public abstract class AbstractExceptions {
|
||||
|
||||
/**
|
||||
* <p>Default max depth used in methods which do not have a maxDepth argument.
|
||||
@@ -90,14 +90,14 @@ public abstract class AbstractExceptions{
|
||||
*
|
||||
* @param packageString root package name to register
|
||||
*/
|
||||
public static void registerRootPackage(final String packageString){
|
||||
public static void registerRootPackage(final String packageString) {
|
||||
rootPackageSet.add(packageString);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Clears previously registered root packages.
|
||||
*/
|
||||
public static void clearRootPackages(){
|
||||
public static void clearRootPackages() {
|
||||
rootPackageSet.clear();
|
||||
}
|
||||
|
||||
@@ -106,14 +106,14 @@ public abstract class AbstractExceptions{
|
||||
*
|
||||
* @param packageString group package name to register
|
||||
*/
|
||||
public static void registerGroupPackage(final String packageString){
|
||||
public static void registerGroupPackage(final String packageString) {
|
||||
groupPackageSet.add(packageString);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Clears previously registered group packages.
|
||||
*/
|
||||
public static void clearGroupPackages(){
|
||||
public static void clearGroupPackages() {
|
||||
groupPackageSet.clear();
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ public abstract class AbstractExceptions{
|
||||
*
|
||||
* @return current stack trace serializer implementation
|
||||
*/
|
||||
public static StackTraceElementSerializer getStackTraceElementSerializer(){
|
||||
public static StackTraceElementSerializer getStackTraceElementSerializer() {
|
||||
return stackTraceElementSerializer;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ public abstract class AbstractExceptions{
|
||||
*
|
||||
* @param stackTraceElementSerializer new stack trace serializer implementation
|
||||
*/
|
||||
public static void setStackTraceElementSerializer(final StackTraceElementSerializer stackTraceElementSerializer){
|
||||
public static void setStackTraceElementSerializer(final StackTraceElementSerializer stackTraceElementSerializer) {
|
||||
AbstractExceptions.stackTraceElementSerializer = stackTraceElementSerializer;
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ public abstract class AbstractExceptions{
|
||||
* @param packageString ignore package name to register
|
||||
* @param ignoreCauseClasses ignore cause classes from this package too
|
||||
*/
|
||||
public static void registerIgnorePackage(final String packageString, final boolean ignoreCauseClasses){
|
||||
public static void registerIgnorePackage(final String packageString, final boolean ignoreCauseClasses) {
|
||||
ignorePackageSet.add(packageString);
|
||||
if (ignoreCauseClasses) {
|
||||
ignoreCausePackageSet.add(packageString);
|
||||
@@ -153,7 +153,7 @@ public abstract class AbstractExceptions{
|
||||
/**
|
||||
* <p>Clears previously registered ignore packages.
|
||||
*/
|
||||
public static void clearIgnorePackages(){
|
||||
public static void clearIgnorePackages() {
|
||||
ignorePackageSet.clear();
|
||||
ignoreCausePackageSet.clear();
|
||||
}
|
||||
@@ -165,7 +165,7 @@ public abstract class AbstractExceptions{
|
||||
* converted to string will not include causes. If value is false causes will be appended to the stack trace of
|
||||
* the main throwable.
|
||||
*/
|
||||
public static boolean getIgnoreAllCauses(){
|
||||
public static boolean getIgnoreAllCauses() {
|
||||
return ignoreAllCauses;
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ public abstract class AbstractExceptions{
|
||||
* or converted to string will not include causes. If value is false causes will be appended to the stack trace of
|
||||
* the main throwable.
|
||||
*/
|
||||
public static void setIgnoreAllCauses(final boolean ignoreAllCauses){
|
||||
public static void setIgnoreAllCauses(final boolean ignoreAllCauses) {
|
||||
AbstractExceptions.ignoreAllCauses = ignoreAllCauses;
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ public abstract class AbstractExceptions{
|
||||
* @param throwable parent throwable
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable){
|
||||
public static String getStackTraceString(final Throwable throwable) {
|
||||
return getStackTraceString(throwable, false, rootPackageSet, groupPackageSet, ignorePackageSet, 0, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ public abstract class AbstractExceptions{
|
||||
* @param ignoreAllCauses ignore all causes in the exception chain
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final boolean ignoreAllCauses){
|
||||
public static String getStackTraceString(final Throwable throwable, final boolean ignoreAllCauses) {
|
||||
return getStackTraceString(throwable, false, rootPackageSet, groupPackageSet, ignorePackageSet, 0, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ public abstract class AbstractExceptions{
|
||||
* @param ignorePackageSet ignore packages to use for building the stack trace
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet){
|
||||
public static String getStackTraceString(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet) {
|
||||
return getStackTraceString(throwable, false, rootPackageSet, groupPackageSet, ignorePackageSet, 0, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ public abstract class AbstractExceptions{
|
||||
* @param ignoreAllCauses ignore all causes in the exception chain
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet, final boolean ignoreAllCauses){
|
||||
public static String getStackTraceString(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet, final boolean ignoreAllCauses) {
|
||||
return getStackTraceString(throwable, false, rootPackageSet, groupPackageSet, ignorePackageSet, 0, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ public abstract class AbstractExceptions{
|
||||
* @param rootPackage root package to use for building the stack trace
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final String rootPackage){
|
||||
public static String getStackTraceString(final Throwable throwable, final String rootPackage) {
|
||||
return getStackTraceString(throwable, false, Collections.singleton(rootPackage), new HashSet<String>(), new HashSet<String>(), 0, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ public abstract class AbstractExceptions{
|
||||
* @param groupPackage group package to use for building the stack trace
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final String rootPackage, final String groupPackage){
|
||||
public static String getStackTraceString(final Throwable throwable, final String rootPackage, final String groupPackage) {
|
||||
return getStackTraceString(throwable, false, Collections.singleton(rootPackage), Collections.singleton(groupPackage), new HashSet<String>(), 0, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ public abstract class AbstractExceptions{
|
||||
* @param maxDepth max depth in exception chain that will be used
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final int maxDepth){
|
||||
public static String getStackTraceString(final Throwable throwable, final int maxDepth) {
|
||||
return getStackTraceString(throwable, false, new HashSet<String>(), new HashSet<String>(), new HashSet<String>(), maxDepth, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ public abstract class AbstractExceptions{
|
||||
* @param ignoreAllCauses ignore all causes in the exception chain
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final int maxDepth, final boolean ignoreAllCauses){
|
||||
public static String getStackTraceString(final Throwable throwable, final int maxDepth, final boolean ignoreAllCauses) {
|
||||
return getStackTraceString(throwable, false, new HashSet<String>(), new HashSet<String>(), new HashSet<String>(), maxDepth, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ public abstract class AbstractExceptions{
|
||||
* @param ignoreAllCauses ignore all causes in the exception chain
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final boolean isCause, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet, final int maxDepth, final boolean ignoreAllCauses){
|
||||
public static String getStackTraceString(final Throwable throwable, final boolean isCause, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet, final int maxDepth, final boolean ignoreAllCauses) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
||||
if (throwable == null) {
|
||||
@@ -386,7 +386,7 @@ public abstract class AbstractExceptions{
|
||||
* @param firstStackTraceElementInTheGroup first stack trace element of this group
|
||||
* @return new value for the group element count
|
||||
*/
|
||||
public static int appendStackTraceGroupElement(final StringBuilder stringBuilder, final String currentGroupPackage, final int numberOfElementsInTheCurrentGroup, final StackTraceElement firstStackTraceElementInTheGroup){
|
||||
public static int appendStackTraceGroupElement(final StringBuilder stringBuilder, final String currentGroupPackage, final int numberOfElementsInTheCurrentGroup, final StackTraceElement firstStackTraceElementInTheGroup) {
|
||||
if (numberOfElementsInTheCurrentGroup > 0) {
|
||||
if (stackTraceElementSerializer == null) {
|
||||
throw new IllegalArgumentException("Stack trace element serializer not initialized.");
|
||||
@@ -407,7 +407,7 @@ public abstract class AbstractExceptions{
|
||||
* @return true if package of the given class name matches one of package names provided in <code>packageSet</code>,
|
||||
* false otherwise
|
||||
*/
|
||||
public static boolean containsPackage(final String fullClassName, final Set<String> packageSet){
|
||||
public static boolean containsPackage(final String fullClassName, final Set<String> packageSet) {
|
||||
return getContainingPackage(fullClassName, packageSet) != null;
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ public abstract class AbstractExceptions{
|
||||
* @return one of the package names in the <code>packageSet</code> that matches the package of the given class name
|
||||
* or null if no matching package name is found in the <code>packageSet</code>
|
||||
*/
|
||||
public static String getContainingPackage(final String fullClassName, final Set<String> packageSet){
|
||||
public static String getContainingPackage(final String fullClassName, final Set<String> packageSet) {
|
||||
for (final String parentExceptionPackage : packageSet) {
|
||||
if (fullClassName.startsWith(parentExceptionPackage)) {
|
||||
return parentExceptionPackage;
|
||||
@@ -436,7 +436,7 @@ public abstract class AbstractExceptions{
|
||||
* @param throwable parent throwable
|
||||
* @return a string containing all messages found in the exception chain
|
||||
*/
|
||||
public static String getAllMessages(final Throwable throwable){
|
||||
public static String getAllMessages(final Throwable throwable) {
|
||||
final StringBuilder messageBuilder = new StringBuilder();
|
||||
getAllMessages(throwable, messageBuilder);
|
||||
return messageBuilder.toString();
|
||||
@@ -448,7 +448,7 @@ public abstract class AbstractExceptions{
|
||||
* @param throwable parent throwable
|
||||
* @param messageBuilder message builder
|
||||
*/
|
||||
public static void getAllMessages(final Throwable throwable, final StringBuilder messageBuilder){
|
||||
public static void getAllMessages(final Throwable throwable, final StringBuilder messageBuilder) {
|
||||
if (throwable != null) {
|
||||
final String message = throwable.getMessage();
|
||||
if (!isEmpty(message)) {
|
||||
@@ -470,7 +470,7 @@ public abstract class AbstractExceptions{
|
||||
* @param maxDepth max depth in exception chain that will be returned
|
||||
* @return an array containing stack trace elements
|
||||
*/
|
||||
public static StackTraceElement[] getStackTrace(final Throwable throwable, final int maxDepth){
|
||||
public static StackTraceElement[] getStackTrace(final Throwable throwable, final int maxDepth) {
|
||||
final ArrayList<StackTraceElement> list = new ArrayList<StackTraceElement>();
|
||||
|
||||
if (throwable != null) {
|
||||
@@ -492,7 +492,7 @@ public abstract class AbstractExceptions{
|
||||
* @param ignorePackageSet ignore packages to use for building the stack trace
|
||||
* @return an array containing stack trace elements
|
||||
*/
|
||||
public static StackTraceElement[] getStackTrace(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> ignorePackageSet){
|
||||
public static StackTraceElement[] getStackTrace(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> ignorePackageSet) {
|
||||
final ArrayList<StackTraceElement> list = new ArrayList<StackTraceElement>();
|
||||
final ArrayList<StackTraceElement> partialList = new ArrayList<StackTraceElement>();
|
||||
|
||||
@@ -529,7 +529,7 @@ public abstract class AbstractExceptions{
|
||||
* @return true if the given cause class is found in the exception chain of the <code>throwable</code>, false
|
||||
* otherwise
|
||||
*/
|
||||
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass){
|
||||
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass) {
|
||||
return containsCause(throwable, causeClass, null);
|
||||
}
|
||||
|
||||
@@ -547,7 +547,7 @@ public abstract class AbstractExceptions{
|
||||
* @return true if the given cause class and cause message is found in the exception chain of the
|
||||
* <code>throwable</code>, false otherwise
|
||||
*/
|
||||
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage){
|
||||
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage) {
|
||||
return (searchCause(throwable, causeClass, causeMessage, DEFAULT_MAX_DEPTH) != null);
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ public abstract class AbstractExceptions{
|
||||
* @param throwable parent throwable
|
||||
* @return the cause of the <code>throwable</code> found or null if <code>throwable</code> does not have a cause
|
||||
*/
|
||||
public static Throwable getCause(final Throwable throwable){
|
||||
public static Throwable getCause(final Throwable throwable) {
|
||||
return getCause(throwable, DEFAULT_MAX_DEPTH);
|
||||
}
|
||||
|
||||
@@ -573,7 +573,7 @@ public abstract class AbstractExceptions{
|
||||
* @return the cause of the <code>throwable</code> found until <code>maxDepth</code> is reached in the exception
|
||||
* chain or null if <code>throwable</code> does not have a cause
|
||||
*/
|
||||
public static Throwable getCause(final Throwable throwable, final int maxDepth){
|
||||
public static Throwable getCause(final Throwable throwable, final int maxDepth) {
|
||||
if (throwable == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -601,7 +601,7 @@ public abstract class AbstractExceptions{
|
||||
* @param causeClass class to search for
|
||||
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
|
||||
*/
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass){
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass) {
|
||||
return searchCause(throwable, causeClass, null, DEFAULT_MAX_DEPTH);
|
||||
}
|
||||
|
||||
@@ -618,7 +618,7 @@ public abstract class AbstractExceptions{
|
||||
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
|
||||
* and cause message
|
||||
*/
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage){
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage) {
|
||||
return searchCause(throwable, causeClass, causeMessage, DEFAULT_MAX_DEPTH);
|
||||
}
|
||||
|
||||
@@ -636,7 +636,7 @@ public abstract class AbstractExceptions{
|
||||
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
|
||||
* and cause message
|
||||
*/
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage, final int maxDepth){
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage, final int maxDepth) {
|
||||
if (throwable == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -675,7 +675,7 @@ public abstract class AbstractExceptions{
|
||||
* @param maxDepth max depth in exception chain that will be searched
|
||||
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
|
||||
*/
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final int maxDepth){
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final int maxDepth) {
|
||||
if (throwable == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -702,7 +702,7 @@ public abstract class AbstractExceptions{
|
||||
* @param value string to check
|
||||
* @return true if given string is null or has zero length after trim(), false otherwise
|
||||
*/
|
||||
public static boolean isEmpty(final String value){
|
||||
public static boolean isEmpty(final String value) {
|
||||
if (value == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -716,7 +716,7 @@ public abstract class AbstractExceptions{
|
||||
* @param className fully qualified class name
|
||||
* @return name of the package
|
||||
*/
|
||||
public static String packageName(final String className){
|
||||
public static String packageName(final String className) {
|
||||
if (className == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ package com.arthenica.smartexception;
|
||||
* @author Taner Sener
|
||||
* @since 0.1.0
|
||||
*/
|
||||
public interface StackTraceElementSerializer{
|
||||
public interface StackTraceElementSerializer {
|
||||
|
||||
/**
|
||||
* <p>Converts the given <code>stackTraceElement</code> into a string.
|
||||
|
||||
@@ -44,13 +44,13 @@ import java.util.Set;
|
||||
* @author Taner Sener
|
||||
* @since 0.1.0
|
||||
*/
|
||||
public class Exceptions{
|
||||
public class Exceptions {
|
||||
|
||||
static{
|
||||
AbstractExceptions.setStackTraceElementSerializer(new StackTraceElementSerializer(){
|
||||
static {
|
||||
AbstractExceptions.setStackTraceElementSerializer(new StackTraceElementSerializer() {
|
||||
|
||||
@Override
|
||||
public String toString(StackTraceElement stackTraceElement){
|
||||
public String toString(StackTraceElement stackTraceElement) {
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
stringBuilder.append(stackTraceElement.getClassName());
|
||||
@@ -75,17 +75,17 @@ public class Exceptions{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModuleName(StackTraceElement stackTraceElement){
|
||||
public String getModuleName(StackTraceElement stackTraceElement) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNativeMethodDefinition(){
|
||||
public String getNativeMethodDefinition() {
|
||||
return "(Native Method)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUnknownSourceDefinition(){
|
||||
public String getUnknownSourceDefinition() {
|
||||
return "(Unknown Source)";
|
||||
}
|
||||
});
|
||||
@@ -96,14 +96,14 @@ public class Exceptions{
|
||||
*
|
||||
* @param packageString root package name to register
|
||||
*/
|
||||
public static void registerRootPackage(final String packageString){
|
||||
public static void registerRootPackage(final String packageString) {
|
||||
AbstractExceptions.registerRootPackage(packageString);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Clears previously registered root packages.
|
||||
*/
|
||||
public static void clearRootPackages(){
|
||||
public static void clearRootPackages() {
|
||||
AbstractExceptions.clearRootPackages();
|
||||
}
|
||||
|
||||
@@ -112,14 +112,14 @@ public class Exceptions{
|
||||
*
|
||||
* @param packageString group package name to register
|
||||
*/
|
||||
public static void registerGroupPackage(final String packageString){
|
||||
public static void registerGroupPackage(final String packageString) {
|
||||
AbstractExceptions.registerGroupPackage(packageString);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Clears previously registered group packages.
|
||||
*/
|
||||
public static void clearGroupPackages(){
|
||||
public static void clearGroupPackages() {
|
||||
AbstractExceptions.clearGroupPackages();
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public class Exceptions{
|
||||
*
|
||||
* @return current stack trace serializer implementation
|
||||
*/
|
||||
public static StackTraceElementSerializer getStackTraceElementSerializer(){
|
||||
public static StackTraceElementSerializer getStackTraceElementSerializer() {
|
||||
return AbstractExceptions.getStackTraceElementSerializer();
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ public class Exceptions{
|
||||
*
|
||||
* @param stackTraceElementSerializer new stack trace serializer implementation
|
||||
*/
|
||||
public static void setStackTraceElementSerializer(final StackTraceElementSerializer stackTraceElementSerializer){
|
||||
public static void setStackTraceElementSerializer(final StackTraceElementSerializer stackTraceElementSerializer) {
|
||||
AbstractExceptions.setStackTraceElementSerializer(stackTraceElementSerializer);
|
||||
}
|
||||
|
||||
@@ -149,14 +149,14 @@ public class Exceptions{
|
||||
* @param packageString ignore package name to register
|
||||
* @param ignoreCauseClasses ignore cause classes from this package too
|
||||
*/
|
||||
public static void registerIgnorePackage(final String packageString, final boolean ignoreCauseClasses){
|
||||
public static void registerIgnorePackage(final String packageString, final boolean ignoreCauseClasses) {
|
||||
AbstractExceptions.registerIgnorePackage(packageString, ignoreCauseClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Clears previously registered ignore packages.
|
||||
*/
|
||||
public static void clearIgnorePackages(){
|
||||
public static void clearIgnorePackages() {
|
||||
AbstractExceptions.clearIgnorePackages();
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ public class Exceptions{
|
||||
* converted to string will not include causes. If value is false causes will be appended to the stack trace of
|
||||
* the main throwable.
|
||||
*/
|
||||
public static boolean getIgnoreAllCauses(){
|
||||
public static boolean getIgnoreAllCauses() {
|
||||
return AbstractExceptions.getIgnoreAllCauses();
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ public class Exceptions{
|
||||
* or converted to string will not include causes. If value is false causes will be appended to the stack trace of
|
||||
* the main throwable.
|
||||
*/
|
||||
public static void setIgnoreAllCauses(final boolean ignoreAllCauses){
|
||||
public static void setIgnoreAllCauses(final boolean ignoreAllCauses) {
|
||||
AbstractExceptions.setIgnoreAllCauses(ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ public class Exceptions{
|
||||
* @param throwable parent throwable
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable){
|
||||
public static String getStackTraceString(final Throwable throwable) {
|
||||
return AbstractExceptions.getStackTraceString(throwable);
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ public class Exceptions{
|
||||
* @param ignoreAllCauses ignore all causes in the exception chain
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final boolean ignoreAllCauses){
|
||||
public static String getStackTraceString(final Throwable throwable, final boolean ignoreAllCauses) {
|
||||
return AbstractExceptions.getStackTraceString(throwable, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ public class Exceptions{
|
||||
* @param ignorePackageSet ignore packages to use for building the stack trace
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet){
|
||||
public static String getStackTraceString(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet) {
|
||||
return AbstractExceptions.getStackTraceString(throwable, rootPackageSet, groupPackageSet, ignorePackageSet);
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ public class Exceptions{
|
||||
* @param ignoreAllCauses ignore all causes in the exception chain
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet, final boolean ignoreAllCauses){
|
||||
public static String getStackTraceString(final Throwable throwable, final Set<String> rootPackageSet, final Set<String> groupPackageSet, final Set<String> ignorePackageSet, final boolean ignoreAllCauses) {
|
||||
return AbstractExceptions.getStackTraceString(throwable, rootPackageSet, groupPackageSet, ignorePackageSet, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ public class Exceptions{
|
||||
* @param rootPackage root package to use for building the stack trace
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final String rootPackage){
|
||||
public static String getStackTraceString(final Throwable throwable, final String rootPackage) {
|
||||
return AbstractExceptions.getStackTraceString(throwable, rootPackage);
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ public class Exceptions{
|
||||
* @param groupPackage group package to use for building the stack trace
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final String rootPackage, final String groupPackage){
|
||||
public static String getStackTraceString(final Throwable throwable, final String rootPackage, final String groupPackage) {
|
||||
return AbstractExceptions.getStackTraceString(throwable, rootPackage, groupPackage);
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ public class Exceptions{
|
||||
* @param maxDepth max depth in exception chain that will be used
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final int maxDepth){
|
||||
public static String getStackTraceString(final Throwable throwable, final int maxDepth) {
|
||||
return AbstractExceptions.getStackTraceString(throwable, maxDepth);
|
||||
}
|
||||
|
||||
@@ -280,7 +280,7 @@ public class Exceptions{
|
||||
* @param ignoreAllCauses ignore all causes in the exception chain
|
||||
* @return a string containing the smart stack trace for the given <code>throwable</code>
|
||||
*/
|
||||
public static String getStackTraceString(final Throwable throwable, final int maxDepth, final boolean ignoreAllCauses){
|
||||
public static String getStackTraceString(final Throwable throwable, final int maxDepth, final boolean ignoreAllCauses) {
|
||||
return AbstractExceptions.getStackTraceString(throwable, maxDepth, ignoreAllCauses);
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ public class Exceptions{
|
||||
* @param throwable parent throwable
|
||||
* @return a string containing all messages found in the exception chain
|
||||
*/
|
||||
public static String getAllMessages(final Throwable throwable){
|
||||
public static String getAllMessages(final Throwable throwable) {
|
||||
return AbstractExceptions.getAllMessages(throwable);
|
||||
}
|
||||
|
||||
@@ -306,7 +306,7 @@ public class Exceptions{
|
||||
* @return true if the given cause class is found in the exception chain of the <code>throwable</code>, false
|
||||
* otherwise
|
||||
*/
|
||||
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass){
|
||||
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass) {
|
||||
return AbstractExceptions.containsCause(throwable, causeClass);
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ public class Exceptions{
|
||||
* @return true if the given cause class and cause message is found in the exception chain of the
|
||||
* <code>throwable</code>, false otherwise
|
||||
*/
|
||||
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage){
|
||||
public static boolean containsCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage) {
|
||||
return AbstractExceptions.containsCause(throwable, causeClass, causeMessage);
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ public class Exceptions{
|
||||
* @param throwable parent throwable
|
||||
* @return the cause of the <code>throwable</code> found or null if <code>throwable</code> does not have a cause
|
||||
*/
|
||||
public static Throwable getCause(final Throwable throwable){
|
||||
public static Throwable getCause(final Throwable throwable) {
|
||||
return AbstractExceptions.getCause(throwable);
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ public class Exceptions{
|
||||
* @return the cause of the <code>throwable</code> found until <code>maxDepth</code> is reached in the exception
|
||||
* chain or null if <code>throwable</code> does not have a cause
|
||||
*/
|
||||
public static Throwable getCause(final Throwable throwable, final int maxDepth){
|
||||
public static Throwable getCause(final Throwable throwable, final int maxDepth) {
|
||||
return AbstractExceptions.getCause(throwable, maxDepth);
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ public class Exceptions{
|
||||
* @param causeClass class to search for
|
||||
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
|
||||
*/
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass){
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass) {
|
||||
return AbstractExceptions.searchCause(throwable, causeClass);
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ public class Exceptions{
|
||||
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
|
||||
* and cause message
|
||||
*/
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage){
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage) {
|
||||
return AbstractExceptions.searchCause(throwable, causeClass, causeMessage);
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ public class Exceptions{
|
||||
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
|
||||
* and cause message
|
||||
*/
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage, final int maxDepth){
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final String causeMessage, final int maxDepth) {
|
||||
return AbstractExceptions.searchCause(throwable, causeClass, causeMessage, maxDepth);
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ public class Exceptions{
|
||||
* @param maxDepth max depth in exception chain that will be searched
|
||||
* @return the <code>throwable</code> found or null if no class in exception chain matches the given cause class
|
||||
*/
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final int maxDepth){
|
||||
public static Throwable searchCause(final Throwable throwable, final Class<?> causeClass, final int maxDepth) {
|
||||
return AbstractExceptions.searchCause(throwable, causeClass, maxDepth);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.vk.api.gifts;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.vk.api.base.ApiRequest;
|
||||
import com.vk.dto.gift.CatalogedGift;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class GiftGetByStickerId extends ApiRequest<GiftGetByStickerId.a> {
|
||||
public static class a {
|
||||
public final int a;
|
||||
public final CatalogedGift b;
|
||||
|
||||
public a(int i, CatalogedGift catalogedGift) {
|
||||
this.a = i;
|
||||
this.b = catalogedGift;
|
||||
}
|
||||
}
|
||||
|
||||
public GiftGetByStickerId(Context context, int i) {
|
||||
super("execute.getGiftByStickerId");
|
||||
b("sticker_id", i);
|
||||
c("no_inapp", "0");
|
||||
b("force_payment", 1);
|
||||
}
|
||||
|
||||
@Override // com.vk.api.sdk.o.VKRequest
|
||||
public GiftGetByStickerId.a a(JSONObject jSONObject) throws JSONException {
|
||||
JSONObject jSONObject2 = jSONObject.getJSONObject("response");
|
||||
return new a(jSONObject2.optInt("balance"),
|
||||
new CatalogedGift(jSONObject2.getJSONObject("gift")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
package com.vk.core.util;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.Preferences.getDownloadsDir;
|
||||
import static ru.vtosters.lite.utils.Preferences.getMusicDir;
|
||||
import static ru.vtosters.lite.utils.Preferences.getPhotosDir;
|
||||
import static ru.vtosters.lite.utils.Preferences.getVideosDir;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.DownloadManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.common.i.MediaUtils;
|
||||
import com.facebook.x.g.EncodedImage;
|
||||
import com.vk.core.concurrent.VkExecutors;
|
||||
import com.vk.imageloader.VKImageLoader;
|
||||
import com.vk.log.L;
|
||||
import com.vk.metrics.eventtracking.VkTracker;
|
||||
import com.vtosters.lite.MainActivity;
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.HashSet;
|
||||
|
||||
import b.h.g.m.CameraUtils;
|
||||
import b.h.g.m.FileUtils;
|
||||
|
||||
public class DownloadUtils {
|
||||
public static final HashSet<Long> a = new HashSet<>();
|
||||
|
||||
public static void a(Context context, String str, String str2) {
|
||||
a(context, str, str2, false);
|
||||
}
|
||||
|
||||
public static void b(Context context, String str, String str2) {
|
||||
a(context, str, str2, true);
|
||||
}
|
||||
|
||||
private static void a(Context context, String str, String str2, boolean z) {
|
||||
try {
|
||||
b(context, str, str2, z);
|
||||
} catch (Exception e2) {
|
||||
L.d(e2);
|
||||
ToastUtils.a(context.getString(R.string.error) + " [" + e2.getMessage() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private static void b(final Context context, String str, String str2, boolean z) {
|
||||
if (TextUtils.isEmpty(str2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String file = a(str, str2);
|
||||
File b2;
|
||||
boolean pic = false;
|
||||
boolean c2 = MediaUtils.c(MediaUtils.b(str2));
|
||||
|
||||
if (file.endsWith(".jpg") || file.endsWith(".png") || file.endsWith(".jpeg")) {
|
||||
b2 = new File(getPhotosDir(), file);
|
||||
pic = true;
|
||||
} else if (file.endsWith(".mp3") || file.endsWith(".wav") || file.endsWith(".ogg") || file.endsWith(".aac") || file.endsWith(".flac") || file.endsWith(".m4a")) {
|
||||
b2 = new File(getMusicDir(), file);
|
||||
} else if (file.endsWith(".mp4") || file.endsWith(".mkv") || file.endsWith(".avi") || file.endsWith(".flv") || file.endsWith(".wmv") || file.endsWith(".mov") || file.endsWith(".3gp")) {
|
||||
b2 = new File(getVideosDir(), file);
|
||||
} else {
|
||||
b2 = new File(getDownloadsDir(), file);
|
||||
}
|
||||
|
||||
if (c2) {
|
||||
EncodedImage c3 = VKImageLoader.c(Uri.parse(str2));
|
||||
final InputStream h = c3 == null ? null : c3.h();
|
||||
if (h != null) {
|
||||
try {
|
||||
if (b2.getParentFile() != null) {
|
||||
b2.createNewFile();
|
||||
}
|
||||
|
||||
if (b2.exists()) {
|
||||
VkExecutors.x.a().execute(() -> ToastUtils.a(context.getString(R.string.file_saved, b2.getAbsoluteFile())));
|
||||
}
|
||||
|
||||
} catch (Exception e2) {
|
||||
L.a(e2);
|
||||
}
|
||||
|
||||
CameraUtils.a(context, b2, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(str2));
|
||||
request.setDestinationUri(Uri.fromFile(b2));
|
||||
request.setMimeType(FileUtils.f(new File(str)));
|
||||
request.setNotificationVisibility(1);
|
||||
request.allowScanningByMediaScanner();
|
||||
request.setTitle(str);
|
||||
DownloadManager a2 = a(context);
|
||||
if (a2 == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
long enqueue = a2.enqueue(request);
|
||||
if (pic) {
|
||||
CameraUtils.a(context, b2, null);
|
||||
}
|
||||
if (!z) {
|
||||
return;
|
||||
}
|
||||
a.add(enqueue);
|
||||
} catch (IllegalArgumentException e3) {
|
||||
L.a(e3);
|
||||
b(context);
|
||||
}
|
||||
}
|
||||
|
||||
private static String a(String str, String str2) {
|
||||
String lastPathSegment = Uri.parse(str2).getLastPathSegment();
|
||||
if (!TextUtils.isEmpty(str)) {
|
||||
String replace = str.replace('/', '_');
|
||||
return !replace.contains(".") ? lastPathSegment : replace;
|
||||
}
|
||||
return lastPathSegment;
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("Range")
|
||||
public static boolean a(Context context, Uri uri) {
|
||||
try {
|
||||
Cursor query = a(context).query(new DownloadManager.Query().setFilterByStatus(11));
|
||||
if (query != null && query.moveToFirst()) {
|
||||
while (!uri.toString().equals(query.getString(query.getColumnIndex("uri")))) {
|
||||
if (!query.moveToNext()) {
|
||||
query.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@SuppressLint("Range")
|
||||
int i = query.getInt(query.getColumnIndex("status"));
|
||||
@SuppressLint("Range")
|
||||
String string = query.getString(query.getColumnIndex("local_uri"));
|
||||
query.close();
|
||||
if (i == 1 || i == 2) {
|
||||
ToastUtils.a(R.string.download_is_in_progress);
|
||||
query.close();
|
||||
return true;
|
||||
} else if (i != 8) {
|
||||
query.close();
|
||||
return false;
|
||||
} else {
|
||||
boolean a2 = a(context, string);
|
||||
query.close();
|
||||
return a2;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (SQLiteException e2) {
|
||||
VkTracker.k.b(e2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void b(Context context) {
|
||||
if (context != null) {
|
||||
try {
|
||||
context.startActivity(new Intent("android.settings.APPLICATION_DETAILS_SETTINGS").setData(Uri.parse("package:com.android.providers.downloads")));
|
||||
} catch (ActivityNotFoundException e2) {
|
||||
L.a(e2);
|
||||
context.startActivity(new Intent("android.settings.MANAGE_APPLICATIONS_SETTINGS"));
|
||||
}
|
||||
ToastUtils.a("Please enable download manager", true);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean a(Context context, String str) {
|
||||
File file;
|
||||
try {
|
||||
try {
|
||||
file = new File(new URI(str));
|
||||
try {
|
||||
if (!file.exists()) {
|
||||
return false;
|
||||
}
|
||||
Intent intent = new Intent("android.intent.action.VIEW");
|
||||
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
String f2 = FileUtils.f(file);
|
||||
if (!TextUtils.isEmpty(f2)) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setDataAndType(FileUtils.uriFromFile(file), f2);
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
throw new ActivityNotFoundException();
|
||||
} catch (ActivityNotFoundException unused) {
|
||||
return a(context, file);
|
||||
}
|
||||
} catch (ActivityNotFoundException unused2) {
|
||||
unused2.printStackTrace();
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
VkTracker.k.b(th);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean a(Context context, File file) {
|
||||
if (file != null && file.exists()) {
|
||||
Intent intent = new Intent("android.intent.action.VIEW");
|
||||
intent.setDataAndType(Uri.parse(file.getAbsolutePath()), "application/*");
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
try {
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e2) {
|
||||
L.a(e2);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static DownloadManager a(Context context) {
|
||||
return (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.vk.im.ui.components.common;
|
||||
|
||||
public enum DialogAction {
|
||||
OPEN_USER_PROFILE,
|
||||
OPEN_GROUP_PROFILE,
|
||||
CHAT_SETTINGS,
|
||||
SEARCH,
|
||||
ADD_CHAT_MEMBER,
|
||||
CREATE_SHORTCUT,
|
||||
PINNED_MSG_HIDE,
|
||||
PINNED_MSG_SHOW,
|
||||
PINNED_MSG_DETACH,
|
||||
SHOW_ATTACHES,
|
||||
NOTIFICATIONS_ON,
|
||||
NOTIFICATIONS_OFF,
|
||||
GROUP_RECEIVE_MSGS_ENABLE,
|
||||
GROUP_RECEIVE_MSGS_DISABLE,
|
||||
GROUP_RECEIVE_NOTIFY_DISABLE,
|
||||
CHANNEL_INVITE_LINK,
|
||||
CLEAR_HISTORY,
|
||||
CLEAR_HISTORY_AND_LEAVE,
|
||||
LEAVE,
|
||||
LEAVE_CHANNEL,
|
||||
RETURN,
|
||||
RETURN_TO_CHANNEL,
|
||||
MARK_AS_READ,
|
||||
AUDIO_BTN_AUDIO_CALL,
|
||||
AUDIO_BTN_VIDEO_CALL,
|
||||
VIDEO_BTN_VIDEO_CALL,
|
||||
VIDEO_BTN_AUDIO_CALL,
|
||||
DNR_ON,
|
||||
DNR_OFF,
|
||||
DNT_ON,
|
||||
DNT_OFF,
|
||||
pinmsg,
|
||||
unpinmsg,
|
||||
ENCRYPT_SETT,
|
||||
ENCRYPT
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package com.vk.im.ui.components.common;
|
||||
|
||||
import com.vk.core.extensions.CollectionExt;
|
||||
import com.vk.core.network.TimeProvider;
|
||||
import com.vk.im.engine.ImConfig;
|
||||
import com.vk.im.engine.models.MemberType;
|
||||
import com.vk.im.engine.models.Profile;
|
||||
import com.vk.im.engine.models.ProfilesSimpleInfo;
|
||||
import com.vk.im.engine.models.dialogs.ChatSettings;
|
||||
import com.vk.im.engine.models.dialogs.Dialog;
|
||||
import com.vk.im.engine.models.groups.Group;
|
||||
import com.vk.im.engine.utils.DialogPermissionHelper;
|
||||
import com.vk.im.ui.p.ImBridge7;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ru.vtosters.lite.dnr.DNRInjector;
|
||||
|
||||
public final class DialogActionsHelper {
|
||||
public static final DialogActionsHelper a = new DialogActionsHelper();
|
||||
|
||||
public final List<DialogAction> a(ImConfig imConfig, Dialog dialog, ProfilesSimpleInfo profilesSimpleInfo) {
|
||||
if (dialog != null && profilesSimpleInfo != null) {
|
||||
long b2 = TimeProvider.f.b();
|
||||
ChatSettings z1 = dialog.z1();
|
||||
boolean z = false;
|
||||
boolean I1 = z1 != null && z1.I1();
|
||||
ArrayList<DialogAction> arrayList = new ArrayList<>();
|
||||
|
||||
DNRInjector.inject(dialog, arrayList);
|
||||
|
||||
arrayList.add(DialogAction.SEARCH);
|
||||
|
||||
if (dialog.S1()) {
|
||||
arrayList.add(DialogAction.SHOW_ATTACHES);
|
||||
}
|
||||
|
||||
if (!I1 && !dialog.W1()) {
|
||||
arrayList.add(DialogAction.CLEAR_HISTORY);
|
||||
}
|
||||
|
||||
if (I1) {
|
||||
arrayList.add(DialogAction.CHANNEL_INVITE_LINK);
|
||||
}
|
||||
|
||||
if (dialog.K1() != null) {
|
||||
CollectionExt.a(arrayList, DialogAction.PINNED_MSG_DETACH, !I1);
|
||||
CollectionExt.a(arrayList, DialogAction.PINNED_MSG_SHOW, !dialog.L1());
|
||||
CollectionExt.a(arrayList, DialogAction.PINNED_MSG_HIDE, dialog.L1());
|
||||
}
|
||||
|
||||
if (dialog.a(MemberType.USER)) {
|
||||
arrayList.add(DialogAction.OPEN_USER_PROFILE);
|
||||
}
|
||||
|
||||
if (dialog.a(MemberType.GROUP)) {
|
||||
arrayList.add(DialogAction.OPEN_GROUP_PROFILE);
|
||||
Group group = profilesSimpleInfo.w1().get(dialog.I1());
|
||||
if (group != null) {
|
||||
if (group.v1()) {
|
||||
arrayList.add(DialogAction.GROUP_RECEIVE_MSGS_DISABLE);
|
||||
} else {
|
||||
CollectionExt.a(arrayList, DialogAction.GROUP_RECEIVE_NOTIFY_DISABLE, group.w1());
|
||||
CollectionExt.a(arrayList, DialogAction.GROUP_RECEIVE_MSGS_ENABLE, !group.w1());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dialog.W1()) {
|
||||
DialogAction dialogAction = DialogAction.ADD_CHAT_MEMBER;
|
||||
ChatSettings z12 = dialog.z1();
|
||||
if (z12 != null) {
|
||||
z = z12.y1();
|
||||
}
|
||||
CollectionExt.a(arrayList, dialogAction, z);
|
||||
CollectionExt.a(arrayList, DialogAction.CHAT_SETTINGS, DialogPermissionHelper.a.a(dialog));
|
||||
}
|
||||
|
||||
CollectionExt.a(arrayList, DialogAction.NOTIFICATIONS_ON, !dialog.b(b2));
|
||||
CollectionExt.a(arrayList, DialogAction.NOTIFICATIONS_OFF, dialog.b(b2));
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public final List<DialogAction> a(Dialog dialog, ProfilesSimpleInfo profilesSimpleInfo) {
|
||||
long b2 = TimeProvider.f.b();
|
||||
Profile profile = profilesSimpleInfo.get(dialog.getId());
|
||||
|
||||
if (!(profile instanceof Group)) {
|
||||
profile = null;
|
||||
}
|
||||
|
||||
Group group = (Group) profile;
|
||||
ChatSettings z1 = dialog.z1();
|
||||
ArrayList<DialogAction> arrayList = new ArrayList<>();
|
||||
|
||||
DNRInjector.inject(dialog, arrayList);
|
||||
|
||||
// if (dialog.hasUnread()) {
|
||||
arrayList.add(DialogAction.MARK_AS_READ);
|
||||
// }
|
||||
|
||||
if (!dialog.W1()) {
|
||||
arrayList.add(DialogAction.CREATE_SHORTCUT);
|
||||
arrayList.add(DialogAction.CLEAR_HISTORY);
|
||||
CollectionExt.a(arrayList, DialogAction.NOTIFICATIONS_OFF, dialog.b(b2));
|
||||
CollectionExt.a(arrayList, DialogAction.NOTIFICATIONS_ON, !dialog.b(b2));
|
||||
}
|
||||
|
||||
if (dialog.a(MemberType.GROUP) && group != null) {
|
||||
if (group.v1()) {
|
||||
arrayList.add(DialogAction.GROUP_RECEIVE_MSGS_DISABLE);
|
||||
} else {
|
||||
CollectionExt.a(arrayList, DialogAction.GROUP_RECEIVE_NOTIFY_DISABLE, group.w1());
|
||||
CollectionExt.a(arrayList, DialogAction.GROUP_RECEIVE_MSGS_ENABLE, !group.w1());
|
||||
}
|
||||
}
|
||||
|
||||
if (dialog.W1() && z1 != null) {
|
||||
if (!z1.L1()) {
|
||||
arrayList.add(DialogAction.CREATE_SHORTCUT);
|
||||
CollectionExt.a(arrayList, DialogAction.NOTIFICATIONS_OFF, dialog.b(b2));
|
||||
CollectionExt.a(arrayList, DialogAction.NOTIFICATIONS_ON, !dialog.b(b2));
|
||||
}
|
||||
CollectionExt.a(arrayList, DialogAction.CLEAR_HISTORY, z1.L1());
|
||||
if (z1.I1()) {
|
||||
CollectionExt.a(arrayList, DialogAction.LEAVE_CHANNEL, !z1.L1());
|
||||
CollectionExt.a(arrayList, DialogAction.RETURN_TO_CHANNEL, z1.L1());
|
||||
} else {
|
||||
CollectionExt.a(arrayList, DialogAction.RETURN, z1.L1());
|
||||
CollectionExt.a(arrayList, DialogAction.LEAVE, !z1.L1());
|
||||
CollectionExt.a(arrayList, DialogAction.CLEAR_HISTORY_AND_LEAVE, !z1.L1());
|
||||
}
|
||||
}
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
public final boolean a(Dialog dialog) {
|
||||
if (dialog.V1() || !dialog.y1()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !dialog.U1() || !ImBridge7.a().a();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.vk.im.ui.components.common;
|
||||
|
||||
public enum MsgAction {
|
||||
RETRY,
|
||||
REPLY,
|
||||
FORWARD,
|
||||
COPY,
|
||||
EDIT,
|
||||
DELETE,
|
||||
SPAM,
|
||||
PIN,
|
||||
UNPIN,
|
||||
TRANSLATE,
|
||||
READTO
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.vk.im.ui.components.common;
|
||||
|
||||
import com.vk.core.extensions.CollectionExt;
|
||||
import com.vk.im.engine.ImConfig;
|
||||
import com.vk.im.engine.ImEngine;
|
||||
import com.vk.im.engine.models.dialogs.Dialog;
|
||||
import com.vk.im.engine.models.messages.Msg;
|
||||
import com.vk.im.engine.utils.MsgPermissionHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public final class MsgActionHelper {
|
||||
public static final MsgActionHelper a = new MsgActionHelper();
|
||||
|
||||
public final List<MsgAction> a(ImEngine imEngine, Dialog dialog, Collection<? extends Msg> collection) {
|
||||
return a(imEngine != null ? imEngine.g() : null, dialog, collection);
|
||||
}
|
||||
|
||||
public final List<MsgAction> a(ImConfig imConfig, Dialog dialog, Collection<? extends Msg> collection) {
|
||||
if (imConfig != null && dialog != null && collection != null) {
|
||||
MsgPermissionHelper.a aVar = new MsgPermissionHelper.a(imConfig, dialog, collection);
|
||||
ArrayList<MsgAction> arrayList = new ArrayList<>();
|
||||
|
||||
CollectionExt.a(arrayList, MsgAction.RETRY, MsgPermissionHelper.b.g(aVar));
|
||||
CollectionExt.a(arrayList, MsgAction.REPLY, MsgPermissionHelper.b.f(aVar));
|
||||
CollectionExt.a(arrayList, MsgAction.FORWARD, MsgPermissionHelper.b.d(aVar));
|
||||
CollectionExt.a(arrayList, MsgAction.COPY, MsgPermissionHelper.b.a(aVar));
|
||||
CollectionExt.a(arrayList, MsgAction.EDIT, MsgPermissionHelper.b.c(aVar));
|
||||
CollectionExt.a(arrayList, MsgAction.DELETE, MsgPermissionHelper.b.b(aVar));
|
||||
CollectionExt.a(arrayList, MsgAction.SPAM, MsgPermissionHelper.b.h(aVar));
|
||||
CollectionExt.a(arrayList, MsgAction.PIN, MsgPermissionHelper.b.e(aVar));
|
||||
CollectionExt.a(arrayList, MsgAction.UNPIN, MsgPermissionHelper.b.i(aVar));
|
||||
CollectionExt.a(arrayList, MsgAction.TRANSLATE, true);
|
||||
CollectionExt.a(arrayList, MsgAction.READTO, true);
|
||||
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.vk.im.ui.views;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class Corners{
|
||||
private int topLeft;
|
||||
private int topRight;
|
||||
private int bottomLeft;
|
||||
private int bottomRight;
|
||||
|
||||
public Corners(int i, int i2, int i3, int i4){
|
||||
this.topLeft = i;
|
||||
this.topRight = i2;
|
||||
this.bottomLeft = i3;
|
||||
this.bottomRight = i4;
|
||||
}
|
||||
|
||||
public Corners(int i, int i2, int i3, int i4, int i5) {
|
||||
this((i5 & 1) != 0 ? 0 : i, (i5 & 2) != 0 ? 0 : i2, (i5 & 4) != 0 ? 0 : i3, (i5 & 8) != 0 ? 0 : i4);
|
||||
}
|
||||
|
||||
public Corners() {
|
||||
this(0, 0, 0, 0, 15);
|
||||
}
|
||||
|
||||
public static Corners a(Corners corners, int i, int i2, int i3, int i4, int i5, Object obj){
|
||||
if ((i5 & 1) != 0) {
|
||||
i = corners.topLeft;
|
||||
}
|
||||
if ((i5 & 2) != 0) {
|
||||
i2 = corners.topRight;
|
||||
}
|
||||
if ((i5 & 4) != 0) {
|
||||
i3 = corners.bottomLeft;
|
||||
}
|
||||
if ((i5 & 8) != 0) {
|
||||
i4 = corners.bottomRight;
|
||||
}
|
||||
corners.a(i, i2, i3, i4);
|
||||
return corners;
|
||||
}
|
||||
|
||||
public int a(){
|
||||
return this.bottomLeft;
|
||||
}
|
||||
|
||||
public int b(){
|
||||
return this.bottomRight;
|
||||
}
|
||||
|
||||
public int c(){
|
||||
return this.topLeft;
|
||||
}
|
||||
|
||||
public int d(){
|
||||
return this.topRight;
|
||||
}
|
||||
|
||||
public boolean e(){
|
||||
int i;
|
||||
int i2 = this.topLeft;
|
||||
int i3 = this.topRight;
|
||||
return i2 == i3 && i3 == (i = this.bottomRight) && this.bottomLeft == i;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj){
|
||||
if (this != obj) {
|
||||
if (!(obj instanceof Corners)) {
|
||||
return false;
|
||||
}
|
||||
Corners corners = (Corners) obj;
|
||||
return this.topLeft == corners.topLeft && this.topRight == corners.topRight && this.bottomLeft == corners.bottomLeft && this.bottomRight == corners.bottomRight;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean f(){
|
||||
return this.topLeft == 0 && e();
|
||||
}
|
||||
|
||||
public void g(){
|
||||
a(0, 0);
|
||||
}
|
||||
|
||||
public int hashCode(){
|
||||
return (((((this.topLeft * 31) + this.topRight) * 31) + this.bottomLeft) * 31) + this.bottomRight;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String toString(){
|
||||
return "Corners(topLeft=" + this.topLeft + ", topRight=" + this.topRight + ", bottomLeft=" + this.bottomLeft + ", bottomRight=" + this.bottomRight + ")";
|
||||
}
|
||||
|
||||
public Corners a(int i, int i2){
|
||||
if ((i2 & 1) > 0) {
|
||||
this.topLeft = i;
|
||||
}
|
||||
if ((i2 & 2) > 0) {
|
||||
this.topRight = i;
|
||||
}
|
||||
if ((i2 & 4) > 0) {
|
||||
this.bottomLeft = i;
|
||||
}
|
||||
if ((i2 & 8) > 0) {
|
||||
this.bottomRight = i;
|
||||
}
|
||||
if (i2 == 0) {
|
||||
this.topLeft = 0;
|
||||
this.topRight = 0;
|
||||
this.bottomLeft = 0;
|
||||
this.bottomRight = 0;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Corners a(int i, int i2, int i3, int i4){
|
||||
this.topLeft = i;
|
||||
this.topRight = i2;
|
||||
this.bottomLeft = i3;
|
||||
this.bottomRight = i4;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Corners a(Corners corners){
|
||||
this.topLeft = corners.topLeft;
|
||||
this.topRight = corners.topRight;
|
||||
this.bottomLeft = corners.bottomLeft;
|
||||
this.bottomRight = corners.bottomRight;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.vk.im.ui.views.avatars;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Shader;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.vk.im.ui.o;
|
||||
|
||||
public class StoryBorderView extends View {
|
||||
private boolean B;
|
||||
private final Paint a;
|
||||
private LinearGradient f15747b;
|
||||
private int f15748c;
|
||||
private int f15749d;
|
||||
private int f15750e;
|
||||
private int f15751f;
|
||||
private final int g;
|
||||
private final int h;
|
||||
|
||||
public StoryBorderView(Context context) {
|
||||
this(context, null, 0, 6);
|
||||
}
|
||||
|
||||
public StoryBorderView(Context context, AttributeSet attributeSet) {
|
||||
this(context, attributeSet, 0, 4);
|
||||
}
|
||||
|
||||
public StoryBorderView(Context context, AttributeSet attributeSet, int i, int i2) {
|
||||
this(context, (i2 & 2) != 0 ? null : attributeSet, (i2 & 4) != 0 ? 0 : i);
|
||||
}
|
||||
|
||||
public int getBorderColor() {
|
||||
return this.f15749d;
|
||||
}
|
||||
|
||||
public int getBorderGradientEndColor() {
|
||||
return this.h;
|
||||
}
|
||||
|
||||
public int getBorderGradientStartColor() {
|
||||
return this.g;
|
||||
}
|
||||
|
||||
public int getBorderWidth() {
|
||||
return this.f15750e;
|
||||
}
|
||||
|
||||
public int getPadding() {
|
||||
return this.f15751f;
|
||||
}
|
||||
|
||||
public int getViewSize() {
|
||||
return this.f15748c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
canvas.drawOval(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom(), this.a);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int i, int i2) {
|
||||
int i3 = this.f15748c;
|
||||
setMeasuredDimension(i3, i3);
|
||||
}
|
||||
|
||||
public void setBorderColor(int i) {
|
||||
if (this.f15749d != i) {
|
||||
this.f15749d = i;
|
||||
this.a.setColor(i);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setBorderWidth(int i) {
|
||||
if (this.f15750e != i) {
|
||||
this.f15750e = i;
|
||||
this.a.setStrokeWidth(i);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutParams(ViewGroup.LayoutParams layoutParams) {
|
||||
super.setLayoutParams(layoutParams);
|
||||
boolean z = false;
|
||||
this.f15748c = Math.min(layoutParams != null ? layoutParams.width : 0, layoutParams != null ? layoutParams.height : 0);
|
||||
this.f15747b = new LinearGradient(0.0f, 0.0f, 0.0f, this.f15748c, this.g, this.h, Shader.TileMode.MIRROR);
|
||||
if (this.f15748c > 0) {
|
||||
z = true;
|
||||
}
|
||||
if (z) {
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException("Only exact size supported, specify avatar sizes in layout params");
|
||||
}
|
||||
|
||||
public void setLive(boolean z) {
|
||||
if (this.B != z) {
|
||||
this.a.setShader(z ? this.f15747b : null);
|
||||
this.a.setColor(z ? -1 : this.f15749d);
|
||||
this.B = z;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPadding(int i) {
|
||||
if (this.f15751f != i) {
|
||||
this.f15751f = i;
|
||||
setPadding(i, i, i, i);
|
||||
}
|
||||
}
|
||||
|
||||
public void setViewSize(int i) {
|
||||
this.f15748c = i;
|
||||
}
|
||||
|
||||
public StoryBorderView(Context context, AttributeSet attributeSet, int i) {
|
||||
super(context, attributeSet, i);
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
this.a = paint;
|
||||
TypedArray obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, o.StoryBorderView);
|
||||
setBorderColor(obtainStyledAttributes.getInt(o.StoryBorderView_vkim_borderColor, 0));
|
||||
this.g = obtainStyledAttributes.getInt(o.StoryBorderView_vkim_borderGradientStartColor, 0);
|
||||
this.h = obtainStyledAttributes.getInt(o.StoryBorderView_vkim_borderGradientEndColor, 0);
|
||||
setBorderWidth(obtainStyledAttributes.getDimensionPixelSize(o.StoryBorderView_vkim_borderWidth, 0));
|
||||
obtainStyledAttributes.recycle();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,106 @@
|
||||
package com.vk.profile.ui.community;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import com.vk.core.ui.themes.Themable;
|
||||
import com.vk.core.ui.themes.VKThemeHelper;
|
||||
import com.vk.core.util.ContextExtKt;
|
||||
import com.vk.dto.stories.model.StoriesContainer;
|
||||
import com.vk.stories.view.BorderedCircleImageView;
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
public final class CommunityBorderedImageView extends BorderedCircleImageView implements Themable{
|
||||
private boolean f0;
|
||||
private int g0;
|
||||
private int h0;
|
||||
private PorterDuffColorFilter i0;
|
||||
private PorterDuffColorFilter j0;
|
||||
private int unread;
|
||||
private int read;
|
||||
|
||||
public CommunityBorderedImageView(Context context){
|
||||
this(context, null, 0, 6);
|
||||
}
|
||||
|
||||
public CommunityBorderedImageView(Context context, AttributeSet attributeSet){
|
||||
this(context, attributeSet, 0, 4);
|
||||
}
|
||||
|
||||
public CommunityBorderedImageView(Context context, AttributeSet attributeSet, int i, int i2){
|
||||
this(context, (i2 & 2) != 0 ? null : attributeSet, (i2 & 4) != 0 ? 0 : i);
|
||||
}
|
||||
|
||||
public CommunityBorderedImageView(Context context, AttributeSet attributeSet, int i){
|
||||
super(context, attributeSet, i);
|
||||
this.g0 = VKThemeHelper.d((int) R.attr.accent);
|
||||
this.h0 = ContextExtKt.a(context, (int) R.color.gray_200);
|
||||
this.i0 = new PorterDuffColorFilter(this.g0, PorterDuff.Mode.SRC_IN);
|
||||
this.j0 = new PorterDuffColorFilter(this.h0, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
public final void c(int unread, int read){ // get unread and read resid
|
||||
this.unread = unread;
|
||||
this.read = read;
|
||||
this.T = BitmapFactory.decodeResource(getResources(), this.unread);
|
||||
}
|
||||
|
||||
public final int getPrimaryColor(){
|
||||
return this.g0;
|
||||
}
|
||||
|
||||
public final void setPrimaryColor(int i){
|
||||
this.g0 = i;
|
||||
this.i0 = new PorterDuffColorFilter(i, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
public final int getWasViewedColor(){
|
||||
return this.h0;
|
||||
}
|
||||
|
||||
public final void setWasViewedColor(int i){
|
||||
this.h0 = i;
|
||||
this.j0 = new PorterDuffColorFilter(i, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
public final void o(){
|
||||
this.f0 = false;
|
||||
l();
|
||||
}
|
||||
|
||||
@Override // com.vk.stories.view.ClippedImageView, android.widget.ImageView, android.view.View
|
||||
public void onDraw(Canvas canvas){
|
||||
super.onDraw(canvas);
|
||||
if (this.f0) {
|
||||
a(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
public final void setStoryContainer(StoriesContainer storiesContainer){
|
||||
if (storiesContainer.L1()) {
|
||||
this.f0 = true;
|
||||
m();
|
||||
if (storiesContainer.K1()) {
|
||||
this.T = BitmapFactory.decodeResource(getResources(), this.unread);
|
||||
setBorderColorFilter(this.i0);
|
||||
b(getWidth(), getHeight());
|
||||
invalidate();
|
||||
return;
|
||||
}
|
||||
this.T = BitmapFactory.decodeResource(getResources(), this.read);
|
||||
setBorderColorFilter(this.j0);
|
||||
b(getWidth(), getHeight());
|
||||
invalidate();
|
||||
return;
|
||||
}
|
||||
o();
|
||||
}
|
||||
|
||||
@Override // com.vk.core.ui.themes.Themable
|
||||
public void v(){
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
package com.vk.sharing.view;
|
||||
|
||||
import static b.h.z.f.roboto_medium;
|
||||
import static ru.vtosters.lite.utils.Preferences.preferences;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.facebook.drawee.drawable.ScalingUtils;
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchy;
|
||||
import com.facebook.drawee.view.DraweeHolder;
|
||||
import com.vk.core.util.ContextExtKt;
|
||||
import com.vk.core.util.Screen;
|
||||
import com.vk.im.ui.views.avatars.AbbreviationAvatarDrawable;
|
||||
import com.vk.imageloader.view.VKMultiImageView;
|
||||
import com.vk.navigation.NavigatorKeys;
|
||||
import com.vtosters.lite.R;
|
||||
import com.vtosters.lite.a0;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
@UiThread
|
||||
public class TargetImageView extends VKMultiImageView {
|
||||
private static final int I = Screen.a(2);
|
||||
private final int B;
|
||||
private final int C;
|
||||
private Drawable D;
|
||||
private String[] F;
|
||||
private int G;
|
||||
private final RectF f21629d;
|
||||
private final Paint f21630e;
|
||||
private Canvas f21631f;
|
||||
private final RectF g;
|
||||
private final Paint h;
|
||||
|
||||
public TargetImageView(Context context, Drawable d) {
|
||||
this(context, null, 0, 6);
|
||||
}
|
||||
|
||||
public TargetImageView(Context context, AttributeSet attributeSet) {
|
||||
this(context, attributeSet, 0, 4);
|
||||
}
|
||||
|
||||
public TargetImageView(Context context, AttributeSet attributeSet, int i, int i2) {
|
||||
this(context, (i2 & 2) != 0 ? null : attributeSet, (i2 & 4) != 0 ? 0 : i);
|
||||
}
|
||||
|
||||
private void e() {
|
||||
int i = this.G;
|
||||
for (int i2 = 0; i2 < i; i2++) {
|
||||
a(i2, this.F[i2]);
|
||||
}
|
||||
}
|
||||
|
||||
private void f() {
|
||||
int paddingLeft = getPaddingLeft();
|
||||
int paddingTop = getPaddingTop();
|
||||
int width = (getWidth() - paddingLeft) - getPaddingRight();
|
||||
int height = (getHeight() - paddingTop) - getPaddingBottom();
|
||||
int i = width / 2;
|
||||
int i2 = height / 2;
|
||||
int i3 = this.G;
|
||||
if (i3 == 1) {
|
||||
DraweeHolder<GenericDraweeHierarchy> a2 = this.a.a(0);
|
||||
Drawable d2 = a2.d();
|
||||
if (d2 != null) {
|
||||
d2.setBounds(paddingLeft, paddingTop, width + paddingLeft, height + paddingTop);
|
||||
}
|
||||
} else if (i3 == 2) {
|
||||
DraweeHolder<GenericDraweeHierarchy> a3 = this.a.a(0);
|
||||
Drawable d3 = a3.d();
|
||||
if (d3 != null) {
|
||||
int i4 = i + paddingLeft;
|
||||
int i5 = height + paddingTop;
|
||||
d3.setBounds(paddingLeft, paddingTop, i4, i5);
|
||||
DraweeHolder<GenericDraweeHierarchy> a4 = this.a.a(1);
|
||||
Drawable d4 = a4.d();
|
||||
if (d4 != null) {
|
||||
d4.setBounds(i4, paddingTop, paddingLeft + width, i5);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (i3 == 3) {
|
||||
DraweeHolder<GenericDraweeHierarchy> a5 = this.a.a(0);
|
||||
Drawable d5 = a5.d();
|
||||
if (d5 != null) {
|
||||
int i6 = i + paddingLeft;
|
||||
int i7 = height + paddingTop;
|
||||
d5.setBounds(paddingLeft, paddingTop, i6, i7);
|
||||
DraweeHolder<GenericDraweeHierarchy> a6 = this.a.a(1);
|
||||
Drawable d6 = a6.d();
|
||||
if (d6 != null) {
|
||||
int i9 = paddingLeft + width;
|
||||
int i10 = i2 + paddingTop;
|
||||
d6.setBounds(i6, paddingTop, i9, i10);
|
||||
DraweeHolder<GenericDraweeHierarchy> a7 = this.a.a(2);
|
||||
Drawable d7 = a7.d();
|
||||
if (d7 != null) {
|
||||
d7.setBounds(i6, i10, i9, i7);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
DraweeHolder<GenericDraweeHierarchy> a8 = this.a.a(0);
|
||||
Drawable d8 = a8.d();
|
||||
if (d8 != null) {
|
||||
int i11 = i + paddingLeft;
|
||||
int i13 = i2 + paddingTop;
|
||||
d8.setBounds(paddingLeft, paddingTop, i11, i13);
|
||||
DraweeHolder<GenericDraweeHierarchy> a9 = this.a.a(1);
|
||||
Drawable d9 = a9.d();
|
||||
if (d9 != null) {
|
||||
int i16 = height + paddingTop;
|
||||
d9.setBounds(paddingLeft, i13, i11, i16);
|
||||
DraweeHolder<GenericDraweeHierarchy> a10 = this.a.a(2);
|
||||
Drawable d10 = a10.d();
|
||||
if (d10 != null) {
|
||||
int i18 = paddingLeft + width;
|
||||
d10.setBounds(i11, paddingTop, i18, i13);
|
||||
DraweeHolder<GenericDraweeHierarchy> a11 = this.a.a(3);
|
||||
Drawable d11 = a11.d();
|
||||
if (d11 != null) {
|
||||
d11.setBounds(i11, i13, i18, i16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void g() {
|
||||
if (getWidth() == 0 || getHeight() == 0) {
|
||||
return;
|
||||
}
|
||||
f();
|
||||
}
|
||||
|
||||
private AbbreviationAvatarDrawable getAbbreviationDrawable() {
|
||||
return a(getContext(), null, 2);
|
||||
}
|
||||
|
||||
private AbbreviationAvatarDrawable a(Context context, Typeface typeface, int i) {
|
||||
return new AbbreviationAvatarDrawable(context, (i & 2) != 0 ? ContextExtKt.e(context, roboto_medium) : typeface);
|
||||
}
|
||||
|
||||
public void a(String str) {
|
||||
Arrays.fill(this.F, null);
|
||||
if (str == null) {
|
||||
b();
|
||||
this.G = 1;
|
||||
g();
|
||||
e();
|
||||
return;
|
||||
}
|
||||
|
||||
Uri uri = Uri.parse(str);
|
||||
if (uri.getScheme().equals("vkchatphoto")) {
|
||||
this.G = 0;
|
||||
while (true) {
|
||||
String queryParameter = uri.getQueryParameter("photo" + this.G);
|
||||
if (queryParameter != null) {
|
||||
int i = this.G;
|
||||
this.G = i + 1;
|
||||
this.F[i] = queryParameter;
|
||||
} else {
|
||||
g();
|
||||
e();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (uri.getScheme().equals("vkchatplaceholder")) {
|
||||
this.G = 1;
|
||||
g();
|
||||
AbbreviationAvatarDrawable abbreviationDrawable = getAbbreviationDrawable();
|
||||
String queryParameter2 = uri.getQueryParameter(NavigatorKeys.Q);
|
||||
int parseInt = queryParameter2 != null ? Integer.parseInt(queryParameter2) : 0;
|
||||
String queryParameter3 = uri.getQueryParameter(NavigatorKeys.d);
|
||||
if (queryParameter3 == null) {
|
||||
queryParameter3 = "";
|
||||
}
|
||||
abbreviationDrawable.a(parseInt, queryParameter3);
|
||||
a(0, getAbbreviationDrawable());
|
||||
} else {
|
||||
this.F[0] = str;
|
||||
this.G = 1;
|
||||
g();
|
||||
e();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // android.view.View
|
||||
protected void onDraw(Canvas canvas) {
|
||||
Canvas canvas2 = this.f21631f;
|
||||
int pref = preferences.getInt("pic_rounding", 0);
|
||||
|
||||
if (canvas2 != null) {
|
||||
canvas2.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
}
|
||||
int i = this.G;
|
||||
for (int i2 = 0; i2 < i; i2++) {
|
||||
DraweeHolder<GenericDraweeHierarchy> a2 = this.a.a(i2);
|
||||
Drawable d2 = a2.d();
|
||||
if (d2 != null) {
|
||||
Canvas canvas3 = this.f21631f;
|
||||
d2.draw(canvas3);
|
||||
}
|
||||
}
|
||||
|
||||
if (pref > 0) {
|
||||
canvas.drawRoundRect(this.f21629d, pref, pref, this.f21630e);
|
||||
} else {
|
||||
canvas.drawOval(this.f21629d, this.f21630e);
|
||||
}
|
||||
|
||||
if (isSelected()) {
|
||||
if (pref > 0) {
|
||||
canvas.drawRoundRect(this.g.left, this.g.top, this.g.right, this.g.bottom, pref, pref, this.h);
|
||||
} else {
|
||||
canvas.drawCircle(this.g.centerX(), this.g.centerY(), this.g.width() / 2, this.h);
|
||||
}
|
||||
|
||||
this.D.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // android.view.View
|
||||
protected void onSizeChanged(int i, int i2, int i3, int i4) {
|
||||
super.onSizeChanged(i, i2, i3, i4);
|
||||
int paddingLeft = getPaddingLeft();
|
||||
int paddingRight = getPaddingRight();
|
||||
int paddingTop = getPaddingTop();
|
||||
int i5 = i - paddingRight;
|
||||
int paddingBottom = i2 - getPaddingBottom();
|
||||
this.f21629d.set(paddingLeft, paddingTop, i5, paddingBottom);
|
||||
Bitmap createBitmap = Bitmap.createBitmap(i5, paddingBottom, Bitmap.Config.ARGB_8888);
|
||||
this.f21631f = new Canvas(createBitmap);
|
||||
Shader.TileMode tileMode = Shader.TileMode.CLAMP;
|
||||
this.f21630e.setShader(new BitmapShader(createBitmap, tileMode, tileMode));
|
||||
float f2 = I / 2;
|
||||
this.g.set(f2, f2, i - f2, (float) i2 - f2);
|
||||
float f4 = i / 2;
|
||||
this.h.setShader(new LinearGradient(f4, 0.0f, f4, (float) i2, this.B, this.C, Shader.TileMode.CLAMP));
|
||||
Drawable drawable = this.D;
|
||||
drawable.setBounds(i - drawable.getIntrinsicWidth(), i2 - this.D.getIntrinsicHeight(), i, i2);
|
||||
f();
|
||||
}
|
||||
|
||||
public TargetImageView(Context context, AttributeSet attributeSet, int i) {
|
||||
super(context, attributeSet, i);
|
||||
this.f21629d = new RectF();
|
||||
Paint paint = new Paint();
|
||||
paint.setAntiAlias(true);
|
||||
paint.setDither(true);
|
||||
paint.setFilterBitmap(true);
|
||||
this.f21630e = paint;
|
||||
this.g = new RectF();
|
||||
Paint paint2 = new Paint();
|
||||
paint2.setAntiAlias(true);
|
||||
paint2.setStrokeWidth(I);
|
||||
paint2.setStyle(Paint.Style.STROKE);
|
||||
this.h = paint2;
|
||||
this.B = getAccentColor();
|
||||
this.C = this.B;
|
||||
Drawable c2 = ContextExtKt.c(context, R.drawable.ic_check_circle_composite_24_full);
|
||||
if (c2 != null) {
|
||||
this.D = c2;
|
||||
this.F = new String[4];
|
||||
int i2 = I * 2;
|
||||
setPadding(i2, i2, i2, i2);
|
||||
if (attributeSet != null) {
|
||||
TypedArray obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, a0.TargetImageView);
|
||||
setSelected(obtainStyledAttributes.getBoolean(0, false));
|
||||
obtainStyledAttributes.recycle();
|
||||
}
|
||||
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.user_placeholder);
|
||||
for (int i3 = 0; i3 <= 3; i3++) {
|
||||
a();
|
||||
DraweeHolder<GenericDraweeHierarchy> a3 = this.a.a(i3);
|
||||
a3.b().e(drawable);
|
||||
}
|
||||
setScaleType(ScalingUtils.b.o);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,447 @@
|
||||
package com.vk.stories.view;
|
||||
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getColor2;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.airbnb.lottie.LottieComposition;
|
||||
import com.airbnb.lottie.LottieCompositionFactory;
|
||||
import com.airbnb.lottie.LottieDrawable;
|
||||
import com.airbnb.lottie.LottieListener;
|
||||
import com.facebook.common.internal.Supplier;
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
import com.facebook.u.b.a.PipelineDraweeControllerBuilder;
|
||||
import com.facebook.x.g.CloseableImage;
|
||||
import com.vk.core.drawable.BorderDrawable;
|
||||
import com.vk.core.ui.themes.Themable;
|
||||
import com.vk.core.ui.themes.VKThemeHelper;
|
||||
import com.vk.core.util.DrawableUtils;
|
||||
import com.vk.core.util.ResUtils;
|
||||
import com.vk.core.util.Screen;
|
||||
import com.vk.dto.stories.d.StoriesContainerExt;
|
||||
import com.vk.dto.stories.model.CommunityGroupedStoriesContainer;
|
||||
import com.vk.dto.stories.model.StoriesContainer;
|
||||
import com.vk.dto.stories.model.StoryEntry;
|
||||
import com.vk.im.engine.models.Image;
|
||||
import com.vk.im.ui.views.avatars.AvatarDataSource;
|
||||
import com.vk.imageloader.FrescoWrapper;
|
||||
import com.vk.stories.StoriesController;
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class StoryCircleImageView extends BorderedCircleImageView implements Themable{
|
||||
private static final HashSet<Integer> B0 = new HashSet<>();
|
||||
private final PipelineDraweeControllerBuilder f0;
|
||||
private int A0;
|
||||
private Drawable g0;
|
||||
private Drawable h0;
|
||||
private Drawable i0;
|
||||
private int j0;
|
||||
private int k0;
|
||||
private int l0;
|
||||
private int m0;
|
||||
private int n0;
|
||||
private int o0;
|
||||
private Bitmap p0;
|
||||
private Bitmap q0;
|
||||
private Bitmap r0;
|
||||
private Bitmap s0;
|
||||
private boolean t0;
|
||||
private boolean u0;
|
||||
private boolean v0;
|
||||
private boolean w0;
|
||||
private boolean x0;
|
||||
private String y0;
|
||||
private LottieDrawable z0;
|
||||
|
||||
public StoryCircleImageView(Context context){
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public StoryCircleImageView(Context context, AttributeSet attributeSet){
|
||||
this(context, attributeSet, 0);
|
||||
}
|
||||
|
||||
public StoryCircleImageView(Context context, AttributeSet attributeSet, int i){
|
||||
super(context, attributeSet, i);
|
||||
this.f0 = FrescoWrapper.c.d();
|
||||
a(context, attributeSet, i);
|
||||
}
|
||||
|
||||
private void b(Canvas canvas){
|
||||
this.z0.draw(canvas);
|
||||
}
|
||||
|
||||
private boolean o(){
|
||||
return !this.u0 && !this.t0 && this.z0 == null && !this.w0 && !this.v0;
|
||||
}
|
||||
|
||||
private void p(){
|
||||
this.z0.stop();
|
||||
this.z0 = null;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void q(){
|
||||
int i = this.j0;
|
||||
if (i != 0 && VKThemeHelper.k.a(i)) {
|
||||
this.k0 = VKThemeHelper.d(this.j0);
|
||||
}
|
||||
this.g0 = DrawableUtils.a(this.g0, ColorStateList.valueOf(this.k0));
|
||||
Drawable drawable = this.g0;
|
||||
int i2 = this.A0;
|
||||
this.p0 = DrawableUtils.a(drawable, i2, i2);
|
||||
int i3 = this.l0;
|
||||
if (i3 != 0 && VKThemeHelper.k.a(i3)) {
|
||||
this.m0 = VKThemeHelper.d(this.l0);
|
||||
}
|
||||
int i4 = this.m0;
|
||||
if (i4 != 0) {
|
||||
this.i0 = DrawableUtils.a(this.i0, ColorStateList.valueOf(i4));
|
||||
}
|
||||
int i5 = this.n0;
|
||||
if (i5 != 0 && VKThemeHelper.k.a(i5)) {
|
||||
this.o0 = VKThemeHelper.d(this.n0);
|
||||
}
|
||||
Drawable a2 = DrawableUtils.a(this.g0, ColorStateList.valueOf(0));
|
||||
int i6 = this.A0;
|
||||
DrawableUtils.a(a2, i6, i6);
|
||||
Drawable a3 = DrawableUtils.a(this.h0, ColorStateList.valueOf(this.o0));
|
||||
int i7 = this.A0;
|
||||
this.r0 = DrawableUtils.a(a3, i7, i7);
|
||||
Drawable a4 = DrawableUtils.a(this.g0, ColorStateList.valueOf(ContextCompat.getColor(getContext(), R.color.orange)));
|
||||
int i8 = this.A0;
|
||||
this.s0 = DrawableUtils.a(a4, i8, i8);
|
||||
}
|
||||
|
||||
private void r(){
|
||||
this.c0 = Screen.a(o() ? 0 : 2);
|
||||
m();
|
||||
q();
|
||||
}
|
||||
|
||||
private void setUploadFailed(boolean z){
|
||||
this.u0 = z;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override // com.vk.stories.view.ClippedImageView, android.widget.ImageView, android.view.View
|
||||
public void onDraw(Canvas canvas){
|
||||
super.onDraw(canvas);
|
||||
setBorderAlpha(255);
|
||||
if (this.u0) {
|
||||
this.i0.draw(canvas);
|
||||
} else if (this.t0) {
|
||||
if (this.z0 != null) {
|
||||
b(canvas);
|
||||
return;
|
||||
}
|
||||
this.T = this.x0 ? this.s0 : this.p0;
|
||||
b(getWidth(), getHeight());
|
||||
a(canvas);
|
||||
} else if (this.z0 != null) {
|
||||
p();
|
||||
} else if (!this.w0) {
|
||||
|
||||
} else {
|
||||
this.T = this.r0;
|
||||
setBorderAlpha(163);
|
||||
b(getWidth(), getHeight());
|
||||
a(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // com.vk.stories.view.BorderedCircleImageView, android.view.View
|
||||
public void onSizeChanged(int i, int i2, int i3, int i4){
|
||||
super.onSizeChanged(i, i2, i3, i4);
|
||||
this.i0.setBounds(0, 0, i, i2);
|
||||
b(i);
|
||||
}
|
||||
|
||||
public void setStoryContainer(@Nullable StoriesContainer storiesContainer){
|
||||
boolean z = true;
|
||||
boolean z2 = storiesContainer != null && storiesContainer.Q1();
|
||||
this.v0 = storiesContainer != null && storiesContainer.S1() && !storiesContainer.L1();
|
||||
boolean z3 = storiesContainer instanceof CommunityGroupedStoriesContainer;
|
||||
this.x0 = z3;
|
||||
if (storiesContainer != null) {
|
||||
if (!StoriesContainerExt.c(storiesContainer) && !StoriesContainerExt.d(storiesContainer)) {
|
||||
this.T = this.p0;
|
||||
} else {
|
||||
this.T = this.q0;
|
||||
}
|
||||
b(getWidth(), getHeight());
|
||||
if (StoriesContainerExt.e(storiesContainer)) {
|
||||
a(storiesContainer);
|
||||
} else if (this.z0 != null) {
|
||||
p();
|
||||
}
|
||||
this.w0 = !storiesContainer.K1() && storiesContainer.L1();
|
||||
if (z2) {
|
||||
String h = storiesContainer.h(ResUtils.c(R.dimen.story_preview_image_size));
|
||||
if (h != null) {
|
||||
a(h);
|
||||
} else {
|
||||
g();
|
||||
}
|
||||
if (StoriesController.a(storiesContainer)) {
|
||||
setUploadFailed(true);
|
||||
a(false, false);
|
||||
} else {
|
||||
setUploadFailed(false);
|
||||
if (!storiesContainer.K1() && !StoriesContainerExt.c(storiesContainer)) {
|
||||
a(false, false);
|
||||
} else {
|
||||
StoryEntry A1 = storiesContainer.A1();
|
||||
if (A1 != null) {
|
||||
a(true, !B0.contains(A1.b));
|
||||
B0.add(A1.b);
|
||||
} else {
|
||||
a(true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setUploadFailed(false);
|
||||
if (!storiesContainer.K1() && !StoriesContainerExt.c(storiesContainer)) {
|
||||
z = false;
|
||||
}
|
||||
a(z, false);
|
||||
if (z3) {
|
||||
b(((CommunityGroupedStoriesContainer) storiesContainer).j(ResUtils.c(R.dimen.story_preview_image_size)));
|
||||
} else {
|
||||
String h2 = storiesContainer.h(ResUtils.c(R.dimen.story_preview_image_size));
|
||||
if (h2 != null) {
|
||||
a(h2);
|
||||
} else {
|
||||
g();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g();
|
||||
a(false, false);
|
||||
setUploadFailed(false);
|
||||
this.w0 = false;
|
||||
}
|
||||
r();
|
||||
}
|
||||
|
||||
@Override // com.vk.core.ui.themes.Themable
|
||||
public void v(){
|
||||
r();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void b(int i){
|
||||
LottieDrawable lottieDrawable = this.z0;
|
||||
if (lottieDrawable == null || lottieDrawable.e() == null) {
|
||||
return;
|
||||
}
|
||||
this.z0.d(i / this.z0.e().a().width());
|
||||
}
|
||||
|
||||
protected void a(Context context, AttributeSet attributeSet, int i){
|
||||
TypedArray obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, com.vtosters.lite.a0.StoryCircleImageView, i, 0);
|
||||
a(context, attributeSet, obtainStyledAttributes);
|
||||
obtainStyledAttributes.recycle();
|
||||
r();
|
||||
this.T = this.p0;
|
||||
}
|
||||
|
||||
public void b(@Nullable List<String> list){
|
||||
PipelineDraweeControllerBuilder pipelineDraweeControllerBuilder = this.f0;
|
||||
pipelineDraweeControllerBuilder.j();
|
||||
pipelineDraweeControllerBuilder.a(getController());
|
||||
setControllerListener(pipelineDraweeControllerBuilder);
|
||||
a(pipelineDraweeControllerBuilder, list);
|
||||
setController(pipelineDraweeControllerBuilder.k0());
|
||||
}
|
||||
|
||||
@SuppressLint("ResourceType")
|
||||
private void a(Context context, AttributeSet attributeSet, TypedArray typedArray){ // bullshit vk code is not working with custom bordered circle image
|
||||
Drawable drawable;
|
||||
this.A0 = typedArray.getDimensionPixelSize(0, Screen.a(64.0f));
|
||||
if (typedArray.hasValue(2)) {
|
||||
this.g0 = typedArray.getDrawable(2);
|
||||
} else {
|
||||
this.g0 = ContextCompat.getDrawable(context, R.drawable.bg_stores_unread_border_80);
|
||||
}
|
||||
if (typedArray.hasValue(3)) {
|
||||
this.h0 = typedArray.getDrawable(3);
|
||||
} else {
|
||||
this.h0 = ContextCompat.getDrawable(context, R.drawable.bg_stores_read_border_80);
|
||||
}
|
||||
|
||||
int b2 = VKThemeHelper.b(attributeSet, "vk_borderTint");
|
||||
if (b2 != 0 && VKThemeHelper.k.a(b2)) {
|
||||
this.j0 = b2;
|
||||
} else if (typedArray.hasValue(5)) {
|
||||
this.k0 = typedArray.getColor(5, 0);
|
||||
} else {
|
||||
this.j0 = R.attr.accent;
|
||||
}
|
||||
|
||||
int b3 = VKThemeHelper.b(attributeSet, "vk_failBorderTint");
|
||||
if (b3 != 0 && VKThemeHelper.k.a(b3)) {
|
||||
this.l0 = b3;
|
||||
} else if (typedArray.hasValue(7)) {
|
||||
this.m0 = typedArray.getColor(7, 0);
|
||||
}
|
||||
|
||||
int b4 = VKThemeHelper.b(attributeSet, "vk_borderSeenTint");
|
||||
if (b4 != 0 && VKThemeHelper.k.a(b4)) {
|
||||
this.n0 = b4;
|
||||
} else if (typedArray.hasValue(4)) {
|
||||
this.o0 = typedArray.getColor(4, 0);
|
||||
} else {
|
||||
this.o0 = 0;
|
||||
}
|
||||
if (typedArray.hasValue(6)) {
|
||||
this.i0 = typedArray.getDrawable(6);
|
||||
} else {
|
||||
this.i0 = ContextCompat.getDrawable(context, R.drawable.ic_story_error_size64);
|
||||
}
|
||||
if (typedArray.hasValue(8)) {
|
||||
drawable = typedArray.getDrawable(8);
|
||||
} else {
|
||||
drawable = ContextCompat.getDrawable(context, R.drawable.bg_live_unread_border);
|
||||
}
|
||||
if (typedArray.hasValue(9)) {
|
||||
this.y0 = typedArray.getString(9);
|
||||
} else {
|
||||
this.y0 = "stories_animation_64.json";
|
||||
}
|
||||
|
||||
int i = this.A0;
|
||||
this.q0 = DrawableUtils.a(Objects.requireNonNull(drawable), i, i);
|
||||
Drawable drawable2 = this.g0;
|
||||
int i2 = this.A0;
|
||||
DrawableUtils.a(drawable2, i2, i2);
|
||||
Drawable drawable3 = this.h0;
|
||||
int i3 = this.A0;
|
||||
this.r0 = DrawableUtils.a(drawable3, i3, i3);
|
||||
Drawable drawable4 = this.g0;
|
||||
int i4 = this.A0;
|
||||
this.s0 = DrawableUtils.a(drawable4, i4, i4);
|
||||
}
|
||||
|
||||
public void a(StoriesContainer storiesContainer){
|
||||
if (this.z0 == null) {
|
||||
LottieCompositionFactory.a(getContext(), this.y0).b(new a(storiesContainer));
|
||||
}
|
||||
}
|
||||
|
||||
public void a(StoriesContainer storiesContainer, LottieComposition lottieComposition){
|
||||
this.z0 = new LottieDrawable();
|
||||
this.z0.a(lottieComposition);
|
||||
this.z0.d(-1);
|
||||
b(getWidth());
|
||||
if (!StoriesContainerExt.f(storiesContainer)) {
|
||||
this.z0.a(new b());
|
||||
this.z0.start();
|
||||
return;
|
||||
}
|
||||
this.z0.stop();
|
||||
}
|
||||
|
||||
private void a(boolean z, boolean z2){
|
||||
k();
|
||||
this.t0 = z;
|
||||
if (!z2) {
|
||||
setSelectionAmount(1.0f);
|
||||
} else {
|
||||
n();
|
||||
}
|
||||
}
|
||||
|
||||
private void a(@NonNull PipelineDraweeControllerBuilder pipelineDraweeControllerBuilder, @Nullable final List<String> list){
|
||||
pipelineDraweeControllerBuilder.b(null);
|
||||
pipelineDraweeControllerBuilder.a((Supplier<DataSource<CloseableReference<com.facebook.x.g.CloseableImage>>>) null);
|
||||
if (list != null && !list.isEmpty()) {
|
||||
if (list.size() == 1) {
|
||||
ImageRequestBuilder b2 = ImageRequestBuilder.b(Uri.parse(list.get(0)));
|
||||
b2.a(ImageRequest.CacheChoice.SMALL);
|
||||
pipelineDraweeControllerBuilder.b(b2.a());
|
||||
return;
|
||||
}
|
||||
|
||||
pipelineDraweeControllerBuilder.a((Supplier<DataSource<CloseableReference<CloseableImage>>>) () -> StoryCircleImageView.this.a(list));
|
||||
return;
|
||||
}
|
||||
pipelineDraweeControllerBuilder.b(null);
|
||||
}
|
||||
|
||||
public DataSource<CloseableReference<CloseableImage>> a(@Nullable List<String> list){
|
||||
ArrayList<Image> arrayList = new ArrayList<>();
|
||||
for (String o : Objects.requireNonNull(list)) {
|
||||
arrayList.add(new Image(-1, -1, o));
|
||||
}
|
||||
return AvatarDataSource.a(arrayList, this.A0, 0);
|
||||
}
|
||||
|
||||
public class a implements LottieListener<LottieComposition>{
|
||||
final StoriesContainer a;
|
||||
|
||||
a(StoriesContainer storiesContainer){
|
||||
this.a = storiesContainer;
|
||||
}
|
||||
|
||||
@Override // com.airbnb.lottie.LottieListener
|
||||
public void a(LottieComposition lottieComposition){
|
||||
if (StoryCircleImageView.this.getWidth() > 0) {
|
||||
StoryCircleImageView.this.a(this.a, lottieComposition);
|
||||
} else {
|
||||
StoryCircleImageView.this.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver$OnGlobalLayoutListenerC0393a(lottieComposition));
|
||||
}
|
||||
}
|
||||
|
||||
public class ViewTreeObserver$OnGlobalLayoutListenerC0393a implements ViewTreeObserver.OnGlobalLayoutListener{
|
||||
final LottieComposition a;
|
||||
|
||||
ViewTreeObserver$OnGlobalLayoutListenerC0393a(LottieComposition lottieComposition){
|
||||
this.a = lottieComposition;
|
||||
}
|
||||
|
||||
@Override // android.view.ViewTreeObserver.OnGlobalLayoutListener
|
||||
public void onGlobalLayout(){
|
||||
StoryCircleImageView.this.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
a aVar = a.this;
|
||||
StoryCircleImageView.this.a(aVar.a, this.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class b implements ValueAnimator.AnimatorUpdateListener{
|
||||
b(){
|
||||
}
|
||||
|
||||
@Override // android.animation.ValueAnimator.AnimatorUpdateListener
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator){
|
||||
StoryCircleImageView.this.invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.vtosters.lite;
|
||||
|
||||
public class R{
|
||||
public static final class anim{
|
||||
public class R {
|
||||
public static final class anim {
|
||||
public static final int abc_fade_in = 0x7f010000;
|
||||
public static final int abc_fade_out = 0x7f010001;
|
||||
public static final int abc_grow_fade_in_from_bottom = 0x7f010002;
|
||||
@@ -75,7 +75,7 @@ public class R{
|
||||
public static final int vkme_exit_noop = 0x7f010046;
|
||||
}
|
||||
|
||||
public static final class animator{
|
||||
public static final class animator {
|
||||
public static final int design_appbar_state_list_animator = 0x7f020000;
|
||||
public static final int design_fab_hide_motion_spec = 0x7f020001;
|
||||
public static final int design_fab_show_motion_spec = 0x7f020002;
|
||||
@@ -88,7 +88,7 @@ public class R{
|
||||
public static final int mtrl_fab_transformation_sheet_expand_spec = 0x7f020009;
|
||||
}
|
||||
|
||||
public static final class array{
|
||||
public static final class array {
|
||||
public static final int ad_report_reasons = 0x7f030000;
|
||||
public static final int ad_report_reasons_api = 0x7f030001;
|
||||
public static final int address_will_be_opened = 0x7f030002;
|
||||
@@ -180,7 +180,7 @@ public class R{
|
||||
public static final int when_day_of_week = 0x7f030058;
|
||||
}
|
||||
|
||||
public static final class attr{
|
||||
public static final class attr {
|
||||
public static final int BMSB_error_text_color = 0x7f040000;
|
||||
public static final int BuyMusicSubscriptionButtonStyle = 0x7f040001;
|
||||
public static final int PIAlphaNormal = 0x7f040002;
|
||||
@@ -2091,7 +2091,7 @@ public class R{
|
||||
public static final int zOrderOnTop = 0x7f040773;
|
||||
}
|
||||
|
||||
public static final class bool{
|
||||
public static final class bool {
|
||||
public static final int abc_action_bar_embed_tabs = 0x7f050000;
|
||||
public static final int abc_allow_stacked_button_bar = 0x7f050001;
|
||||
public static final int abc_config_actionMenuItemAllCaps = 0x7f050002;
|
||||
@@ -2110,7 +2110,7 @@ public class R{
|
||||
public static final int vk_is_tablet = 0x7f05000f;
|
||||
}
|
||||
|
||||
public static final class color{
|
||||
public static final class color {
|
||||
public static final int abc_background_cache_hint_selector_material_dark = 0x7f060000;
|
||||
public static final int abc_background_cache_hint_selector_material_light = 0x7f060001;
|
||||
public static final int abc_btn_colored_borderless_text_material = 0x7f060002;
|
||||
@@ -2918,7 +2918,7 @@ public class R{
|
||||
public static final int abc_color_highlight_material = 0x7f060004;
|
||||
}
|
||||
|
||||
public static final class dimen{
|
||||
public static final class dimen {
|
||||
public static final int _post_side_padding = 0x7f070000;
|
||||
public static final int abc_action_bar_content_inset_material = 0x7f070001;
|
||||
public static final int abc_action_bar_content_inset_with_nav = 0x7f070002;
|
||||
@@ -3560,26 +3560,26 @@ public class R{
|
||||
public static final int stickers_notifications_size = 0x7f070285;
|
||||
public static final int stickers_tabs_padding = 0x7f070286;
|
||||
public static final int stickers_tabs_size = 0x7f070287;
|
||||
public static final int stiсkers_catalog_button_padding_bottom = 0x7f070288;
|
||||
public static final int stiсkers_catalog_button_padding_left = 0x7f070289;
|
||||
public static final int stiсkers_catalog_button_padding_right = 0x7f07028a;
|
||||
public static final int stiсkers_catalog_button_padding_top = 0x7f07028b;
|
||||
public static final int stiсkers_catalog_double_stacked_slider_image_bg_size = 0x7f07028c;
|
||||
public static final int stiсkers_catalog_double_stacked_slider_image_corner_radius = 0x7f07028d;
|
||||
public static final int stiсkers_catalog_double_stacked_slider_image_size = 0x7f07028e;
|
||||
public static final int stiсkers_catalog_large_slider_image_bg_height = 0x7f07028f;
|
||||
public static final int stiсkers_catalog_large_slider_image_bg_width = 0x7f070290;
|
||||
public static final int stiсkers_catalog_large_slider_image_corner_radius = 0x7f070291;
|
||||
public static final int stiсkers_catalog_large_slider_image_size = 0x7f070292;
|
||||
public static final int stiсkers_catalog_small_slider_image_bg_size = 0x7f070293;
|
||||
public static final int stiсkers_catalog_small_slider_image_corner_radius = 0x7f070294;
|
||||
public static final int stiсkers_catalog_small_slider_image_size = 0x7f070295;
|
||||
public static final int stiсkers_catalog_triple_stacked_slider_image_bg_size = 0x7f070296;
|
||||
public static final int stiсkers_catalog_triple_stacked_slider_image_corner_radius = 0x7f070297;
|
||||
public static final int stiсkers_catalog_triple_stacked_slider_image_size = 0x7f070298;
|
||||
public static final int stiсkers_catalog_vertical_list_image_bg_size = 0x7f070299;
|
||||
public static final int stiсkers_catalog_vertical_list_image_corner_radius = 0x7f07029a;
|
||||
public static final int stiсkers_catalog_vertical_list_image_size = 0x7f07029b;
|
||||
public static final int stickers_catalog_button_padding_bottom = 0x7f070288;
|
||||
public static final int stickers_catalog_button_padding_left = 0x7f070289;
|
||||
public static final int stickers_catalog_button_padding_right = 0x7f07028a;
|
||||
public static final int stickers_catalog_button_padding_top = 0x7f07028b;
|
||||
public static final int stickers_catalog_double_stacked_slider_image_bg_size = 0x7f07028c;
|
||||
public static final int stickers_catalog_double_stacked_slider_image_corner_radius = 0x7f07028d;
|
||||
public static final int stickers_catalog_double_stacked_slider_image_size = 0x7f07028e;
|
||||
public static final int stickers_catalog_large_slider_image_bg_height = 0x7f07028f;
|
||||
public static final int stickers_catalog_large_slider_image_bg_width = 0x7f070290;
|
||||
public static final int stickers_catalog_large_slider_image_corner_radius = 0x7f070291;
|
||||
public static final int stickers_catalog_large_slider_image_size = 0x7f070292;
|
||||
public static final int stickers_catalog_small_slider_image_bg_size = 0x7f070293;
|
||||
public static final int stickers_catalog_small_slider_image_corner_radius = 0x7f070294;
|
||||
public static final int stickers_catalog_small_slider_image_size = 0x7f070295;
|
||||
public static final int stickers_catalog_triple_stacked_slider_image_bg_size = 0x7f070296;
|
||||
public static final int stickers_catalog_triple_stacked_slider_image_corner_radius = 0x7f070297;
|
||||
public static final int stickers_catalog_triple_stacked_slider_image_size = 0x7f070298;
|
||||
public static final int stickers_catalog_vertical_list_image_bg_size = 0x7f070299;
|
||||
public static final int stickers_catalog_vertical_list_image_corner_radius = 0x7f07029a;
|
||||
public static final int stickers_catalog_vertical_list_image_size = 0x7f07029b;
|
||||
public static final int story_author_title_top_space = 0x7f07029c;
|
||||
public static final int story_cadre_bottom_btn_top_padding = 0x7f07029d;
|
||||
public static final int story_camera_tabs_height = 0x7f07029e;
|
||||
@@ -3783,7 +3783,7 @@ public class R{
|
||||
public static final int camera_target_text_size = 0x7f070074;
|
||||
}
|
||||
|
||||
public static final class drawable{
|
||||
public static final class drawable {
|
||||
public static final int $$notification_receive_28_60fps__1__0 = 0x7f080000;
|
||||
public static final int $$notification_receive_28_60fps__1__1 = 0x7f080001;
|
||||
public static final int $$notification_receive_28_60fps__1__2 = 0x7f080002;
|
||||
@@ -6801,7 +6801,7 @@ public class R{
|
||||
public static final int promo_qr_2 = 0x7f0809cf;
|
||||
}
|
||||
|
||||
public static final class font{
|
||||
public static final class font {
|
||||
public static final int fortun_af_led7seg_3 = 0x7f090000;
|
||||
public static final int roboto_black = 0x7f090001;
|
||||
public static final int roboto_black_italic = 0x7f090002;
|
||||
@@ -6824,7 +6824,7 @@ public class R{
|
||||
public static final int vk_tt_commons_demi_bold = 0x7f090013;
|
||||
}
|
||||
|
||||
public static final class id{
|
||||
public static final class id {
|
||||
public static final int ALT = 0x7f0a0000;
|
||||
public static final int CIRCLE = 0x7f0a0001;
|
||||
public static final int CTRL = 0x7f0a0002;
|
||||
@@ -10931,7 +10931,7 @@ public class R{
|
||||
public static final int choose_btn = 0x7f0a1007;
|
||||
}
|
||||
|
||||
public static final class integer{
|
||||
public static final class integer {
|
||||
public static final int abc_config_activityDefaultDur = 0x7f0b0000;
|
||||
public static final int abc_config_activityShortDur = 0x7f0b0001;
|
||||
public static final int angle_rtl_180 = 0x7f0b0002;
|
||||
@@ -10980,14 +10980,14 @@ public class R{
|
||||
public static final int s2dip = 0x7f0b0028;
|
||||
}
|
||||
|
||||
public static final class interpolator{
|
||||
public static final class interpolator {
|
||||
public static final int mtrl_fast_out_linear_in = 0x7f0c0000;
|
||||
public static final int mtrl_fast_out_slow_in = 0x7f0c0001;
|
||||
public static final int mtrl_linear = 0x7f0c0002;
|
||||
public static final int mtrl_linear_out_slow_in = 0x7f0c0003;
|
||||
}
|
||||
|
||||
public static final class layout{
|
||||
public static final class layout {
|
||||
public static final int ab_done_right = 0x7f0d0000;
|
||||
public static final int abc_action_bar_title_item = 0x7f0d0001;
|
||||
public static final int abc_action_bar_up_container = 0x7f0d0002;
|
||||
@@ -12749,7 +12749,7 @@ public class R{
|
||||
public static final int tgs_entry = 0x7f0d06de;
|
||||
}
|
||||
|
||||
public static final class menu{
|
||||
public static final class menu {
|
||||
public static final int add = 0x7f0e0000;
|
||||
public static final int attach_item = 0x7f0e0001;
|
||||
public static final int audio = 0x7f0e0002;
|
||||
@@ -12824,7 +12824,7 @@ public class R{
|
||||
public static final int vkim_photo_viewer = 0x7f0e0047;
|
||||
}
|
||||
|
||||
public static final class mipmap{
|
||||
public static final class mipmap {
|
||||
public static final int adaptive_launcher_background = 0x7f0f0000;
|
||||
public static final int adaptive_launcher_foreground = 0x7f0f0001;
|
||||
public static final int ic_launcher_round = 0x7f0f0002;
|
||||
@@ -12840,7 +12840,7 @@ public class R{
|
||||
public static final int ic_skip_previous_alpha_40_28 = 0x7f0f000b;
|
||||
}
|
||||
|
||||
public static final class plurals{
|
||||
public static final class plurals {
|
||||
public static final int accessibility_comments = 0x7f100000;
|
||||
public static final int accessibility_likes = 0x7f100001;
|
||||
public static final int accessibility_reposts = 0x7f100002;
|
||||
@@ -13113,7 +13113,7 @@ public class R{
|
||||
public static final int x_stickers = 0x7f10010d;
|
||||
}
|
||||
|
||||
public static final class raw{
|
||||
public static final class raw {
|
||||
public static final int amu_ballon_gx_prefix = 0x7f110000;
|
||||
public static final int amu_basic_folder = 0x7f110001;
|
||||
public static final int amu_basic_placemark = 0x7f110002;
|
||||
@@ -13153,7 +13153,7 @@ public class R{
|
||||
public static final int vklogo = 0x7f110024;
|
||||
}
|
||||
|
||||
public static final class string{
|
||||
public static final class string {
|
||||
public static final int abc_action_bar_home_description = 0x7f120000;
|
||||
public static final int abc_action_bar_up_description = 0x7f120001;
|
||||
public static final int abc_action_menu_overflow_description = 0x7f120002;
|
||||
@@ -18525,7 +18525,7 @@ public class R{
|
||||
public static final int your_gender = 0x7f1214f8;
|
||||
}
|
||||
|
||||
public static final class style{
|
||||
public static final class style {
|
||||
public static final int ActionBarGrayTheme = 0x7f130000;
|
||||
public static final int ActionBarProgress = 0x7f130001;
|
||||
public static final int ActionBarSpinner = 0x7f130002;
|
||||
@@ -19662,7 +19662,7 @@ public class R{
|
||||
public static final int Base_V28_Theme_AppCompat_Light = 0x7f1300a3;
|
||||
}
|
||||
|
||||
public static final class xml{
|
||||
public static final class xml {
|
||||
public static final int account_preferences = 0x7f150000;
|
||||
public static final int authenticator = 0x7f150001;
|
||||
public static final int contacts_custom_type = 0x7f150002;
|
||||
|
||||
+342
@@ -0,0 +1,342 @@
|
||||
package com.vtosters.lite.ui.bottomnavigation;
|
||||
|
||||
import static ru.vtosters.lite.utils.Preferences.*;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getCSTDock;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.view.menu.MenuItemImpl;
|
||||
import androidx.appcompat.view.menu.MenuView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.vk.core.ui.themes.VKThemeHelper;
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import me.grishka.appkit.utils.V;
|
||||
import ru.vtosters.lite.utils.Preferences;
|
||||
|
||||
public class BottomNavigationItemView extends FrameLayout implements MenuView.ItemView {
|
||||
private final TextView mSmallLabel;
|
||||
private final TextView mLargeLabel;
|
||||
private final View mCounterContainer;
|
||||
private final TextView mCounter;
|
||||
private final View mDot;
|
||||
private int mItemPos;
|
||||
private MenuItemImpl mItemData;
|
||||
private ColorStateList mColorStateList;
|
||||
private final int mMargin;
|
||||
private final float mSmallScale;
|
||||
private boolean mShiftingModeEnabled;
|
||||
private boolean mIconsModeEnabled;
|
||||
private boolean mStaticModeEnabled;
|
||||
private final ImageView mIcon;
|
||||
private final ImageView mActionIcon;
|
||||
|
||||
public BottomNavigationItemView(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BottomNavigationItemView(@NonNull Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BottomNavigationItemView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
this.mItemPos = -1;
|
||||
|
||||
this.mMargin = getResources().getDimensionPixelSize(R.dimen.design_bottom_navigation_margin);
|
||||
this.mSmallScale = 10.0f;
|
||||
float mLargeScale = 10.0f;
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.design_bottom_navigation_item, this, true);
|
||||
this.setBackgroundResource(R.drawable.design_bottom_navigation_item_background);
|
||||
this.mIcon = this.findViewById(R.id.icon);
|
||||
this.mIcon.getLayoutParams().width = V.a(28.0F);
|
||||
this.mIcon.getLayoutParams().height = V.a(28.0F);
|
||||
|
||||
var colorStateList = getCSTDock();
|
||||
this.mSmallLabel = this.findViewById(R.id.smallLabel);
|
||||
mSmallLabel.setTextColor(colorStateList);
|
||||
|
||||
this.mLargeLabel = this.findViewById(R.id.largeLabel);
|
||||
mLargeLabel.setTextColor(colorStateList);
|
||||
|
||||
LayoutInflater.from(this.getContext()).inflate(R.layout.navigation_bottom_counter, this, true);
|
||||
this.mCounterContainer = this.findViewById(R.id.counter_container);
|
||||
this.mCounter = this.findViewById(R.id.counter);
|
||||
this.mDot = this.findViewById(R.id.dot);
|
||||
|
||||
LayoutInflater.from(this.getContext()).inflate(R.layout.navigation_bottom_action, this, true);
|
||||
this.mActionIcon = this.findViewById(R.id.action_icon);
|
||||
VKThemeHelper.a(this.mActionIcon, R.attr.tabbar_active_icon, PorterDuff.Mode.MULTIPLY);
|
||||
}
|
||||
|
||||
public void a() {
|
||||
this.mActionIcon.setVisibility(GONE);
|
||||
}
|
||||
|
||||
public void b() {
|
||||
this.mActionIcon.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public MenuItemImpl getItemData() {
|
||||
return this.mItemData;
|
||||
}
|
||||
|
||||
public int getItemPosition() {
|
||||
return this.mItemPos;
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public void initialize(MenuItemImpl impl, int i) {
|
||||
this.mItemData = impl;
|
||||
this.setCheckable(impl.isCheckable());
|
||||
this.setChecked(impl.isChecked());
|
||||
this.setEnabled(impl.isEnabled());
|
||||
this.setIcon(impl.getIcon());
|
||||
this.setTitle(impl.getTitle());
|
||||
this.setId(impl.getItemId());
|
||||
this.setContentDescription(impl.getTitle());
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public int[] onCreateDrawableState(int extraSpace) {
|
||||
int[] baseState = super.onCreateDrawableState(extraSpace + 1);
|
||||
if (this.mItemData != null && this.mItemData.isCheckable() && this.mItemData.isChecked()) {
|
||||
FrameLayout.mergeDrawableStates(baseState, new int[]{android.R.attr.state_checked});
|
||||
}
|
||||
|
||||
return baseState;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
if (/*this.mShiftingModeEnabled &&*/ this.mCounterContainer.getVisibility() != GONE) {
|
||||
left = this.mCounterContainer.getMeasuredWidth() / 2
|
||||
+ V.a(4.0F)
|
||||
+ Math.min(this.getMeasuredWidth() / 2
|
||||
- this.mCounterContainer.getWidth()
|
||||
- V.a(4.0F), 0);
|
||||
this.mCounterContainer.layout(this.mCounterContainer.getLeft() + left,
|
||||
this.mCounterContainer.getTop(),
|
||||
this.mCounterContainer.getRight() + left,
|
||||
this.mCounterContainer.getBottom());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public boolean prefersCondensedTitle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public void setCheckable(boolean var1) {
|
||||
this.refreshDrawableState();
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public void setChecked(boolean checked) {
|
||||
this.mItemData.setChecked(checked);
|
||||
|
||||
ViewCompat.setPivotX(mLargeLabel, mLargeLabel.getWidth() / 2);
|
||||
ViewCompat.setPivotY(mLargeLabel, mLargeLabel.getBaseline());
|
||||
ViewCompat.setPivotX(mSmallLabel, mSmallLabel.getWidth() / 2);
|
||||
ViewCompat.setPivotY(mSmallLabel, mSmallLabel.getBaseline());
|
||||
|
||||
if (this.mIconsModeEnabled) {
|
||||
var iconParams = (LayoutParams) this.mIcon.getLayoutParams();
|
||||
iconParams.gravity = Gravity.CENTER;
|
||||
iconParams.topMargin = 0;
|
||||
iconParams.bottomMargin = 0;
|
||||
this.mIcon.setLayoutParams(iconParams);
|
||||
|
||||
var counterContainerParams = (LayoutParams) this.mCounterContainer.getLayoutParams();
|
||||
counterContainerParams.gravity = Gravity.CENTER;
|
||||
counterContainerParams.topMargin = this.mMargin + V.a(1.5F);
|
||||
counterContainerParams.bottomMargin = this.mMargin + V.a(1.5F);
|
||||
this.mCounterContainer.setLayoutParams(counterContainerParams);
|
||||
this.mCounterContainer.setTranslationY((float) (-V.a(5.5F)));
|
||||
|
||||
this.mLargeLabel.setVisibility(GONE);
|
||||
this.mSmallLabel.setVisibility(GONE);
|
||||
} else {
|
||||
if (mShiftingModeEnabled) {
|
||||
if (checked) {
|
||||
var iconParams = (LayoutParams) this.mIcon.getLayoutParams();
|
||||
iconParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
|
||||
iconParams.topMargin = this.mMargin;
|
||||
this.mIcon.setLayoutParams(iconParams);
|
||||
|
||||
var counterContainerParams = (LayoutParams) this.mCounterContainer.getLayoutParams();
|
||||
counterContainerParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
|
||||
counterContainerParams.topMargin = this.mMargin + V.a(1.5F);
|
||||
counterContainerParams.bottomMargin = this.mMargin + V.a(1.5F);
|
||||
|
||||
this.mCounterContainer.setLayoutParams(counterContainerParams);
|
||||
this.mCounterContainer.setTranslationY(-V.a(5.5F));
|
||||
|
||||
this.mLargeLabel.setVisibility(VISIBLE);
|
||||
ViewCompat.setScaleX(this.mLargeLabel, 1.0F);
|
||||
ViewCompat.setScaleY(this.mLargeLabel, 1.0F);
|
||||
} else {
|
||||
var iconParams = (LayoutParams) this.mIcon.getLayoutParams();
|
||||
iconParams.gravity = Gravity.CENTER;
|
||||
iconParams.topMargin = this.mMargin;
|
||||
this.mIcon.setLayoutParams(iconParams);
|
||||
|
||||
var counterContainerParams = (LayoutParams) this.mCounterContainer.getLayoutParams();
|
||||
counterContainerParams.gravity = Gravity.CENTER;
|
||||
counterContainerParams.topMargin = this.mMargin + V.a(1.5F);
|
||||
counterContainerParams.bottomMargin = this.mMargin + V.a(1.5F);
|
||||
this.mCounterContainer.setLayoutParams(counterContainerParams);
|
||||
this.mCounterContainer.setTranslationY((float) (-V.a(5.5F)));
|
||||
|
||||
this.mLargeLabel.setVisibility(INVISIBLE);
|
||||
ViewCompat.setScaleX(this.mLargeLabel, 0.5F);
|
||||
ViewCompat.setScaleY(this.mLargeLabel, 0.5F);
|
||||
}
|
||||
mSmallLabel.setVisibility(INVISIBLE);
|
||||
} else {
|
||||
// ViewCompat.setScaleX(mLargeLabel, !mStaticModeEnabled && !checked ? mLargeScale : 1.0f);
|
||||
// ViewCompat.setScaleY(mLargeLabel, !mStaticModeEnabled && !checked ? mLargeScale : 1.0f);
|
||||
ViewCompat.setScaleX(mSmallLabel, !mStaticModeEnabled && checked ? mSmallScale : 1.0f);
|
||||
ViewCompat.setScaleY(mSmallLabel, !mStaticModeEnabled && checked ? mSmallScale : 1.0f);
|
||||
mLargeLabel.setTypeface(null, Typeface.BOLD);
|
||||
mSmallLabel.setTypeface(null, Typeface.BOLD);
|
||||
|
||||
int textsize;
|
||||
|
||||
if (vkme()){
|
||||
textsize = 11;
|
||||
} else {
|
||||
textsize = 10;
|
||||
}
|
||||
|
||||
mLargeLabel.setTextSize(TypedValue.COMPLEX_UNIT_SP, textsize);
|
||||
mSmallLabel.setTextSize(TypedValue.COMPLEX_UNIT_SP, textsize);
|
||||
|
||||
mLargeLabel.setVisibility(/*checked ? VISIBLE :*/ INVISIBLE);
|
||||
mSmallLabel.setVisibility(VISIBLE);//checked ? INVISIBLE : VISIBLE);
|
||||
|
||||
var iconParams = (LayoutParams) this.mIcon.getLayoutParams();
|
||||
iconParams.gravity = Gravity.CENTER;
|
||||
iconParams.topMargin = 0;
|
||||
iconParams.bottomMargin = V.a(6);
|
||||
this.mIcon.setLayoutParams(iconParams);
|
||||
|
||||
var counterContainerParams = (LayoutParams) this.mCounterContainer.getLayoutParams();
|
||||
counterContainerParams.gravity = Gravity.CENTER;
|
||||
counterContainerParams.topMargin = 0;
|
||||
counterContainerParams.bottomMargin = V.a(8);
|
||||
this.mCounterContainer.setLayoutParams(counterContainerParams);
|
||||
this.mCounterContainer.setTranslationY(-V.a(5.5F));
|
||||
}
|
||||
}
|
||||
|
||||
this.refreshDrawableState();
|
||||
}
|
||||
|
||||
public void setCounterText(@Nullable CharSequence text) {
|
||||
this.mCounter.setText(text);
|
||||
if (text == null) {
|
||||
this.mCounterContainer.setVisibility(GONE);
|
||||
} else if (TextUtils.isEmpty(text)) {
|
||||
this.mCounterContainer.setVisibility(VISIBLE);
|
||||
this.mCounter.setVisibility(GONE);
|
||||
this.mDot.setVisibility(VISIBLE);
|
||||
} else {
|
||||
this.mCounterContainer.setVisibility(VISIBLE);
|
||||
this.mCounter.setVisibility(VISIBLE);
|
||||
this.mDot.setVisibility(mItemPos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setEnabled(boolean b) {
|
||||
super.setEnabled(b);
|
||||
this.mSmallLabel.setEnabled(b);
|
||||
this.mLargeLabel.setEnabled(b);
|
||||
this.mIcon.setEnabled(b);
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public void setIcon(Drawable drawable) {
|
||||
if (drawable != null) {
|
||||
if (drawable.getConstantState() != null)
|
||||
drawable = drawable.getConstantState().newDrawable();
|
||||
|
||||
drawable = DrawableCompat.wrap(drawable).mutate();
|
||||
DrawableCompat.setTintList(drawable, this.mColorStateList);
|
||||
}
|
||||
|
||||
this.mIcon.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public void setIconTintList(ColorStateList colorStateList) {
|
||||
this.mColorStateList = colorStateList;
|
||||
MenuItemImpl impl = this.mItemData;
|
||||
if (impl != null) {
|
||||
this.setIcon(impl.getIcon());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setIconsMode(boolean enabled) {
|
||||
this.mIconsModeEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setStaticMode(boolean enabled) {
|
||||
this.mStaticModeEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setItemBackground(int resId) {
|
||||
ViewCompat.setBackground(this, resId != 0 ? ContextCompat.getDrawable(this.getContext(), resId) : null);
|
||||
}
|
||||
|
||||
public void setItemPosition(int pos) {
|
||||
this.mItemPos = pos;
|
||||
}
|
||||
|
||||
public void setShiftingMode(boolean var1) {
|
||||
this.mShiftingModeEnabled = var1;
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public void setShortcut(boolean b, char c) {
|
||||
}
|
||||
|
||||
public void setTextColor(ColorStateList colorStateList) {
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public void setTitle(CharSequence title) {
|
||||
this.mSmallLabel.setText(title);
|
||||
this.mLargeLabel.setText(title);
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public boolean showsIcon() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package ru.vtosters.lite.deviceinfo;
|
||||
|
||||
public class Device{
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class Device {
|
||||
private String androidId;
|
||||
private String bluetoothMac;
|
||||
private String boardName;
|
||||
@@ -16,81 +18,82 @@ public class Device{
|
||||
private String serialId;
|
||||
private String wifiMac;
|
||||
|
||||
public Device withSerialId(String str){
|
||||
public Device withSerialId(String str) {
|
||||
this.serialId = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withAndroidId(String str){
|
||||
public Device withAndroidId(String str) {
|
||||
this.androidId = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withWifiMac(String str){
|
||||
public Device withWifiMac(String str) {
|
||||
this.wifiMac = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withBluetoothMac(String str){
|
||||
public Device withBluetoothMac(String str) {
|
||||
this.bluetoothMac = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withSdkVersion(int i){
|
||||
public Device withSdkVersion(int i) {
|
||||
this.sdkVersion = i;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withFirmwareId(String str){
|
||||
public Device withFirmwareId(String str) {
|
||||
this.firmwareId = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withFirmwareDisplay(String str){
|
||||
public Device withFirmwareDisplay(String str) {
|
||||
this.firmwareDisplay = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withProductName(String str){
|
||||
public Device withProductName(String str) {
|
||||
this.productName = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withDeviceName(String str){
|
||||
public Device withDeviceName(String str) {
|
||||
this.deviceName = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withBoardName(String str){
|
||||
public Device withBoardName(String str) {
|
||||
this.boardName = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withCpuAbi(String str){
|
||||
public Device withCpuAbi(String str) {
|
||||
this.cpuAbi = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withManufacturerName(String str){
|
||||
public Device withManufacturerName(String str) {
|
||||
this.manufacturerName = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withBrandName(String str){
|
||||
public Device withBrandName(String str) {
|
||||
this.brandName = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Device withModelName(String str){
|
||||
public Device withModelName(String str) {
|
||||
this.modelName = str;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
@NonNull
|
||||
public String toString() {
|
||||
return "Device{serialId='" + this.serialId + "', androidId='" + this.androidId + "', wifiMac='" + this.wifiMac + "', bluetoothMac='" + this.bluetoothMac + "'}";
|
||||
}
|
||||
|
||||
public String toDeviceName(){
|
||||
public String toDeviceName() {
|
||||
return "Device{sdkVersion=" + this.sdkVersion + ", productName='" + this.productName + "', deviceName='" + this.deviceName + "', boardName='" + this.boardName + "', cpuAbi='" + this.cpuAbi + "', manufacturerName='" + this.manufacturerName + "', brandName='" + this.brandName + "', modelName='" + this.modelName + "'}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ru.vtosters.lite.deviceinfo;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.Context;
|
||||
import android.net.wifi.WifiInfo;
|
||||
@@ -18,16 +19,17 @@ import java.lang.reflect.Method;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.Collections;
|
||||
|
||||
public class DeviceInfoCollector{
|
||||
public class DeviceInfoCollector {
|
||||
private static final String TAG = "DeviceInfoCollector";
|
||||
|
||||
public Device collect(Context context){
|
||||
public Device collect(Context context) {
|
||||
return new Device().withSerialId(serialId()).withAndroidId(androidId(context)).withWifiMac(wifiMac(context)).withBluetoothMac(bluetoothMac(context)).withSdkVersion(Build.VERSION.SDK_INT).withFirmwareId(Build.ID).withFirmwareDisplay(Build.DISPLAY).withProductName(Build.PRODUCT).withDeviceName(Build.DEVICE).withBoardName(Build.BOARD).withCpuAbi(Build.CPU_ABI).withManufacturerName(Build.MANUFACTURER).withBrandName(Build.BRAND).withModelName(Build.MODEL);
|
||||
}
|
||||
|
||||
private String serialId(){
|
||||
private String serialId() {
|
||||
String str;
|
||||
try {
|
||||
@SuppressLint("PrivateApi")
|
||||
Class<?> cls = Class.forName("android.os.SystemProperties");
|
||||
Method method = cls.getMethod("get", String.class);
|
||||
str = (String) method.invoke(cls, "gsm.sn1");
|
||||
@@ -53,11 +55,12 @@ public class DeviceInfoCollector{
|
||||
return null;
|
||||
}
|
||||
|
||||
private String androidId(Context context){
|
||||
@SuppressLint("HardwareIds")
|
||||
private String androidId(Context context) {
|
||||
return Settings.Secure.getString(context.getContentResolver(), "android_id").toLowerCase();
|
||||
}
|
||||
|
||||
private String wifiMac(Context context){
|
||||
private String wifiMac(Context context) {
|
||||
String wifiMacFromManager = wifiMacFromManager(context);
|
||||
if (isInvalidMac(wifiMacFromManager)) {
|
||||
wifiMacFromManager = wifiMacFromNetworkInterfaces();
|
||||
@@ -74,7 +77,7 @@ public class DeviceInfoCollector{
|
||||
return null;
|
||||
}
|
||||
|
||||
private String wifiMacFromManager(Context context){
|
||||
private String wifiMacFromManager(Context context) {
|
||||
WifiInfo connectionInfo;
|
||||
try {
|
||||
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||
@@ -88,7 +91,7 @@ public class DeviceInfoCollector{
|
||||
}
|
||||
}
|
||||
|
||||
private String wifiMacFromNetworkInterfaces(){
|
||||
private String wifiMacFromNetworkInterfaces() {
|
||||
try {
|
||||
for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) {
|
||||
if ("wlan0".equalsIgnoreCase(networkInterface.getName())) {
|
||||
@@ -99,7 +102,7 @@ public class DeviceInfoCollector{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int length = hardwareAddress.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(String.format("%02X:", Byte.valueOf(hardwareAddress[i])));
|
||||
sb.append(String.format("%02X:", hardwareAddress[i]));
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
@@ -114,7 +117,7 @@ public class DeviceInfoCollector{
|
||||
}
|
||||
}
|
||||
|
||||
private String wifiMacFromFileSystem(){
|
||||
private String wifiMacFromFileSystem() {
|
||||
try {
|
||||
FileReader fileReader = new FileReader("/sys/class/net/wlan0/address");
|
||||
try {
|
||||
@@ -137,7 +140,7 @@ public class DeviceInfoCollector{
|
||||
return null;
|
||||
}
|
||||
|
||||
private String bluetoothMac(Context context){
|
||||
private String bluetoothMac(Context context) {
|
||||
String bluetoothMacFromAdapter = bluetoothMacFromAdapter();
|
||||
if (isInvalidMac(bluetoothMacFromAdapter)) {
|
||||
bluetoothMacFromAdapter = bluetoothMacFromContentResolver(context);
|
||||
@@ -151,7 +154,7 @@ public class DeviceInfoCollector{
|
||||
return null;
|
||||
}
|
||||
|
||||
private String bluetoothMacFromAdapter(){
|
||||
private String bluetoothMacFromAdapter() {
|
||||
try {
|
||||
BluetoothAdapter defaultAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (defaultAdapter == null) {
|
||||
@@ -173,7 +176,7 @@ public class DeviceInfoCollector{
|
||||
}
|
||||
}
|
||||
|
||||
private String bluetoothMacFromContentResolver(Context context){
|
||||
private String bluetoothMacFromContentResolver(Context context) {
|
||||
try {
|
||||
return Settings.Secure.getString(context.getContentResolver(), "bluetooth_address");
|
||||
} catch (Exception e) {
|
||||
@@ -182,11 +185,11 @@ public class DeviceInfoCollector{
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInvalidSerial(String str){
|
||||
private boolean isInvalidSerial(String str) {
|
||||
return TextUtils.isEmpty(str) || EnvironmentCompat.MEDIA_UNKNOWN.equalsIgnoreCase(str);
|
||||
}
|
||||
|
||||
private boolean isInvalidMac(String str){
|
||||
private boolean isInvalidMac(String str) {
|
||||
return TextUtils.isEmpty(str) || "02:00:00:00:00:00".equalsIgnoreCase(str) || "00:00:00:00:00:00".equalsIgnoreCase(str);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
package ru.vtosters.lite.utils;
|
||||
package ru.vtosters.lite.deviceinfo;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
@@ -6,36 +6,36 @@ import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class OEMDetector{
|
||||
public static boolean isOEM(){
|
||||
public class OEMDetector {
|
||||
public static boolean isOEM() {
|
||||
return isMIUI() || isEMUI() || isFlyme() || isZenUI() || isSamsung() || isVivo();
|
||||
}
|
||||
|
||||
private static boolean isMIUI(){
|
||||
private static boolean isMIUI() {
|
||||
return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.name"));
|
||||
}
|
||||
|
||||
private static boolean isEMUI(){
|
||||
private static boolean isEMUI() {
|
||||
return !TextUtils.isEmpty(getSystemProperty("ro.build.hw_emui_api_level"));
|
||||
}
|
||||
|
||||
private static boolean isZenUI(){
|
||||
private static boolean isZenUI() {
|
||||
return !TextUtils.isEmpty(getSystemProperty("ro.asus.ui"));
|
||||
}
|
||||
|
||||
private static boolean isVivo(){
|
||||
private static boolean isVivo() {
|
||||
return !TextUtils.isEmpty(getSystemProperty("ro.vivo.os.version")) || !TextUtils.isEmpty(getSystemProperty("ro.vivo.rom")) || !TextUtils.isEmpty(getSystemProperty("ro.vivo.rom.version")) || !TextUtils.isEmpty(getSystemProperty("ro.vivo.build.version.sdk"));
|
||||
}
|
||||
|
||||
private static boolean isSamsung(){
|
||||
private static boolean isSamsung() {
|
||||
return !TextUtils.isEmpty(getSystemProperty("ro.config.knox"));
|
||||
}
|
||||
|
||||
private static boolean isFlyme(){
|
||||
private static boolean isFlyme() {
|
||||
return !TextUtils.isEmpty(getSystemProperty("ro.build.ro.meizu.rom.config")) || !TextUtils.isEmpty(getSystemProperty("persist.sys.static_blur_mode")) || !TextUtils.isEmpty(getSystemProperty("persist.sys.use.flyme.icon"));
|
||||
}
|
||||
|
||||
private static String getSystemProperty(String str){
|
||||
private static String getSystemProperty(String str) {
|
||||
BufferedReader bufferedReader;
|
||||
try {
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("getprop " + str).getInputStream()), 1024);
|
||||
@@ -1,70 +1,324 @@
|
||||
package ru.vtosters.lite.dnr;
|
||||
|
||||
import static com.vk.im.engine.h.im_ic_done;
|
||||
import static com.vk.im.engine.h.im_ic_edit_msg;
|
||||
import static com.vk.im.engine.h.im_ic_more_vertical;
|
||||
import static com.vk.im.engine.h.im_ic_pinned_msg_hide;
|
||||
import static com.vk.im.engine.h.im_ic_pinned_msg_show;
|
||||
import static com.vk.im.engine.h.im_ic_write_msg;
|
||||
import static com.vk.im.ui.c.im_ic_keyboard;
|
||||
import static ru.vtosters.lite.dnr.DNRModule.hookDNR;
|
||||
import static ru.vtosters.lite.dnr.DNRModule.hookDNT;
|
||||
import static ru.vtosters.lite.dnr.DNRModule.isDnrEnabledFor;
|
||||
import static ru.vtosters.lite.dnr.DNRModule.isDntEnabledFor;
|
||||
import static ru.vtosters.lite.utils.Globals.getIdentifier;
|
||||
import static ru.vtosters.lite.encryption.EncryptProvider.decryptMessage;
|
||||
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.vk.core.network.Network;
|
||||
import com.vk.im.engine.ImEngine1;
|
||||
import com.vk.im.engine.events.OnDialogUpdateEvent;
|
||||
import com.vk.im.engine.models.EntityIntMap;
|
||||
import com.vk.im.engine.models.ProfilesSimpleInfo;
|
||||
import com.vk.im.engine.models.dialogs.Dialog;
|
||||
import com.vk.im.engine.models.messages.Msg;
|
||||
import com.vk.im.engine.models.messages.MsgFromUser;
|
||||
import com.vk.im.ui.components.common.DialogAction;
|
||||
import com.vk.im.ui.components.common.MsgAction;
|
||||
import com.vk.im.ui.components.viewcontrollers.popup.DelegateMsg;
|
||||
import com.vk.im.ui.views.dialog_actions.DialogActionsListView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class DNRInjector{
|
||||
public static void inject(Dialog dialog, List<DialogAction> list){
|
||||
int peerId = dialog.getId();
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import ru.vtosters.lite.encryption.EncryptProvider;
|
||||
import ru.vtosters.lite.encryption.base.IMProcessor;
|
||||
import ru.vtosters.lite.hooks.CryptImHook;
|
||||
import ru.vtosters.lite.ui.dialogs.Translate;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class DNRInjector {
|
||||
public static void inject(Dialog dialog, List<DialogAction> list) {
|
||||
int peerId = 0;
|
||||
|
||||
if (dialog != null) {
|
||||
peerId = dialog.getId();
|
||||
}
|
||||
|
||||
list.add(DialogAction.pinmsg);
|
||||
list.add(DialogAction.unpinmsg);
|
||||
|
||||
if (isDnrEnabledFor(peerId)) {
|
||||
list.add(DialogAction.valueOf("DNR_OFF"));
|
||||
list.add(DialogAction.DNR_OFF);
|
||||
} else {
|
||||
list.add(DialogAction.valueOf("DNR_ON"));
|
||||
list.add(DialogAction.DNR_ON);
|
||||
}
|
||||
|
||||
if (isDntEnabledFor(peerId)) {
|
||||
list.add(DialogAction.valueOf("DNT_OFF"));
|
||||
list.add(DialogAction.DNT_OFF);
|
||||
} else {
|
||||
list.add(DialogAction.valueOf("DNT_ON"));
|
||||
list.add(DialogAction.DNT_ON);
|
||||
}
|
||||
|
||||
list.add(DialogAction.ENCRYPT);
|
||||
IMProcessor prov = EncryptProvider.getProcessorFor(peerId);
|
||||
if (prov != null && !prov.isPublic()) {
|
||||
list.add(DialogAction.ENCRYPT_SETT);
|
||||
}
|
||||
}
|
||||
|
||||
public static LinkedHashMap<DialogAction, Integer> injectToHashMap(LinkedHashMap<DialogAction, Integer> hashMap){
|
||||
hashMap.put(DialogAction.valueOf("DNR_ON"), getIdentifier("DNR_ON", "string"));
|
||||
hashMap.put(DialogAction.valueOf("DNR_OFF"), getIdentifier("DNR_OFF", "string"));
|
||||
hashMap.put(DialogAction.valueOf("DNT_ON"), getIdentifier("DNT_ON", "string"));
|
||||
hashMap.put(DialogAction.valueOf("DNT_OFF"), getIdentifier("DNT_OFF", "string"));
|
||||
public static LinkedHashMap<DialogAction, Integer> injectToHashMap(LinkedHashMap<DialogAction, Integer> hashMap) {
|
||||
hashMap.put(DialogAction.DNR_ON, getIdentifier("DNR_ON", "string"));
|
||||
hashMap.put(DialogAction.DNR_OFF, getIdentifier("DNR_OFF", "string"));
|
||||
hashMap.put(DialogAction.DNT_ON, getIdentifier("DNT_ON", "string"));
|
||||
hashMap.put(DialogAction.DNT_OFF, getIdentifier("DNT_OFF", "string"));
|
||||
|
||||
hashMap.put(DialogAction.ENCRYPT, getIdentifier("encryption", "string"));
|
||||
hashMap.put(DialogAction.ENCRYPT_SETT, getIdentifier("encryption_sett", "string"));
|
||||
|
||||
// hashMap.put(DialogAction.pinmsg, getIdentifier("pinmsg", "string"));
|
||||
// hashMap.put(DialogAction.unpinmsg, getIdentifier("unpinmsg", "string"));
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
public static boolean onClick(Dialog dialog, DialogAction action){
|
||||
var id = dialog.getId();
|
||||
@SuppressLint("ResourceType")
|
||||
public static List<Object> injectToList(List<Object> actions) {
|
||||
var list = new ArrayList<>(actions);
|
||||
|
||||
if (action == DialogAction.valueOf("DNR_ON")) {
|
||||
list.add(new DialogActionsListView.b.a(DialogAction.DNR_ON, 2, im_ic_pinned_msg_hide, getIdentifier("DNR_ON", "string"))); // DialogAction, Int, Icon, String
|
||||
list.add(new DialogActionsListView.b.a(DialogAction.DNR_OFF, 2, im_ic_pinned_msg_show, getIdentifier("DNR_OFF", "string"))); // DialogAction, Int, Icon, String
|
||||
|
||||
list.add(new DialogActionsListView.b.a(DialogAction.DNT_ON, 2, im_ic_edit_msg, getIdentifier("DNT_ON", "string"))); // DialogAction, Int, Icon, String
|
||||
list.add(new DialogActionsListView.b.a(DialogAction.DNT_OFF, 2, im_ic_edit_msg, getIdentifier("DNT_OFF", "string"))); // DialogAction, Int, Icon, String
|
||||
|
||||
list.add(new DialogActionsListView.b.a(DialogAction.ENCRYPT, 3, im_ic_keyboard, getIdentifier("encryption", "string"))); // DialogAction, Int, Icon, String
|
||||
list.add(new DialogActionsListView.b.a(DialogAction.ENCRYPT_SETT, 3, im_ic_more_vertical, getIdentifier("encryption_sett", "string"))); // DialogAction, Int, Icon, String
|
||||
|
||||
list.add(new DialogActionsListView.b.a(DialogAction.MARK_AS_READ, 4, im_ic_done, getIdentifier("vkim_dialogs_list_option_mark_as_read", "string"))); // DialogAction, Int, Icon, String
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static void forceInvalidateDialogActions(Dialog d) {
|
||||
EntityIntMap<Dialog> map = new EntityIntMap<>();
|
||||
map.a(d.getId(), d);
|
||||
ImEngine1.a().a(new OnDialogUpdateEvent(null, map));
|
||||
}
|
||||
|
||||
public static List<DialogAction> injectToListAccess(List<DialogAction> actions, Dialog dialog) {
|
||||
int peerId = 0;
|
||||
|
||||
if (dialog != null) {
|
||||
peerId = dialog.getId();
|
||||
}
|
||||
|
||||
if (isDnrEnabledFor(peerId)) {
|
||||
actions.add(DialogAction.DNR_OFF);
|
||||
} else {
|
||||
actions.add(DialogAction.DNR_ON);
|
||||
}
|
||||
|
||||
if (isDntEnabledFor(peerId)) {
|
||||
actions.add(DialogAction.DNT_OFF);
|
||||
} else {
|
||||
actions.add(DialogAction.DNT_ON);
|
||||
}
|
||||
|
||||
actions.add(DialogAction.ENCRYPT);
|
||||
IMProcessor prov = EncryptProvider.getProcessorFor(peerId);
|
||||
if (prov != null && !prov.isPublic()) {
|
||||
actions.add(DialogAction.ENCRYPT_SETT);
|
||||
}
|
||||
|
||||
actions.add(DialogAction.MARK_AS_READ);
|
||||
return actions;
|
||||
}
|
||||
|
||||
public static boolean onClickHeader(DialogAction action, Dialog dialog) {
|
||||
int peerId = 0;
|
||||
|
||||
if (dialog != null) {
|
||||
peerId = dialog.getId();
|
||||
}
|
||||
|
||||
if (action == DialogAction.MARK_AS_READ) {
|
||||
DNRModule.hookRead(dialog);
|
||||
forceInvalidateDialogActions(dialog);
|
||||
}
|
||||
|
||||
if (action == DialogAction.DNR_ON) {
|
||||
setDnr(dialog, true);
|
||||
forceInvalidateDialogActions(dialog);
|
||||
return true;
|
||||
} else if (action == DialogAction.valueOf("DNR_OFF")) {
|
||||
} else if (action == DialogAction.DNR_OFF) {
|
||||
setDnr(dialog, false);
|
||||
forceInvalidateDialogActions(dialog);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == DialogAction.valueOf("DNT_ON")) {
|
||||
if (action == DialogAction.DNT_ON) {
|
||||
setDnt(dialog, true);
|
||||
forceInvalidateDialogActions(dialog);
|
||||
return true;
|
||||
} else if (action == DialogAction.valueOf("DNT_OFF")) {
|
||||
} else if (action == DialogAction.DNT_OFF) {
|
||||
setDnt(dialog, false);
|
||||
forceInvalidateDialogActions(dialog);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == DialogAction.ENCRYPT_SETT) {
|
||||
CryptImHook.hookPref(peerId);
|
||||
return true;
|
||||
} else if (action == DialogAction.ENCRYPT) {
|
||||
CryptImHook.hook(peerId, dialog);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void setDnr(Dialog dialog, boolean value){
|
||||
hookDNR(dialog.getId());
|
||||
public static boolean onClick(Dialog dialog, DialogAction action) {
|
||||
int peerId = 0;
|
||||
|
||||
if (dialog != null) {
|
||||
peerId = dialog.getId();
|
||||
}
|
||||
|
||||
if (action == DialogAction.MARK_AS_READ) {
|
||||
DNRModule.hookRead(dialog);
|
||||
}
|
||||
|
||||
if (action == DialogAction.DNR_ON) {
|
||||
setDnr(dialog, true);
|
||||
return true;
|
||||
} else if (action == DialogAction.DNR_OFF) {
|
||||
setDnr(dialog, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == DialogAction.DNT_ON) {
|
||||
setDnt(dialog, true);
|
||||
return true;
|
||||
} else if (action == DialogAction.DNT_OFF) {
|
||||
setDnt(dialog, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == DialogAction.pinmsg) {
|
||||
pinnedMsg(peerId, true);
|
||||
return true;
|
||||
} else if (action == DialogAction.unpinmsg) {
|
||||
pinnedMsg(peerId, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == DialogAction.ENCRYPT_SETT) {
|
||||
CryptImHook.hookPref(peerId);
|
||||
return true;
|
||||
} else if (action == DialogAction.ENCRYPT) {
|
||||
CryptImHook.hook(peerId, dialog);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void setDnt(Dialog dialog, boolean value){
|
||||
hookDNT(dialog.getId());
|
||||
public static LinkedHashMap<MsgAction, DelegateMsg.a.a> injectToHashMapMsg(LinkedHashMap<MsgAction, DelegateMsg.a.a> hashMap) {
|
||||
hashMap.put(MsgAction.valueOf("TRANSLATE"), new DelegateMsg.a.a(getIdentifier("translator", "string")));
|
||||
hashMap.put(MsgAction.valueOf("READTO"), new DelegateMsg.a.a(getIdentifier("readto", "string")));
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
public static boolean onClickMsg(Context context, MsgAction action, Msg msg) {
|
||||
var text = ((MsgFromUser) msg).f();
|
||||
var peerId = msg.v1();
|
||||
var fullMsg = ((MsgFromUser) msg).j2(); // text + reply
|
||||
var reply = fullMsg.substring(text.length() + 1);
|
||||
|
||||
if (action == MsgAction.valueOf("READTO")) {
|
||||
DNRModule.hookReadStartMsgTo(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
var isTextExist = !text.isEmpty() && !text.equals(" ");
|
||||
var isReplyExist = !reply.isEmpty() && !reply.equals(" ");
|
||||
|
||||
|
||||
if (isReplyExist) {
|
||||
reply = decryptMessage(reply, peerId);
|
||||
}
|
||||
|
||||
if (isTextExist) {
|
||||
text = decryptMessage(text, peerId);
|
||||
}
|
||||
|
||||
if (action == MsgAction.valueOf("TRANSLATE")) {
|
||||
if (isTextExist && isReplyExist) {
|
||||
Translate.showTranslatedText(context, text + "\n\n" + AndroidUtils.getString("translator_reply") + "\n" + reply);
|
||||
} else if (isReplyExist) {
|
||||
Translate.showTranslatedText(context, AndroidUtils.getString("translator_reply") + "\n" + reply);
|
||||
} else if (isTextExist) {
|
||||
Translate.showTranslatedText(context, text);
|
||||
} else {
|
||||
sendToast(AndroidUtils.getString("translator_no_text"));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void pinnedMsg(int dialogid, boolean needToBePinned) {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
var request = new Request.a()
|
||||
.b("https://api.vk.com/method/" + (needToBePinned ? "messages.pinConversation" : "messages.unpinConversation") + "?peer_id=" + dialogid + "&access_token=" + getUserToken() + "&v=5.119")
|
||||
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8"))
|
||||
.a();
|
||||
|
||||
try {
|
||||
var response = new OkHttpClient().a(request).execute().a().g();
|
||||
Log.d("Pins", response);
|
||||
} catch (IOException e) {
|
||||
Log.e("Pins", "Error while pinning message", e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
thread.start();
|
||||
|
||||
sendToast(AndroidUtils.getString("pin_dialog") + " " + (needToBePinned ? AndroidUtils.getString("dialog_pinned") : AndroidUtils.getString("dialog_unpinned")));
|
||||
}
|
||||
|
||||
public static void setDnr(Dialog dialog, boolean value) {
|
||||
int peerId = 0;
|
||||
|
||||
if (dialog != null) {
|
||||
peerId = dialog.getId();
|
||||
}
|
||||
|
||||
hookDNR(peerId);
|
||||
}
|
||||
|
||||
public static void setDnt(Dialog dialog, boolean value) {
|
||||
int peerId = 0;
|
||||
|
||||
if (dialog != null) {
|
||||
peerId = dialog.getId();
|
||||
}
|
||||
|
||||
hookDNT(peerId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,66 +1,73 @@
|
||||
package ru.vtosters.lite.dnr;
|
||||
|
||||
import static ru.vtosters.lite.net.Request.makeRequest;
|
||||
import static ru.vtosters.lite.utils.Globals.getUserToken;
|
||||
import static ru.vtosters.lite.utils.Proxy.getApi;
|
||||
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken;
|
||||
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.vk.core.util.ToastUtils;
|
||||
import com.vk.im.engine.commands.messages.SetUserActivityCmd;
|
||||
import com.vk.im.engine.models.dialogs.Dialog;
|
||||
import com.vk.im.engine.models.messages.Msg;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ru.vtosters.lite.dnr.helpers.DoNotReadDBHelper;
|
||||
import ru.vtosters.lite.dnr.helpers.DoNotTypeDBHelper;
|
||||
|
||||
public class DNRModule{
|
||||
public class DNRModule {
|
||||
public static DoNotReadDBHelper mDoNotReadDBHelper = new DoNotReadDBHelper();
|
||||
public static DoNotTypeDBHelper mDoNotTypeDBHelper = new DoNotTypeDBHelper();
|
||||
public static Dialog mDialog;
|
||||
|
||||
public static boolean isDnrEnabledFor(int id){
|
||||
public static boolean isDnrEnabledFor(int id) {
|
||||
var isEnabled = mDoNotReadDBHelper.isEnabledForPeerId(id);
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
public static List<Integer> getDnrEnabled(){
|
||||
public static List<Integer> getDnrEnabled() {
|
||||
return mDoNotReadDBHelper.get();
|
||||
}
|
||||
|
||||
public static List<Integer> getDntEnabled(){
|
||||
public static List<Integer> getDntEnabled() {
|
||||
return mDoNotTypeDBHelper.get();
|
||||
}
|
||||
|
||||
public static boolean isDntEnabledFor(int id){
|
||||
public static boolean isDntEnabledFor(int id) {
|
||||
var isEnabled = mDoNotTypeDBHelper.isEnabledForPeerId(id);
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
public static boolean isDntEnabledFor(SetUserActivityCmd cmd){
|
||||
public static boolean isDntEnabledFor(SetUserActivityCmd cmd) {
|
||||
return isDntEnabledFor(cmd.b);
|
||||
}
|
||||
|
||||
public static boolean isDnrEnabledFor(Dialog dialog){
|
||||
public static boolean isDnrEnabledFor(Dialog dialog) {
|
||||
if (dialog == null) return false;
|
||||
return isDnrEnabledFor(dialog.getId());
|
||||
}
|
||||
|
||||
public static boolean isDntEnabledFor(Dialog dialog){
|
||||
public static boolean isDntEnabledFor(Dialog dialog) {
|
||||
if (dialog == null) return false;
|
||||
return isDntEnabledFor(dialog.getId());
|
||||
}
|
||||
|
||||
public static void hookRead(Dialog dialog){
|
||||
makeRequest("https://" + getApi() + "/method/messages.markAsRead?start_message_id=" + dialog.F1() + "&peer_id=" + dialog.getId() + "&v=5.91&access_token=" + getUserToken(), response -> {
|
||||
ToastUtils.a("Чат помечен как прочитанный!");
|
||||
public static void hookRead(Dialog dialog) {
|
||||
makeRequest("https://" + getApi() + "/method/messages.markAsRead?start_message_id=" + dialog.F1() + "&peer_id=" + dialog.getId() + "&v=5.119&access_token=" + getUserToken(), response -> {
|
||||
});
|
||||
}
|
||||
|
||||
public static void hookDNR(int peerId){
|
||||
public static void hookReadStartMsgTo(Msg dialog) {
|
||||
Log.d("DNR", "hookReadStartMsgTo: " + dialog.C1() + " " + dialog.v1());
|
||||
makeRequest("https://" + getApi() + "/method/messages.markAsRead?start_message_id=" + dialog.C1() + "&peer_id=" + dialog.v1() + "&v=5.119&access_token=" + getUserToken(), response -> {
|
||||
});
|
||||
}
|
||||
|
||||
public static void hookDNR(int peerId) {
|
||||
mDoNotReadDBHelper.setEnabledForPeerId(peerId, !mDoNotReadDBHelper.isEnabledForPeerId(peerId));
|
||||
}
|
||||
|
||||
public static void hookDNT(int peerId){
|
||||
public static void hookDNT(int peerId) {
|
||||
mDoNotTypeDBHelper.setEnabledForPeerId(peerId, !mDoNotTypeDBHelper.isEnabledForPeerId(peerId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,16 @@ package ru.vtosters.lite.dnr;
|
||||
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
|
||||
public class DNRPrefs{
|
||||
public static boolean getStoriesRead(){
|
||||
public class DNRPrefs {
|
||||
public static boolean getStoriesRead() {
|
||||
return getBoolValue("read_s", false);
|
||||
}
|
||||
|
||||
public static boolean getVoiceListened(){
|
||||
public static boolean getVoiceListened() {
|
||||
return getBoolValue("listen_v", false);
|
||||
}
|
||||
|
||||
public static boolean getMarkAsReadWithoutExceptions(int peerId){
|
||||
public static boolean getMarkAsReadWithoutExceptions(int peerId) {
|
||||
if (readPM(peerId))
|
||||
return true;
|
||||
if (readConversations(peerId))
|
||||
@@ -19,43 +19,43 @@ public class DNRPrefs{
|
||||
return readBots(peerId);
|
||||
}
|
||||
|
||||
public static boolean getMarkAsRead(int peerId){
|
||||
public static boolean getMarkAsRead(int peerId) {
|
||||
return isInDNRExceptions(peerId);
|
||||
}
|
||||
|
||||
public static boolean isInDNRExceptions(int peerId){
|
||||
public static boolean isInDNRExceptions(int peerId) {
|
||||
return DNRModule.mDoNotReadDBHelper.isEnabledForPeerId(peerId);
|
||||
}
|
||||
|
||||
public static boolean isInDNTExceptions(int peerId){
|
||||
public static boolean isInDNTExceptions(int peerId) {
|
||||
return DNRModule.mDoNotTypeDBHelper.isEnabledForPeerId(peerId);
|
||||
}
|
||||
|
||||
public static boolean readPM(int peer){
|
||||
public static boolean readPM(int peer) {
|
||||
return (peer > 0 && peer < 2000000000) && getBoolValue("read_pm", false);
|
||||
}
|
||||
|
||||
public static boolean readConversations(int peer){
|
||||
public static boolean readConversations(int peer) {
|
||||
return (peer > 2000000000) && getBoolValue("read_conversations", false);
|
||||
}
|
||||
|
||||
public static boolean readBots(int peer){
|
||||
public static boolean readBots(int peer) {
|
||||
return (peer < 0) && getBoolValue("read_bot", false);
|
||||
}
|
||||
|
||||
public static boolean writePM(int peer){
|
||||
public static boolean writePM(int peer) {
|
||||
return (peer > 0 && peer < 2000000000) && getBoolValue("write_pm", false);
|
||||
}
|
||||
|
||||
public static boolean writeConversations(int peer){
|
||||
public static boolean writeConversations(int peer) {
|
||||
return (peer > 2000000000) && getBoolValue("write_conversations", false);
|
||||
}
|
||||
|
||||
public static boolean writeBots(int peer){
|
||||
public static boolean writeBots(int peer) {
|
||||
return (peer < 0) && getBoolValue("write_bot", false);
|
||||
}
|
||||
|
||||
public static boolean getActivityWithoutExceptions(int peerId){
|
||||
public static boolean getActivityWithoutExceptions(int peerId) {
|
||||
if (writePM(peerId))
|
||||
return true;
|
||||
if (writeConversations(peerId))
|
||||
@@ -63,7 +63,7 @@ public class DNRPrefs{
|
||||
return writeBots(peerId);
|
||||
}
|
||||
|
||||
public static boolean getActivity(int peerId){
|
||||
public static boolean getActivity(int peerId) {
|
||||
return isInDNTExceptions(peerId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ru.vtosters.lite.dnr.helpers;
|
||||
|
||||
import static ru.vtosters.lite.utils.Globals.getContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
@@ -12,22 +12,22 @@ import java.util.List;
|
||||
|
||||
import ru.vtosters.lite.dnr.DNRPrefs;
|
||||
|
||||
public class DoNotReadDBHelper extends SQLiteOpenHelper{
|
||||
public DoNotReadDBHelper(){
|
||||
super(getContext(), "dnr", null, 1);
|
||||
public class DoNotReadDBHelper extends SQLiteOpenHelper {
|
||||
public DoNotReadDBHelper() {
|
||||
super(getGlobalContext(), "dnr", null, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db){
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("create table dnr (peerId integer primary key, enabled integer)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
|
||||
}
|
||||
|
||||
public boolean isEnabledForPeerId(int peerId){
|
||||
public boolean isEnabledForPeerId(int peerId) {
|
||||
try (Cursor c = getReadableDatabase().query("dnr", null, null, null, null, null, null)) {
|
||||
if (c.moveToFirst()) {
|
||||
int peerIdIndex = c.getColumnIndex("peerId");
|
||||
@@ -36,7 +36,7 @@ public class DoNotReadDBHelper extends SQLiteOpenHelper{
|
||||
do {
|
||||
if (c.getInt(peerIdIndex) == peerId)
|
||||
return c.getInt(enabledIndex) == 1;
|
||||
} while(c.moveToNext());
|
||||
} while (c.moveToNext());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -45,7 +45,7 @@ public class DoNotReadDBHelper extends SQLiteOpenHelper{
|
||||
return DNRPrefs.getMarkAsReadWithoutExceptions(peerId);
|
||||
}
|
||||
|
||||
public List<Integer> get(){
|
||||
public List<Integer> get() {
|
||||
ArrayList<Integer> rs = new ArrayList<>();
|
||||
|
||||
try (Cursor c = getReadableDatabase().query("dnr", null, null, null, null, null, null)) {
|
||||
@@ -57,7 +57,7 @@ public class DoNotReadDBHelper extends SQLiteOpenHelper{
|
||||
if (c.getInt(enabledIndex) == 1) {
|
||||
rs.add(c.getInt(peerIdIndex));
|
||||
}
|
||||
} while(c.moveToNext());
|
||||
} while (c.moveToNext());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -66,7 +66,7 @@ public class DoNotReadDBHelper extends SQLiteOpenHelper{
|
||||
return rs;
|
||||
}
|
||||
|
||||
public void setEnabledForPeerId(int peerId, boolean enabled){
|
||||
public void setEnabledForPeerId(int peerId, boolean enabled) {
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put("enabled", enabled ? 1 : 0);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ru.vtosters.lite.dnr.helpers;
|
||||
|
||||
import static ru.vtosters.lite.utils.Globals.getContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
@@ -12,22 +12,22 @@ import java.util.List;
|
||||
|
||||
import ru.vtosters.lite.dnr.DNRPrefs;
|
||||
|
||||
public class DoNotTypeDBHelper extends SQLiteOpenHelper{
|
||||
public DoNotTypeDBHelper(){
|
||||
super(getContext(), "dnt", null, 1);
|
||||
public class DoNotTypeDBHelper extends SQLiteOpenHelper {
|
||||
public DoNotTypeDBHelper() {
|
||||
super(getGlobalContext(), "dnt", null, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db){
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("create table dnt (peerId integer primary key, enabled integer)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
|
||||
}
|
||||
|
||||
public List<Integer> get(){
|
||||
public List<Integer> get() {
|
||||
ArrayList<Integer> rs = new ArrayList<>();
|
||||
|
||||
try (Cursor c = getReadableDatabase().query("dnt", null, null, null, null, null, null)) {
|
||||
@@ -39,7 +39,7 @@ public class DoNotTypeDBHelper extends SQLiteOpenHelper{
|
||||
if (c.getInt(enabledIndex) == 1) {
|
||||
rs.add(c.getInt(peerIdIndex));
|
||||
}
|
||||
} while(c.moveToNext());
|
||||
} while (c.moveToNext());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -48,7 +48,7 @@ public class DoNotTypeDBHelper extends SQLiteOpenHelper{
|
||||
return rs;
|
||||
}
|
||||
|
||||
public boolean isEnabledForPeerId(int peerId){
|
||||
public boolean isEnabledForPeerId(int peerId) {
|
||||
try (Cursor c = getReadableDatabase().query("dnt", null, null, null, null, null, null)) {
|
||||
if (c.moveToFirst()) {
|
||||
int peerIdIndex = c.getColumnIndex("peerId");
|
||||
@@ -57,7 +57,7 @@ public class DoNotTypeDBHelper extends SQLiteOpenHelper{
|
||||
do {
|
||||
if (c.getInt(peerIdIndex) == peerId)
|
||||
return c.getInt(enabledIndex) == 1;
|
||||
} while(c.moveToNext());
|
||||
} while (c.moveToNext());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -66,7 +66,7 @@ public class DoNotTypeDBHelper extends SQLiteOpenHelper{
|
||||
return DNRPrefs.getActivityWithoutExceptions(peerId);
|
||||
}
|
||||
|
||||
public void setEnabledForPeerId(int peerId, boolean enabled){
|
||||
public void setEnabledForPeerId(int peerId, boolean enabled) {
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put("enabled", enabled ? 1 : 0);
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package ru.vtosters.lite.downloaders;
|
||||
|
||||
import static ru.vtosters.lite.utils.Preferences.getMusicDir;
|
||||
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -15,36 +17,56 @@ import ru.vtosters.lite.downloaders.notifications.NotificationChannels;
|
||||
import ru.vtosters.lite.music.Callback;
|
||||
import ru.vtosters.lite.music.FFMpeg;
|
||||
import ru.vtosters.lite.music.M3UDownloader;
|
||||
import ru.vtosters.lite.utils.Globals;
|
||||
import ru.vtosters.lite.music.MP3Downloader;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class AudioDownloader{
|
||||
private static NotificationManagerCompat notificationManager = NotificationManagerCompat.from(Globals.getContext());
|
||||
public class AudioDownloader {
|
||||
private static NotificationManagerCompat notificationManager = NotificationManagerCompat.from(AndroidUtils.getGlobalContext());
|
||||
|
||||
public static void downloadAudio(MusicTrack track){
|
||||
public static void downloadAudio(MusicTrack track) {
|
||||
if (AndroidUtils.getDefaultPrefs().getBoolean("new_music_downloading_way", false)) {
|
||||
downloadMP3(track);
|
||||
} else {
|
||||
downloadM3U8(track);
|
||||
}
|
||||
}
|
||||
|
||||
public static void downloadM3U8(MusicTrack track) {
|
||||
if (track.D == null) {
|
||||
ToastUtils.a("Не удалось найти ссылку на аудиозапись");
|
||||
ToastUtils.a(AndroidUtils.getString("link_audio_error"));
|
||||
return;
|
||||
}
|
||||
var musicPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath();
|
||||
|
||||
var musicPath = getMusicDir().getAbsolutePath();
|
||||
var musicDir = new File(musicPath);
|
||||
if (!musicDir.exists()) {
|
||||
if (musicDir.mkdirs()) {
|
||||
Log.d("AudioDownloader", "Created music dir");
|
||||
} else {
|
||||
Log.e("AudioDownloader", "Failed to create music dir");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var tempId = track.d;
|
||||
var downloadPath = musicPath + File.separator + tempId;
|
||||
var notification = buildDownloadNotification(track, tempId);
|
||||
|
||||
downloadM3U8(track, downloadPath, new Callback(){
|
||||
var notification = buildDownloadNotification(track, tempId);
|
||||
downloadM3U8(track, downloadPath, new Callback() {
|
||||
@Override
|
||||
public void onProgress(int progress){
|
||||
public void onProgress(int progress) {
|
||||
notification.setProgress(100, progress, false);
|
||||
notificationManager.notify(tempId, notification.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(){
|
||||
public void onSuccess() {
|
||||
try {
|
||||
var fileName = track.toString();
|
||||
var success = FFMpeg.convert(downloadPath, musicPath + File.separator + fileName + ".mp3");
|
||||
if (success) {
|
||||
notification
|
||||
.setContentText("Загрузка завершена")
|
||||
.setContentText(AndroidUtils.getString("player_download_finished"))
|
||||
.setProgress(0, 0, false)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download_done);
|
||||
notificationManager.notify(tempId, notification.build());
|
||||
@@ -52,26 +74,26 @@ public class AudioDownloader{
|
||||
onFailure();
|
||||
}
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
Log.e("AudioDownloader", "Опять эти нативные либы");
|
||||
Log.e("AudioDownloader", "native libs");
|
||||
Log.e("AudioDownloader", e.getMessage());
|
||||
onFailure();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(){
|
||||
notification.setContentText("Не удалось загрузить аудиозапись").setProgress(0, 0, false);
|
||||
public void onFailure() {
|
||||
notification.setContentText(AndroidUtils.getString("load_audio_error")).setProgress(0, 0, false);
|
||||
notificationManager.notify(tempId, notification.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSizeReceived(long size, long header){
|
||||
public void onSizeReceived(long size, long header) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void downloadM3U8(MusicTrack track, String path, Callback callback){
|
||||
private static void downloadM3U8(MusicTrack track, String path, Callback callback) {
|
||||
File outDir = new File(path);
|
||||
if (!outDir.exists())
|
||||
if (outDir.mkdir())
|
||||
@@ -79,13 +101,17 @@ public class AudioDownloader{
|
||||
else
|
||||
Log.e("AudioDownloader", "Directory creation failed");
|
||||
Log.i("AudioDownloader", "Downloading audio to " + path);
|
||||
new M3UDownloader(track.D, outDir, callback).execute();
|
||||
M3UDownloader.execute(track.D, outDir, callback);
|
||||
}
|
||||
|
||||
private static NotificationCompat.Builder buildDownloadNotification(MusicTrack track, int id){
|
||||
var notificationBuilder = new NotificationCompat.Builder(Globals.getContext(), NotificationChannels.MUSIC_DOWNLOAD_CHANNEL_ID)
|
||||
private static void downloadMP3(MusicTrack track) {
|
||||
MP3Downloader.execute(track);
|
||||
}
|
||||
|
||||
private static NotificationCompat.Builder buildDownloadNotification(MusicTrack track, int id) {
|
||||
var notificationBuilder = new NotificationCompat.Builder(AndroidUtils.getGlobalContext(), NotificationChannels.MUSIC_DOWNLOAD_CHANNEL_ID)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
.setContentTitle("Загрузка аудиозаписи")
|
||||
.setContentTitle(AndroidUtils.getString("audio_downloading"))
|
||||
.setContentText(track.toString())
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ru.vtosters.lite.downloaders;
|
||||
|
||||
import static ru.vtosters.lite.utils.Globals.getString;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.DownloadManager;
|
||||
@@ -11,17 +11,19 @@ import android.content.IntentFilter;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
|
||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import b.h.g.m.FileUtils;
|
||||
import ru.vtosters.lite.ui.activities.APKInstallActivity;
|
||||
import ru.vtosters.lite.utils.Globals;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class OTADownloader{
|
||||
public class OTADownloader {
|
||||
|
||||
private static final BroadcastReceiver callback = new BroadcastReceiver(){
|
||||
private static final BroadcastReceiver callback = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent){
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
var extras = intent.getExtras();
|
||||
if (extras == null || !intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
|
||||
return;
|
||||
@@ -29,7 +31,7 @@ public class OTADownloader{
|
||||
var query = new DownloadManager.Query();
|
||||
var id = extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
|
||||
query.setFilterById(id);
|
||||
var manager = (DownloadManager) Globals.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
var manager = (DownloadManager) AndroidUtils.getGlobalContext().getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
var cursor = manager.query(query);
|
||||
if (cursor.moveToFirst()) {
|
||||
@SuppressLint("Range") var status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
|
||||
@@ -46,26 +48,41 @@ public class OTADownloader{
|
||||
maxIndex = Math.max(maxIndex, Integer.parseInt(name.replaceFirst(".+-(\\d+).+", "$1")));
|
||||
}
|
||||
File apk = maxIndex == -1 ? new File(downloadDir, "VTLite.apk") : new File(downloadDir, "VTLite-" + maxIndex + ".apk");
|
||||
APKInstallActivity.installOta(context, FileUtils.n(apk));
|
||||
APKInstallActivity.installOta(context, FileUtils.uriFromFile(apk));
|
||||
} else if (status == DownloadManager.STATUS_FAILED) {
|
||||
Globals.sendToast(getString("downloaderr"));
|
||||
AndroidUtils.sendToast(getString("downloaderr"));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static void downloadBuild(String url){
|
||||
var context = Globals.getContext();
|
||||
var uri = Uri.parse(url);
|
||||
public static void downloadBuild(String url) {
|
||||
var context = AndroidUtils.getGlobalContext();
|
||||
try {
|
||||
var uri = Uri.parse(url);
|
||||
|
||||
context.registerReceiver(callback, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
|
||||
context.registerReceiver(callback, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
|
||||
|
||||
var request = new DownloadManager.Request(uri);
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.setTitle("VTLite.apk");
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "VTLite.apk");
|
||||
var request = new DownloadManager.Request(uri);
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.setTitle("VTLite.apk");
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "VTLite.apk");
|
||||
|
||||
var manager = (DownloadManager) Globals.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
manager.enqueue(request);
|
||||
var manager = (DownloadManager) AndroidUtils.getGlobalContext().getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
manager.enqueue(request);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
VkAlertDialog.Builder alertDialog = new VkAlertDialog.Builder(context);
|
||||
alertDialog.setTitle(AndroidUtils.getString("update_error"));
|
||||
alertDialog.setMessage(AndroidUtils.getString("update_error_text"));
|
||||
alertDialog.setPositiveButton(AndroidUtils.getString("no"), (dialog, which) -> {
|
||||
dialog.cancel();
|
||||
});
|
||||
alertDialog.setNeutralButton(AndroidUtils.getString("yes"), (dialog, which) -> {
|
||||
context.startActivity(new Intent("android.intent.action.VIEW").setData(Uri.parse("https://github.com/vtosters/lite/releases/latest/download/VTLite.apk")));
|
||||
});
|
||||
var alert = alertDialog.create();
|
||||
alert.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package ru.vtosters.lite.downloaders;
|
||||
|
||||
import static ru.vtosters.lite.downloaders.VideoDownloader.downloadVideo;
|
||||
import static ru.vtosters.lite.utils.Globals.getContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.Preferences.getPhotosDir;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
import android.content.Context;
|
||||
@@ -10,10 +12,11 @@ import android.os.Environment;
|
||||
import com.vk.dto.common.ImageSize;
|
||||
import com.vk.dto.stories.model.StoryEntry;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
public class StoryDownloader{
|
||||
public static Runnable injectButton(StoryEntry story){
|
||||
public class StoryDownloader {
|
||||
public static Runnable injectButton(StoryEntry story) {
|
||||
return () -> {
|
||||
// if story is a pic
|
||||
if (story.T1()) {
|
||||
@@ -21,9 +24,10 @@ public class StoryDownloader{
|
||||
String url = imageSizes.get(imageSizes.size() - 1).url;
|
||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.setTitle("photo" + story.E.a);
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DCIM, "/Stories/photo" + story.E.a + ".jpg");
|
||||
((DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
|
||||
request.setTitle("photo" + story.E.a + ".jpg");
|
||||
request.setDestinationInExternalPublicDir(getPhotosDir().getName(), "photo" + story.E.a + ".jpg");
|
||||
request.allowScanningByMediaScanner();
|
||||
((DownloadManager) getGlobalContext().getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package ru.vtosters.lite.downloaders;
|
||||
|
||||
import static ru.vtosters.lite.net.Request.makeRequest;
|
||||
import static ru.vtosters.lite.utils.Globals.getContext;
|
||||
import static ru.vtosters.lite.utils.Globals.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.Globals.getString;
|
||||
import static ru.vtosters.lite.utils.Globals.getUserToken;
|
||||
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||
import static ru.vtosters.lite.utils.Preferences.getVideosDir;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.DownloadManager;
|
||||
@@ -14,6 +15,7 @@ import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||
import com.vk.core.dialogs.bottomsheet.MenuBottomSheetAction;
|
||||
import com.vk.core.util.ToastUtils;
|
||||
import com.vk.dto.common.VideoFile;
|
||||
@@ -27,23 +29,24 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.vtosters.lite.utils.ExternalLinkHandler;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.ExternalLinkParser;
|
||||
|
||||
public class VideoDownloader{
|
||||
public class VideoDownloader {
|
||||
private static final int DOWNLOAD_ID = 0;
|
||||
private static final int OPEN_EXTERNAL_LINK_ID = 1;
|
||||
|
||||
public static boolean onClick(int id, VideoFile video, Context ctx){
|
||||
public static boolean onClick(int id, VideoFile video, Context ctx) {
|
||||
if (id == DOWNLOAD_ID) {
|
||||
downloadVideo(video, ctx);
|
||||
return true;
|
||||
} else if (id == OPEN_EXTERNAL_LINK_ID) {
|
||||
ExternalLinkHandler.parseVideoFile(video, ctx, true);
|
||||
ExternalLinkParser.parseVideoFile(video, ctx, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void injectAction(ArrayList<MenuBottomSheetAction> list, VideoFile video){
|
||||
public static void injectAction(ArrayList<MenuBottomSheetAction> list, VideoFile video) {
|
||||
if (!video.U && !video.I1()) {
|
||||
addAction(list, DOWNLOAD_ID, R.drawable.ic_download_outline_24, R.string.download, 9);
|
||||
addAction(list, OPEN_EXTERNAL_LINK_ID, R.drawable.ic_link_outline_28, getIdentifier("interfacevideoext_short", "string"), 9);
|
||||
@@ -54,7 +57,7 @@ public class VideoDownloader{
|
||||
actions.add(new MenuBottomSheetAction(ints[0], ints[1], ints[2], ints[3]));
|
||||
}
|
||||
|
||||
public static void downloadVideo(VideoFile videoFile, Context context){
|
||||
public static void downloadVideo(VideoFile videoFile, Context context) {
|
||||
final List<String> list = new ArrayList<>();
|
||||
final List<String> urls = new ArrayList<>();
|
||||
|
||||
@@ -104,31 +107,33 @@ public class VideoDownloader{
|
||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.setTitle(videoFile.toString());
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MOVIES, videoFile + ".mp4");
|
||||
((DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
|
||||
request.allowScanningByMediaScanner();
|
||||
request.setDestinationInExternalPublicDir(getVideosDir().getName(), videoFile + ".mp4");
|
||||
((DownloadManager) getGlobalContext().getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
|
||||
return;
|
||||
}
|
||||
|
||||
var builder = new AlertDialog.Builder(context);
|
||||
var builder = new VkAlertDialog.Builder(context);
|
||||
builder.setItems(max, ((dialog, which) -> {
|
||||
var url = urls.get(which);
|
||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||
request.setTitle(videoFile.toString());
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MOVIES, videoFile + ".mp4");
|
||||
request.allowScanningByMediaScanner();
|
||||
request.setDestinationInExternalPublicDir(getVideosDir().getName(), videoFile + ".mp4");
|
||||
((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
|
||||
}));
|
||||
builder.show();
|
||||
}
|
||||
|
||||
public static void parseVideoLink(String url, Context ctx){
|
||||
public static void parseVideoLink(String url, Context ctx) {
|
||||
if (url.contains("vk.com/story")) {
|
||||
ToastUtils.a("Не поддерживается загрузка историй");
|
||||
ToastUtils.a(AndroidUtils.getString("video_dl_stories_not_supported"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!url.contains("vk.com/video")) {
|
||||
ToastUtils.a("Неверная ссылка");
|
||||
ToastUtils.a(AndroidUtils.getString("video_dl_wrong_link"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -136,7 +141,7 @@ public class VideoDownloader{
|
||||
String ownerId = videoId.split("_")[0];
|
||||
|
||||
final ProgressDialog progressDialog = new ProgressDialog(ctx);
|
||||
progressDialog.setMessage("Обработка видео");
|
||||
progressDialog.setMessage(AndroidUtils.getString("video_dl_progress"));
|
||||
progressDialog.show();
|
||||
|
||||
makeRequest("https://" + "api.vk.com" + "/method/video.get?owner_id=" + ownerId + "&videos=" + videoId + "&v=5.99&access_token=" + getUserToken(),
|
||||
@@ -152,7 +157,7 @@ public class VideoDownloader{
|
||||
downloadVideo(videoFile, ctx);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(ctx, "Видео нельзя скачать", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(ctx, AndroidUtils.getString("video_dl_error"), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+4
-4
@@ -8,12 +8,12 @@ import android.os.Build;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
|
||||
import ru.vtosters.lite.utils.Globals;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class NotificationChannels {
|
||||
public static final String MUSIC_DOWNLOAD_CHANNEL_ID = "music_download_channel";
|
||||
public static final String MUSIC_DOWNLOAD_CHANNEL_NAME = "Загрузка музыки";
|
||||
public static final String MUSIC_DOWNLOAD_CHANNEL_DESCRIPTION = "Прогресс загрузки музыки";
|
||||
public static final String MUSIC_DOWNLOAD_CHANNEL_NAME = AndroidUtils.getString("music_dl_title");
|
||||
public static final String MUSIC_DOWNLOAD_CHANNEL_DESCRIPTION = AndroidUtils.getString("music_dl_progress");
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public static void createChannels() {
|
||||
@@ -26,7 +26,7 @@ public class NotificationChannels {
|
||||
musicDownloadChannel.setDescription(MUSIC_DOWNLOAD_CHANNEL_DESCRIPTION);
|
||||
musicDownloadChannel.setShowBadge(true);
|
||||
musicDownloadChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
|
||||
var notificationManager = NotificationManagerCompat.from(Globals.getContext());
|
||||
var notificationManager = NotificationManagerCompat.from(AndroidUtils.getGlobalContext());
|
||||
notificationManager.createNotificationChannel(musicDownloadChannel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package ru.vtosters.lite.encryption;
|
||||
|
||||
import static ru.vtosters.lite.hooks.MessagesHook.injectOwnText;
|
||||
import static ru.vtosters.lite.hooks.MessagesHook.injectOwnTextAll;
|
||||
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.vk.im.engine.models.messages.Msg;
|
||||
import com.vk.im.engine.models.messages.MsgFromUser;
|
||||
import com.vk.im.ui.components.msg_list.MsgListComponent;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -19,10 +23,10 @@ import ru.vtosters.lite.encryption.processors.MP3InvisibleProcessor;
|
||||
import ru.vtosters.lite.encryption.processors.VTostersAESProcessor;
|
||||
import ru.vtosters.lite.encryption.processors.VTostersProcessor;
|
||||
|
||||
public class EncryptProvider{
|
||||
public class EncryptProvider {
|
||||
public static List<IMProcessor> processors = new ArrayList<>();
|
||||
|
||||
static{
|
||||
static {
|
||||
processors.add(new VTostersProcessor());
|
||||
processors.add(new VTostersAESProcessor());
|
||||
processors.add(new DefaultCoffeeProcessor());
|
||||
@@ -31,7 +35,7 @@ public class EncryptProvider{
|
||||
processors.add(new MP3InvisibleProcessor());
|
||||
}
|
||||
|
||||
public static IMProcessor getProcessorFor(int peerId){
|
||||
public static IMProcessor getProcessorFor(int peerId) {
|
||||
IMProcessor enabled = null;
|
||||
for (IMProcessor processor : EncryptProvider.processors) {
|
||||
if (processor.isUsedToEncrypt(peerId)) {
|
||||
@@ -41,32 +45,75 @@ public class EncryptProvider{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public static String getBody(MsgFromUser msg){
|
||||
public static String getBody(MsgFromUser msg) {
|
||||
return msg.f();
|
||||
}
|
||||
|
||||
public static int getPeerId(Msg msg){
|
||||
public static int getPeerId(Msg msg) {
|
||||
return msg.v1();
|
||||
}
|
||||
|
||||
// For message editing
|
||||
public static String decryptMessage(MsgFromUser msg, boolean showEmoji) {
|
||||
var decryptedMessage = decryptMessage(getBody(msg), getPeerId(msg));
|
||||
if (!showEmoji && !decryptedMessage.equals(injectOwnTextAll(getBody(msg)))) decryptedMessage = decryptedMessage.replaceAll("^\uD83D\uDD12 ", "");
|
||||
return decryptedMessage;
|
||||
}
|
||||
|
||||
public static String decryptMessage(String msg, MsgListComponent list) {
|
||||
var peerid = list.G().getId();
|
||||
var decryptedMessage = decryptMessage(msg, peerid);
|
||||
if (!decryptedMessage.equals(injectOwnTextAll(msg))) decryptedMessage = decryptedMessage.replaceAll("^\uD83D\uDD12 ", "");
|
||||
return decryptedMessage;
|
||||
}
|
||||
|
||||
public static CharSequence decryptMessage(CharSequence msg, int peerid) {
|
||||
return decryptMessage(msg.toString(), peerid);
|
||||
}
|
||||
|
||||
public static CharSequence decryptMessage(Msg msg, CharSequence orig) {
|
||||
if (msg instanceof MsgFromUser) {
|
||||
var decrypted = decryptMessage(((MsgFromUser) msg).f(), msg.v1());
|
||||
|
||||
if (decrypted.contains("\uD83D\uDD12")) {
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return orig;
|
||||
}
|
||||
|
||||
public static String decryptMessages(String msgBody, int peer, boolean showEmoji) {
|
||||
return (String) decryptMessage(msgBody, peer, showEmoji);
|
||||
}
|
||||
|
||||
// For MentionsFormatter that requires CharSequence
|
||||
public static CharSequence decryptMessage(String msgBody, int peer, boolean showEmoji) {
|
||||
var decryptedMessage = decryptMessage(msgBody, peer);
|
||||
if (!showEmoji && !decryptedMessage.equals(injectOwnTextAll(msgBody))) decryptedMessage = decryptedMessage.replaceAll("^\uD83D\uDD12 ", "");
|
||||
return decryptedMessage;
|
||||
}
|
||||
|
||||
// This will run through EVERY single processor available.
|
||||
public static String decryptMessage(MsgFromUser msg){
|
||||
public static String decryptMessage(MsgFromUser msg) {
|
||||
return decryptMessage(getBody(msg), getPeerId(msg));
|
||||
}
|
||||
|
||||
public static String decryptMessage(String msgBody, int peer){
|
||||
public static String decryptMessage(String msgBody, int peer) {
|
||||
try {
|
||||
for (IMProcessor processor : processors) {
|
||||
if ((processor.isUsed() || !processor.isPublic()) && processor.isEncrypted(msgBody) && (processor.isPublic() || getKeyForProcessor(processor, peer) != null))
|
||||
return "\uD83D\uDD12 " + processor.decode(msgBody, getKeyForProcessor(processor, peer));
|
||||
return "\uD83D\uDD12 " + injectOwnTextAll(processor.decode(msgBody, getKeyForProcessor(processor, peer)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return msgBody;
|
||||
|
||||
return injectOwnTextAll(msgBody);
|
||||
}
|
||||
|
||||
private static byte[] getKeyForProcessor(IMProcessor processor, int peer){
|
||||
private static byte[] getKeyForProcessor(IMProcessor processor, int peer) {
|
||||
if (processor.isPublic()) return null;
|
||||
String keyString = processor.getEncryptionKeyFor(peer);
|
||||
if (keyString == null) return null;
|
||||
@@ -84,9 +131,8 @@ public class EncryptProvider{
|
||||
return keyString.getBytes();
|
||||
}
|
||||
|
||||
// This will use only the processor which was chosen in chat menu [that's why ID is needed, bruh]
|
||||
public static String encryptMessage(MsgFromUser msg){
|
||||
|
||||
// This will use only the processor which was chosen in chat menu
|
||||
public static String encryptMessage(MsgFromUser msg) {
|
||||
String msgBody = getBody(msg);
|
||||
|
||||
Log.d("EncryptProvider", "encryptMessage: msg = " + msg);
|
||||
@@ -96,15 +142,15 @@ public class EncryptProvider{
|
||||
for (IMProcessor processor : processors) {
|
||||
int peer = getPeerId(msg);
|
||||
if (processor.isUsedToEncrypt(peer)) {
|
||||
return processor.encode(msgBody, getKeyForProcessor(processor, peer));
|
||||
return injectOwnText(processor.encode(msgBody, getKeyForProcessor(processor, peer)));
|
||||
}
|
||||
}
|
||||
|
||||
return msgBody;
|
||||
return injectOwnText(msgBody);
|
||||
}
|
||||
|
||||
// For rendering UI
|
||||
public static List<Pair<String, String>> getUserVisibleEncoders(){
|
||||
public static List<Pair<String, String>> getUserVisibleEncoders() {
|
||||
List<Pair<String, String>> theList = new ArrayList<>();
|
||||
|
||||
for (IMProcessor processor : processors) {
|
||||
|
||||
@@ -5,11 +5,11 @@ import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import ru.vtosters.lite.utils.Globals;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public abstract class IMProcessor{
|
||||
public abstract class IMProcessor {
|
||||
// By default it checks start and end tag.
|
||||
public boolean isEncrypted(String source){
|
||||
public boolean isEncrypted(String source) {
|
||||
//Log.d("IMProcessor", "Checking if encrypted: "+source+" / "+getUIName());
|
||||
return source.startsWith(startTag()) && source.endsWith(endTag());
|
||||
}
|
||||
@@ -23,19 +23,19 @@ public abstract class IMProcessor{
|
||||
|
||||
// Automatically removes tags. Magic!
|
||||
@NonNull
|
||||
public String encode(@NonNull String source, @Nullable byte[] key){
|
||||
public String encode(@NonNull String source, @Nullable byte[] key) {
|
||||
//Log.d("IMProcessor", "Encoding "+source);
|
||||
return startTag() + encodeInternal(source, key) + endTag();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String decode(@NonNull String source, @Nullable byte[] key){
|
||||
public String decode(@NonNull String source, @Nullable byte[] key) {
|
||||
//Log.d("IMProcessor", "Decoding");
|
||||
return decodeInternal(source.substring(startTag().length(), source.length() - endTag().length()), key);
|
||||
}
|
||||
|
||||
// Public - no key required.
|
||||
public boolean isPublic(){
|
||||
public boolean isPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,40 +47,40 @@ public abstract class IMProcessor{
|
||||
abstract public String getPrefKey();
|
||||
|
||||
@NonNull
|
||||
public String startTag(){
|
||||
public String startTag() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String endTag(){
|
||||
public String endTag() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean isUsed(){
|
||||
public boolean isUsed() {
|
||||
//Log.d("IMProcessor", "Checking if decoded with "+getUIName());
|
||||
return getBoolValue("VT_IMDecode_" + getPrefKey(), true);
|
||||
}
|
||||
|
||||
public boolean isUsedToEncrypt(int id){
|
||||
public boolean isUsedToEncrypt(int id) {
|
||||
//Log.d("IMProcessor", "Checking if "+id+" is ready to be encrypted with "+getUIName());
|
||||
return getBoolValue("VT_IMEncode_" + getPrefKey() + "_" + id, false);
|
||||
}
|
||||
|
||||
public void enableEncryptFor(int id){
|
||||
Globals.getDefprefs().edit().putBoolean("VT_IMEncode_" + getPrefKey() + "_" + id, true).apply();
|
||||
public void enableEncryptFor(int id) {
|
||||
AndroidUtils.getDefaultPrefs().edit().putBoolean("VT_IMEncode_" + getPrefKey() + "_" + id, true).apply();
|
||||
}
|
||||
|
||||
public void disableEncryptFor(int id){
|
||||
Globals.getDefprefs().edit().putBoolean("VT_IMEncode_" + getPrefKey() + "_" + id, false).apply();
|
||||
public void disableEncryptFor(int id) {
|
||||
AndroidUtils.getDefaultPrefs().edit().putBoolean("VT_IMEncode_" + getPrefKey() + "_" + id, false).apply();
|
||||
}
|
||||
|
||||
public void setEncryptionKeyFor(int id, @Nullable String key){
|
||||
public void setEncryptionKeyFor(int id, @Nullable String key) {
|
||||
if (key == null || key.isEmpty()) key = "VTAesDefault";
|
||||
Globals.getDefprefs().edit().putString("VT_IMEncodeKey_" + getPrefKey() + "_" + id, key).apply();
|
||||
AndroidUtils.getDefaultPrefs().edit().putString("VT_IMEncodeKey_" + getPrefKey() + "_" + id, key).apply();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getEncryptionKeyFor(int id){
|
||||
return Globals.getDefprefs().getString("VT_IMEncodeKey_" + getPrefKey() + "_" + id, null);
|
||||
public String getEncryptionKeyFor(int id) {
|
||||
return AndroidUtils.getDefaultPrefs().getString("VT_IMEncodeKey_" + getPrefKey() + "_" + id, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,12 @@ import java.nio.charset.StandardCharsets;
|
||||
|
||||
import ru.vtosters.lite.encryption.base.IMProcessor;
|
||||
|
||||
public class BeeCryptProcessor extends IMProcessor{
|
||||
public class BeeCryptProcessor extends IMProcessor {
|
||||
private static final String BC_CHARSET = "жъЖЪ";
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected String encodeInternal(@NonNull String source, @Nullable byte[] key){
|
||||
protected String encodeInternal(@NonNull String source, @Nullable byte[] key) {
|
||||
try {
|
||||
String a = Base64.encodeToString(source.getBytes(StandardCharsets.UTF_8), 2);
|
||||
StringBuilder res = new StringBuilder();
|
||||
@@ -35,16 +35,16 @@ public class BeeCryptProcessor extends IMProcessor{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncrypted(String source){
|
||||
public boolean isEncrypted(String source) {
|
||||
return source.matches("[жъЖЪ]{16,}");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected String decodeInternal(@NonNull String source, @Nullable byte[] key){
|
||||
protected String decodeInternal(@NonNull String source, @Nullable byte[] key) {
|
||||
StringBuilder b64 = new StringBuilder();
|
||||
int i = 0;
|
||||
while(i < source.length() - 3) {
|
||||
while (i < source.length() - 3) {
|
||||
try {
|
||||
String bintxt = source.substring(i, i + 4);
|
||||
int c = 0;
|
||||
@@ -63,13 +63,13 @@ public class BeeCryptProcessor extends IMProcessor{
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getUIName(){
|
||||
public String getUIName() {
|
||||
return "MP3 [beecrypt]";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPrefKey(){
|
||||
public String getPrefKey() {
|
||||
return "mp3_bc";
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -10,11 +10,11 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import ru.vtosters.lite.encryption.base.IMProcessor;
|
||||
|
||||
public class DefaultCoffeeProcessor extends IMProcessor{
|
||||
public class DefaultCoffeeProcessor extends IMProcessor {
|
||||
private final static String KEY = "stupidUsersMustD";
|
||||
private static Cipher dCipher, eCipher;
|
||||
|
||||
static{
|
||||
static {
|
||||
try {
|
||||
SecretKeySpec key = new SecretKeySpec(KEY.getBytes(), "AES");
|
||||
|
||||
@@ -28,7 +28,7 @@ public class DefaultCoffeeProcessor extends IMProcessor{
|
||||
}
|
||||
}
|
||||
|
||||
private String toHex(String text){
|
||||
private String toHex(String text) {
|
||||
char[] chars = text.toCharArray();
|
||||
StringBuilder str = new StringBuilder();
|
||||
for (char aChar : chars) {
|
||||
@@ -41,7 +41,7 @@ public class DefaultCoffeeProcessor extends IMProcessor{
|
||||
return string.substring(0, string.length() - 1);
|
||||
}
|
||||
|
||||
private String fromHex(String text){
|
||||
private String fromHex(String text) {
|
||||
text = text.replace(" ", "");
|
||||
char[] chars = text.toCharArray();
|
||||
char[] chars2 = new char[chars.length / 2];
|
||||
@@ -55,7 +55,7 @@ public class DefaultCoffeeProcessor extends IMProcessor{
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected String encodeInternal(@NonNull String source, @Nullable byte[] key){
|
||||
protected String encodeInternal(@NonNull String source, @Nullable byte[] key) {
|
||||
try {
|
||||
return toHex(Base64.encodeToString(eCipher.doFinal(source.getBytes()), 0));
|
||||
} catch (Exception e) {
|
||||
@@ -67,7 +67,7 @@ public class DefaultCoffeeProcessor extends IMProcessor{
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected String decodeInternal(@NonNull String source, @Nullable byte[] key){
|
||||
protected String decodeInternal(@NonNull String source, @Nullable byte[] key) {
|
||||
try {
|
||||
return new String(dCipher.doFinal(Base64.decode(fromHex(source), 0)));
|
||||
} catch (Exception e) {
|
||||
@@ -79,25 +79,25 @@ public class DefaultCoffeeProcessor extends IMProcessor{
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String startTag(){
|
||||
public String startTag() {
|
||||
return "VK CO FF EE ";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String endTag(){
|
||||
public String endTag() {
|
||||
return " VK CO FF EE";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getUIName(){
|
||||
public String getUIName() {
|
||||
return "VK Coffee [default]";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPrefKey(){
|
||||
public String getPrefKey() {
|
||||
return "coffee_default";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,28 +2,28 @@ package ru.vtosters.lite.encryption.processors;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class DonateCoffeeProcessor extends DefaultCoffeeProcessor{
|
||||
public class DonateCoffeeProcessor extends DefaultCoffeeProcessor {
|
||||
@Override
|
||||
@NonNull
|
||||
public String startTag(){
|
||||
public String startTag() {
|
||||
return "II ";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String endTag(){
|
||||
public String endTag() {
|
||||
return " II";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getUIName(){
|
||||
public String getUIName() {
|
||||
return "VK Coffee [hidden]";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPrefKey(){
|
||||
public String getPrefKey() {
|
||||
return "coffee_donate";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,17 +9,17 @@ import java.nio.charset.StandardCharsets;
|
||||
|
||||
import ru.vtosters.lite.encryption.base.IMProcessor;
|
||||
|
||||
public class MP3InvisibleProcessor extends IMProcessor{
|
||||
private static String toStr(int a, String cc){
|
||||
public class MP3InvisibleProcessor extends IMProcessor {
|
||||
private static String toStr(int a, String cc) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
while(a > 0) {
|
||||
while (a > 0) {
|
||||
s.insert(0, cc.charAt(a % cc.length()));
|
||||
a /= cc.length();
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
private static int toNum(String a, String cc){
|
||||
private static int toNum(String a, String cc) {
|
||||
int n = 0;
|
||||
for (int i = 0; i < a.length(); i++) {
|
||||
int start = (a.length() - i) - 1;
|
||||
@@ -30,7 +30,7 @@ public class MP3InvisibleProcessor extends IMProcessor{
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected String encodeInternal(@NonNull String source, @Nullable byte[] key){
|
||||
protected String encodeInternal(@NonNull String source, @Nullable byte[] key) {
|
||||
try {
|
||||
byte[] bytes = source.getBytes(StandardCharsets.UTF_8);
|
||||
java.lang.String[] plainText = new String[bytes.length];
|
||||
@@ -46,7 +46,7 @@ public class MP3InvisibleProcessor extends IMProcessor{
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected String decodeInternal(@NonNull String source, @Nullable byte[] key){
|
||||
protected String decodeInternal(@NonNull String source, @Nullable byte[] key) {
|
||||
try {
|
||||
java.lang.String[] t = source.replaceAll("^" + " ", "").split(" ");
|
||||
byte[] plainText = new byte[t.length];
|
||||
@@ -61,19 +61,19 @@ public class MP3InvisibleProcessor extends IMProcessor{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncrypted(String source){
|
||||
public boolean isEncrypted(String source) {
|
||||
return source.matches("^" + " " + "([" + " " + "\\s]*)");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getUIName(){
|
||||
public String getUIName() {
|
||||
return "MP3 [invisible]";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPrefKey(){
|
||||
public String getPrefKey() {
|
||||
return "mp3";
|
||||
}
|
||||
}
|
||||
|
||||
+17
-17
@@ -17,22 +17,22 @@ import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import ru.vtosters.lite.encryption.base.IMProcessor;
|
||||
import ru.vtosters.lite.utils.Globals;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class VTostersAESProcessor extends IMProcessor{
|
||||
public class VTostersAESProcessor extends IMProcessor {
|
||||
private final static String CIPHER_INSTANCE = "AES/CBC/PKCS7Padding";
|
||||
private final static String KEY_METHOD = "AES";
|
||||
|
||||
private final HashMap<byte[], Cipher> decodeMap = new HashMap<>();
|
||||
private final HashMap<byte[], Cipher> encodeMap = new HashMap<>();
|
||||
|
||||
public void free(byte[] key){
|
||||
public void free(byte[] key) {
|
||||
decodeMap.remove(key);
|
||||
encodeMap.remove(key);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Cipher wrapEncoder(byte[] key) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException{
|
||||
private Cipher wrapEncoder(byte[] key) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
|
||||
if (encodeMap.containsKey(key)) return encodeMap.get(key);
|
||||
|
||||
Triple<Cipher, SecretKeySpec, IvParameterSpec> encodeCipher = getBaseCipher(key);
|
||||
@@ -43,7 +43,7 @@ public class VTostersAESProcessor extends IMProcessor{
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Cipher wrapDecoder(byte[] key) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException{
|
||||
private Cipher wrapDecoder(byte[] key) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
|
||||
if (decodeMap.containsKey(key)) return decodeMap.get(key);
|
||||
|
||||
Triple<Cipher, SecretKeySpec, IvParameterSpec> decodeCipher = getBaseCipher(key);
|
||||
@@ -54,7 +54,7 @@ public class VTostersAESProcessor extends IMProcessor{
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Triple<Cipher, SecretKeySpec, IvParameterSpec> getBaseCipher(byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException{
|
||||
private Triple<Cipher, SecretKeySpec, IvParameterSpec> getBaseCipher(byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException {
|
||||
byte[] off = new byte[16];
|
||||
System.arraycopy(key, 0, off, 0, off.length);
|
||||
return new Triple<>(Cipher.getInstance(CIPHER_INSTANCE), new SecretKeySpec(key, KEY_METHOD), new IvParameterSpec(off));
|
||||
@@ -62,7 +62,7 @@ public class VTostersAESProcessor extends IMProcessor{
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected String encodeInternal(@NonNull String source, @Nullable byte[] key){
|
||||
protected String encodeInternal(@NonNull String source, @Nullable byte[] key) {
|
||||
try {
|
||||
return Base64.encodeToString(wrapEncoder(key).doFinal(source.getBytes(StandardCharsets.UTF_8)), Base64.DEFAULT);
|
||||
} catch (Exception e) {
|
||||
@@ -73,7 +73,7 @@ public class VTostersAESProcessor extends IMProcessor{
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected String decodeInternal(@NonNull String source, @Nullable byte[] key){
|
||||
protected String decodeInternal(@NonNull String source, @Nullable byte[] key) {
|
||||
try {
|
||||
return new String(wrapDecoder(key).doFinal(Base64.decode(source, Base64.DEFAULT)), StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
@@ -83,46 +83,46 @@ public class VTostersAESProcessor extends IMProcessor{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPublic(){
|
||||
public boolean isPublic() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String startTag(){
|
||||
public String startTag() {
|
||||
return "VT0ST3RS [AES] ";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String endTag(){
|
||||
public String endTag() {
|
||||
return " VT0ST3RS [AES]";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getUIName(){
|
||||
public String getUIName() {
|
||||
return "VTosters [AES]";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPrefKey(){
|
||||
public String getPrefKey() {
|
||||
return "vtaes";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getEncryptionKeyFor(int id){
|
||||
return Globals.getDefprefs().getString("VT_IMEncodeKey_" + getPrefKey() + "_" + id, "VTAesDefault");
|
||||
public String getEncryptionKeyFor(int id) {
|
||||
return AndroidUtils.getDefaultPrefs().getString("VT_IMEncodeKey_" + getPrefKey() + "_" + id, "VTAesDefault");
|
||||
}
|
||||
|
||||
public static class Triple<F, S, T>{
|
||||
public static class Triple<F, S, T> {
|
||||
public final F first;
|
||||
public final S second;
|
||||
public final T third;
|
||||
|
||||
public Triple(F first, S second, T third){
|
||||
public Triple(F first, S second, T third) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
this.third = third;
|
||||
|
||||
@@ -7,40 +7,40 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import ru.vtosters.lite.encryption.base.IMProcessor;
|
||||
|
||||
public class VTostersProcessor extends IMProcessor{
|
||||
public class VTostersProcessor extends IMProcessor {
|
||||
@NonNull
|
||||
@Override
|
||||
protected String encodeInternal(@NonNull String source, @Nullable byte[] key){
|
||||
protected String encodeInternal(@NonNull String source, @Nullable byte[] key) {
|
||||
return Base64.encodeToString(source.getBytes(), Base64.DEFAULT);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected String decodeInternal(@NonNull String source, @Nullable byte[] key){
|
||||
protected String decodeInternal(@NonNull String source, @Nullable byte[] key) {
|
||||
return new String(Base64.decode(source, Base64.DEFAULT));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String startTag(){
|
||||
public String startTag() {
|
||||
return "VT0ST3RS ";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public String endTag(){
|
||||
public String endTag() {
|
||||
return " VT0ST3RS";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getUIName(){
|
||||
public String getUIName() {
|
||||
return "VTosters Classique [Base64]";
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getPrefKey(){
|
||||
public String getPrefKey() {
|
||||
return "vt64";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,54 +2,120 @@ package ru.vtosters.lite.foaf;
|
||||
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
import static android.widget.Toast.makeText;
|
||||
import static ru.vtosters.lite.utils.Globals.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.Globals.getString;
|
||||
import static ru.vtosters.lite.utils.Proxy.apiproxy;
|
||||
import static ru.vtosters.lite.utils.Proxy.getApi;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||
import static ru.vtosters.lite.proxy.ProxyUtils.isApiProxyEnabled;
|
||||
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
|
||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||
import com.vk.core.network.Network;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.OkHttpClient;
|
||||
import ru.vtosters.lite.net.Request;
|
||||
import ru.vtosters.lite.utils.Preferences;
|
||||
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||
|
||||
public class FoafBase{
|
||||
public class FoafBase {
|
||||
private static final Pattern FOAF_REGEX = Pattern.compile("<ya:created dc:date=\"(.+?)\"\\/>");
|
||||
private static final Pattern FOAF_REGEX_LAST_SEEN = Pattern.compile("<ya:lastLoggedIn dc:date=\"(.*)(((\\+|-)\\d\\d):(\\d\\d))\"\\/>");
|
||||
private static final Pattern FOAF_REGEX_LOGIN = Pattern.compile("<ya:created dc:date=\"(.+?)\"\\/>");
|
||||
private static final String API_VKNEXT = "https://api.vtosters.app/v1/getBypassedOnlineInfo?json=1&ids=";
|
||||
private static final OkHttpClient client = new OkHttpClient();
|
||||
|
||||
public static long getLastSeen(long origtime, int id) throws ParseException, IOException{
|
||||
if (!Preferences.foaf()) return origtime;
|
||||
public static long getLastSeen(long origtime, int id) throws ParseException, IOException {
|
||||
var request = new okhttp3.Request.a()
|
||||
.b(getLink(id))
|
||||
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8")).a();
|
||||
|
||||
String response = null;
|
||||
|
||||
try {
|
||||
response = client.a(request).execute().a().g();
|
||||
} catch (IOException e) {
|
||||
Log.e("FoafBase", e.getMessage());
|
||||
}
|
||||
|
||||
Matcher matcher = FOAF_REGEX_LAST_SEEN.matcher(response);
|
||||
|
||||
Matcher matcher = FOAF_REGEX_LAST_SEEN.matcher(
|
||||
client.a(
|
||||
new okhttp3.Request.a().a(getLink(id)).b().a()
|
||||
).execute().a().g());
|
||||
if (!matcher.find()) {
|
||||
return origtime;
|
||||
}
|
||||
return new SimpleDateFormat("yyyy-MM-dd'T'kk:mm:ss", Locale.getDefault()).parse(matcher.group(1)).getTime() / 1000;
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));
|
||||
Date date = sdf.parse(Objects.requireNonNull(matcher.group(1)));
|
||||
sdf.setTimeZone(TimeZone.getDefault());
|
||||
return sdf.parse(sdf.format(date)).getTime() / 1000;
|
||||
}
|
||||
|
||||
private static String getLink(int i){
|
||||
|
||||
public static JSONObject getBypassedOnlineInfo(int id) throws JSONException {
|
||||
var request = new okhttp3.Request.a()
|
||||
.b(API_VKNEXT + Integer.toString(id))
|
||||
.a();
|
||||
|
||||
String response = null;
|
||||
|
||||
var dummy = new JSONObject();
|
||||
dummy.put("last_seen", 0);
|
||||
|
||||
try {
|
||||
response = client.a(request).execute().a().g();
|
||||
var online_info = new JSONObject(response).optJSONObject("response").optJSONObject(Integer.toString(id));
|
||||
return online_info == null ? dummy : online_info;
|
||||
} catch (Exception e) {
|
||||
Log.e("GetBypassedOnlineInfo", e.getMessage());
|
||||
return dummy;
|
||||
}
|
||||
}
|
||||
|
||||
public static JSONObject getBypassedOnlineInfo(String ids) throws JSONException {
|
||||
|
||||
|
||||
var request = new okhttp3.Request.a()
|
||||
.b(API_VKNEXT + ids)
|
||||
.a();
|
||||
|
||||
String response = null;
|
||||
|
||||
var dummy = new JSONObject();
|
||||
|
||||
try {
|
||||
response = client.a(request).execute().a().g();
|
||||
var online_info = new JSONObject(response).optJSONObject("response");
|
||||
return online_info == null ? dummy : online_info;
|
||||
} catch (Exception e) {
|
||||
Log.e("GetBypassedOnlineInfo1", e.getMessage());
|
||||
return dummy;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getLink(int i) {
|
||||
String str;
|
||||
StringBuilder sb;
|
||||
if (apiproxy()) {
|
||||
if (isApiProxyEnabled()) {
|
||||
sb = new StringBuilder();
|
||||
str = "https://" + getApi() + "/_/vk.com/foaf.php?id=";
|
||||
} else {
|
||||
@@ -61,7 +127,7 @@ public class FoafBase{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void loadAndShow(Context context, int i){
|
||||
public static void loadAndShow(Context context, int i) {
|
||||
ProgressDialog progressDialog = new ProgressDialog(context);
|
||||
progressDialog.setMessage(getString("com_facebook_loading"));
|
||||
progressDialog.setCancelable(false);
|
||||
@@ -71,25 +137,26 @@ public class FoafBase{
|
||||
Request.makeRequest(getLink(i), callback);
|
||||
}
|
||||
|
||||
static void lambdaLoadAndShow(ProgressDialog progressDialog, Context context, int i, String str){
|
||||
static void lambdaLoadAndShow(ProgressDialog progressDialog, Context context, int i, String str) {
|
||||
try {
|
||||
progressDialog.cancel();
|
||||
Matcher matcher = FOAF_REGEX.matcher(str);
|
||||
Matcher matcher2 = FOAF_REGEX_LOGIN.matcher(str);
|
||||
matcher.find();
|
||||
matcher2.find();
|
||||
String normalHumanDate = getNormalHumanDate(matcher.group(1));
|
||||
getNormalHumanDate(matcher2.group(1));
|
||||
String normalHumanDate = getNormalHumanDate(Objects.requireNonNull(matcher.group(1)));
|
||||
getNormalHumanDate(Objects.requireNonNull(matcher2.group(1)));
|
||||
VkAlertDialog.Builder a2 = new VkAlertDialog.Builder(context).setTitle(getIdentifier("addinf", "string"));
|
||||
a2.setMessage(getString("foafid") + " " + i + getString("foafregdate") + " " + normalHumanDate + getString("foafdate") + " " + daysPassedFromFoafDate(normalHumanDate)).setPositiveButton(17039370, null).create().show();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
makeText(context, getString("foaferr"), LENGTH_SHORT).show();
|
||||
makeText(getGlobalContext(), getString("foaferr"), LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
private static long daysPassedFromFoafDate(String str){
|
||||
private static long daysPassedFromFoafDate(String str) {
|
||||
try {
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
Date parse = new SimpleDateFormat("yyyy-MM-dd").parse(str.split(" ")[1]);
|
||||
return TimeUnit.DAYS.convert(new Date().getTime() - parse.getTime(), TimeUnit.MILLISECONDS);
|
||||
} catch (ParseException e) {
|
||||
@@ -98,7 +165,7 @@ public class FoafBase{
|
||||
}
|
||||
}
|
||||
|
||||
private static String getNormalHumanDate(String str){
|
||||
private static String getNormalHumanDate(String str) {
|
||||
String[] split = str.split(ExifInterface.GPS_DIRECTION_TRUE);
|
||||
return split[1].split("\\+")[0] + " " + split[0];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
import static ru.vtosters.lite.dnr.DNRInjector.forceInvalidateDialogActions;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||
import static ru.vtosters.lite.utils.LifecycleUtils.getCurrentActivity;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getAlertStyle;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.text.Editable;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||
import com.vk.im.engine.models.dialogs.Dialog;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.vtosters.lite.encryption.EncryptProvider;
|
||||
import ru.vtosters.lite.encryption.base.IMProcessor;
|
||||
|
||||
public class CryptImHook{
|
||||
public static boolean isPrivateProcessor(int peerID){
|
||||
for (IMProcessor processor : EncryptProvider.processors) {
|
||||
if (processor.isUsedToEncrypt(peerID)) {
|
||||
return !processor.isPublic();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void hook(int peerId, Dialog d){
|
||||
List<IMProcessor> processors = EncryptProvider.processors;
|
||||
|
||||
IMProcessor enabled = null;
|
||||
int enabledPosition = 0;
|
||||
|
||||
String[] titles = new String[processors.size() + 1];
|
||||
titles[0] = getString("encryption_disable");
|
||||
|
||||
for (int i = 0; i < processors.size(); i++) {
|
||||
IMProcessor proc = processors.get(i);
|
||||
|
||||
titles[i + 1] = proc.getUIName();
|
||||
|
||||
if (proc.isUsedToEncrypt(peerId)) {
|
||||
enabled = proc;
|
||||
enabledPosition = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
IMProcessor finalEnabled = enabled;
|
||||
new VkAlertDialog.Builder(getCurrentActivity())
|
||||
.setTitle(getString("encryption_sett"))
|
||||
.setSingleChoiceItems(titles, enabledPosition, (dialog, which) -> {
|
||||
if (which == 0) {
|
||||
if (finalEnabled != null) finalEnabled.disableEncryptFor(peerId);
|
||||
} else {
|
||||
IMProcessor proc = processors.get(which - 1);
|
||||
|
||||
if (proc.isUsedToEncrypt(peerId)) {
|
||||
proc.disableEncryptFor(peerId);
|
||||
} else {
|
||||
proc.enableEncryptFor(peerId);
|
||||
if (finalEnabled != null) finalEnabled.disableEncryptFor(peerId);
|
||||
}
|
||||
}
|
||||
|
||||
dialog.dismiss();
|
||||
forceInvalidateDialogActions(d);
|
||||
}).create().show();
|
||||
}
|
||||
|
||||
public static void hookPref(int peerId){
|
||||
IMProcessor enabled = null;
|
||||
String key = null;
|
||||
|
||||
for (IMProcessor processor : EncryptProvider.processors) {
|
||||
if (processor.isUsedToEncrypt(peerId)) {
|
||||
enabled = processor;
|
||||
}
|
||||
}
|
||||
|
||||
if (enabled != null && enabled.isPublic()) {
|
||||
sendToast(getString("encryption_public_algorithm_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Objects.requireNonNull(enabled).getEncryptionKeyFor(peerId) != null) {
|
||||
key = enabled.getEncryptionKeyFor(peerId);
|
||||
}
|
||||
|
||||
if (key.equals("VTAesDefault")) {
|
||||
key = null;
|
||||
}
|
||||
|
||||
Context ctx = getCurrentActivity();
|
||||
|
||||
LinearLayout linearLayout = new LinearLayout(ctx);
|
||||
|
||||
final EditText editText = new EditText(ctx);
|
||||
editText.setHintTextColor(getSTextAttr());
|
||||
editText.setBackgroundTintList(ColorStateList.valueOf(getSTextAttr()));
|
||||
|
||||
linearLayout.addView(editText);
|
||||
editText.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) editText.getLayoutParams());
|
||||
margin.setMargins(dp2px(24f), 0, dp2px(24f), 0);
|
||||
editText.setLayoutParams(margin);
|
||||
editText.setText(key == null ? "" : key);
|
||||
|
||||
IMProcessor finalEnabled = enabled;
|
||||
new AlertDialog.Builder(ctx, getAlertStyle())
|
||||
.setTitle(getString("encryption_enter_key"))
|
||||
.setMessage(String.format(getString("encryption_current_algorithm_title"), enabled.getUIName()))
|
||||
.setView(linearLayout)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
Editable edit = editText.getText();
|
||||
finalEnabled.setEncryptionKeyFor(peerId, edit == null ? null : edit.toString());
|
||||
}).setNegativeButton(android.R.string.cancel, null).create().show();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
import static ru.vtosters.lite.utils.Globals.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.Globals.getPrefsValue;
|
||||
import static ru.vtosters.lite.utils.Globals.getString;
|
||||
import static ru.vtosters.lite.utils.Globals.getStringDate;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getStringDate;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
|
||||
@@ -10,13 +11,13 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class DateHook{
|
||||
public static boolean fulltime(){
|
||||
public class DateHook {
|
||||
public static boolean fulltime() {
|
||||
return getPrefsValue("dateformat").equals("noyear") || getPrefsValue("dateformat").equals("full") || getPrefsValue("dateformat").equals("noseconds");
|
||||
}
|
||||
|
||||
public static String getDateFormat(){
|
||||
switch(getPrefsValue("dateformat")) {
|
||||
public static String getDateFormat() {
|
||||
switch (getPrefsValue("dateformat")) {
|
||||
case "noyear":
|
||||
return getString("fulltime2");
|
||||
case "full":
|
||||
@@ -27,11 +28,11 @@ public class DateHook{
|
||||
}
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
public static SimpleDateFormat setDateFormat(){
|
||||
public static SimpleDateFormat setDateFormat() {
|
||||
return new SimpleDateFormat(getDateFormat());
|
||||
}
|
||||
|
||||
public static String getFormattedDate(boolean isFemale, long time){
|
||||
public static String getFormattedDate(boolean isFemale, long time) {
|
||||
SimpleDateFormat date = new SimpleDateFormat(getDateFormat(), Locale.getDefault());
|
||||
|
||||
if (!fulltime()) return null;
|
||||
@@ -44,7 +45,7 @@ public class DateHook{
|
||||
}
|
||||
}
|
||||
|
||||
public static String getLocale(){
|
||||
public static String getLocale() {
|
||||
String string = getPrefsValue("lang_value");
|
||||
|
||||
if (string.equals("system")) {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.MD5;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class DeviceInfoHook{
|
||||
public static String getDeviceInfo(String input) {
|
||||
Log.d("DeviceInfoHook", "getDeviceInfo: " + input);
|
||||
if (getBoolValue("hideDeviceInfo", true)) return "";
|
||||
return input;
|
||||
}
|
||||
|
||||
public static String getDeviceId(String input) {
|
||||
return findDeviceId() + ":" + getDeviceId();
|
||||
}
|
||||
|
||||
public static String getDeviceId() {
|
||||
String sb2 = Build.PRODUCT +
|
||||
Build.BOARD +
|
||||
Build.BOOTLOADER +
|
||||
Build.BRAND +
|
||||
Build.DEVICE +
|
||||
Build.DISPLAY +
|
||||
Build.FINGERPRINT +
|
||||
Build.HARDWARE +
|
||||
Build.HOST +
|
||||
Build.ID +
|
||||
Build.MANUFACTURER +
|
||||
Build.MODEL +
|
||||
Build.PRODUCT +
|
||||
Build.TAGS;
|
||||
|
||||
return MD5(sb2);
|
||||
}
|
||||
|
||||
@SuppressLint("HardwareIds")
|
||||
private static String findDeviceId() {
|
||||
return Settings.Secure.getString(getGlobalContext().getContentResolver(), "android_id");
|
||||
}
|
||||
}
|
||||
+76
-39
@@ -1,23 +1,33 @@
|
||||
package ru.vtosters.lite.ui.fragments.dockbar;
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static com.vtosters.lite.R.id.menu_fave;
|
||||
import static com.vtosters.lite.R.id.menu_feedback;
|
||||
import static com.vtosters.lite.R.id.menu_friends;
|
||||
import static com.vtosters.lite.R.id.menu_games;
|
||||
import static com.vtosters.lite.R.id.menu_groups;
|
||||
import static com.vtosters.lite.R.id.menu_messages;
|
||||
import static com.vtosters.lite.R.id.menu_newsfeed;
|
||||
import static com.vtosters.lite.R.id.menu_photos;
|
||||
import static com.vtosters.lite.R.id.menu_search;
|
||||
import static com.vtosters.lite.R.id.menu_videos;
|
||||
import static com.vtosters.lite.R.id.menu_vk_pay;
|
||||
import static com.vtosters.lite.R.id.tab_discover;
|
||||
import static com.vtosters.lite.R.id.tab_feedback;
|
||||
import static com.vtosters.lite.R.id.tab_menu;
|
||||
import static com.vtosters.lite.R.id.tab_messages;
|
||||
import static com.vtosters.lite.R.id.tab_news;
|
||||
import static ru.vtosters.lite.utils.Globals.getResources;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getResources;
|
||||
import static ru.vtosters.lite.utils.Preferences.dockcounter;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getCSTDock;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.vk.apps.AppsFragment;
|
||||
import com.vk.core.drawable.RecoloredDrawable;
|
||||
@@ -25,6 +35,7 @@ import com.vk.core.fragments.FragmentImpl;
|
||||
import com.vk.core.util.StringUtils;
|
||||
import com.vk.navigation.right.RightMenu;
|
||||
import com.vtosters.lite.MenuCountersState;
|
||||
import com.vtosters.lite.fragments.ProfileFragment;
|
||||
import com.vtosters.lite.ui.bottomnavigation.BottomNavigationMenuView;
|
||||
import com.vtosters.lite.ui.bottomnavigation.BottomNavigationView;
|
||||
|
||||
@@ -41,12 +52,13 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ru.vtosters.lite.utils.Preferences;
|
||||
import ru.vtosters.lite.ui.components.DockBarEditorManager;
|
||||
import ru.vtosters.lite.ui.items.DockBarTab;
|
||||
|
||||
public class DockBarInjector{
|
||||
private static final DockBarManager sManager = DockBarManager.getInstance();
|
||||
public class DockBarInjector {
|
||||
private static final DockBarEditorManager sManager = DockBarEditorManager.getInstance();
|
||||
|
||||
public static Map<Class<? extends FragmentImpl>, Integer> injectMap(){
|
||||
public static Map<Class<? extends FragmentImpl>, Integer> injectMap() {
|
||||
LinkedHashMap<Class<? extends FragmentImpl>, Integer> map = new LinkedHashMap<>();
|
||||
for (DockBarTab tab : sManager.getSelectedTabs()) {
|
||||
map.put(tab.fragmentClass, tab.id);
|
||||
@@ -54,7 +66,8 @@ public class DockBarInjector{
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void inject(BottomNavigationView navigationView){
|
||||
@SuppressLint("RestrictedApi")
|
||||
public static void inject(BottomNavigationView navigationView) {
|
||||
Menu menu = navigationView.getMenu();
|
||||
menu.clear();
|
||||
try {
|
||||
@@ -67,7 +80,7 @@ public class DockBarInjector{
|
||||
Method acquire = synchronisedPoolCls.getDeclaredMethod("acquire");
|
||||
if (synchronizedPool != null) {
|
||||
do {
|
||||
} while(acquire.invoke(synchronizedPool) != null);
|
||||
} while (acquire.invoke(synchronizedPool) != null);
|
||||
}
|
||||
|
||||
} catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) {
|
||||
@@ -78,24 +91,31 @@ public class DockBarInjector{
|
||||
MenuItem add = menu.add(0, tab.id, 0, tab.titleID);
|
||||
Drawable drawable = getResources().getDrawable(tab.iconID);
|
||||
|
||||
ColorStateList dockcolors = new ColorStateList(
|
||||
new int[][] {
|
||||
new int[] {android.R.attr.state_checked},
|
||||
new int[] {-android.R.attr.state_checked}
|
||||
},
|
||||
new int[] {
|
||||
Color.parseColor("#ff528bcc"),
|
||||
Color.parseColor("#ffaaaeb3")
|
||||
}
|
||||
);
|
||||
|
||||
add.setIcon(new RecoloredDrawable(drawable, dockcolors));
|
||||
add.setShowAsAction(1);
|
||||
add.setIcon(new RecoloredDrawable(drawable, getCSTDock()));
|
||||
add.setTitle(getGlobalContext().getString(tab.titleID));
|
||||
add.setCheckable(true);
|
||||
}
|
||||
if (getBoolValue("dockbar_tab_titles", true)) {
|
||||
var menuView = (BottomNavigationMenuView) navigationView.getChildAt(0);
|
||||
for (int i = 0; i < menuView.getChildCount(); i++) {
|
||||
var item = (com.vtosters.lite.ui.bottomnavigation.BottomNavigationItemView) menuView.getChildAt(i);
|
||||
item.setStaticMode(true);
|
||||
item.setIconsMode(false);
|
||||
item.setShiftingMode(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int injectId(String tag){
|
||||
private static void removeAllChildren(ViewGroup view) {
|
||||
for (int i = 0; i < view.getChildCount(); i++) {
|
||||
if (view instanceof ViewGroup) {
|
||||
removeAllChildren((ViewGroup) view.getChildAt(i));
|
||||
view.removeAllViews();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int injectId(String tag) {
|
||||
for (DockBarTab tab : sManager.getSelectedTabs()) {
|
||||
if (tag.equals(tab.tag))
|
||||
return tab.id;
|
||||
@@ -103,7 +123,7 @@ public class DockBarInjector{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void injectMenuFragment(Menu menu){
|
||||
public static void injectMenuFragment(Menu menu) {
|
||||
List<MenuItem> menuItems = new ArrayList<>();
|
||||
for (int i = 0; i < menu.size(); i++) {
|
||||
menuItems.add(menu.getItem(i));
|
||||
@@ -160,25 +180,41 @@ public class DockBarInjector{
|
||||
}
|
||||
}
|
||||
|
||||
public static void setCounter(int tabId, BottomNavigationView navigationView){
|
||||
navigationView.a(tabId, counters(tabId, navigationView));
|
||||
public static void setCounter(int tabId, BottomNavigationView navigationView) {
|
||||
navigationView.a(tabId, counters(tabId));
|
||||
}
|
||||
|
||||
private static CharSequence counters(int tabId, BottomNavigationView navigationView){
|
||||
if (!Preferences.dockcounter()) return null;
|
||||
@SuppressLint("NonConstantResourceId")
|
||||
private static CharSequence counters(int tabId) {
|
||||
if (!dockcounter()) return null;
|
||||
|
||||
int val = 0;
|
||||
switch (tabId) {
|
||||
case tab_messages:
|
||||
val = MenuCountersState.j();
|
||||
break;
|
||||
case menu_groups:
|
||||
val = MenuCountersState.h();
|
||||
break;
|
||||
case menu_fave:
|
||||
val = MenuCountersState.c();
|
||||
break;
|
||||
case menu_games:
|
||||
val = MenuCountersState.a();
|
||||
break;
|
||||
case menu_photos:
|
||||
val = MenuCountersState.l();
|
||||
break;
|
||||
case menu_videos:
|
||||
val = MenuCountersState.n();
|
||||
break;
|
||||
case tab_feedback:
|
||||
if (Preferences.milkshake())
|
||||
val = MenuCountersState.k();
|
||||
if (milkshake())
|
||||
val = MenuCountersState.k();
|
||||
break;
|
||||
case menu_friends:
|
||||
if (!Preferences.milkshake())
|
||||
val = MenuCountersState.k();
|
||||
if (!milkshake())
|
||||
val = MenuCountersState.k();
|
||||
break;
|
||||
}
|
||||
//
|
||||
@@ -199,7 +235,7 @@ public class DockBarInjector{
|
||||
return val > 0 ? StringUtils.a(val) : null;
|
||||
}
|
||||
|
||||
public static JSONArray injectMenuJSON(JSONArray arr){
|
||||
public static JSONArray injectMenuJSON(JSONArray arr) {
|
||||
List<String> arrayList = new ArrayList(Arrays.asList(
|
||||
"news",
|
||||
"messages",
|
||||
@@ -232,15 +268,15 @@ public class DockBarInjector{
|
||||
}
|
||||
}
|
||||
|
||||
public static int getItemCount(){
|
||||
public static int getItemCount() {
|
||||
return sManager.getSelectedTabs().size();
|
||||
}
|
||||
|
||||
public static boolean isDockOpenAllowed(FragmentImpl fragment){
|
||||
public static boolean isDockOpenAllowed(FragmentImpl fragment) {
|
||||
return isDockOpenAllowed(fragment.getClass());
|
||||
}
|
||||
|
||||
public static boolean isDockOpenAllowed(Class<?> cls){
|
||||
public static boolean isDockOpenAllowed(Class<?> cls) {
|
||||
for (DockBarTab tab : sManager.getSelectedTabs())
|
||||
if (tab.fragmentClass == cls)
|
||||
return false;
|
||||
@@ -250,8 +286,8 @@ public class DockBarInjector{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Class<?> interceptClick(int id, RightMenu rightMenu){
|
||||
if (id == tab_menu) {
|
||||
public static Class<?> interceptClick(int id, RightMenu rightMenu) {
|
||||
if (id == tab_menu && rightMenu != null) {
|
||||
rightMenu.a();
|
||||
}
|
||||
|
||||
@@ -259,6 +295,7 @@ public class DockBarInjector{
|
||||
if (id == tab.id)
|
||||
return tab.fragmentClass;
|
||||
}
|
||||
|
||||
for (DockBarTab tab : sManager.getDisabledTabs()) {
|
||||
if (id == tab.id)
|
||||
return tab.fragmentClass;
|
||||
@@ -1,17 +1,18 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
import static ru.vtosters.lite.utils.FragAnimationKit.setAnimations;
|
||||
import static ru.vtosters.lite.utils.Globals.getPrefsValue;
|
||||
|
||||
import static ru.vtosters.lite.ui.components.FragAnimationKit.setAnimations;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
public class FragAnimationHook{
|
||||
public static boolean animateOpen(FragmentTransaction transaction){
|
||||
public class FragAnimationHook {
|
||||
public static boolean animateOpen(FragmentTransaction transaction) {
|
||||
setAnimations(transaction);
|
||||
|
||||
return getPrefsValue("anim_rtrn_type").equals("noanim") || getPrefsValue("anim_rtrn_type").isEmpty();
|
||||
}
|
||||
|
||||
public static void animateClose(FragmentTransaction transaction){
|
||||
public static void animateClose(FragmentTransaction transaction) {
|
||||
setAnimations(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,28 +27,28 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
public class GcmHook{
|
||||
public class GcmHook {
|
||||
private static final String agent = String.format("Android-GCM/1.5 (%s %s)", Build.MODEL, Build.MODEL);
|
||||
public static ArrayList<String> langs = new ArrayList<>();
|
||||
private static KeyPair pair;
|
||||
private static int rid = 0;
|
||||
|
||||
static{
|
||||
static {
|
||||
genNewKey();
|
||||
}
|
||||
|
||||
public static String requestTokenV2(String orig){
|
||||
public static String requestTokenV2(String orig) {
|
||||
if (musicFixNew()) return "null";
|
||||
return orig;
|
||||
}
|
||||
|
||||
public static String requestToken(String orig){
|
||||
public static String requestToken(String orig) {
|
||||
if (musicFixNew()) return "{null}";
|
||||
if (orig.equals("")) return requestToken();
|
||||
return orig;
|
||||
}
|
||||
|
||||
public static String requestToken(){
|
||||
public static String requestToken() {
|
||||
String xappide;
|
||||
try {
|
||||
String aid = getRandomAid();
|
||||
@@ -59,7 +59,7 @@ public class GcmHook{
|
||||
bytes[0] = (byte) (((bytes[0] & 15) + 112) & 255);
|
||||
xappide = Base64.encodeToString(bytes, 2).substring(0, 11);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
xappide = "";
|
||||
xappide = "";
|
||||
}
|
||||
AtomicBoolean wait = new AtomicBoolean(false);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -69,7 +69,7 @@ public class GcmHook{
|
||||
Callback callback = str -> GcmHook.lambdaRequestToken(sb, wait, str);
|
||||
|
||||
doRequest("https://android.clients.google.com/c2dm/register3", "POST", params, aid, callback);
|
||||
while(!wait.get()) {
|
||||
while (!wait.get()) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
String token = sb.toString();
|
||||
@@ -90,15 +90,15 @@ public class GcmHook{
|
||||
}
|
||||
}
|
||||
|
||||
static void lambdaRequestToken(StringBuilder sb, AtomicBoolean wait, String s){
|
||||
static void lambdaRequestToken(StringBuilder sb, AtomicBoolean wait, String s) {
|
||||
sb.append(s.substring(20));
|
||||
wait.set(true);
|
||||
}
|
||||
|
||||
static void lambda$requestToken$1(String str){
|
||||
static void lambda$requestToken$1(String str) {
|
||||
}
|
||||
|
||||
private static void fillParams(List<String> params, String sig, String pub2, String xappid, long androidId, boolean del){
|
||||
private static void fillParams(List<String> params, String sig, String pub2, String xappid, long androidId, boolean del) {
|
||||
rid++;
|
||||
params.add("X-subtype=841415684880");
|
||||
if (del) {
|
||||
@@ -108,7 +108,7 @@ public class GcmHook{
|
||||
params.add("X-X-subscription=841415684880");
|
||||
}
|
||||
params.add("X-X-subtype=841415684880");
|
||||
params.add("X-app_ver=" + "5.56.1");
|
||||
params.add("X-app_ver=" + "7.26");
|
||||
params.add("X-kid=|ID|" + rid + "|");
|
||||
params.add("X-osv=30");
|
||||
params.add("X-sig=" + sig);
|
||||
@@ -129,16 +129,16 @@ public class GcmHook{
|
||||
if (!del) {
|
||||
params.add("X-gmp_app_id=1:841415684880:android:632f429381141121");
|
||||
}
|
||||
params.add("X-app_ver_name=" + "5.56.1");
|
||||
params.add("X-app_ver_name=" + "7.26");
|
||||
params.add("app=com.vkontakte.android");
|
||||
params.add("sender=841415684880");
|
||||
params.add("device=" + androidId);
|
||||
params.add("cert=48761eef50ee53afc4cc9c5f10e6bde7f8f5b82f");
|
||||
params.add("app_ver=" + "4838");
|
||||
params.add("app_ver=" + "12338");
|
||||
params.add("gcm_ver=11949470");
|
||||
}
|
||||
|
||||
private static String join(String chr, Iterable<String> arr){
|
||||
private static String join(String chr, Iterable<String> arr) {
|
||||
String str = "";
|
||||
for (String s : arr) {
|
||||
str = str.isEmpty() ? s : str + chr + s;
|
||||
@@ -146,11 +146,11 @@ public class GcmHook{
|
||||
return str;
|
||||
}
|
||||
|
||||
private static String join(String chr, String[] arr){
|
||||
private static String join(String chr, String[] arr) {
|
||||
return join(chr, Arrays.asList(arr));
|
||||
}
|
||||
|
||||
private static void doRequest(String url, String method, List<String> params, String aidlogin, Callback callback) throws IOException{
|
||||
private static void doRequest(String url, String method, List<String> params, String aidlogin, Callback callback) throws IOException {
|
||||
HttpsURLConnection con = (HttpsURLConnection) new URL(url).openConnection();
|
||||
con.setRequestMethod(method);
|
||||
con.setRequestProperty("Authorization", aidlogin);
|
||||
@@ -169,13 +169,13 @@ public class GcmHook{
|
||||
}
|
||||
|
||||
private static String getRandomAid() {
|
||||
var arr1 = new String[]{ "3974055026275073921", "4418584909973341826", "4585634953328772978" };
|
||||
var arr2 = new String[]{ "1932960345884890854", "6594645578425092292", "1792344590975444730" };
|
||||
var arr1 = new String[]{"3974055026275073921", "4418584909973341826", "4585634953328772978"};
|
||||
var arr2 = new String[]{"1932960345884890854", "6594645578425092292", "1792344590975444730"};
|
||||
int r = new Random().nextInt(2);
|
||||
return "AidLogin " + arr1[r] + ":" + arr2[r];
|
||||
}
|
||||
|
||||
private static String genNewKey(){
|
||||
private static String genNewKey() {
|
||||
try {
|
||||
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
|
||||
gen.initialize(2048);
|
||||
@@ -186,12 +186,12 @@ public class GcmHook{
|
||||
return Base64.encodeToString(pair.getPublic().getEncoded(), 0);
|
||||
}
|
||||
|
||||
private static String getSig(String pub2){
|
||||
private static String getSig(String pub2) {
|
||||
try {
|
||||
PrivateKey key = pair.getPrivate();
|
||||
Signature sign = Signature.getInstance(key instanceof RSAPrivateKey ? "SHA256withRSA" : "SHA256withECDSA");
|
||||
sign.initSign(key);
|
||||
sign.update(join("\n", new String[] {"com.vkontakte.android", pub2}).getBytes(StandardCharsets.UTF_8));
|
||||
sign.update(join("\n", new String[]{"com.vkontakte.android", pub2}).getBytes(StandardCharsets.UTF_8));
|
||||
return Base64.encodeToString(sign.sign(), 0);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -199,7 +199,7 @@ public class GcmHook{
|
||||
}
|
||||
}
|
||||
|
||||
public interface Callback{
|
||||
public interface Callback {
|
||||
void doCallback(String str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,77 +1,209 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static ru.vtosters.lite.f0x1d.VTVerifications.isDeveloper;
|
||||
import static ru.vtosters.lite.f0x1d.VTVerifications.isPrometheus;
|
||||
import static ru.vtosters.lite.f0x1d.VTVerifications.isVerified;
|
||||
import static ru.vtosters.lite.foaf.FoafBase.getLastSeen;
|
||||
import static ru.vtosters.lite.foaf.FoafBase.getBypassedOnlineInfo;
|
||||
import static ru.vtosters.lite.hooks.OnlineFormatterHook.onlineHookProfiles;
|
||||
import static ru.vtosters.lite.hooks.DateHook.getLocale;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
||||
import static ru.vtosters.lite.utils.Base64Utils.decode;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.checkCaption;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.checkCopyright;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.isBadNews;
|
||||
import static ru.vtosters.lite.utils.Preferences.ads;
|
||||
import static ru.vtosters.lite.utils.Preferences.adsgroup;
|
||||
import static ru.vtosters.lite.utils.Preferences.adsstories;
|
||||
import static ru.vtosters.lite.utils.Preferences.authorsrecomm;
|
||||
import static ru.vtosters.lite.utils.Preferences.dev;
|
||||
import static ru.vtosters.lite.utils.Preferences.friendsblock;
|
||||
import static ru.vtosters.lite.utils.Preferences.friendsrecomm;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.hasVerification;
|
||||
import static ru.vtosters.lite.utils.Preferences.podcastcatalog;
|
||||
import static ru.vtosters.lite.utils.Preferences.postsrecomm;
|
||||
import static ru.vtosters.lite.utils.VTVerifications.isDeveloper;
|
||||
import static ru.vtosters.lite.utils.VTVerifications.isPrometheus;
|
||||
import static ru.vtosters.lite.utils.VTVerifications.isVerified;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.vk.core.network.Network;
|
||||
import com.vk.core.util.DeviceIdProvider;
|
||||
import com.vk.core.util.LangUtils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
public class JsonInjectors{
|
||||
public static JSONObject profileButton(JSONObject orig) throws JSONException{
|
||||
if (haveDonateButton()) return orig;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.NewsFeedFiltersUtils;
|
||||
|
||||
var pic = "https://sun1-18.userapi.com/NLd_rNpGuSaBnPV6O-j5mqCGZk8BK8drAMd2LQ/5R-DEF37PFs.png";
|
||||
var title = "Помоги проекту донатом и получи бонус!";
|
||||
public class JsonInjectors {
|
||||
private static final OkHttpClient mClient = new OkHttpClient();
|
||||
|
||||
public static JSONObject profileButton(JSONObject orig) throws JSONException {
|
||||
var id = orig.getInt("id");
|
||||
|
||||
var newItem = new JSONArray();
|
||||
|
||||
if (orig.has("buttons")) {
|
||||
newItem = orig.getJSONArray("buttons");
|
||||
}
|
||||
|
||||
if (!haveDonateButton() && id == AccountManagerUtils.getUserId()) {
|
||||
newItem.put(donateRecomm());
|
||||
}
|
||||
|
||||
if (!orig.has("type") && AccountManagerUtils.isVKTester()) {
|
||||
newItem.put(vktesters(id));
|
||||
}
|
||||
|
||||
orig.put("buttons", newItem);
|
||||
|
||||
return orig;
|
||||
}
|
||||
|
||||
public static JSONObject donateRecomm() throws JSONException {
|
||||
var title = AndroidUtils.getString("donate_to_vtl");
|
||||
var link = "https://vk.com/vtosters_official";
|
||||
var text_color = "2D81E0";
|
||||
|
||||
// JSONObject jsonObj = new JSONObject("{\"action\":{\"target\":\"internal\",\"type\":\"open_url\",\"url\":\"" + link + "\"},\"title\":\"" + title + "\",\"icons\":[{\"url\":\"" + pic + "\",\"width\":20,\"height\":20},{\"url\":\"" + pic + "\",\"width\":40,\"height\":40},{\"url\":\"" + pic + "\",\"width\":60,\"height\":60},{\"url\":\"" + pic + "\",\"width\":80,\"height\":80}],\"text_color\":\"" + text_color + "\"}");
|
||||
return new JSONObject(decode("eyJhY3Rpb24iOnsidGFyZ2V0IjoiaW50ZXJuYWwiLCJ0eXBlIjoib3Blbl91cmwiLCJ1cmwiOiI=")
|
||||
+ link + decode("In0sInRpdGxlIjoi")
|
||||
+ title + decode("IiwiaWNvbnMiOlt7InVybCI6Ig==")
|
||||
+ pic + decode("Iiwid2lkdGgiOjIwLCJoZWlnaHQiOjIwfSx7InVybCI6Ig==")
|
||||
+ pic + decode("Iiwid2lkdGgiOjQwLCJoZWlnaHQiOjQwfSx7InVybCI6Ig==")
|
||||
+ pic + decode("Iiwid2lkdGgiOjYwLCJoZWlnaHQiOjYwfSx7InVybCI6Ig==")
|
||||
+ pic + decode("Iiwid2lkdGgiOjgwLCJoZWlnaHQiOjgwfV0sInRleHRfY29sb3IiOiI=")
|
||||
+ text_color + decode("In0="));
|
||||
var json = new JSONObject();
|
||||
var icons = new JSONArray();
|
||||
|
||||
var action = new JSONObject();
|
||||
action.put("target", "internal");
|
||||
action.put("type", "open_url"); // may be open_url, open_internal_vkui, open_game, help_hint, show_full_post, open_vkapp, show_recommendations_for_post and groups_advertisement
|
||||
action.put("url", link);
|
||||
json.put("action", action);
|
||||
|
||||
json.put("title", title);
|
||||
|
||||
var icon1 = new JSONObject();
|
||||
icon1.put("url", "https://sun2-10.userapi.com/NLd_rNpGuSaBnPV6O-j5mqCGZk8BK8drAMd2LQ/5R-DEF37PFs.png");
|
||||
icon1.put("width", "20");
|
||||
icon1.put("height", "20");
|
||||
icons.put(icon1);
|
||||
|
||||
var icon2 = new JSONObject();
|
||||
icon2.put("url", "https://sun2-12.userapi.com/N8y9pU1meJq_eug-wB1u-HUuGyMqDfdq7A025w/A4Aio-xuLY8.png");
|
||||
icon2.put("width", "40");
|
||||
icon2.put("height", "40");
|
||||
icons.put(icon2);
|
||||
|
||||
var icon3 = new JSONObject();
|
||||
icon3.put("url", "https://sun2-9.userapi.com/3Hx4hff63_2Lt6wjjthJMF_3QLUswNNlQKoAXQ/oyzEu1NL9T8.png");
|
||||
icon3.put("width", "80");
|
||||
icon3.put("height", "80");
|
||||
icons.put(icon3);
|
||||
|
||||
json.put("icons", icons);
|
||||
|
||||
json.put("text_color", text_color);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static JSONObject convBar(JSONObject orig) throws JSONException{
|
||||
if (!dev()) return orig.optJSONObject("conversation_bar"); // TODO Make it server-side
|
||||
public static JSONObject vktesters(int id) throws JSONException {
|
||||
var title = AndroidUtils.getString("tester_profile");
|
||||
var text_color = "2D81E0";
|
||||
var link = "https://static.vk.com/bugs?lang=" + LangUtils.a() + "#/reporter" + id;
|
||||
|
||||
var json = new JSONObject();
|
||||
var icons = new JSONArray();
|
||||
|
||||
var action = new JSONObject();
|
||||
action.put("target", "internal");
|
||||
action.put("type", "open_internal_vkui");
|
||||
action.put("url", link);
|
||||
json.put("action", action);
|
||||
|
||||
json.put("title", title);
|
||||
|
||||
var icon1 = new JSONObject();
|
||||
icon1.put("url", "https://sun2-10.userapi.com/NLd_rNpGuSaBnPV6O-j5mqCGZk8BK8drAMd2LQ/5R-DEF37PFs.png");
|
||||
icon1.put("width", "20");
|
||||
icon1.put("height", "20");
|
||||
icons.put(icon1);
|
||||
|
||||
var icon2 = new JSONObject();
|
||||
icon2.put("url", "https://sun2-12.userapi.com/N8y9pU1meJq_eug-wB1u-HUuGyMqDfdq7A025w/A4Aio-xuLY8.png");
|
||||
icon2.put("width", "40");
|
||||
icon2.put("height", "40");
|
||||
icons.put(icon2);
|
||||
|
||||
var icon3 = new JSONObject();
|
||||
icon3.put("url", "https://sun2-9.userapi.com/3Hx4hff63_2Lt6wjjthJMF_3QLUswNNlQKoAXQ/oyzEu1NL9T8.png");
|
||||
icon3.put("width", "80");
|
||||
icon3.put("height", "80");
|
||||
icons.put(icon3);
|
||||
|
||||
json.put("icons", icons);
|
||||
|
||||
json.put("text_color", text_color);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static JSONObject convBar(JSONObject orig) throws JSONException {
|
||||
if (!dev()) return orig.optJSONObject("conversation_bar"); // for devs only
|
||||
|
||||
var peerid = Objects.requireNonNull(orig.optJSONObject("peer")).optInt("id");
|
||||
|
||||
var pic = "https://image.pngaaa.com/641/326641-middle.png"; // can be null
|
||||
var text = "Я не загрузил данные (9(9((";
|
||||
var text = AndroidUtils.getString("no_data_error");
|
||||
var link = "https://vtosters.app"; // can be null
|
||||
var linktitle = "Test button"; // can be null
|
||||
|
||||
// "{\"layout\":\"tertiary\",\"text\":\"" + linktitle + "\",\"type\":\"link\",\"link\":\"" + link + "\"}";
|
||||
var buttons = decode("eyJsYXlvdXQiOiJ0ZXJ0aWFyeSIsInRleHQiOiI=") + linktitle + decode("IiwidHlwZSI6ImxpbmsiLCJsaW5rIjoi") + link + decode("In0=");
|
||||
// ,"icon":" + pic + "
|
||||
var icon = decode("LCJpY29uIjoi") + pic + decode("Ig==");
|
||||
|
||||
var hasIcon = !pic.isEmpty();
|
||||
var hasButton = !buttons.isEmpty();
|
||||
var hasButton = !link.isEmpty();
|
||||
|
||||
var isPicture = pic.endsWith(".png") || pic.endsWith(".jpg") || pic.endsWith(".jpeg") || pic.endsWith(".webp");
|
||||
|
||||
if (!isPicture) hasIcon = false;
|
||||
if (!hasIcon) icon = "";
|
||||
if (!hasButton) buttons = "";
|
||||
if (isVerified(peerid)) text = AndroidUtils.getString("i_bought") + " VTosters Premium";
|
||||
if (isPrometheus(peerid)) text = AndroidUtils.getString("i_bought") + " VTosters Premium Gold Prime Pro Plus";
|
||||
if (isDeveloper(peerid)) text = AndroidUtils.getString("i_created_poop");
|
||||
|
||||
if (isVerified(peerid)) text = "Я купил VTosters Premium";
|
||||
if (isPrometheus(peerid)) text = "Я купил VTosters Premium Gold Prime Pro Plus";
|
||||
if (isDeveloper(peerid)) text = "Я создал говно";
|
||||
if (!isVerified(peerid) || text.equals("")) return orig.optJSONObject("conversation_bar");
|
||||
if (!isVerified(peerid) || text.equals("") || peerid == AccountManagerUtils.getUserId() || peerid == 0) {
|
||||
if (getBoolValue("convBarRecomm", false)) {
|
||||
return null;
|
||||
} else {
|
||||
return orig.optJSONObject("conversation_bar");
|
||||
}
|
||||
}
|
||||
var json = new JSONObject();
|
||||
|
||||
// JSONObject("{\"name\":\"group_admin_welcome\",\"text\":\"" + textverif + "\",\"buttons\":[],\"icon\":\"" + pic + "\"}");
|
||||
return new JSONObject(decode("eyJuYW1lIjoiZ3JvdXBfYWRtaW5fd2VsY29tZSIsInRleHQiOiI=")
|
||||
+ text + decode("IiwiYnV0dG9ucyI6Ww==")
|
||||
+ buttons + decode("XQ==")
|
||||
+ icon
|
||||
+ decode("fQ=="));
|
||||
var buttonsJson = new JSONObject();
|
||||
buttonsJson.put("layout", "tertiary");
|
||||
buttonsJson.put("text", linktitle);
|
||||
buttonsJson.put("type", "link");
|
||||
buttonsJson.put("link", link);
|
||||
|
||||
var buttonsjson = new JSONArray(); // max 3 buttons in array
|
||||
if (hasButton) buttonsjson.put(buttonsJson);
|
||||
|
||||
json.put("name", "group_admin_welcome");
|
||||
json.put("text", text);
|
||||
json.put("buttons", buttonsjson);
|
||||
if (hasIcon && isPicture) {
|
||||
json.put("icon", pic);
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static JSONObject menu(JSONObject orig) throws JSONException{
|
||||
public static JSONObject menu(JSONObject orig) throws JSONException {
|
||||
var Special = orig.optJSONArray("special");
|
||||
var Main = orig.getJSONArray("main");
|
||||
var Other = orig.optJSONArray("other");
|
||||
@@ -83,23 +215,465 @@ public class JsonInjectors{
|
||||
return orig;
|
||||
}
|
||||
|
||||
public static JSONObject superapp(JSONObject json) throws JSONException{
|
||||
public static JSONObject superapp(JSONObject json) throws JSONException {
|
||||
var superApps = AndroidUtils.getPreferences().getString("superapp_items",
|
||||
"menu,miniapps,vkpay_slim,greeting,promo,holiday,weather,sport,games,informer,food,event,music,vk_run").split(",");
|
||||
if (superApps.length == 0) return json;
|
||||
|
||||
var oldItems = json.optJSONArray("items");
|
||||
var newItems = new JSONArray();
|
||||
if (oldItems != null) {
|
||||
for (int i = 0; i < oldItems.length(); i++) {
|
||||
var item = oldItems.optJSONObject(i);
|
||||
var type = item.optString("type");
|
||||
if (!getBoolValue("superapp_" + type, false))
|
||||
newItems.put(item);
|
||||
for (String superApp : superApps) {
|
||||
if (type.equals(superApp))
|
||||
newItems.put(item);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < superApps.length; i++) {
|
||||
for (int j = i; j < newItems.length(); j++) {
|
||||
var item = newItems.optJSONObject(j);
|
||||
if (superApps[i].equals(item.optString("type")))
|
||||
newItems.put(j, newItems.getJSONObject(i))
|
||||
.put(i, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json.putOpt("items", newItems);
|
||||
}
|
||||
|
||||
public static JSONObject friends(JSONObject json) throws JSONException{
|
||||
JSONObject catalog = json;
|
||||
public static JSONObject musiclink(JSONObject json) {
|
||||
var oldItems = json.optJSONArray("links");
|
||||
var section = json.optJSONObject("section");
|
||||
var linksblock = section.optJSONArray("blocks");
|
||||
var newBlock = new JSONArray();
|
||||
|
||||
if (oldItems != null) {
|
||||
if (oldItems.optJSONObject(0).optString("url").contains("?section=recent")) {
|
||||
json.remove("links");
|
||||
|
||||
for (int i = 0; i < linksblock.length(); i++) {
|
||||
var item = linksblock.optJSONObject(i);
|
||||
var datatype = item.optString("data_type");
|
||||
var layname = item.optJSONObject("layout").optString("name");
|
||||
if (!datatype.equals("links") && !layname.equals("separator")) {
|
||||
newBlock.put(item);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
section.putOpt("blocks", newBlock);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (dev()) Log.d("VKMusic", "Removed links buttons");
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static JSONObject setOnlineInfo(JSONObject json) throws ParseException, IOException, JSONException {
|
||||
var id = json.optInt("id");
|
||||
if (id == AccountManagerUtils.getUserId()) {
|
||||
return json;
|
||||
}
|
||||
var onlineinfo = json.optJSONObject("online_info");
|
||||
if (onlineinfo != null && !onlineinfo.optBoolean("visible")) {
|
||||
var bypassed = getBypassedOnlineInfo(id);
|
||||
if (bypassed.optInt("last_seen", 0) != 0) {
|
||||
json.remove("online_info");
|
||||
|
||||
var online_info = new JSONObject()
|
||||
.put("visible", true)
|
||||
.put("last_seen", bypassed.optInt("last_seen"))
|
||||
.put("is_online", bypassed.optBoolean("is_online"))
|
||||
.put("app_id", bypassed.optInt("app_id"))
|
||||
.put("is_mobile", bypassed.optBoolean("is_mobile"));
|
||||
|
||||
var last_seen = new JSONObject()
|
||||
.put("platform", bypassed.optInt("platform"))
|
||||
.put("time", bypassed.optInt("last_seen"));
|
||||
|
||||
json.put("last_seen", last_seen).put("online_info", online_info);
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static JSONArray setOnlineInfoUsers(JSONArray profiles) throws ParseException, IOException, JSONException {
|
||||
if (profiles == null || profiles.length() == 0) return profiles;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
var curVkId = AccountManagerUtils.getUserId();
|
||||
for (int i=0; i < profiles.length(); i++) {
|
||||
JSONObject profile = profiles.getJSONObject(i);
|
||||
int id = profile.optInt("id", -1);
|
||||
JSONObject onlinfo = profile.optJSONObject("online_info");
|
||||
if (id == curVkId || id < 0 || onlinfo == null || onlinfo.optBoolean("visible")) {
|
||||
continue;
|
||||
}
|
||||
sb.append(id);
|
||||
sb.append(",");
|
||||
}
|
||||
var ids = sb.toString();
|
||||
if (ids.length() > 0) {
|
||||
ids = ids.substring(0, ids.length() - 1);
|
||||
} else {
|
||||
return profiles;
|
||||
}
|
||||
|
||||
JSONObject bypassedObj = getBypassedOnlineInfo(ids);
|
||||
for (int i=0; i < profiles.length(); i++) {
|
||||
JSONObject profile = profiles.getJSONObject(i);
|
||||
int id = profile.optInt("id");
|
||||
JSONObject bypassed = bypassedObj.optJSONObject(Integer.toString(id));
|
||||
if (bypassed == null) {
|
||||
continue;
|
||||
}
|
||||
profile.remove("online_info");
|
||||
|
||||
var online_info = new JSONObject()
|
||||
.put("visible", true)
|
||||
.put("last_seen", bypassed.optInt("last_seen"))
|
||||
.put("is_online", bypassed.optBoolean("is_online"))
|
||||
.put("app_id", bypassed.optInt("app_id"))
|
||||
.put("is_mobile", bypassed.optBoolean("is_mobile"));
|
||||
|
||||
var last_seen = new JSONObject()
|
||||
.put("platform", bypassed.optInt("platform"))
|
||||
.put("time", bypassed.optInt("last_seen"));
|
||||
|
||||
profile.put("last_seen", last_seen).put("online_info", online_info);
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
|
||||
public static JSONObject storiesads(JSONObject json, boolean isDeleteFix) throws JSONException {
|
||||
if (!adsstories()) {
|
||||
return json;
|
||||
}
|
||||
|
||||
if (json.has("ads")) {
|
||||
if (isDeleteFix) {
|
||||
json.optJSONObject("ads").optJSONObject("settings")
|
||||
.put("stories_interval", 0)
|
||||
.put("authors_interval", 0)
|
||||
.put("time_interval", 0)
|
||||
.put("stories_init", 0)
|
||||
.put("authors_init", 0)
|
||||
.put("time_init", 0);
|
||||
if (dev()) Log.d("StoriesAds", "Set ads settings at zero values");
|
||||
} else {
|
||||
json.remove("ads");
|
||||
if (dev()) Log.d("StoriesAds", "Removed ads block");
|
||||
}
|
||||
}
|
||||
|
||||
if (!json.has("items")) return json;
|
||||
|
||||
var items = json.optJSONArray("items");
|
||||
for (int i = 0; i < items.length(); i++) {
|
||||
var item = items.optJSONObject(i);
|
||||
if (item != null) {
|
||||
parseStoriesItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
private static void parseStoriesItem(JSONObject item) throws JSONException {
|
||||
var stories = item.optJSONArray("stories");
|
||||
var newStories = new JSONArray();
|
||||
|
||||
if (stories == null) return;
|
||||
|
||||
for (int j = 0; j < stories.length(); j++) {
|
||||
var story = stories.optJSONObject(j);
|
||||
|
||||
if (!story.optBoolean("is_ads") && !story.optBoolean("is_promo")) {
|
||||
newStories.put(story);
|
||||
} else {
|
||||
if (dev())
|
||||
Log.d("StoriesAds", "Fetched ad, owner id " + story.optString("owner_id") + ", caption " + story.optString("caption"));
|
||||
}
|
||||
}
|
||||
|
||||
item.put("stories", newStories);
|
||||
}
|
||||
|
||||
public static Boolean isAds(JSONObject list, String type) throws JSONException {
|
||||
if (list == null || type == null || !ads()) return false;
|
||||
|
||||
if (list.has("ads")
|
||||
|| type.equals("ads")
|
||||
|| type.equals("carousel")
|
||||
|| type.equals("html5_ad")
|
||||
|| type.equals("ads_easy_promote")) {
|
||||
if (dev())
|
||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: ads");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.equals("promo_button")
|
||||
|| type.equals("app_widget")
|
||||
|| type.equals("app_video")
|
||||
|| type.equals("app_slider")
|
||||
|| type.equals("tags_suggestions")) {
|
||||
if (dev())
|
||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: promo");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static JSONArray newsfeedlist(JSONArray items) throws JSONException {
|
||||
var selectedItems = getDefaultPrefs().getString("news_feed_selected_items", "");
|
||||
var filtersSet = getDefaultPrefs().getStringSet("news_feed_items_set", null);
|
||||
var mutableFiltersSet = Collections.synchronizedSet(new LinkedHashSet<String>());
|
||||
if (filtersSet != null)
|
||||
mutableFiltersSet.addAll(filtersSet);
|
||||
|
||||
synchronized (mutableFiltersSet) {
|
||||
for (int i = 0; i < items.length(); i++) {
|
||||
var item = items.optJSONObject(i);
|
||||
if (item == null) continue;
|
||||
|
||||
var id = item.optString("id");
|
||||
var title = item.optString("title");
|
||||
|
||||
if (TextUtils.isEmpty(id) || TextUtils.isEmpty(title)
|
||||
// this items not working
|
||||
|| id.equals("kpop") || id.equals("foryou")
|
||||
|| id.equals("qazaqstan") || id.equals("podcasts"))
|
||||
continue;
|
||||
|
||||
mutableFiltersSet.add(id + "|" + title);
|
||||
|
||||
var hide = selectedItems.contains(id);
|
||||
|
||||
Log.d("NewsfeedList", "Added list " + id + " to feed");
|
||||
item.put("is_hidden", hide)
|
||||
.put("is_unavailable", hide);
|
||||
if (dev()) Log.d("NewsfeedListInj", "Unlocked " + id + " in newsfeed list");
|
||||
}
|
||||
getDefaultPrefs().edit().putStringSet("news_feed_items_set", mutableFiltersSet)
|
||||
.apply();
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public static JSONArray newsfeedadtest(JSONArray items) throws JSONException {
|
||||
if (!getBoolValue("newadblock", true)) return items;
|
||||
var newItems = new JSONArray();
|
||||
|
||||
for (int j = 0; j < items.length(); j++) {
|
||||
var list = items.optJSONObject(j);
|
||||
var type = list.optString("type");
|
||||
|
||||
if (isAds(list, type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (authorsrecomm() && (type.equals("authors_rec")
|
||||
|| type.startsWith("recommended_") && (type.endsWith("audios")
|
||||
|| type.endsWith("artists")
|
||||
|| type.endsWith("playlists")
|
||||
|| type.endsWith("groups")))) {
|
||||
if (dev())
|
||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: authorsrecomm");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (postsrecomm() && (type.equals("inline_user_rec") || type.equals("live_recommended"))) {
|
||||
if (dev())
|
||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: postsrecomm");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (friendsrecomm() && (type.equals("user_rec") || type.equals("friends_recomm"))) {
|
||||
if (dev())
|
||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: friendsrecomm");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (adsgroup() && list.optInt("marked_as_ads") == 1) {
|
||||
if (dev())
|
||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: marked_as_ads is true");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isBadNews(list.optString("text"))) {
|
||||
if (dev())
|
||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: text filters");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checkCopyright(list)) {
|
||||
if (dev())
|
||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: copyright filters");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (checkCaption(list)) {
|
||||
if (dev())
|
||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: caption filters");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NewsFeedFiltersUtils.injectFiltersReposts(list)) {
|
||||
if (dev())
|
||||
Log.d("NewsfeedAdBlockV2", "Removed post " + list.optInt("post_id") + " from feed, Reason: repost ad");
|
||||
continue;
|
||||
}
|
||||
|
||||
newItems.put(list);
|
||||
}
|
||||
|
||||
return newItems;
|
||||
}
|
||||
|
||||
public static JSONObject music(JSONObject json) throws JSONException {
|
||||
var catalog = json.optJSONObject("catalog");
|
||||
|
||||
JSONArray oldItems = null;
|
||||
|
||||
if (catalog != null) {
|
||||
oldItems = catalog.optJSONArray("sections");
|
||||
}
|
||||
|
||||
if (oldItems != null && oldItems.optJSONObject(0).optString("url").contains("general")) {
|
||||
if (podcastcatalog()) {
|
||||
var podcasts = fetchCatalogPodcast();
|
||||
if (podcasts != null) {
|
||||
var catalogarr = podcasts.optJSONObject("catalog").optJSONArray("sections").optJSONObject(0);
|
||||
|
||||
var title = catalogarr.optString("title");
|
||||
var id = catalogarr.optString("id");
|
||||
var url = catalogarr.optString("url");
|
||||
|
||||
if (dev()) Log.d("VKMusic", "Added " + title + " in music sections");
|
||||
|
||||
oldItems.put(new JSONObject().put("id", id).put("title", title).put("url", url));
|
||||
}
|
||||
}
|
||||
|
||||
var playlists = fetchCatalogId("https://vk.com/audio?section=my_playlists");
|
||||
if (playlists != null) {
|
||||
var catalogarr = playlists.optJSONObject("catalog").optJSONArray("sections").optJSONObject(0);
|
||||
|
||||
var title = catalogarr.optString("title");
|
||||
var id = catalogarr.optString("id");
|
||||
var url = catalogarr.optString("url");
|
||||
|
||||
if (dev()) Log.d("VKMusic", "Added " + title + " in music sections");
|
||||
|
||||
oldItems.put(new JSONObject().put("id", id).put("title", title).put("url", url));
|
||||
}
|
||||
|
||||
var albums = fetchCatalogId("https://vk.com/audio?section=albums");
|
||||
if (albums != null) {
|
||||
var catalogarr = albums.optJSONObject("catalog").optJSONArray("sections").optJSONObject(0);
|
||||
|
||||
var title = catalogarr.optString("title");
|
||||
var id = catalogarr.optString("id");
|
||||
var url = catalogarr.optString("url");
|
||||
|
||||
if (dev()) Log.d("VKMusic", "Added " + title + " in music sections");
|
||||
|
||||
oldItems.put(new JSONObject().put("id", id).put("title", title).put("url", url));
|
||||
}
|
||||
|
||||
var recent = fetchCatalogId("https://vk.com/audio?section=recent");
|
||||
if (recent != null) {
|
||||
var catalogarr = recent.optJSONObject("catalog").optJSONArray("sections").optJSONObject(0);
|
||||
|
||||
var title = catalogarr.optString("title");
|
||||
var id = catalogarr.optString("id");
|
||||
var url = catalogarr.optString("url");
|
||||
|
||||
if (dev()) Log.d("VKMusic", "Added " + title + " in music sections");
|
||||
|
||||
oldItems.put(new JSONObject().put("id", id).put("title", title).put("url", url));
|
||||
}
|
||||
|
||||
for (int i = 0; i < oldItems.length(); i++) {
|
||||
var item = oldItems.optJSONObject(i);
|
||||
var title = item.optString("title");
|
||||
var id = item.optString("id");
|
||||
var url = item.optString("url");
|
||||
var value = AndroidUtils.getPrefsValue("musicdefcatalog");
|
||||
|
||||
Log.d("VKMusic", "title: " + title + " id: " + id + " url: " + url + " value: " + value);
|
||||
|
||||
if (url.contains(value) && !value.isEmpty()) {
|
||||
catalog.put("default_section", id);
|
||||
if (dev()) Log.d("VKMusic", "Added " + title + " as default music section");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static JSONObject fetchCatalogId(String section) {
|
||||
if (section == null) return null;
|
||||
|
||||
var request = new Request.a()
|
||||
.b("https://api.vk.com/method/catalog.getAudio"
|
||||
+ "?v=5.119"
|
||||
+ "&https=1"
|
||||
+ "&need_blocks=1"
|
||||
+ "&lang="
|
||||
+ getLocale()
|
||||
+ "&device_id="
|
||||
+ DeviceIdProvider.d(AndroidUtils.getGlobalContext())
|
||||
+ "&url="
|
||||
+ section
|
||||
+ "&access_token="
|
||||
+ AccountManagerUtils.getUserToken())
|
||||
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8")).a();
|
||||
try {
|
||||
return new JSONObject(mClient.a(request).execute().a().g()).getJSONObject("response");
|
||||
} catch (JSONException | IOException e) {
|
||||
Log.d("VTLMusic", "Error: " + e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static JSONObject fetchCatalogPodcast() {
|
||||
var request = new Request.a()
|
||||
.b("https://api.vk.com/method/catalog.getPodcasts"
|
||||
+ "?v=5.119"
|
||||
+ "&https=1"
|
||||
+ "&need_blocks=1"
|
||||
+ "&lang="
|
||||
+ getLocale()
|
||||
+ "&device_id="
|
||||
+ DeviceIdProvider.d(AndroidUtils.getGlobalContext())
|
||||
+ "&access_token="
|
||||
+ AccountManagerUtils.getUserToken())
|
||||
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8")).a();
|
||||
try {
|
||||
return new JSONObject(mClient.a(request).execute().a().g()).getJSONObject("response");
|
||||
} catch (JSONException | IOException e) {
|
||||
Log.d("VTLMusic", "Error: " + e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static JSONObject friends(JSONObject json) throws JSONException, ParseException, IOException {
|
||||
JSONObject catalog = onlineHookProfiles(json);
|
||||
boolean sectionexecute = true;
|
||||
boolean hasBirthday = false;
|
||||
|
||||
@@ -139,11 +713,11 @@ public class JsonInjectors{
|
||||
skip = friendsblock();
|
||||
}
|
||||
|
||||
if (buttons.contains("friends_birthdays_list")){
|
||||
if (buttons.contains("friends_birthdays_list")) {
|
||||
hasBirthday = true;
|
||||
}
|
||||
|
||||
if (name.contains("separator") && hasBirthday){
|
||||
if (name.contains("separator") && hasBirthday) {
|
||||
skip = false;
|
||||
hasBirthday = false;
|
||||
}
|
||||
@@ -165,7 +739,7 @@ public class JsonInjectors{
|
||||
}
|
||||
|
||||
|
||||
public static boolean haveDonateButton(){
|
||||
public static boolean haveDonateButton() {
|
||||
int randomshower = new Random().nextInt(6);
|
||||
|
||||
return hasVerification() || randomshower != 1;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static ru.vtosters.lite.ui.dialogs.ServerDialog.sendRequest;
|
||||
import static ru.vtosters.lite.utils.CacheUtils.getInstance;
|
||||
import static ru.vtosters.lite.utils.DeletedMessagesHandler.reloadMessagesList;
|
||||
import static ru.vtosters.lite.utils.Preferences.checkupdates;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.isDarkTheme;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.setNeededTheme;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import ru.vtosters.lite.downloaders.notifications.NotificationChannels;
|
||||
import ru.vtosters.lite.ui.dialogs.DisableBattery;
|
||||
import ru.vtosters.lite.ui.dialogs.InstallGMS;
|
||||
import ru.vtosters.lite.ui.dialogs.OTADialog;
|
||||
import ru.vtosters.lite.ui.dialogs.ServerDialog;
|
||||
import ru.vtosters.lite.ui.dialogs.Start;
|
||||
|
||||
public class MainActivityInjector {
|
||||
|
||||
public static void inject(Activity activity) {
|
||||
setNeededTheme(activity);
|
||||
ServerDialog.activity = activity;
|
||||
sendRequest();
|
||||
if (checkupdates()) OTADialog.checkUpdates(activity);
|
||||
reloadMessagesList();
|
||||
Start.alert(activity);
|
||||
InstallGMS.alert(activity);
|
||||
DisableBattery.alert(activity);
|
||||
PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
.edit()
|
||||
.putBoolean("isdark", isDarkTheme())
|
||||
.commit();
|
||||
getInstance().autoCleaningCache();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannels.createChannels();
|
||||
}
|
||||
|
||||
// VKIDProtection.alert(activity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static ru.vtosters.lite.ui.dialogs.MessageSettings.argDialog;
|
||||
import static ru.vtosters.lite.ui.dialogs.MessageSettings.bombCount;
|
||||
import static ru.vtosters.lite.ui.dialogs.MessageSettings.isSilentEnabled;
|
||||
import static ru.vtosters.lite.utils.Preferences.autoalltranslate;
|
||||
import static ru.vtosters.lite.utils.Preferences.autotranslate;
|
||||
import static ru.vtosters.lite.utils.Preferences.savemsgsett;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import com.vk.api.internal.MethodCall;
|
||||
|
||||
import ru.vtosters.lite.translators.BaseTranslator;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class MessagesHook {
|
||||
public static String injectOwnText(String oldText) {
|
||||
if (!autotranslate() || TextUtils.isEmpty(oldText))
|
||||
return oldText;
|
||||
var instance = BaseTranslator.getInstance();
|
||||
|
||||
return replaceMentions(oldText, instance);
|
||||
}
|
||||
|
||||
public static String injectOwnTextAll(String oldText) {
|
||||
if (!autoalltranslate() || TextUtils.isEmpty(oldText)) {
|
||||
return oldText;
|
||||
}
|
||||
var instance = BaseTranslator.getInstance();
|
||||
|
||||
return replaceMentions(oldText, instance);
|
||||
}
|
||||
|
||||
public static String replaceMentions(String oldText, BaseTranslator instance) {
|
||||
try {
|
||||
var matcher = Pattern.compile("(\\[(?:club|id|public)\\d+\\|[^]]+\\])|(@[^\\s]+)").matcher(oldText);
|
||||
var mentionsCount = 0;
|
||||
|
||||
var textBuff = new StringBuffer();
|
||||
var mentions = new ArrayList<String>();
|
||||
while (matcher.find()) {
|
||||
mentions.add(matcher.group());
|
||||
matcher.appendReplacement(textBuff, "vtl_mention" + mentionsCount + ""); ++mentionsCount;
|
||||
}
|
||||
matcher.appendTail(textBuff);
|
||||
|
||||
var translatedText = instance.getTranslation(textBuff.toString());
|
||||
var matcherMentions = Pattern.compile("vtl_mention(\\d+)").matcher(translatedText);
|
||||
var retTextBuff = new StringBuffer();
|
||||
while (matcherMentions.find()) {
|
||||
matcherMentions.appendReplacement(retTextBuff, mentions.get(
|
||||
Integer.parseInt(matcherMentions.group(1))
|
||||
));
|
||||
}
|
||||
matcherMentions.appendTail(retTextBuff);
|
||||
|
||||
return retTextBuff.toString();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
return instance.getTranslation(oldText);
|
||||
}
|
||||
}
|
||||
|
||||
public static void onLongClick(View view) {
|
||||
view.setOnLongClickListener(v -> {
|
||||
argDialog(v.getContext());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public static void injRequest(MethodCall.a req) {
|
||||
var time = expireTime();
|
||||
|
||||
if (time > 0) {
|
||||
req.a("expire_ttl", time);
|
||||
if (!savemsgsett()) bombCount = "0";
|
||||
}
|
||||
|
||||
if (isSilentEnabled) {
|
||||
req.a("silent", 1);
|
||||
if (!savemsgsett()) isSilentEnabled = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int expireTime() {
|
||||
switch (bombCount) {
|
||||
case "15s":
|
||||
return 15;
|
||||
case "1m":
|
||||
return 60;
|
||||
case "5m":
|
||||
return 300;
|
||||
case "1h":
|
||||
return 3600;
|
||||
case "24h":
|
||||
return 86400;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,25 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static java.lang.Long.MAX_VALUE;
|
||||
import static ru.vtosters.lite.utils.Globals.getPrefsValue;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.checkCaption;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.checkCopyright;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.injectFiltersReposts;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.isAds;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.isAuthorRecommendations;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.isBadNew;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.isFriendsRecommendations;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.isGroupAds;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.isMusicBlock;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.isNewsBlock;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.isPostRecommendations;
|
||||
import static ru.vtosters.lite.utils.Newsfeed.isRecomsGroup;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.checkCaption;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.checkCopyright;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.injectFiltersReposts;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.isAds;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.isAuthorRecommendations;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.isBadNews;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.isFriendsRecommendations;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.isGroupAds;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.isMusicBlock;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.isNewsBlock;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.isPostRecommendations;
|
||||
import static ru.vtosters.lite.utils.NewsFeedFiltersUtils.isRecomsGroup;
|
||||
import static ru.vtosters.lite.utils.Preferences.ads;
|
||||
import static ru.vtosters.lite.utils.Preferences.adsslider;
|
||||
import static ru.vtosters.lite.utils.Preferences.authorsrecomm;
|
||||
import static ru.vtosters.lite.utils.Preferences.friendsrecomm;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
||||
import static ru.vtosters.lite.utils.Preferences.vkme;
|
||||
|
||||
import com.vk.core.preference.Preference;
|
||||
@@ -20,8 +27,14 @@ import com.vk.core.preference.Preference;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class NewsfeedHook{
|
||||
public static boolean injectFilters(JSONObject obj) throws JSONException{
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class NewsfeedHook {
|
||||
public static boolean injectFilters(JSONObject obj) throws JSONException {
|
||||
if (getBoolValue("newadblock", true)) return true;
|
||||
|
||||
var optString = obj.optString("type", "");
|
||||
if (isAds(optString) || isAuthorRecommendations(optString) || isPostRecommendations(optString) || isFriendsRecommendations(optString) || isRecomsGroup(optString) || isMusicBlock(optString) || isNewsBlock(optString)) {
|
||||
return false;
|
||||
@@ -37,7 +50,7 @@ public class NewsfeedHook{
|
||||
|
||||
if (checkCopyright(obj)) return false;
|
||||
|
||||
if (isBadNew(obj.optString("text", ""))) return false;
|
||||
if (isBadNews(obj.optString("text", ""))) return false;
|
||||
|
||||
if (checkCaption(obj)) return false;
|
||||
|
||||
@@ -46,11 +59,11 @@ public class NewsfeedHook{
|
||||
return !injectFiltersReposts(obj);
|
||||
} // inject our filters to newsfeed, getpost and discover
|
||||
|
||||
public static long getUpdateNewsfeed(boolean refresh_timeout){
|
||||
public static long getUpdateNewsfeed(boolean refresh_timeout) {
|
||||
if (vkme()) {
|
||||
return MAX_VALUE;
|
||||
}
|
||||
switch(getPrefsValue("newsupdate")) {
|
||||
switch (getPrefsValue("newsupdate")) {
|
||||
case "no_update":
|
||||
return MAX_VALUE;
|
||||
case "imd_update":
|
||||
@@ -59,4 +72,51 @@ public class NewsfeedHook{
|
||||
return Preference.b().getLong(refresh_timeout ? "refresh_timeout_top" : "refresh_timeout_recent", 600000L);
|
||||
}
|
||||
}
|
||||
|
||||
public static List hideElement(ArrayList list) {
|
||||
if (!getBoolValue("whatsnew", true)) {
|
||||
list.clear();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static String[] feedParams(){
|
||||
HashSet<String> params = new HashSet<>();
|
||||
params.add("post");
|
||||
params.add("photo");
|
||||
params.add("photo_tag");
|
||||
|
||||
if (!friendsrecomm()) {
|
||||
params.add("friends_recomm");
|
||||
}
|
||||
|
||||
if (!ads()) {
|
||||
params.add("app_widget");
|
||||
params.add("promo_button");
|
||||
}
|
||||
|
||||
if (!authorsrecomm()) {
|
||||
params.add("authors_rec");
|
||||
}
|
||||
|
||||
return params.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public static void adsParams(HashSet<String> hashSet) {
|
||||
if (ads() || adsslider()) {
|
||||
hashSet.add("ads_disabled");
|
||||
if (milkshake()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
hashSet.add("ads_app");
|
||||
hashSet.add("ads_site");
|
||||
hashSet.add("ads_post");
|
||||
hashSet.add("ads_app_slider");
|
||||
hashSet.add("ads_site_slider");
|
||||
hashSet.add("ads_app_video");
|
||||
hashSet.add("ads_post_pretty_cards");
|
||||
hashSet.add("ads_post_snippet_video");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,34 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static ru.vtosters.lite.hooks.JsonInjectors.setOnlineInfo;
|
||||
import static ru.vtosters.lite.hooks.JsonInjectors.setOnlineInfoUsers;
|
||||
import static ru.vtosters.lite.net.Request.makeRequest;
|
||||
import static ru.vtosters.lite.utils.Globals.getString;
|
||||
import static ru.vtosters.lite.utils.Globals.getUserToken;
|
||||
import static ru.vtosters.lite.utils.Globals.sendToast;
|
||||
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||
import static ru.vtosters.lite.utils.Preferences.dev;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.getPrefsFromFile;
|
||||
import static ru.vtosters.lite.utils.Proxy.getApi;
|
||||
import static ru.vtosters.lite.proxy.ProxyUtils.getApi;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class OnlineFormatterHook{
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class OnlineFormatterHook {
|
||||
private static String AppName;
|
||||
|
||||
public static String getAppName(int appid){ // thanks to egormetlitsky (vk mp3 mod) for helping with online ids
|
||||
public static String getAppName(int appid) { // thanks to egormetlitsky (vk mp3 mod) for helping with online ids
|
||||
if (appid <= 3 || !getBoolValue("onlineformatter", true)) return null;
|
||||
|
||||
switch(appid) {
|
||||
switch (appid) {
|
||||
case 2274003:
|
||||
return "Android";
|
||||
case 6328039:
|
||||
@@ -54,37 +64,37 @@ public class OnlineFormatterHook{
|
||||
case 5027722:
|
||||
return "VK Messenger (Desktop)";
|
||||
case 6146827:
|
||||
return "VK Мессенджер (Android)";
|
||||
return AndroidUtils.getString("vk_messenger") + " (Android)"; // VK Мессенджер (Android)
|
||||
case 6482950:
|
||||
return "VK Мессенджер (iPhone)";
|
||||
return AndroidUtils.getString("vk_messenger") + " (iPhone)"; // VK Мессенджер (iPhone)
|
||||
case 6481715:
|
||||
return "VK Мессенджер Dev (iPhone)";
|
||||
return AndroidUtils.getString("vk_messenger") + " Dev (iPhone)"; // VK Мессенджер Dev (iPhone)
|
||||
case 7799655:
|
||||
return "VK Почта";
|
||||
return AndroidUtils.getString("vk_mail_online"); // VK Почта
|
||||
case 7598572:
|
||||
return "Сферум (Android)";
|
||||
return AndroidUtils.getString("sferum_online") + " (Android)"; // Сферум (Android)
|
||||
case 7571751:
|
||||
return "Сферум (iPhone)";
|
||||
return AndroidUtils.getString("sferum_online") + " (iPhone)"; // Сферум (iPhone)
|
||||
case 7556576:
|
||||
return "Сферум";
|
||||
return AndroidUtils.getString("sferum_online"); // Сферум
|
||||
case 7497650:
|
||||
return "VK ID";
|
||||
case 8094476:
|
||||
return "VK Звонки (Android)";
|
||||
return AndroidUtils.getString("vk_calls_online") + " (Android)"; // VK Звонки (Android)
|
||||
case 8093730:
|
||||
return "VK Звонки (iPhone)";
|
||||
return AndroidUtils.getString("vk_calls_online") + " (iPhone)"; // VK Звонки (iPhone)
|
||||
case 7793118:
|
||||
return "VK Звонки (Desktop)";
|
||||
return AndroidUtils.getString("vk_calls_online") + " (Desktop)"; // VK Звонки (Desktop)
|
||||
case 6767438:
|
||||
return "VK Музыка (Android)";
|
||||
return AndroidUtils.getString("vk_music_online") + " (Android)"; // VK Музыка (Android)
|
||||
case 8113297:
|
||||
return "VK Клипы (Android)";
|
||||
return AndroidUtils.getString("vk_clips_online") + " (Android)"; // VK Клипы (Android)
|
||||
case 8106428:
|
||||
return "VK Клипы (iPhone)";
|
||||
return AndroidUtils.getString("vk_clips_online") + " (iPhone)"; // VK Клипы (iPhone)
|
||||
case 5044491:
|
||||
return "Candy";
|
||||
case 8114066:
|
||||
return "VK Видео";
|
||||
return AndroidUtils.getString("vk_video_online"); // VK Видео
|
||||
case 4894723:
|
||||
return "Phoenix Lite";
|
||||
case 4994316:
|
||||
@@ -126,7 +136,7 @@ public class OnlineFormatterHook{
|
||||
|
||||
}
|
||||
|
||||
public static String getAppNameFromOnline(int appid){
|
||||
public static String getAppNameFromOnline(int appid) {
|
||||
var prefs = getPrefsFromFile("onlines");
|
||||
var appname = prefs.getString(String.valueOf(appid), null);
|
||||
|
||||
@@ -152,12 +162,75 @@ public class OnlineFormatterHook{
|
||||
return AppName;
|
||||
}
|
||||
|
||||
public static String getOnline(int appid){
|
||||
public static String getOnline(int appid) {
|
||||
var appname = getAppName(appid);
|
||||
|
||||
if (appname == null) return null;
|
||||
|
||||
return getString("custom_online") + " " + appname;
|
||||
}
|
||||
|
||||
public static JSONObject onlineHook(JSONObject json) throws ParseException, IOException, JSONException {
|
||||
if (getBoolValue("onlinefix", false)) setOnlineInfo(json);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public static JSONArray onlineHookList(JSONArray jsonArr) throws ParseException, IOException, JSONException {
|
||||
if (!getBoolValue("onlinefix", false)) return jsonArr;
|
||||
|
||||
try {
|
||||
setOnlineInfoUsers(jsonArr);
|
||||
} catch (Exception e) {
|
||||
Log.e("onlineHookProfiles", e.getMessage());
|
||||
}
|
||||
|
||||
return jsonArr;
|
||||
}
|
||||
|
||||
public static JSONObject onlineHookProfiles(JSONObject json) throws ParseException, IOException, JSONException {
|
||||
if (!getBoolValue("onlinefix", false)) return json;
|
||||
|
||||
try {
|
||||
setOnlineInfoUsers(json.optJSONArray("profiles"));
|
||||
} catch (Exception e) {
|
||||
Log.e("onlineHookProfiles", e.getMessage());
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
public static JSONObject onlineHookItems(JSONObject json) throws ParseException, IOException, JSONException {
|
||||
if (!getBoolValue("onlinefix", false)) return json;
|
||||
|
||||
try {
|
||||
setOnlineInfoUsers(json.optJSONArray("items"));
|
||||
} catch (Exception e) {
|
||||
Log.e("onlineHookItems", e.getMessage());
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
public static JSONObject onlineHookRequestsAndRecommendations(JSONObject json) throws ParseException, IOException, JSONException {
|
||||
if (!getBoolValue("onlinefix", false)) return json;
|
||||
|
||||
try {
|
||||
setOnlineInfoUsers(json.optJSONObject("read_requests").optJSONArray("items"));
|
||||
} catch (Exception e) {
|
||||
Log.e("onlineHookItems", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
setOnlineInfoUsers(json.optJSONObject("recommendations").optJSONArray("items"));
|
||||
} catch (Exception e) {
|
||||
Log.e("onlineHookItems", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
setOnlineInfoUsers(json.optJSONArray("profiles"));
|
||||
} catch (Exception e) {
|
||||
Log.e("onlineHookItems", e.getMessage());
|
||||
}
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static ru.vtosters.lite.utils.Globals.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.Globals.getPreferences;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
@@ -14,10 +16,15 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.vk.core.dialogs.actionspopup.ActionsPopup;
|
||||
import com.vk.core.drawable.RecoloredDrawable;
|
||||
import com.vk.core.util.ToastUtils;
|
||||
import com.vk.dto.common.AttachmentWithMedia;
|
||||
import com.vk.dto.common.ImageSize;
|
||||
import com.vtosters.lite.R;
|
||||
import com.vtosters.lite.attachments.DocumentAttachment;
|
||||
import com.vtosters.lite.attachments.PhotoAttachment;
|
||||
|
||||
import org.json.JSONException;
|
||||
@@ -25,69 +32,88 @@ import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import ru.vtosters.lite.utils.Globals;
|
||||
import ru.vtosters.lite.utils.Themes;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
|
||||
public class PhotoViewer {
|
||||
|
||||
static OkHttpClient client = new OkHttpClient();
|
||||
|
||||
public static boolean interceptClick(AttachmentWithMedia attachment, MenuItem item, View view) {
|
||||
if (item.getItemId() == Globals.getIdentifier("search_photo", "id")) {
|
||||
searchPhoto(getUrlFromAttachment((PhotoAttachment) attachment));
|
||||
if (item.getItemId() == AndroidUtils.getIdentifier("search_photo", "id")) {
|
||||
searchPhoto(getUrlFromPhotoAttachment((PhotoAttachment) attachment));
|
||||
return true;
|
||||
} else if (item.getItemId() == Globals.getIdentifier("copy_photo_url", "id")) {
|
||||
copyPhotoUrl(getUrlFromAttachment((PhotoAttachment) attachment));
|
||||
} else if (item.getItemId() == AndroidUtils.getIdentifier("copy_photo_url", "id")) {
|
||||
copyPhotoUrl(getUrlFromPhotoAttachment((PhotoAttachment) attachment));
|
||||
return true;
|
||||
} else if (item.getItemId() == Globals.getIdentifier("open_original_photo", "id")) {
|
||||
openUrl(getUrlFromAttachment((PhotoAttachment) attachment));
|
||||
} else if (item.getItemId() == AndroidUtils.getIdentifier("open_original_photo", "id")) {
|
||||
openUrl(getUrlFromPhotoAttachment((PhotoAttachment) attachment));
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
public static void addMenuItems(AttachmentWithMedia attachment, ActionsPopup.b actionPopup, int i, boolean z) {
|
||||
actionPopup.a(getIdentifier("search_photo_content", "string"),
|
||||
Themes.isDarkTheme()
|
||||
? Globals.getContext().getDrawable(R.drawable.ic_menu_search_outline_28)
|
||||
: new RecoloredDrawable(Globals.getContext().getDrawable(R.drawable.ic_menu_search_outline_28), Themes.getAccentColor()),
|
||||
false,
|
||||
() -> {
|
||||
searchPhoto(getUrlFromAttachment((PhotoAttachment) attachment));
|
||||
return null;
|
||||
}
|
||||
);
|
||||
actionPopup.a(getIdentifier("copy_photo_url_content", "string"),
|
||||
!Themes.isDarkTheme()
|
||||
? new RecoloredDrawable(Globals.getContext().getDrawable(R.drawable.ic_copy_outline_28), Themes.getAccentColor())
|
||||
: new RecoloredDrawable(Globals.getContext().getDrawable(R.drawable.ic_copy_outline_28), Color.WHITE),
|
||||
ThemesUtils.isDarkTheme()
|
||||
? AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_menu_search_outline_28)
|
||||
: new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_menu_search_outline_28), ThemesUtils.getAccentColor()),
|
||||
false,
|
||||
() -> {
|
||||
copyPhotoUrl(getUrlFromAttachment((PhotoAttachment) attachment));
|
||||
searchPhoto(getUrlFromPhotoAttachment((PhotoAttachment) attachment));
|
||||
return null;
|
||||
}
|
||||
);
|
||||
actionPopup.a(getIdentifier("copy_photo_url_content", "string"),
|
||||
!ThemesUtils.isDarkTheme()
|
||||
? new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_copy_outline_28), ThemesUtils.getAccentColor())
|
||||
: new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_copy_outline_28), Color.WHITE),
|
||||
false,
|
||||
() -> {
|
||||
copyPhotoUrl(getUrlFromPhotoAttachment((PhotoAttachment) attachment));
|
||||
return null;
|
||||
}
|
||||
);
|
||||
actionPopup.a(getIdentifier("open_original_photo_content", "string"),
|
||||
Themes.isDarkTheme()
|
||||
? Globals.getContext().getDrawable(R.drawable.ic_link_outline_28)
|
||||
: new RecoloredDrawable(Globals.getContext().getDrawable(R.drawable.ic_link_outline_28),
|
||||
Themes.getAccentColor()),
|
||||
ThemesUtils.isDarkTheme()
|
||||
? AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_link_outline_28)
|
||||
: new RecoloredDrawable(AndroidUtils.getGlobalContext().getDrawable(R.drawable.ic_link_outline_28),
|
||||
ThemesUtils.getAccentColor()),
|
||||
false,
|
||||
() -> {
|
||||
openUrl(getUrlFromAttachment((PhotoAttachment) attachment));
|
||||
if (attachment instanceof PhotoAttachment) {
|
||||
openUrl(getUrlFromPhotoAttachment((PhotoAttachment) attachment));
|
||||
} else if (attachment instanceof DocumentAttachment) {
|
||||
var documentAttachment = (DocumentAttachment) attachment;
|
||||
if (documentAttachment.J != null)
|
||||
openUrl(getUrlFromDocumentAttachment(documentAttachment));
|
||||
else
|
||||
ToastUtils.a(getString("photo_get_error"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static String getUrlFromAttachment(PhotoAttachment attachment) {
|
||||
private static String getUrlFromDocumentAttachment(DocumentAttachment attachment) {
|
||||
var imageSizes = attachment.J.t1();
|
||||
return getUrlFromImageSizeList(imageSizes);
|
||||
}
|
||||
|
||||
private static String getUrlFromPhotoAttachment(PhotoAttachment attachment) {
|
||||
var imageSizes = attachment.D.Q.t1();
|
||||
return getUrlFromImageSizeList(imageSizes);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getUrlFromImageSizeList(List<ImageSize> imageSizes) {
|
||||
if (imageSizes.isEmpty())
|
||||
return null;
|
||||
var max = imageSizes.get(0);
|
||||
@@ -99,7 +125,7 @@ public class PhotoViewer {
|
||||
}
|
||||
return max.url;
|
||||
}
|
||||
|
||||
|
||||
private static void searchPhoto(String url) {
|
||||
if (url == null || url.isEmpty()) return;
|
||||
switch (getPreferences().getInt("search_engine", 0)) {
|
||||
@@ -123,7 +149,7 @@ public class PhotoViewer {
|
||||
client.a(request).a(new Callback() {
|
||||
@Override
|
||||
public void a(Call call, IOException e) {
|
||||
Log.d("PhotoViewer", e+"");
|
||||
Log.d("PhotoViewer", e + "");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,15 +179,15 @@ public class PhotoViewer {
|
||||
|
||||
private static void copyPhotoUrl(String url) {
|
||||
if (url == null || url.isEmpty()) return;
|
||||
ClipboardManager manager = (ClipboardManager) Globals.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipboardManager manager = (ClipboardManager) AndroidUtils.getGlobalContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
manager.setPrimaryClip(ClipData.newPlainText("vk_photo_url", url));
|
||||
Toast.makeText(Globals.getContext(), Globals.getIdentifier("copied_to_clipboard", "string"), Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(AndroidUtils.getGlobalContext(), AndroidUtils.getIdentifier("copied_to_clipboard", "string"), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private static void openUrl(String url) {
|
||||
var uri = Uri.parse(url);
|
||||
var intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
Globals.getContext().startActivity(intent);
|
||||
AndroidUtils.getGlobalContext().startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
import static ru.vtosters.lite.utils.Preferences.preferences;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
|
||||
import com.facebook.drawee.generic.RoundingParams;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class PicRoundingHook{
|
||||
private static final int pref = preferences.getInt("pic_rounding", 0);
|
||||
|
||||
public static RoundingParams inject() {
|
||||
if (pref > 0) {
|
||||
return customParams();
|
||||
} else {
|
||||
return new RoundingParams().a(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static RoundingParams inject(float orig) {
|
||||
if (pref > 0) {
|
||||
return customParams();
|
||||
} else {
|
||||
return new RoundingParams().b(orig);
|
||||
}
|
||||
}
|
||||
|
||||
public static RoundingParams inject(float orig, float orig2, float orig3, float orig4) {
|
||||
if (pref > 0) {
|
||||
return new RoundingParams().a(AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref));
|
||||
} else {
|
||||
return new RoundingParams().a(orig, orig2, orig3, orig4);
|
||||
}
|
||||
}
|
||||
|
||||
public static void inject(float orig, Canvas canvas, Paint paint){
|
||||
if (pref > 0) {
|
||||
canvas.drawRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), paint);
|
||||
} else {
|
||||
canvas.drawCircle(orig, orig, orig, paint);
|
||||
}
|
||||
}
|
||||
|
||||
public static void inject(Canvas canvas, Paint paint, float orig){
|
||||
if (pref > 0) {
|
||||
canvas.drawRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), paint);
|
||||
} else {
|
||||
canvas.drawCircle(canvas.getClipBounds().exactCenterX(), canvas.getClipBounds().exactCenterY(), orig, paint);
|
||||
}
|
||||
}
|
||||
|
||||
public static void inject(Canvas canvas, float orig, float orig2, float orig3, Paint paint){
|
||||
if (pref > 0) {
|
||||
canvas.drawRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), paint);
|
||||
} else {
|
||||
canvas.drawCircle(orig, orig2, orig3, paint);
|
||||
}
|
||||
}
|
||||
|
||||
public static void inject(Bitmap bitmap, Bitmap bitmap2, Paint b2) {
|
||||
Shader.TileMode tileMode = Shader.TileMode.CLAMP;
|
||||
b2.setShader(new BitmapShader(bitmap2, tileMode, tileMode));
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
float width = bitmap2.getWidth() / 2;
|
||||
|
||||
if (pref > 0) {
|
||||
canvas.drawRoundRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), b2);
|
||||
} else {
|
||||
canvas.drawCircle(width, width, width, b2);
|
||||
}
|
||||
}
|
||||
|
||||
private static RoundingParams customParams(){
|
||||
return RoundingParams.b(AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref), AndroidUtils.dp2px(pref));
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@ import android.widget.TextView;
|
||||
import com.vk.dto.polls.PollOption;
|
||||
import com.vk.polls.ui.views.PollOptionView;
|
||||
|
||||
public class PollHook{
|
||||
public static void show(PollOptionView view){
|
||||
public class PollHook {
|
||||
public static void show(PollOptionView view) {
|
||||
if (!getBoolValue("pollresults", false)) return;
|
||||
|
||||
TextView resultsView = view.c;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.vk.newsfeed.holders.BaseFooterHolder;
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import ru.vtosters.lite.utils.Preferences;
|
||||
|
||||
public class PostViewHook {
|
||||
|
||||
/**
|
||||
* For displaying child elements with custom direction in rtl container we should remove their, set layout direction and add again */
|
||||
private static void saveChildDirectionForRlt(ViewGroup container) {
|
||||
var children = new View[container.getChildCount()];
|
||||
for (int i = 0; i < container.getChildCount(); i++) {
|
||||
var child = container.getChildAt(i);
|
||||
child.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
|
||||
children[i] = child;
|
||||
}
|
||||
container.removeAllViews();
|
||||
for (View child : children) {
|
||||
container.addView(child);
|
||||
}
|
||||
container.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
|
||||
}
|
||||
|
||||
// res/layout/likes_panel.xml
|
||||
public static void injectBaseFooterHolder(BaseFooterHolder baseFooterHolder) {
|
||||
if (!Preferences.isLikesOnRightEnabled())
|
||||
return;
|
||||
try {
|
||||
var container = (ViewGroup) ((RecyclerView.ViewHolder) baseFooterHolder).itemView;
|
||||
saveChildDirectionForRlt((ViewGroup) container.getChildAt(1));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// res/layout/photo_viewer_bottom.xml
|
||||
public static void injectPhotoViewer(View container) {
|
||||
if (!Preferences.isLikesOnRightEnabled())
|
||||
return;
|
||||
try {
|
||||
var bottomPanel = (ViewGroup) container.findViewById(R.id.photo_viewer_bottom_panel);
|
||||
saveChildDirectionForRlt(bottomPanel);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// res/layout/video_bottom_view.xml
|
||||
public static void injectVideoView(RelativeLayout container) {
|
||||
if (!Preferences.isLikesOnRightEnabled())
|
||||
return;
|
||||
try {
|
||||
var bottomBar = (ViewGroup) container.findViewById(R.id.bottom_bar);
|
||||
saveChildDirectionForRlt(bottomBar);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
import static ru.vtosters.lite.utils.Globals.convertDpToPixel;
|
||||
import static ru.vtosters.lite.utils.Globals.edit;
|
||||
import static ru.vtosters.lite.utils.Globals.getPrefsValue;
|
||||
import static ru.vtosters.lite.utils.Globals.restartApplication;
|
||||
import static ru.vtosters.lite.utils.Proxy.apiproxy;
|
||||
import static ru.vtosters.lite.utils.Proxy.isZaboronaEnabled;
|
||||
import static ru.vtosters.lite.utils.Themes.getAccentColor;
|
||||
import static ru.vtosters.lite.utils.Themes.getAlertStyle;
|
||||
import static ru.vtosters.lite.utils.Themes.getTextAttr;
|
||||
|
||||
import static ru.vtosters.lite.proxy.ProxyUtils.isVikaProxyEnabled;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplication;
|
||||
import static ru.vtosters.lite.proxy.ProxyUtils.isRandomProxyEnabled;
|
||||
import static ru.vtosters.lite.proxy.ProxyUtils.isZaboronaEnabled;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getAlertStyle;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.RadioButton;
|
||||
@@ -26,57 +26,74 @@ import com.vk.auth.ui.VkAuthTextView;
|
||||
import com.vk.navigation.Navigator;
|
||||
|
||||
import ru.vtosters.lite.ui.fragments.ProxySettingsFragment;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class ProxyHook{
|
||||
public static void hookAuth(View v){
|
||||
public class ProxyHook {
|
||||
public static void hookAuth(View v) {
|
||||
VkAuthTextView button = (VkAuthTextView) v;
|
||||
button.setText("Настроить прокси");
|
||||
button.setText(AndroidUtils.getString("proxy_setup"));
|
||||
button.setOnClickListener(v1 -> callProxyDialog(v1.getContext()));
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
public static void callProxyDialog(Context ctx){
|
||||
public static void callProxyDialog(Context ctx) {
|
||||
RadioGroup rg = new RadioGroup(ctx);
|
||||
|
||||
RadioButton rgDefault = new RadioButton(new ContextThemeWrapper(ctx, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||
RadioButton rgProxy = new RadioButton(new ContextThemeWrapper(ctx, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||
RadioButton rgZaborona = new RadioButton(new ContextThemeWrapper(ctx, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||
RadioButton rgRandomProxy = new RadioButton(new ContextThemeWrapper(ctx, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||
RadioButton rgVika = new RadioButton(new ContextThemeWrapper(ctx, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_RadioButton));
|
||||
|
||||
rg.addView(rgDefault);
|
||||
rg.addView(rgProxy);
|
||||
rg.addView(rgZaborona);
|
||||
rg.addView(rgVika);
|
||||
rg.addView(rgRandomProxy);
|
||||
|
||||
rgDefault.setTextSize(TypedValue.COMPLEX_UNIT_PX, convertDpToPixel(14f));
|
||||
rgProxy.setTextSize(TypedValue.COMPLEX_UNIT_PX, convertDpToPixel(14f));
|
||||
rgDefault.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(14f));
|
||||
rgZaborona.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(14f));
|
||||
rgRandomProxy.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(14f));
|
||||
rgVika.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(14f));
|
||||
|
||||
rg.setPadding(convertDpToPixel(18f), convertDpToPixel(12f), convertDpToPixel(18f), 0);
|
||||
rg.setPadding(dp2px(18f), dp2px(12f), dp2px(18f), 0);
|
||||
|
||||
rgDefault.setText("Отключить");
|
||||
rgDefault.setText(AndroidUtils.getString("proxy_disable"));
|
||||
rgDefault.setTextColor(getTextAttr());
|
||||
|
||||
rgProxy.setText("Включить (Zaborona)");
|
||||
rgProxy.setTextColor(getTextAttr());
|
||||
rgZaborona.setText(AndroidUtils.getString("proxy_enable") + " (Zaborona)");
|
||||
rgZaborona.setTextColor(getTextAttr());
|
||||
|
||||
rgProxy.setChecked(isZaboronaEnabled());
|
||||
rgDefault.setChecked(!isZaboronaEnabled());
|
||||
rgRandomProxy.setText(AndroidUtils.getString("proxy_enable") + " (Random Proxy)");
|
||||
rgRandomProxy.setTextColor(getTextAttr());
|
||||
|
||||
rgVika.setText(AndroidUtils.getString("proxy_enable") + " (Vika)");
|
||||
rgVika.setTextColor(getTextAttr());
|
||||
|
||||
rgZaborona.setChecked(isZaboronaEnabled());
|
||||
rgDefault.setChecked(!isZaboronaEnabled() && !isRandomProxyEnabled() && !isVikaProxyEnabled());
|
||||
rgRandomProxy.setChecked(isRandomProxyEnabled());
|
||||
rgVika.setChecked(isVikaProxyEnabled());
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ctx, getAlertStyle());
|
||||
builder.setTitle("Прокси");
|
||||
builder.setMessage("Zaborona никак не связана с ВТостерс и мы не можем гарантировать её работу и безопасность");
|
||||
builder.setTitle(AndroidUtils.getString("vtlproxy"));
|
||||
builder.setMessage(AndroidUtils.getString("proxy_warning"));
|
||||
builder.setView(rg);
|
||||
builder.setPositiveButton("Применить", ((dialog, which) -> {
|
||||
if (rgProxy.isChecked()) {
|
||||
builder.setPositiveButton(AndroidUtils.getString("vtl_confirm"), ((dialog, which) -> { // Применить
|
||||
if (rgZaborona.isChecked()) {
|
||||
edit().putString("proxy", "zaborona").commit();
|
||||
restartApplication();
|
||||
} else if (rgRandomProxy.isChecked()) {
|
||||
edit().putString("proxy", "randomproxy").commit();
|
||||
restartApplication();
|
||||
} else if (rgVika.isChecked()) {
|
||||
edit().putString("proxy", "vika").commit();
|
||||
restartApplication();
|
||||
} else {
|
||||
if (isZaboronaEnabled()) {
|
||||
edit().putString("proxy", "noproxy").commit();
|
||||
restartApplication();
|
||||
}
|
||||
|
||||
edit().putString("proxy", "noproxy").commit();
|
||||
restartApplication();
|
||||
}
|
||||
}));
|
||||
|
||||
builder.setNeutralButton("Настройки прокси", ((dialog, which) -> {
|
||||
builder.setNeutralButton(AndroidUtils.getString("proxy_settings"), ((dialog, which) -> {
|
||||
Intent a2 = new Navigator(ProxySettingsFragment.class).b(ctx);
|
||||
a2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
ctx.startActivity(a2);
|
||||
@@ -89,47 +106,4 @@ public class ProxyHook{
|
||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
||||
alert.getButton(DialogInterface.BUTTON_NEUTRAL).setTextColor(getAccentColor());
|
||||
}
|
||||
|
||||
public static String linkReplacer(String link){
|
||||
var vkapi = "api.vk.com";
|
||||
var oauth = "oauth.vk.com";
|
||||
var vkstatic = "static.vk.com";
|
||||
|
||||
var proxyapi = getPrefsValue("proxyapi");
|
||||
var proxyoauth = getPrefsValue("proxyoauth");
|
||||
var proxystatic = getPrefsValue("proxystatic");
|
||||
|
||||
if (!apiproxy() || link.isEmpty()) {
|
||||
return link;
|
||||
}
|
||||
|
||||
if (proxyapi.isEmpty() || proxyoauth.isEmpty() || proxystatic.isEmpty()) {
|
||||
Log.d("VTLite", "Proxy is not set" + " " + proxyapi + " " + proxyoauth + " " + proxystatic);
|
||||
return link;
|
||||
}
|
||||
|
||||
if (link.contains(vkapi)) {
|
||||
return link.replace(proxyapi, vkapi);
|
||||
}
|
||||
|
||||
if (link.contains(oauth)) {
|
||||
return link.replace(proxyoauth, oauth);
|
||||
}
|
||||
|
||||
if (link.contains(vkstatic)) {
|
||||
return link.replace(proxystatic, vkstatic);
|
||||
}
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
public static String getAwayPhpCom(){
|
||||
var proxyapi = getPrefsValue("proxyapi");
|
||||
|
||||
if (apiproxy() & !proxyapi.isEmpty()) {
|
||||
return proxyapi;
|
||||
}
|
||||
|
||||
return "m.vk.com";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static ru.vtosters.lite.encryption.EncryptProvider.decryptMessage;
|
||||
|
||||
import com.vk.im.engine.models.ProfilesSimpleInfo;
|
||||
import com.vk.im.engine.models.messages.MsgFromUser;
|
||||
import com.vk.im.engine.models.messages.NestedMsg;
|
||||
import com.vk.im.engine.models.messages.WithUserContent;
|
||||
import com.vk.im.ui.views.ReplyView;
|
||||
|
||||
public class ReplyMsgHook {
|
||||
public static void injectWithDecrypt(ReplyView replyView, MsgFromUser msgFromUser, ProfilesSimpleInfo profilesSimpleInfo, boolean someBool) {
|
||||
msgFromUser.d(decryptMessage(msgFromUser)); // set new value of text in MsgFromUser class
|
||||
replyView.a((WithUserContent) msgFromUser, profilesSimpleInfo, someBool);
|
||||
}
|
||||
|
||||
public static void injectWithDecrypt(ReplyView replyView, NestedMsg nestedMsg, ProfilesSimpleInfo profilesSimpleInfo, boolean someBool) {
|
||||
nestedMsg.d(decryptMessage(nestedMsg.f(), nestedMsg.t1())); // set new value of text in NestedMsg class
|
||||
replyView.a((WithUserContent) nestedMsg, profilesSimpleInfo, someBool);
|
||||
}
|
||||
|
||||
public static void injectWithDecrypt(ReplyView replyView, NestedMsg nestedMsg, ProfilesSimpleInfo profilesSimpleInfo, boolean someBool, int i) {
|
||||
if ((i & 4) != 0) someBool = false;
|
||||
injectWithDecrypt(replyView, nestedMsg, profilesSimpleInfo, someBool);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
import static ru.vtosters.lite.utils.Preferences.dev;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.vk.api.internal.MethodCall;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class RequestDumper{
|
||||
public static void addParams(MethodCall.a paramslist, String method, LinkedHashMap params, String apiver) {
|
||||
if (method.contains("execute.getGiftByStickerId") ) {
|
||||
apiver = "5.187";
|
||||
}
|
||||
|
||||
if (dev()) {
|
||||
Log.d("RequestDumper", "Method: " + method);
|
||||
Log.d("RequestDumper", "API version: " + apiver);
|
||||
Log.d("RequestDumper", "Params: " + params);
|
||||
}
|
||||
|
||||
paramslist.a(method);
|
||||
paramslist.a(params);
|
||||
paramslist.b(apiver);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
import static ru.vtosters.lite.ui.fragments.dockbar.DockBarManager.getInstance;
|
||||
import static ru.vtosters.lite.utils.Globals.getPrefsValue;
|
||||
|
||||
import static ru.vtosters.lite.ui.components.DockBarEditorManager.getInstance;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
||||
import static ru.vtosters.lite.utils.Preferences.superapp;
|
||||
import static ru.vtosters.lite.utils.Preferences.useNewSettings;
|
||||
import static ru.vtosters.lite.utils.Preferences.videonewcatalog;
|
||||
import static ru.vtosters.lite.utils.Preferences.vkme;
|
||||
|
||||
import com.vk.apps.AppsFragment;
|
||||
@@ -27,16 +29,17 @@ import com.vtosters.lite.fragments.money.MoneyTransfersFragment;
|
||||
import com.vtosters.lite.fragments.p2.DocumentsViewFragment;
|
||||
import com.vtosters.lite.fragments.s2.GroupsFragment1;
|
||||
import com.vtosters.lite.fragments.t2.c.DialogsFragment;
|
||||
import com.vtosters.lite.fragments.y2.VideoCatalogFragment;
|
||||
import com.vtosters.lite.fragments.y2.VideosFragment;
|
||||
import com.vtosters.lite.general.fragments.GamesFragment;
|
||||
import com.vtosters.lite.general.fragments.PhotosFragment;
|
||||
|
||||
public class StartFragmentHook{
|
||||
public static Class getStartFragment(){
|
||||
public class StartFragmentHook {
|
||||
public static Class getStartFragment() {
|
||||
if (vkme()) {
|
||||
return DialogsFragment.class;
|
||||
}
|
||||
switch(getPrefsValue("start_values")) {
|
||||
switch (getPrefsValue("start_values")) {
|
||||
case "newsfeed":
|
||||
return milkshake() ? HomeFragment.class : NewsfeedFragment.class;
|
||||
case "messenger":
|
||||
@@ -50,7 +53,7 @@ public class StartFragmentHook{
|
||||
case "photos":
|
||||
return PhotosFragment.class;
|
||||
case "videos":
|
||||
return VideosFragment.class;
|
||||
return videonewcatalog() ? VideoCatalogFragment.class : VideosFragment.class;
|
||||
case "settings":
|
||||
return useNewSettings();
|
||||
case "apps":
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static ru.vtosters.lite.utils.Preferences.adsstories;
|
||||
import static ru.vtosters.lite.utils.Preferences.stories;
|
||||
|
||||
public class StoriesHook{
|
||||
public static String ads(){
|
||||
public class StoriesHook {
|
||||
public static String ads() {
|
||||
return adsstories() ? "null" : "ads";
|
||||
}
|
||||
|
||||
public static boolean showstories(){
|
||||
public static boolean showstories() {
|
||||
return stories();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static ru.vtosters.lite.utils.Preferences.feedcache;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
||||
import static ru.vtosters.lite.utils.Preferences.miniapps;
|
||||
import static ru.vtosters.lite.utils.Preferences.musicnewcatalog;
|
||||
import static ru.vtosters.lite.utils.Preferences.postsredesign;
|
||||
import static ru.vtosters.lite.utils.Preferences.superapp;
|
||||
@@ -9,9 +11,9 @@ import static ru.vtosters.lite.utils.Preferences.superapp;
|
||||
import com.vk.toggle.FeatureManager;
|
||||
import com.vk.toggle.Features;
|
||||
|
||||
public class TogglesHook{
|
||||
public static boolean shouldPatch(Features.Type feature){
|
||||
switch(feature) {
|
||||
public class TogglesHook {
|
||||
public static boolean shouldPatch(Features.Type feature) {
|
||||
switch (feature) {
|
||||
case AB_IM_LONGPOLL_MSG_BATCHING:
|
||||
case AB_IM_VIEW_POOL:
|
||||
case AB_MULTI_GIFTS:
|
||||
@@ -41,11 +43,8 @@ public class TogglesHook{
|
||||
case FEATURE_ML_FEATURES:
|
||||
case FEATURE_ML_MODELS_LOADING:
|
||||
case FEATURE_MONEY_TRANSFERS_VKPAY:
|
||||
case FEATURE_MOZJPEG:
|
||||
case FEATURE_MUSIC_ARTIST_CATALOG:
|
||||
case FEATURE_MUSIC_NEW_CATALOG:
|
||||
case FEATURE_MUSIC_STOP_PLAYER_ON_TASK_REMOVAL:
|
||||
case FEATURE_MUS_PUSH_RES_COUNT:
|
||||
case FEATURE_NARRATIVE_SNIPPET_TYPE:
|
||||
case FEATURE_NEWS_GAMES_IN_DISCOVER:
|
||||
case FEATURE_NEWS_HEADER_SCROLL:
|
||||
@@ -123,8 +122,8 @@ public class TogglesHook{
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean redirect(Features.Type feature){
|
||||
switch(feature) {
|
||||
public static boolean redirect(Features.Type feature) {
|
||||
switch (feature) {
|
||||
case EXPERIMENT_NEWS_DISABLE_CACHE:
|
||||
return !feedcache();
|
||||
case FEATURE_SUPERAPP_MENU:
|
||||
@@ -142,14 +141,14 @@ public class TogglesHook{
|
||||
return postsredesign();
|
||||
case FEATURE_IMAGE_QUALITY_UPGRADE:
|
||||
return !getBoolValue("compressPhotos", true);
|
||||
case FEATURE_MUSIC_STOP_PLAYER_ON_TASK_REMOVAL:
|
||||
return getBoolValue("musictask", false);
|
||||
case FEATURE_MENU_GAMES_CAROUSEL:
|
||||
return miniapps();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static FeatureManager.b redirectStrings(Features.Type feature){
|
||||
public static FeatureManager.b redirectStrings(Features.Type feature) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import static android.util.Base64.encodeToString;
|
||||
import static ru.vtosters.lite.utils.Globals.getContext;
|
||||
import static ru.vtosters.lite.utils.Globals.getPrefsValue;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
import static ru.vtosters.lite.utils.Themes.getAccentColor;
|
||||
import static ru.vtosters.lite.utils.Themes.getBackgroundContent;
|
||||
import static ru.vtosters.lite.utils.Themes.getBackgroundPage;
|
||||
import static ru.vtosters.lite.utils.Themes.getHeaderBackground;
|
||||
import static ru.vtosters.lite.utils.Themes.getHeaderText;
|
||||
import static ru.vtosters.lite.utils.Themes.getTextAttr;
|
||||
import static ru.vtosters.lite.utils.Themes.hex;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getAttrId;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getBackgroundContent;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getBackgroundPage;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getColorFromAttr;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getHeaderBackground;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getHeaderText;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.hex;
|
||||
|
||||
import android.webkit.WebView;
|
||||
|
||||
@@ -22,19 +25,19 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class VKUIHook{
|
||||
public class VKUIHook {
|
||||
public static boolean isLoaded = false;
|
||||
private static String loadedCSS = "";
|
||||
private static String loadedCSSAmoled = "";
|
||||
|
||||
private static String load(String str){
|
||||
private static String load(String str) {
|
||||
try {
|
||||
InputStream open = getContext().getAssets().open(str);
|
||||
InputStream open = getGlobalContext().getAssets().open(str);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(open, StandardCharsets.UTF_8));
|
||||
|
||||
while(true) {
|
||||
while (true) {
|
||||
String readLine = bufferedReader.readLine();
|
||||
if (readLine != null) {
|
||||
sb.append(readLine);
|
||||
@@ -51,24 +54,29 @@ public class VKUIHook{
|
||||
}
|
||||
}
|
||||
|
||||
public static void load(){
|
||||
public static void load() {
|
||||
loadedCSS = load("vt_ui_accent.css")
|
||||
.replace("%header_background%", hex(getHeaderBackground()))
|
||||
.replace("%background_content%", hex(getBackgroundContent()))
|
||||
.replace("%header_text%", hex(getHeaderText()))
|
||||
.replace("%accent%", hex(getAccentColor()))
|
||||
.replace("%background_page%", hex(getBackgroundPage()))
|
||||
.replace("%content_tint_background%", hex(getColorFromAttr(getAttrId("content_tint_background"))))
|
||||
.replace("%button_primary_background%", hex(getColorFromAttr(getAttrId("button_primary_background"))))
|
||||
.replace("%button_outline_foreground%", hex(getColorFromAttr(getAttrId("button_outline_foreground"))))
|
||||
.replace("%button_outline_border%", hex(getColorFromAttr(getAttrId("button_outline_border"))))
|
||||
.replace("%text_primary%", hex(getTextAttr()));
|
||||
|
||||
|
||||
loadedCSSAmoled = load("vt_ui_oled.css");
|
||||
isLoaded = true;
|
||||
}
|
||||
|
||||
private static void inject(WebView webView, String str){
|
||||
private static void inject(WebView webView, String str) {
|
||||
webView.loadUrl("javascript:(function() {var parent = document.getElementsByTagName('head').item(0);var style = document.createElement('style');style.type = 'text/css';style.innerHTML = window.atob('" + str + "');parent.appendChild(style)})()");
|
||||
}
|
||||
|
||||
public static void inject(WebView webView){
|
||||
public static void inject(WebView webView) {
|
||||
String string = getPrefsValue("darktheme");
|
||||
|
||||
if (getBoolValue("VKUI_INJ", true)) {
|
||||
@@ -93,10 +101,10 @@ public class VKUIHook{
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearWebCache(){
|
||||
public static void clearWebCache() {
|
||||
ThemeTracker.a();
|
||||
isLoaded = false;
|
||||
new WebView(getContext()).clearCache(true);
|
||||
new WebView(getGlobalContext()).clearCache(true);
|
||||
WebCachePreloader.e();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package ru.vtosters.lite.music;
|
||||
|
||||
public interface Callback{
|
||||
public interface Callback {
|
||||
void onProgress(int progress);
|
||||
|
||||
void onSuccess();
|
||||
|
||||
@@ -11,21 +11,22 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import ru.vtosters.lite.utils.Globals;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.IOUtils;
|
||||
|
||||
public class FFMpeg{
|
||||
public class FFMpeg {
|
||||
private static final int BUFFER_SIZE = 2048;
|
||||
|
||||
private static void copyAssets(){
|
||||
private static void copyAssets() {
|
||||
try {
|
||||
String[] files = Globals.getContext().getAssets().list("ffmpeg");
|
||||
String[] files = AndroidUtils.getGlobalContext().getAssets().list("ffmpeg");
|
||||
for (String file : files) {
|
||||
if (file.endsWith(".so")) {
|
||||
InputStream in = Globals.getContext().getAssets().open("ffmpeg" + File.separator + file);
|
||||
FileOutputStream out = new FileOutputStream(Globals.getContext().getFilesDir() + File.separator + file);
|
||||
InputStream in = AndroidUtils.getGlobalContext().getAssets().open("ffmpeg" + File.separator + file);
|
||||
FileOutputStream out = new FileOutputStream(AndroidUtils.getGlobalContext().getFilesDir() + File.separator + file);
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
int read;
|
||||
while((read = in.read(buffer)) != -1) {
|
||||
while ((read = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
in.close();
|
||||
@@ -37,15 +38,15 @@ public class FFMpeg{
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkFFMpegLibs(){
|
||||
var lib = new File(Globals.getContext().getFilesDir(), "libffmpegkit_abidetect.so");
|
||||
private static void checkFFMpegLibs() {
|
||||
var lib = new File(AndroidUtils.getGlobalContext().getFilesDir(), "libffmpegkit_abidetect.so");
|
||||
if (!lib.exists()) {
|
||||
ToastUtils.a("Копирование библиотеки ffmpegkit");
|
||||
ToastUtils.a(AndroidUtils.getString("ffmpegkit_copy"));
|
||||
copyAssets();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean convert(String in, String out){
|
||||
public static boolean convert(String in, String out) {
|
||||
checkFFMpegLibs();
|
||||
|
||||
// write the list of all .ts files to a txt file in "in" directory
|
||||
@@ -64,9 +65,8 @@ public class FFMpeg{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
// concatenate .ts files to a single .ts file
|
||||
var concat = FFmpegKit.execute("-f concat -safe 0 -i " + in + "/list.txt -c copy " + in + "/all.ts");
|
||||
FFmpegKit.execute("-f concat -safe 0 -i " + in + "/list.txt -c copy " + in + "/all.ts");
|
||||
|
||||
// convert .ts file to .mp3 file via ffmpeg
|
||||
var session = FFmpegKit.execute("-i " + in + "/all.ts -f mp3 -acodec mp3 -q:a 0 -y '" + out + "'");
|
||||
@@ -74,17 +74,11 @@ public class FFMpeg{
|
||||
|
||||
if (ReturnCode.isSuccess(rc)) {
|
||||
// remove temp files
|
||||
deleteRecursively(new File(in));
|
||||
IOUtils.deleteRecursive(new File(in));
|
||||
return true;
|
||||
} else {
|
||||
Log.e("FFMpeg", "FFmpegKit failed with return code " + rc);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteRecursively(File fileOrDirectory){
|
||||
if (fileOrDirectory.isDirectory()) for (File child : fileOrDirectory.listFiles())
|
||||
deleteRecursively(child);
|
||||
fileOrDirectory.delete();
|
||||
Log.e("FFMpeg", "FFmpegKit failed with return code " + rc);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,64 +16,55 @@ import okhttp3.Call;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import ru.vtosters.lite.utils.StreamUtils;
|
||||
import ru.vtosters.lite.utils.IOUtils;
|
||||
|
||||
public class M3UDownloader{
|
||||
public class M3UDownloader {
|
||||
|
||||
private final String mURL;
|
||||
private final File mOutDir;
|
||||
private final Callback mCallback;
|
||||
private OkHttpClient mClient = new OkHttpClient();
|
||||
private static OkHttpClient client = new OkHttpClient();
|
||||
|
||||
public M3UDownloader(String url, File outDir, Callback callback){
|
||||
mURL = url;
|
||||
mOutDir = outDir;
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public void execute(){
|
||||
public static void execute(String url, File outDir, Callback callback) {
|
||||
var request = new Request.a()
|
||||
.b(mURL)
|
||||
.b(url)
|
||||
.a();
|
||||
mClient.a(request).a(new okhttp3.Callback(){
|
||||
client.a(request).a(new okhttp3.Callback() {
|
||||
@Override
|
||||
public void a(Call call, IOException e){
|
||||
public void a(Call call, IOException e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void a(Call call, Response response) throws IOException{
|
||||
parse(response.a().g());
|
||||
public void a(Call call, Response response) throws IOException {
|
||||
parse(response.a().g(), outDir, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void parse(String payload){
|
||||
private static void parse(String payload, File outDir, Callback callback) {
|
||||
try {
|
||||
VKM3UParser parser = new VKM3UParser(payload);
|
||||
List<TransportStream> tses = parser.getTransportStreams();
|
||||
mCallback.onProgress(5);
|
||||
callback.onProgress(5);
|
||||
for (TransportStream ts : tses) {
|
||||
String tsURL = parser.getBaseUrl() + ts.getName();
|
||||
Log.d("M3UDownloader", "Downloading " + tsURL);
|
||||
InputStream is = StreamUtils.openStream(tsURL);
|
||||
InputStream is = IOUtils.openStream(tsURL);
|
||||
byte[] content;
|
||||
if (TransportStream.METHOD_AES128.equals(ts.getMethod())) {
|
||||
String key = StreamUtils.readAllLines(StreamUtils.openStream(ts.getKeyURL()));
|
||||
content = StreamUtils.decodeStream(is, key);
|
||||
String key = IOUtils.readAllLines(IOUtils.openStream(ts.getKeyURL()));
|
||||
content = IOUtils.decodeStream(is, key);
|
||||
} else {
|
||||
content = StreamUtils.readAllBytes(is);
|
||||
content = IOUtils.readAllBytes(is);
|
||||
}
|
||||
File tsDump = new File(mOutDir, ts.getName());
|
||||
StreamUtils.writeToFile(tsDump, content);
|
||||
mCallback.onSizeReceived((long) content.length * tses.size(), parser.getHeapSize());
|
||||
mCallback.onProgress(10 + Math.round(80.0f * tses.indexOf(ts) / tses.size()));
|
||||
File tsDump = new File(outDir, ts.getName());
|
||||
IOUtils.writeToFile(tsDump, content);
|
||||
callback.onSizeReceived((long) content.length * tses.size(), parser.getHeapSize());
|
||||
callback.onProgress(10 + Math.round(80.0f * tses.indexOf(ts) / tses.size()));
|
||||
}
|
||||
} catch (IOException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
mCallback.onFailure();
|
||||
callback.onFailure();
|
||||
return;
|
||||
}
|
||||
mCallback.onSuccess();
|
||||
callback.onSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package ru.vtosters.lite.music;
|
||||
|
||||
import static ru.vtosters.lite.utils.Preferences.getMusicDir;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.vk.dto.music.MusicTrack;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import ru.vtosters.lite.downloaders.AudioDownloader;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class MP3Downloader {
|
||||
|
||||
private static final String URL_FORMAT = "https://api.vk.com/method/audio.getById?v=5.131&access_token=%s&audios=%s©right=https://vtosters.app/";
|
||||
private static final OkHttpClient client = new OkHttpClient();
|
||||
|
||||
public static void execute(MusicTrack track) {
|
||||
var token = AndroidUtils.getPreferences().getString("vk_admin_token", "");
|
||||
if (token.isEmpty()) {
|
||||
Toast.makeText(AndroidUtils.getGlobalContext(), AndroidUtils.getString("update_vk_admin_token"), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
var request = new Request.a()
|
||||
.b(String.format(URL_FORMAT, token, track.y1()))
|
||||
.a();
|
||||
client.a(request).a(new Callback() {
|
||||
@Override
|
||||
public void a(Call call, IOException e) {
|
||||
Log.d("MP3Downloader", e + "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void a(Call call, Response response) throws IOException {
|
||||
var payload = response.a().g();
|
||||
Log.d("MP3Downloader", payload);
|
||||
try {
|
||||
JSONObject jsonObj = new JSONObject(payload);
|
||||
if (jsonObj.has("response")) {
|
||||
JSONObject responseNode = new JSONObject(payload).getJSONArray("response")
|
||||
.getJSONObject(0);
|
||||
if (responseNode.has("url")) {
|
||||
var url = responseNode.optString("url");
|
||||
Log.d("MP3Downloader", url);
|
||||
if (url.endsWith(".mp3")) {
|
||||
downloadMP3(track.toString(), url);
|
||||
} else if (VKM3UParser.isM3U8(url)) {
|
||||
AudioDownloader.downloadM3U8(track);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.d("MP3Downloader", e + "");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
private static void downloadMP3(String title, String url) {
|
||||
var downloadManager = AndroidUtils.getGlobalContext().getSystemService(DownloadManager.class);
|
||||
var request = new DownloadManager.Request(Uri.parse(url))
|
||||
.setAllowedOverRoaming(true)
|
||||
.setTitle("Downloading " + title)
|
||||
.setDestinationInExternalFilesDir(AndroidUtils.getGlobalContext(),
|
||||
getMusicDir().getAbsolutePath(),
|
||||
title + ".mp3")
|
||||
.setVisibleInDownloadsUi(true);
|
||||
downloadManager.enqueue(request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package ru.vtosters.lite.music;
|
||||
|
||||
import static java.lang.String.valueOf;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.MD5;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.vk.dto.music.MusicTrack;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import ru.vtosters.lite.net.NetCall;
|
||||
import ru.vtosters.lite.net.NetCallback;
|
||||
import ru.vtosters.lite.net.NetClient;
|
||||
import ru.vtosters.lite.net.NetRequest;
|
||||
import ru.vtosters.lite.net.NetResponse;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class Scrobbler {
|
||||
private static final String key = "5965d63402414776c54c266db0211746";
|
||||
private static final String keysecret = "d982180eed13275bb948e41cf225f88f";
|
||||
private static final String url = "https://ws.audioscrobbler.com/2.0/";
|
||||
private static final NetClient client = new NetClient.Builder().build();
|
||||
private static final ArrayList<String> scrobbled = new ArrayList<>();
|
||||
|
||||
public static void scrobbleTrack(long duration, String artist, String title, String uid) {
|
||||
var string = getDefaultPrefs().getString("sessionKey", null);
|
||||
var timestamp = System.currentTimeMillis() / 1000;
|
||||
|
||||
Log.d("Scrobbler", "scrobbleTrack: " + title + " - " + artist + " - " + duration + " - " + uid);
|
||||
|
||||
if (!needToBeScrobble(uid) ||
|
||||
string == null ||
|
||||
string.isEmpty() ||
|
||||
artist == null ||
|
||||
artist.isEmpty() ||
|
||||
title == null ||
|
||||
title.isEmpty() ||
|
||||
duration == 0) return;
|
||||
|
||||
scrobbled.add(uid); // add to scrobbled list
|
||||
|
||||
TreeMap<String, String> treeMap = new TreeMap<>(); // create map for request
|
||||
treeMap.put("method", "track.scrobble");
|
||||
treeMap.put("sk", string);
|
||||
treeMap.put("artist[0]", artist);
|
||||
treeMap.put("track[0]", title);
|
||||
treeMap.put("timestamp[0]", valueOf(timestamp));
|
||||
treeMap.put("api_key", key);
|
||||
treeMap.put("duration[0]", valueOf(duration));
|
||||
treeMap.put("api_sig", signMD5(treeMap));
|
||||
treeMap.put("format", "json");
|
||||
|
||||
client.newCall(new NetRequest.Builder().url(url).post().params(treeMap).build()).enqueue(new NetCallback() {
|
||||
@Override
|
||||
public void onFailure(NetCall call, IOException e) {
|
||||
Log.d("Scrobbler", "Error: " + e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(NetCall call, NetResponse response) {
|
||||
Log.d("Scrobbler", "Scrobbled: " + artist + " - " + title);
|
||||
Log.d("Scrobbler", "Response scrobble: " + response.getDataString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void grabMusicTrack(MusicTrack musictrack) {
|
||||
var uid = musictrack.y1();
|
||||
var artist = musictrack.C;
|
||||
var title = musictrack.f;
|
||||
var duration = musictrack.h;
|
||||
|
||||
if (uid.isEmpty() || artist == null || artist.isEmpty() || title == null || title.isEmpty() || duration == 0) {
|
||||
Log.d("Scrobbler", "grabTrackInfo: " + "Empty track, info: " + artist + " - " + title + " - " + duration + " - " + uid);
|
||||
return;
|
||||
}
|
||||
|
||||
scrobbleTrack(duration, artist, title, uid);
|
||||
}
|
||||
|
||||
private static String signMD5(Map<String, String> map) {
|
||||
var sb = new StringBuilder();
|
||||
|
||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||
sb.append(entry.getKey());
|
||||
sb.append(entry.getValue());
|
||||
}
|
||||
|
||||
sb.append(keysecret);
|
||||
|
||||
return MD5(sb.toString());
|
||||
}
|
||||
|
||||
public static void auth(String login, String pass) {
|
||||
if (login == null || pass == null) {
|
||||
sendToast(AndroidUtils.getString("lastfm_credentials_empty"));
|
||||
return;
|
||||
}
|
||||
|
||||
TreeMap<String, String> treeMap = new TreeMap<>(); // create map for request
|
||||
treeMap.put("method", "auth.getMobileSession");
|
||||
treeMap.put("api_key", key);
|
||||
treeMap.put("username", login);
|
||||
treeMap.put("password", pass);
|
||||
treeMap.put("api_sig", signMD5(treeMap));
|
||||
treeMap.put("format", "json");
|
||||
|
||||
client.newCall(new NetRequest.Builder().url(url).post().params(treeMap).build()).enqueue(new NetCallback() {
|
||||
@Override
|
||||
public void onFailure(NetCall call, IOException e) {
|
||||
Log.d("Scrobbler", "Auth failed", e);
|
||||
sendToast(AndroidUtils.getString("lastfm_auth_error"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(NetCall call, NetResponse response) {
|
||||
try {
|
||||
var jSONObject = new JSONObject(response.getDataString());
|
||||
sessionFetcher(jSONObject);
|
||||
Log.d("Scrobbler", "Auth response " + response.getDataString());
|
||||
} catch (JSONException e) {
|
||||
Log.d("Scrobbler", "Auth failed", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void sessionFetcher(JSONObject jsonObject) throws JSONException {
|
||||
if (!jsonObject.has("session")) {
|
||||
Log.d("Scrobbler", "Auth failed - no session");
|
||||
return;
|
||||
}
|
||||
|
||||
var session = jsonObject.getJSONObject("session");
|
||||
var name = session.getString("name");
|
||||
var key = session.getString("key");
|
||||
|
||||
getDefaultPrefs().edit().putString("username", name).
|
||||
putString("sessionKey", key).apply();
|
||||
|
||||
Log.d("Scrobbler", "Auth success as " + name + ", key " + key);
|
||||
}
|
||||
|
||||
public static void logout() {
|
||||
edit().remove("username").apply();
|
||||
edit().remove("sessionKey").apply();
|
||||
scrobbled.clear();
|
||||
sendToast(AndroidUtils.getString("lastfm_logout_success"));
|
||||
}
|
||||
|
||||
public static boolean needToBeScrobble(String uid) {
|
||||
return isLoggedIn() && isScrobblingEnabled() && !scrobbled.contains(uid);
|
||||
}
|
||||
|
||||
public static boolean isLoggedIn() {
|
||||
return getDefaultPrefs().getString("sessionKey", null) != null;
|
||||
}
|
||||
|
||||
public static boolean isScrobblingEnabled() {
|
||||
return getPreferences().getBoolean("lastfm_enabled", false);
|
||||
}
|
||||
|
||||
public static String getUserName() {
|
||||
return getDefaultPrefs().getString("username", null);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package ru.vtosters.lite.music;
|
||||
|
||||
public class TransportStream{
|
||||
public class TransportStream {
|
||||
|
||||
public static final String METHOD_NONE = "NONE";
|
||||
public static final String METHOD_AES128 = "AES-128";
|
||||
@@ -9,28 +9,28 @@ public class TransportStream{
|
||||
private String mName;
|
||||
private String mKeyURL;
|
||||
|
||||
public TransportStream(){
|
||||
public TransportStream() {
|
||||
this.mMethod = METHOD_NONE;
|
||||
}
|
||||
|
||||
public TransportStream(String method, String keyURL){
|
||||
public TransportStream(String method, String keyURL) {
|
||||
this.mMethod = method;
|
||||
this.mKeyURL = keyURL;
|
||||
}
|
||||
|
||||
public String getMethod(){
|
||||
public String getMethod() {
|
||||
return mMethod;
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public void setName(String name){
|
||||
public void setName(String name) {
|
||||
mName = name;
|
||||
}
|
||||
|
||||
public String getKeyURL(){
|
||||
public String getKeyURL() {
|
||||
return mKeyURL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class VKM3UParser{
|
||||
public class VKM3UParser {
|
||||
private final String mData;
|
||||
private final List<TransportStream> mTransportStreams = new ArrayList<>();
|
||||
|
||||
@@ -13,15 +13,15 @@ public class VKM3UParser{
|
||||
private int mHeapSize = 0;
|
||||
private String mBaseURL;
|
||||
|
||||
public VKM3UParser(String data){
|
||||
public VKM3UParser(String data) {
|
||||
mData = data;
|
||||
init();
|
||||
}
|
||||
|
||||
private void init(){
|
||||
private void init() {
|
||||
int i = 0;
|
||||
Scanner scanner = new Scanner(mData);
|
||||
while(scanner.hasNext()) {
|
||||
while (scanner.hasNext()) {
|
||||
String line = scanner.nextLine();
|
||||
mHeapSize += line.getBytes().length;
|
||||
if (line.startsWith("#EXT-X-TARGETDURATION")) {
|
||||
@@ -40,26 +40,30 @@ public class VKM3UParser{
|
||||
} else if (line.startsWith("#EXTINF")) {
|
||||
if (mTransportStreams.size() == i)
|
||||
mTransportStreams.add(new TransportStream());
|
||||
} else if (line.endsWith(".ts") || line.endsWith(".tp") || line.endsWith(".mpeg-ts") || line.endsWith(".m2ts")) {
|
||||
} else if (isM3U8(line)) {
|
||||
mTransportStreams.get(i).setName(line);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getDirectiveValue(String directive){
|
||||
private String getDirectiveValue(String directive) {
|
||||
return directive.substring(directive.indexOf(":") + 1);
|
||||
}
|
||||
|
||||
public int getHeapSize(){
|
||||
public static boolean isM3U8(String str) {
|
||||
return str.endsWith(".ts") || str.endsWith(".tp") || str.endsWith(".mpeg-ts") || str.endsWith(".m2ts");
|
||||
}
|
||||
|
||||
public int getHeapSize() {
|
||||
return mHeapSize;
|
||||
}
|
||||
|
||||
public String getBaseUrl(){
|
||||
public String getBaseUrl() {
|
||||
return mBaseURL;
|
||||
}
|
||||
|
||||
public List<TransportStream> getTransportStreams(){
|
||||
public List<TransportStream> getTransportStreams() {
|
||||
return mTransportStreams;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user