Compare commits
1174
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff404b21b5 | ||
|
|
aeed9efaeb | ||
|
|
29b9251763 | ||
|
|
91e6c3185f | ||
|
|
7169e3ab8b | ||
|
|
97a0ae4b95 | ||
|
|
5d5ad70e7e | ||
|
|
752c59e2a2 | ||
|
|
e3b33a88c7 | ||
|
|
b35d5c428f | ||
|
|
c796006b94 | ||
|
|
70d3b8f8c0 | ||
|
|
15f678e20d | ||
|
|
011698a722 | ||
|
|
d127fbbd22 | ||
|
|
eb167be1c0 | ||
|
|
19fa48a1f6 | ||
|
|
e96ba600cb | ||
|
|
70c75edacc | ||
|
|
5a048eff92 | ||
|
|
9abed48ec0 | ||
|
|
6758c8735c | ||
|
|
b20fdee8da | ||
|
|
dffa4ff7c4 | ||
|
|
6dd715af0b | ||
|
|
10de24f119 | ||
|
|
2cd856e574 | ||
|
|
9e9617fd16 | ||
|
|
3ae2637da0 | ||
|
|
94438662cb | ||
|
|
aa3d4df40a | ||
|
|
e499d98050 | ||
|
|
7299c9e33a | ||
|
|
4d0573ffe5 | ||
|
|
83d13dce1e | ||
|
|
55dbb029c0 | ||
|
|
3df51d0685 | ||
|
|
9bc87a1d79 | ||
|
|
94667ac741 | ||
|
|
3a354b359a | ||
|
|
09443d6ec1 | ||
|
|
ca27776aaf | ||
|
|
3b6cdacf96 | ||
|
|
1e5fdde641 | ||
|
|
b37b41ddd3 | ||
|
|
25d6231ae3 | ||
|
|
db83fbff52 | ||
|
|
c7621c44d5 | ||
|
|
89997317bf | ||
|
|
c87be6c9b8 | ||
|
|
48e6b4f54d | ||
|
|
4ae5ea8e57 | ||
|
|
b967e72a04 | ||
|
|
cc66af3e3a | ||
|
|
f82ef2f64e | ||
|
|
646329f93b | ||
|
|
3f7b9eb796 | ||
|
|
a3d8a9ba70 | ||
|
|
8d05973848 | ||
|
|
2b553d263c | ||
|
|
265d3afbff | ||
|
|
858fced1aa | ||
|
|
a01d12b012 | ||
|
|
8bde61b059 | ||
|
|
05eec57058 | ||
|
|
c2a1a4bb5f | ||
|
|
5e01ebcff6 | ||
|
|
ffe0955ef1 | ||
|
|
f4ca7c9e66 | ||
|
|
57b19369a0 | ||
|
|
4019219293 | ||
|
|
5d6c001dfb | ||
|
|
1f2b1b1180 | ||
|
|
cb7862a0e2 | ||
|
|
1cd23341e2 | ||
|
|
f85dac2ff8 | ||
|
|
992b29894e | ||
|
|
9e67ded6bd | ||
|
|
24607e1ea5 | ||
|
|
8e260a9de4 | ||
|
|
de045f749a | ||
|
|
fde1628fac | ||
|
|
fdeaa05360 | ||
|
|
d0197142cd | ||
|
|
8257393909 | ||
|
|
9542317b23 | ||
|
|
de595c93f4 | ||
|
|
7596b4117a | ||
|
|
8b6ef6d3af | ||
|
|
1d71def416 | ||
|
|
18799ce11c | ||
|
|
b4e34e34b1 | ||
|
|
cd6f975e56 | ||
|
|
de73c6216b | ||
|
|
937c7efb03 | ||
|
|
86c513ed58 | ||
|
|
e701d03233 | ||
|
|
129ae95121 | ||
|
|
78cd5cac9a | ||
|
|
f7fab596ba | ||
|
|
85afaa5057 | ||
|
|
f1ed0fc221 | ||
|
|
b64b17038d | ||
|
|
e5b5bf9d48 | ||
|
|
c58e511040 | ||
|
|
a067a35040 | ||
|
|
dbee2a5a42 | ||
|
|
104ca05772 | ||
|
|
ad5eca635a | ||
|
|
6c86b49e97 | ||
|
|
ad8f2b5b5a | ||
|
|
3058c220a8 | ||
|
|
6531a21fb4 | ||
|
|
3366d28e7e | ||
|
|
39b08702d5 | ||
|
|
b90b27e8ce | ||
|
|
9b03299c7b | ||
|
|
a9343c6777 | ||
|
|
a03505f27f | ||
|
|
b9126aa184 | ||
|
|
613a101c82 | ||
|
|
43fe0577cd | ||
|
|
6208c966d0 | ||
|
|
097faf6b38 | ||
|
|
4f4b167d99 | ||
|
|
d886e43f3d | ||
|
|
fcf1ee608d | ||
|
|
cd15541583 | ||
|
|
636341b4f2 | ||
|
|
576ce7d6b0 | ||
|
|
e74001e17e | ||
|
|
7bdaa736ef | ||
|
|
74f10e6ab2 | ||
|
|
678a398612 | ||
|
|
7e1c3d62cf | ||
|
|
c0ce22565e | ||
|
|
217a376f5b | ||
|
|
35f486dc86 | ||
|
|
252d761b9e | ||
|
|
237be0cc88 | ||
|
|
2717fd5736 | ||
|
|
48f6b35abe | ||
|
|
5beea5d273 | ||
|
|
842130628e | ||
|
|
ab26bab35d | ||
|
|
6ffcbe8329 | ||
|
|
ca3d1e9585 | ||
|
|
05a9e9a12c | ||
|
|
9e2f3bb048 | ||
|
|
91aef33725 | ||
|
|
32c5aa9ac2 | ||
|
|
e32c3ec74b | ||
|
|
3fea0e9c40 | ||
|
|
c9c5c96d63 | ||
|
|
2a91238b4f | ||
|
|
e4d740061d | ||
|
|
f96f2cb7d7 | ||
|
|
81cf7ad694 | ||
|
|
34007658d5 | ||
|
|
0482f75172 | ||
|
|
eaed8fc752 | ||
|
|
f871e63002 | ||
|
|
189d699d48 | ||
|
|
f3b6b3c1b0 | ||
|
|
519722d613 | ||
|
|
3aaca80da1 | ||
|
|
b889015368 | ||
|
|
1d3463df0c | ||
|
|
60ac497e6d | ||
|
|
f8192c7169 | ||
|
|
3f2e0c9b98 | ||
|
|
2a9ea90df5 | ||
|
|
aa40bbb390 | ||
|
|
4782401f0a | ||
|
|
0255cfb1b9 | ||
|
|
764b68d47f | ||
|
|
126154fc9b | ||
|
|
ec2df87e42 | ||
|
|
e963080385 | ||
|
|
23286a21f0 | ||
|
|
3d1ca8d36a | ||
|
|
99f8e4f896 | ||
|
|
4e48faec16 | ||
|
|
666c562092 | ||
|
|
4f5cbe426a | ||
|
|
5635cd4139 | ||
|
|
4bb31d492a | ||
|
|
f85fe81881 | ||
|
|
5295e465e9 | ||
|
|
7f30e66c0c | ||
|
|
d55361fd72 | ||
|
|
63d1c1a3b0 | ||
|
|
4cc6bfabd0 | ||
|
|
802f639633 | ||
|
|
8a90602328 | ||
|
|
6f607e9ae8 | ||
|
|
dd0f238701 | ||
|
|
600a9da953 | ||
|
|
d14dec88bc | ||
|
|
6e216830d1 | ||
|
|
2b6012b1e7 | ||
|
|
ded283df35 | ||
|
|
86a5c60f7f | ||
|
|
1d964762ca | ||
|
|
4a2d2b23f2 | ||
|
|
a06d129c8d | ||
|
|
a0b1adbfe9 | ||
|
|
0093463fae | ||
|
|
9e572d7844 | ||
|
|
900dbcfe0a | ||
|
|
e3e06d1638 | ||
|
|
69a4cfa715 | ||
|
|
21d9c13fdf | ||
|
|
09bf8e26ce | ||
|
|
21c0ccd9fc | ||
|
|
aa95b368f8 | ||
|
|
4be234632c | ||
|
|
00d37e3721 | ||
|
|
4c4a3ae11c | ||
|
|
7e09e6d4e6 | ||
|
|
b92fa69628 | ||
|
|
d127a84b07 | ||
|
|
95916b4289 | ||
|
|
5cb5d06993 | ||
|
|
f0da269968 | ||
|
|
2fb021ad05 | ||
|
|
1981bc9d14 | ||
|
|
c60cce5467 | ||
|
|
2035d513f1 | ||
|
|
3849569794 | ||
|
|
9f2f6d6f60 | ||
|
|
586a82a15f | ||
|
|
eba922871f | ||
|
|
337aa7493e | ||
|
|
1ed9f871c3 | ||
|
|
083d96707c | ||
|
|
10e0bd50da | ||
|
|
2864056186 | ||
|
|
8876a66449 | ||
|
|
41a1d29c4b | ||
|
|
1bb10807c4 | ||
|
|
7f8100660a | ||
|
|
274a1b9fa8 | ||
|
|
03c5f83a42 | ||
|
|
f394bdfec5 | ||
|
|
19c9dd102f | ||
|
|
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 |
@@ -1,27 +0,0 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Заготовка для репорта багов
|
||||
title: Ошибка обновлении ленты новостей
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Опишите сам баг**
|
||||
При обновлении новостей вылезает ошибка
|
||||
|
||||
**Опишите действия для воспроизведения ошибки**
|
||||
1. Обновил ленту интересных новостей
|
||||
2. Пролистал до конца страницы
|
||||
|
||||
**Опишите ожидаемый результат**
|
||||
Интересная лента должна прогружать результаты
|
||||
|
||||
**Скриншот ошибки**
|
||||
|
||||
**Информация об устройстве:**
|
||||
- Устройство: Samsung Galaxy J1 Mini
|
||||
- OS: Android 9 | OneUi 3.0
|
||||
- Коммит: fa12e8f (В О Приложении написана версия коммита)
|
||||
|
||||
**Дополнительная информация о баге или мыслях почему оно может происходить (если есть)**
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Предложение функции
|
||||
title: Улучшение голосовых сообщений
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Опишите вашу идею максимально подробно и понятно**
|
||||
Необходима функция улучшения голосовых сообщений. Она значительно улучшит запись голосовых сообщений и собеседнику будет лучше слышно меня
|
||||
|
||||
**Опишите возможное решение/реализацию функции (если понимаете как это можно реализовать на Java/C++)**
|
||||
|
||||
**Остальные мысли о предложенной функции**
|
||||
@@ -66,7 +66,6 @@
|
||||
* Округление чисел
|
||||
* Сокращение постов **(Показать полностью)**
|
||||
* Результаты опросов без участия
|
||||
* Возможность указывать папку для загрузки фото/видео/музыки/всего
|
||||
* Интеграция с <a href="https://www.last.fm/">LAST.FM</a> (а также возможность скробблинга)
|
||||
* Новый раздел музыки
|
||||
* Возможность скачивать видео
|
||||
@@ -91,7 +90,6 @@
|
||||
* Возможность видеть онлайн пользователей, если у вас скрыт онлайн через VK Messenger
|
||||
* Отключить уведомление о том, что вы сделали скриншот в беседе
|
||||
* Отключение редиректа через away.php
|
||||
* Отключение отправки метрики
|
||||
* Внешний вид
|
||||
* **Milkshake** тема (дизайн новых версий ВК)
|
||||
* Название заголовков в докбаре
|
||||
@@ -105,10 +103,8 @@
|
||||
* Возможность отключить блок историй наверху ленты
|
||||
* Возможность отключить боковую камеру в разделе «Новости»
|
||||
* Возможность отключить блок «Что у вас нового?» в разделе «Новости»
|
||||
* Возможность показывать лайки у постов справа
|
||||
* Возможность менять стартовый раздел при запуске приложения
|
||||
* Возможность менять раздел, который запускается при запуске
|
||||
* Анимации фрагментов
|
||||
* Возможность изменять размер закругления картинок (аватарок и прочего)
|
||||
* Возможность отключить редизайн видеопостов
|
||||
* Возможность отключить блок миниаппов/VK Pay/Superapp
|
||||
* Возможность отключить сокращение названий разделов в меню
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
5df53281cbfd1b6caf676bd10d2a403361a2904b
|
||||
Binary file not shown.
Binary file not shown.
@@ -16,7 +16,6 @@ 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.
|
||||
@@ -40,7 +39,7 @@ public class NotificationsHelper {
|
||||
downloadingPacksNotificationsIds = new HashMap<>();
|
||||
|
||||
if (oreo()) {
|
||||
NotificationChannel notificationChan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, AndroidUtils.getString("telegram_stickers_service"), NotificationManager.IMPORTANCE_HIGH);
|
||||
NotificationChannel notificationChan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Сервис стикеров Telegram в VTosters", NotificationManager.IMPORTANCE_HIGH);
|
||||
((NotificationManager) c.getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(notificationChan);
|
||||
}
|
||||
}
|
||||
@@ -50,8 +49,8 @@ public class NotificationsHelper {
|
||||
downloadingPacksNotificationsIds.put(pack, notificationId);
|
||||
|
||||
Notification.Builder builder = commonBuilder();
|
||||
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.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + ": загрузка" : pack.title + ": обновление");
|
||||
builder.setContentText("Получение информации");
|
||||
builder.setOngoing(true);
|
||||
|
||||
manager.notify(notificationId, builder.build());
|
||||
@@ -64,7 +63,7 @@ public class NotificationsHelper {
|
||||
lastNotificationTime.set(System.currentTimeMillis());
|
||||
|
||||
Notification.Builder builder = commonBuilder();
|
||||
builder.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + AndroidUtils.getString("telegram_stickers_downloading") : pack.title + AndroidUtils.getString("telegram_stickers_updating"));
|
||||
builder.setContentTitle(pack.state == TelegramStickersPack.DOWNLOADING ? pack.title + ": загрузка" : pack.title + ": обновление");
|
||||
builder.setContentText(downloadProgress + "/" + pack.stickersCount);
|
||||
builder.setProgress(pack.stickersCount, downloadProgress, false);
|
||||
builder.setOngoing(true);
|
||||
@@ -78,13 +77,13 @@ public class NotificationsHelper {
|
||||
Notification.Builder builder = commonBuilder();
|
||||
builder.setProgress(0, 0, false);
|
||||
builder.setOngoing(false);
|
||||
builder.setContentTitle(AndroidUtils.getString("telegram_stickers_service"));
|
||||
builder.setContentTitle("Сервис стикеров Telegram в VTosters");
|
||||
|
||||
String text;
|
||||
if (success)
|
||||
text = wasUpdate ? pack.title + AndroidUtils.getString("telegram_stickers_updated") : pack.title + AndroidUtils.getString("telegram_stickers_downloaded");
|
||||
text = wasUpdate ? pack.title + " успешно обновлен" : pack.title + " успешно загружен";
|
||||
else
|
||||
text = wasUpdate ? pack.title + AndroidUtils.getString("telegram_stickers_error_update") : pack.title + AndroidUtils.getString("telegram_stickers_error_download");
|
||||
text = wasUpdate ? pack.title + ": ошибка при обновлении" : pack.title + ": ошибка при загрузке";
|
||||
|
||||
if (e instanceof TelegramStickersGrabber.TSGException) {
|
||||
text = pack.title + ": " + e.getMessage();
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.vk.core.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
public class VKLayoutInflater extends LayoutInflater {
|
||||
|
||||
private final static String[] DEFAULT_PACKAGES = {
|
||||
"android.widget.", "android.webkit.", "android.app."
|
||||
};
|
||||
|
||||
public VKLayoutInflater(LayoutInflater original, Context context) {
|
||||
super(original, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutInflater cloneInContext(Context newContext) {
|
||||
return new VKLayoutInflater(this, newContext);
|
||||
}
|
||||
|
||||
public final View createView(View parent, String name, Context context, AttributeSet attrs) {
|
||||
if (!name.startsWith("android.")) {
|
||||
try {
|
||||
return onCreateView(parent, name, attrs);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
return createView(name, null, attrs);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
|
||||
for (var defPackage : DEFAULT_PACKAGES) {
|
||||
try {
|
||||
View view = createView(name, defPackage, attrs);
|
||||
if (view != null) return view;
|
||||
} catch (ClassCastException | ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return super.onCreateView(name, attrs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package com.vk.core.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.InflateException;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
|
||||
import com.vk.core.ui.themes.VKThemeHelper;
|
||||
import com.vk.core.util.OsUtil;
|
||||
import com.vk.core.view.NavigationSpinner;
|
||||
import com.vk.core.view.TextViewColorStateListAndAlphaSupportPreV23;
|
||||
import com.vk.core.view.VKAppBarLayout;
|
||||
|
||||
public class VKUILayoutFactory implements LayoutInflater.Factory2 {
|
||||
|
||||
private final static int[] FONT_ATTR = { android.R.attr.font };
|
||||
private AppCompatDelegate mDelegate;
|
||||
private VKLayoutInflater mInflater;
|
||||
|
||||
public VKUILayoutFactory(AppCompatDelegate delegate, VKLayoutInflater inflater) {
|
||||
mDelegate = delegate;
|
||||
mInflater = inflater;
|
||||
}
|
||||
|
||||
private void setTypeface(TextView textView, Context context, AttributeSet attrs) {
|
||||
TypedArray ta = context.obtainStyledAttributes(attrs, FONT_ATTR, android.R.attr.textViewStyle, 0);
|
||||
if (ta == null) return;
|
||||
Font font = Font.Companion.a(ta.getString(0));
|
||||
if (font != null && Build.VERSION.SDK_INT < font.a())
|
||||
textView.setTypeface(font.c());
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
|
||||
View view = null;
|
||||
try {
|
||||
if (!(parent instanceof NavigationSpinner) && !OsUtil.b())
|
||||
view = new TextViewColorStateListAndAlphaSupportPreV23(context, attrs, 0);
|
||||
else if (mDelegate != null)
|
||||
view = mDelegate.createView(parent, name, context, attrs);
|
||||
else if (mInflater != null)
|
||||
view = mInflater.createView(parent, name, context, attrs);
|
||||
} catch (Throwable unused) {
|
||||
throw new InflateException(
|
||||
"parent=" + parent.getClass().getName()
|
||||
+ ":" + getResourceIdName(view)
|
||||
+ ", view=" + name
|
||||
+ ":" + getResourceIdName(context, attrs));
|
||||
}
|
||||
if (view == null &&
|
||||
("com.google.android.material.appbar.AppBarLayout".equals(name)
|
||||
|| "android.support.design.widget.AppBarLayout".equals(name)))
|
||||
view = new VKAppBarLayout(context, attrs);
|
||||
|
||||
if (view != null) {
|
||||
if (!(view.getTag() instanceof String)) {
|
||||
if (view instanceof TextView) {
|
||||
setTypeface((TextView) view, context, attrs);
|
||||
if (view instanceof CheckBox)
|
||||
VKThemeHelper.k.a((CheckBox) view);
|
||||
else if (view instanceof RadioButton)
|
||||
VKThemeHelper.k.a((RadioButton) view);
|
||||
else if (view instanceof SwitchCompat)
|
||||
VKThemeHelper.k.a((SwitchCompat) view);
|
||||
else if (view instanceof Switch)
|
||||
VKThemeHelper.k.a((Switch) view);
|
||||
} else if (view instanceof WebView) {
|
||||
VKThemeHelper.a((WebView) view);
|
||||
}
|
||||
VKThemeHelper.k.a(view, attrs);
|
||||
}
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private String getResourceIdName(View view) {
|
||||
try {
|
||||
if (view != null) {
|
||||
if (view.getId() != -1)
|
||||
return view.getResources().getResourceName(view.getId());
|
||||
return "NO_ID";
|
||||
}
|
||||
return "null";
|
||||
} catch (Throwable unused) {
|
||||
return "FAILED_TO_GET_ID";
|
||||
}
|
||||
}
|
||||
|
||||
private String getResourceIdName(Context context, AttributeSet attrs) {
|
||||
TypedArray ta = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.id });
|
||||
int resId = ta.getResourceId(0, -1);
|
||||
ta.recycle();
|
||||
return resId != -1
|
||||
? context.getResources().getResourceName(resId)
|
||||
: "NO_ID";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
|
||||
return onCreateView(null, name, context, attrs);
|
||||
}
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
package com.vk.core.util;
|
||||
|
||||
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.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.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 c2 = MediaUtils.c(MediaUtils.b(str2));
|
||||
|
||||
if (file.endsWith(".jpg") || file.endsWith(".png") || file.endsWith(".jpeg")) {
|
||||
b2 = new File(getPhotosDir(), file);
|
||||
} 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 (!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);
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,4 @@ public enum DialogAction {
|
||||
DNT_OFF,
|
||||
pinmsg,
|
||||
unpinmsg,
|
||||
ENCRYPT_SETT,
|
||||
ENCRYPT
|
||||
}
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
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
@@ -1,106 +0,0 @@
|
||||
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(){
|
||||
}
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,447 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 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 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 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;
|
||||
|
||||
+4
-12
@@ -1,6 +1,5 @@
|
||||
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;
|
||||
@@ -31,7 +30,6 @@ 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;
|
||||
@@ -221,19 +219,13 @@ public class BottomNavigationItemView extends FrameLayout implements MenuView.It
|
||||
// ViewCompat.setScaleY(mLargeLabel, !mStaticModeEnabled && !checked ? mLargeScale : 1.0f);
|
||||
ViewCompat.setScaleX(mSmallLabel, !mStaticModeEnabled && checked ? mSmallScale : 1.0f);
|
||||
ViewCompat.setScaleY(mSmallLabel, !mStaticModeEnabled && checked ? mSmallScale : 1.0f);
|
||||
// make mLargeLabel and mSmallLabel are bold
|
||||
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);
|
||||
// make mLargeLabel and mSmallLabel text size is 10sp
|
||||
mLargeLabel.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
|
||||
mSmallLabel.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
|
||||
|
||||
mLargeLabel.setVisibility(/*checked ? VISIBLE :*/ INVISIBLE);
|
||||
mSmallLabel.setVisibility(VISIBLE);//checked ? INVISIBLE : VISIBLE);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package ru.vtosters.lite.deviceinfo;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class Device {
|
||||
private String androidId;
|
||||
private String bluetoothMac;
|
||||
@@ -88,7 +86,6 @@ public class Device {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String toString() {
|
||||
return "Device{serialId='" + this.serialId + "', androidId='" + this.androidId + "', wifiMac='" + this.wifiMac + "', bluetoothMac='" + this.bluetoothMac + "'}";
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package ru.vtosters.lite.deviceinfo;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.Context;
|
||||
import android.net.wifi.WifiInfo;
|
||||
@@ -29,7 +28,6 @@ public class DeviceInfoCollector {
|
||||
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");
|
||||
@@ -55,7 +53,6 @@ public class DeviceInfoCollector {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressLint("HardwareIds")
|
||||
private String androidId(Context context) {
|
||||
return Settings.Secure.getString(context.getContentResolver(), "android_id").toLowerCase();
|
||||
}
|
||||
@@ -102,7 +99,7 @@ public class DeviceInfoCollector {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int length = hardwareAddress.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(String.format("%02X:", hardwareAddress[i]));
|
||||
sb.append(String.format("%02X:", Byte.valueOf(hardwareAddress[i])));
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
|
||||
@@ -1,219 +1,96 @@
|
||||
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.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;
|
||||
|
||||
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 = dialog.getId();
|
||||
|
||||
list.add(DialogAction.pinmsg);
|
||||
list.add(DialogAction.unpinmsg);
|
||||
list.add(DialogAction.valueOf("pinmsg"));
|
||||
list.add(DialogAction.valueOf("unpinmsg"));
|
||||
|
||||
if (isDnrEnabledFor(peerId)) {
|
||||
list.add(DialogAction.DNR_OFF);
|
||||
list.add(DialogAction.valueOf("DNR_OFF"));
|
||||
} else {
|
||||
list.add(DialogAction.DNR_ON);
|
||||
list.add(DialogAction.valueOf("DNR_ON"));
|
||||
}
|
||||
|
||||
if (isDntEnabledFor(peerId)) {
|
||||
list.add(DialogAction.DNT_OFF);
|
||||
list.add(DialogAction.valueOf("DNT_OFF"));
|
||||
} else {
|
||||
list.add(DialogAction.DNT_ON);
|
||||
}
|
||||
|
||||
list.add(DialogAction.ENCRYPT);
|
||||
IMProcessor prov = EncryptProvider.getProcessorFor(peerId);
|
||||
if (prov != null && !prov.isPublic()) {
|
||||
list.add(DialogAction.ENCRYPT_SETT);
|
||||
list.add(DialogAction.valueOf("DNT_ON"));
|
||||
}
|
||||
}
|
||||
|
||||
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.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"));
|
||||
|
||||
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"));
|
||||
hashMap.put(DialogAction.valueOf("pinmsg"), getIdentifier("pinmsg", "string"));
|
||||
hashMap.put(DialogAction.valueOf("unpinmsg"), getIdentifier("unpinmsg", "string"));
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
@SuppressLint("ResourceType")
|
||||
public static List<Object> injectToList(List<Object> actions) {
|
||||
var list = new ArrayList<>(actions);
|
||||
|
||||
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, ProfilesSimpleInfo profilesSimpleInfo) {
|
||||
var 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) {
|
||||
var id = 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.DNR_OFF) {
|
||||
setDnr(dialog, false);
|
||||
forceInvalidateDialogActions(dialog);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == DialogAction.DNT_ON) {
|
||||
setDnt(dialog, true);
|
||||
forceInvalidateDialogActions(dialog);
|
||||
return true;
|
||||
} else if (action == DialogAction.DNT_OFF) {
|
||||
setDnt(dialog, false);
|
||||
forceInvalidateDialogActions(dialog);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == DialogAction.ENCRYPT_SETT) {
|
||||
CryptImHook.hookPref(id);
|
||||
return true;
|
||||
} else if (action == DialogAction.ENCRYPT) {
|
||||
CryptImHook.hook(id, dialog);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean onClick(Dialog dialog, DialogAction action) {
|
||||
var id = dialog.getId();
|
||||
|
||||
if (action == DialogAction.MARK_AS_READ) {
|
||||
if (action == DialogAction.valueOf("MARK_AS_READ")) {
|
||||
DNRModule.hookRead(dialog);
|
||||
}
|
||||
|
||||
if (action == DialogAction.DNR_ON) {
|
||||
if (action == DialogAction.valueOf("DNR_ON")) {
|
||||
setDnr(dialog, true);
|
||||
return true;
|
||||
} else if (action == DialogAction.DNR_OFF) {
|
||||
} else if (action == DialogAction.valueOf("DNR_OFF")) {
|
||||
setDnr(dialog, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == DialogAction.DNT_ON) {
|
||||
if (action == DialogAction.valueOf("DNT_ON")) {
|
||||
setDnt(dialog, true);
|
||||
return true;
|
||||
} else if (action == DialogAction.DNT_OFF) {
|
||||
} else if (action == DialogAction.valueOf("DNT_OFF")) {
|
||||
setDnt(dialog, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == DialogAction.pinmsg) {
|
||||
if (action == DialogAction.valueOf("pinmsg")) {
|
||||
pinnedMsg(id, true);
|
||||
return true;
|
||||
} else if (action == DialogAction.unpinmsg) {
|
||||
} else if (action == DialogAction.valueOf("unpinmsg")) {
|
||||
pinnedMsg(id, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == DialogAction.ENCRYPT_SETT) {
|
||||
CryptImHook.hookPref(id);
|
||||
return true;
|
||||
} else if (action == DialogAction.ENCRYPT) {
|
||||
CryptImHook.hook(id, dialog);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -225,7 +102,6 @@ public class DNRInjector {
|
||||
|
||||
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);
|
||||
|
||||
@@ -237,24 +113,15 @@ public class DNRInjector {
|
||||
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);
|
||||
Translate.showTranslatedText(context, text + "\n\nРеплай:\n" + reply);
|
||||
} else if (isReplyExist) {
|
||||
Translate.showTranslatedText(context, AndroidUtils.getString("translator_reply") + "\n" + reply);
|
||||
Translate.showTranslatedText(context, "Реплай:\n" + reply);
|
||||
} else if (isTextExist) {
|
||||
Translate.showTranslatedText(context, text);
|
||||
} else {
|
||||
sendToast(AndroidUtils.getString("translator_no_text"));
|
||||
sendToast("Нет текста для перевода");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +149,7 @@ public class DNRInjector {
|
||||
|
||||
thread.start();
|
||||
|
||||
sendToast(AndroidUtils.getString("pin_dialog") + (needToBePinned ? AndroidUtils.getString("dialog_pinned") : AndroidUtils.getString("dialog_unpinned")));
|
||||
sendToast("Диалог успешно " + (needToBePinned ? "закреплен" : "откреплен"));
|
||||
}
|
||||
|
||||
public static void setDnr(Dialog dialog, boolean value) {
|
||||
|
||||
@@ -31,21 +31,11 @@ public class AudioDownloader {
|
||||
|
||||
public static void downloadM3U8(MusicTrack track) {
|
||||
if (track.D == null) {
|
||||
ToastUtils.a(AndroidUtils.getString("link_audio_error"));
|
||||
ToastUtils.a("Не удалось найти ссылку на аудиозапись");
|
||||
return;
|
||||
}
|
||||
|
||||
var musicPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).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;
|
||||
|
||||
@@ -64,7 +54,7 @@ public class AudioDownloader {
|
||||
var success = FFMpeg.convert(downloadPath, musicPath + File.separator + fileName + ".mp3");
|
||||
if (success) {
|
||||
notification
|
||||
.setContentText(AndroidUtils.getString("player_download_finished"))
|
||||
.setContentText("Загрузка завершена")
|
||||
.setProgress(0, 0, false)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download_done);
|
||||
notificationManager.notify(tempId, notification.build());
|
||||
@@ -72,7 +62,7 @@ public class AudioDownloader {
|
||||
onFailure();
|
||||
}
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
Log.e("AudioDownloader", "native libs");
|
||||
Log.e("AudioDownloader", "Опять эти нативные либы");
|
||||
Log.e("AudioDownloader", e.getMessage());
|
||||
onFailure();
|
||||
}
|
||||
@@ -80,7 +70,7 @@ public class AudioDownloader {
|
||||
|
||||
@Override
|
||||
public void onFailure() {
|
||||
notification.setContentText(AndroidUtils.getString("load_audio_error")).setProgress(0, 0, false);
|
||||
notification.setContentText("Не удалось загрузить аудиозапись").setProgress(0, 0, false);
|
||||
notificationManager.notify(tempId, notification.build());
|
||||
}
|
||||
|
||||
@@ -109,7 +99,7 @@ public class AudioDownloader {
|
||||
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(AndroidUtils.getString("audio_downloading"))
|
||||
.setContentTitle("Загрузка аудиозаписи")
|
||||
.setContentText(track.toString())
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
|
||||
|
||||
@@ -46,7 +46,7 @@ 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.uriFromFile(apk));
|
||||
APKInstallActivity.installOta(context, FileUtils.n(apk));
|
||||
} else if (status == DownloadManager.STATUS_FAILED) {
|
||||
AndroidUtils.sendToast(getString("downloaderr"));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package ru.vtosters.lite.downloaders;
|
||||
|
||||
import static ru.vtosters.lite.downloaders.VideoDownloader.downloadVideo;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.Preferences.getPhotosDir;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
import android.content.Context;
|
||||
@@ -24,7 +23,7 @@ public class StoryDownloader {
|
||||
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(getPhotosDir().getAbsolutePath(), "/Stories/photo" + story.E.a + ".jpg");
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DCIM, "/Stories/photo" + story.E.a + ".jpg");
|
||||
((DownloadManager) getGlobalContext().getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ 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;
|
||||
@@ -28,7 +27,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.ExternalLinkParser;
|
||||
|
||||
public class VideoDownloader {
|
||||
@@ -106,7 +104,7 @@ 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(getVideosDir().getAbsolutePath(), videoFile + ".mp4");
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MOVIES, videoFile + ".mp4");
|
||||
((DownloadManager) getGlobalContext().getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
|
||||
return;
|
||||
}
|
||||
@@ -117,7 +115,7 @@ 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(getVideosDir().getAbsolutePath(), videoFile + ".mp4");
|
||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MOVIES, videoFile + ".mp4");
|
||||
((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
|
||||
}));
|
||||
builder.show();
|
||||
@@ -125,12 +123,12 @@ public class VideoDownloader {
|
||||
|
||||
public static void parseVideoLink(String url, Context ctx) {
|
||||
if (url.contains("vk.com/story")) {
|
||||
ToastUtils.a(AndroidUtils.getString("video_dl_stories_not_supported"));
|
||||
ToastUtils.a("Не поддерживается загрузка историй");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!url.contains("vk.com/video")) {
|
||||
ToastUtils.a(AndroidUtils.getString("video_dl_wrong_link"));
|
||||
ToastUtils.a("Неверная ссылка");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -138,7 +136,7 @@ public class VideoDownloader {
|
||||
String ownerId = videoId.split("_")[0];
|
||||
|
||||
final ProgressDialog progressDialog = new ProgressDialog(ctx);
|
||||
progressDialog.setMessage(AndroidUtils.getString("video_dl_progress"));
|
||||
progressDialog.setMessage("Обработка видео");
|
||||
progressDialog.show();
|
||||
|
||||
makeRequest("https://" + "api.vk.com" + "/method/video.get?owner_id=" + ownerId + "&videos=" + videoId + "&v=5.99&access_token=" + getUserToken(),
|
||||
@@ -154,7 +152,7 @@ public class VideoDownloader {
|
||||
downloadVideo(videoFile, ctx);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(ctx, AndroidUtils.getString("video_dl_error"), Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(ctx, "Видео нельзя скачать", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+2
-2
@@ -12,8 +12,8 @@ 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 = AndroidUtils.getString("music_dl_title");
|
||||
public static final String MUSIC_DOWNLOAD_CHANNEL_DESCRIPTION = AndroidUtils.getString("music_dl_progress");
|
||||
public static final String MUSIC_DOWNLOAD_CHANNEL_NAME = "Загрузка музыки";
|
||||
public static final String MUSIC_DOWNLOAD_CHANNEL_DESCRIPTION = "Прогресс загрузки музыки";
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public static void createChannels() {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
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;
|
||||
|
||||
@@ -61,13 +58,12 @@ public class EncryptProvider {
|
||||
try {
|
||||
for (IMProcessor processor : processors) {
|
||||
if ((processor.isUsed() || !processor.isPublic()) && processor.isEncrypted(msgBody) && (processor.isPublic() || getKeyForProcessor(processor, peer) != null))
|
||||
return "\uD83D\uDD12 " + injectOwnTextAll(processor.decode(msgBody, getKeyForProcessor(processor, peer)));
|
||||
return "\uD83D\uDD12 " + processor.decode(msgBody, getKeyForProcessor(processor, peer));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return injectOwnTextAll(msgBody);
|
||||
return msgBody;
|
||||
}
|
||||
|
||||
private static byte[] getKeyForProcessor(IMProcessor processor, int peer) {
|
||||
@@ -88,8 +84,9 @@ public class EncryptProvider {
|
||||
return keyString.getBytes();
|
||||
}
|
||||
|
||||
// This will use only the processor which was chosen in chat menu
|
||||
// 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) {
|
||||
|
||||
String msgBody = getBody(msg);
|
||||
|
||||
Log.d("EncryptProvider", "encryptMessage: msg = " + msg);
|
||||
@@ -99,11 +96,11 @@ public class EncryptProvider {
|
||||
for (IMProcessor processor : processors) {
|
||||
int peer = getPeerId(msg);
|
||||
if (processor.isUsedToEncrypt(peer)) {
|
||||
return injectOwnText(processor.encode(msgBody, getKeyForProcessor(processor, peer)));
|
||||
return processor.encode(msgBody, getKeyForProcessor(processor, peer));
|
||||
}
|
||||
}
|
||||
|
||||
return injectOwnText(msgBody);
|
||||
return msgBody;
|
||||
}
|
||||
|
||||
// For rendering UI
|
||||
|
||||
@@ -8,7 +8,6 @@ import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||
import static ru.vtosters.lite.utils.ProxyUtils.apiproxy;
|
||||
import static ru.vtosters.lite.utils.ProxyUtils.getApi;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
@@ -23,7 +22,6 @@ 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;
|
||||
@@ -60,7 +58,7 @@ public class FoafBase {
|
||||
|
||||
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)));
|
||||
Date date = sdf.parse(matcher.group(1));
|
||||
sdf.setTimeZone(TimeZone.getDefault());
|
||||
return sdf.parse(sdf.format(date)).getTime() / 1000;
|
||||
}
|
||||
@@ -97,8 +95,8 @@ public class FoafBase {
|
||||
Matcher matcher2 = FOAF_REGEX_LOGIN.matcher(str);
|
||||
matcher.find();
|
||||
matcher2.find();
|
||||
String normalHumanDate = getNormalHumanDate(Objects.requireNonNull(matcher.group(1)));
|
||||
getNormalHumanDate(Objects.requireNonNull(matcher2.group(1)));
|
||||
String normalHumanDate = getNormalHumanDate(matcher.group(1));
|
||||
getNormalHumanDate(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) {
|
||||
@@ -109,7 +107,6 @@ public class FoafBase {
|
||||
|
||||
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) {
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
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.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 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;
|
||||
for (IMProcessor processor : EncryptProvider.processors) {
|
||||
if (processor.isUsedToEncrypt(peerId)) {
|
||||
enabled = processor;
|
||||
}
|
||||
}
|
||||
|
||||
if (enabled != null && enabled.isPublic()) {
|
||||
sendToast(getString("encryption_public_algorithm_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
IMProcessor finalEnabled = enabled;
|
||||
new AlertDialog.Builder(ctx)
|
||||
.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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package ru.vtosters.lite.hooks;
|
||||
|
||||
import com.vk.extensions.ViewExtKt;
|
||||
import com.vk.navigation.right.RightMenuPresenter;
|
||||
|
||||
import ru.vtosters.lite.ui.views.VTLCheckableButton;
|
||||
|
||||
public class DayNightButtonHook {
|
||||
|
||||
public static void injectOnClick(VTLCheckableButton button, RightMenuPresenter presenter) {
|
||||
button.postOnAnimationDelayed(() -> {
|
||||
var rect = ViewExtKt.e(button);
|
||||
presenter.a(new float[] { rect.centerX(), rect.centerY() });
|
||||
}, 550); // minimal delay for fix toggle animation
|
||||
button.toggle();
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ import java.util.Map;
|
||||
|
||||
import ru.vtosters.lite.ui.components.DockBarEditorManager;
|
||||
import ru.vtosters.lite.ui.items.DockBarTab;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
|
||||
public class DockBarInjector {
|
||||
private static final DockBarEditorManager sManager = DockBarEditorManager.getInstance();
|
||||
@@ -67,6 +68,7 @@ public class DockBarInjector {
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
public static void inject(BottomNavigationView navigationView) {
|
||||
navigationView.setBackgroundColor(ThemesUtils.getBackgroundContent());
|
||||
Menu menu = navigationView.getMenu();
|
||||
menu.clear();
|
||||
try {
|
||||
@@ -86,14 +88,11 @@ public class DockBarInjector {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for (DockBarTab tab : sManager.getSelectedTabs()) {
|
||||
MenuItem add = menu.add(0, tab.id, 0, tab.titleID);
|
||||
Drawable drawable = getResources().getDrawable(tab.iconID);
|
||||
for (DockBarTab tab : sManager.getSelectedTabs())
|
||||
menu.add(0, tab.id, 0, tab.titleID)
|
||||
.setIcon(tab.iconID)
|
||||
.setCheckable(true);
|
||||
|
||||
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++) {
|
||||
|
||||
@@ -2,7 +2,6 @@ package ru.vtosters.lite.hooks;
|
||||
|
||||
import static ru.vtosters.lite.foaf.FoafBase.getLastSeen;
|
||||
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;
|
||||
@@ -18,11 +17,14 @@ 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.ThemesUtils.accentColors;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getAccentColor;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.hex2;
|
||||
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.graphics.Color;
|
||||
import android.util.Log;
|
||||
|
||||
import com.vk.core.network.Network;
|
||||
@@ -35,8 +37,7 @@ import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -67,13 +68,24 @@ public class JsonInjectors {
|
||||
newItem.put(vktesters(id));
|
||||
}
|
||||
|
||||
// get text color from all items
|
||||
for (int i = 0; i < newItem.length(); i++) {
|
||||
var item = newItem.getJSONObject(i);
|
||||
if (item.has("text_color")) {
|
||||
var textColor = item.getString("text_color");
|
||||
if (accentColors.contains(Color.parseColor(textColor.startsWith("#") ? textColor : "#" + textColor))) {
|
||||
item.put("text_color", hex2(getAccentColor()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
orig.put("buttons", newItem);
|
||||
|
||||
return orig;
|
||||
}
|
||||
|
||||
public static JSONObject donateRecomm() throws JSONException {
|
||||
var title = AndroidUtils.getString("donate_to_vtl");
|
||||
var title = "Помоги проекту донатом и получи бонус!";
|
||||
var link = "https://vk.com/vtosters_official";
|
||||
var text_color = "2D81E0";
|
||||
|
||||
@@ -114,7 +126,7 @@ public class JsonInjectors {
|
||||
}
|
||||
|
||||
public static JSONObject vktesters(int id) throws JSONException {
|
||||
var title = AndroidUtils.getString("tester_profile");
|
||||
var title = "Карточка Тестера";
|
||||
var text_color = "2D81E0";
|
||||
var link = "https://static.vk.com/bugs?lang=" + LangUtils.a() + "#/reporter" + id;
|
||||
|
||||
@@ -158,7 +170,7 @@ public class JsonInjectors {
|
||||
var peerid = Objects.requireNonNull(orig.optJSONObject("peer")).optInt("id");
|
||||
|
||||
var pic = "https://image.pngaaa.com/641/326641-middle.png"; // can be null
|
||||
var text = AndroidUtils.getString("no_data_error");
|
||||
var text = "Я не загрузил данные (9(9((";
|
||||
var link = "https://vtosters.app"; // can be null
|
||||
var linktitle = "Test button"; // can be null
|
||||
|
||||
@@ -175,9 +187,9 @@ public class JsonInjectors {
|
||||
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("")) {
|
||||
if (getBoolValue("convBarRecomm", false)) {
|
||||
return null;
|
||||
@@ -375,37 +387,14 @@ public class JsonInjectors {
|
||||
}
|
||||
|
||||
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);
|
||||
for (int j = 0; j < items.length(); j++) {
|
||||
var list = items.optJSONObject(j);
|
||||
var name = list.optString("id");
|
||||
|
||||
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");
|
||||
if (!name.equals("kpop") && !name.equals("foryou") && !name.equals("qazaqstan")) {
|
||||
list.put("is_hidden", false).put("is_unavailable", false);
|
||||
if (dev()) Log.d("NewsfeedListInj", "Unlocked " + name + " in newsfeed list");
|
||||
}
|
||||
getDefaultPrefs().edit().putStringSet("news_feed_items_set", mutableFiltersSet)
|
||||
.apply();
|
||||
}
|
||||
|
||||
return items;
|
||||
@@ -554,7 +543,7 @@ public class JsonInjectors {
|
||||
|
||||
Log.d("VKMusic", "title: " + title + " id: " + id + " url: " + url + " value: " + value);
|
||||
|
||||
if (url.contains(value) && !value.isEmpty()) {
|
||||
if (url.contains(value)) {
|
||||
catalog.put("default_section", id);
|
||||
if (dev()) Log.d("VKMusic", "Added " + title + " as default music section");
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ 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;
|
||||
@@ -19,13 +18,11 @@ 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);
|
||||
@@ -37,7 +34,6 @@ public class MainActivityInjector {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannels.createChannels();
|
||||
}
|
||||
|
||||
// VKIDProtection.alert(activity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@ 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.vkme;
|
||||
|
||||
@@ -27,7 +23,6 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class NewsfeedHook {
|
||||
@@ -78,42 +73,4 @@ public class NewsfeedHook {
|
||||
}
|
||||
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");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ import org.json.JSONObject;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class OnlineFormatterHook {
|
||||
private static String AppName;
|
||||
|
||||
@@ -61,37 +59,37 @@ public class OnlineFormatterHook {
|
||||
case 5027722:
|
||||
return "VK Messenger (Desktop)";
|
||||
case 6146827:
|
||||
return AndroidUtils.getString("vk_messenger") + " (Android)"; // VK Мессенджер (Android)
|
||||
return "VK Мессенджер (Android)";
|
||||
case 6482950:
|
||||
return AndroidUtils.getString("vk_messenger") + " (iPhone)"; // VK Мессенджер (iPhone)
|
||||
return "VK Мессенджер (iPhone)";
|
||||
case 6481715:
|
||||
return AndroidUtils.getString("vk_messenger") + " Dev (iPhone)"; // VK Мессенджер Dev (iPhone)
|
||||
return "VK Мессенджер Dev (iPhone)";
|
||||
case 7799655:
|
||||
return AndroidUtils.getString("vk_mail_online"); // VK Почта
|
||||
return "VK Почта";
|
||||
case 7598572:
|
||||
return AndroidUtils.getString("sferum_online") + " (Android)"; // Сферум (Android)
|
||||
return "Сферум (Android)";
|
||||
case 7571751:
|
||||
return AndroidUtils.getString("sferum_online") + " (iPhone)"; // Сферум (iPhone)
|
||||
return "Сферум (iPhone)";
|
||||
case 7556576:
|
||||
return AndroidUtils.getString("sferum_online"); // Сферум
|
||||
return "Сферум";
|
||||
case 7497650:
|
||||
return "VK ID";
|
||||
case 8094476:
|
||||
return AndroidUtils.getString("vk_calls_online") + " (Android)"; // VK Звонки (Android)
|
||||
return "VK Звонки (Android)";
|
||||
case 8093730:
|
||||
return AndroidUtils.getString("vk_calls_online") + " (iPhone)"; // VK Звонки (iPhone)
|
||||
return "VK Звонки (iPhone)";
|
||||
case 7793118:
|
||||
return AndroidUtils.getString("vk_calls_online") + " (Desktop)"; // VK Звонки (Desktop)
|
||||
return "VK Звонки (Desktop)";
|
||||
case 6767438:
|
||||
return AndroidUtils.getString("vk_music_online") + " (Android)"; // VK Музыка (Android)
|
||||
return "VK Музыка (Android)";
|
||||
case 8113297:
|
||||
return AndroidUtils.getString("vk_clips_online") + " (Android)"; // VK Клипы (Android)
|
||||
return "VK Клипы (Android)";
|
||||
case 8106428:
|
||||
return AndroidUtils.getString("vk_clips_online") + " (iPhone)"; // VK Клипы (iPhone)
|
||||
return "VK Клипы (iPhone)";
|
||||
case 5044491:
|
||||
return "Candy";
|
||||
case 8114066:
|
||||
return AndroidUtils.getString("vk_video_online"); // VK Видео
|
||||
return "VK Видео";
|
||||
case 4894723:
|
||||
return "Phoenix Lite";
|
||||
case 4994316:
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -27,12 +27,11 @@ 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) {
|
||||
VkAuthTextView button = (VkAuthTextView) v;
|
||||
button.setText(AndroidUtils.getString("proxy_setup"));
|
||||
button.setText("Настроить прокси");
|
||||
button.setOnClickListener(v1 -> callProxyDialog(v1.getContext()));
|
||||
}
|
||||
|
||||
@@ -51,20 +50,20 @@ public class ProxyHook {
|
||||
|
||||
rg.setPadding(dp2px(18f), dp2px(12f), dp2px(18f), 0);
|
||||
|
||||
rgDefault.setText(AndroidUtils.getString("proxy_disable"));
|
||||
rgDefault.setText("Отключить");
|
||||
rgDefault.setTextColor(getTextAttr());
|
||||
|
||||
rgProxy.setText(AndroidUtils.getString("proxy_enable") + " (Zaborona)");
|
||||
rgProxy.setText("Включить (Zaborona)");
|
||||
rgProxy.setTextColor(getTextAttr());
|
||||
|
||||
rgProxy.setChecked(isZaboronaEnabled());
|
||||
rgDefault.setChecked(!isZaboronaEnabled());
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ctx, getAlertStyle());
|
||||
builder.setTitle(AndroidUtils.getString("vtlproxy"));
|
||||
builder.setMessage(AndroidUtils.getString("proxy_warning"));
|
||||
builder.setTitle("Прокси");
|
||||
builder.setMessage("Zaborona никак не связана с ВТостерс и мы не можем гарантировать её работу и безопасность");
|
||||
builder.setView(rg);
|
||||
builder.setPositiveButton(AndroidUtils.getString("vtl_confirm"), ((dialog, which) -> { // Применить
|
||||
builder.setPositiveButton("Применить", ((dialog, which) -> {
|
||||
if (rgProxy.isChecked()) {
|
||||
edit().putString("proxy", "zaborona").commit();
|
||||
restartApplication();
|
||||
@@ -78,7 +77,7 @@ public class ProxyHook {
|
||||
}
|
||||
}));
|
||||
|
||||
builder.setNeutralButton(AndroidUtils.getString("proxy_settings"), ((dialog, which) -> {
|
||||
builder.setNeutralButton("Настройки прокси", ((dialog, which) -> {
|
||||
Intent a2 = new Navigator(ProxySettingsFragment.class).b(ctx);
|
||||
a2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
ctx.startActivity(a2);
|
||||
|
||||
@@ -9,7 +9,7 @@ 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") ) {
|
||||
if (method.contains("execute.getGiftByStickerId")) {
|
||||
apiver = "5.187";
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ 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;
|
||||
|
||||
@@ -34,6 +33,8 @@ import com.vtosters.lite.fragments.y2.VideosFragment;
|
||||
import com.vtosters.lite.general.fragments.GamesFragment;
|
||||
import com.vtosters.lite.general.fragments.PhotosFragment;
|
||||
|
||||
import ru.vtosters.lite.ui.fragments.VTSettings;
|
||||
|
||||
public class StartFragmentHook {
|
||||
public static Class getStartFragment() {
|
||||
if (vkme()) {
|
||||
@@ -55,7 +56,7 @@ public class StartFragmentHook {
|
||||
case "videos":
|
||||
return videonewcatalog() ? VideoCatalogFragment.class : VideosFragment.class;
|
||||
case "settings":
|
||||
return useNewSettings();
|
||||
return VTSettings.class;
|
||||
case "apps":
|
||||
return AppsFragment.class;
|
||||
case "discover":
|
||||
|
||||
@@ -41,7 +41,7 @@ public class FFMpeg {
|
||||
private static void checkFFMpegLibs() {
|
||||
var lib = new File(AndroidUtils.getGlobalContext().getFilesDir(), "libffmpegkit_abidetect.so");
|
||||
if (!lib.exists()) {
|
||||
ToastUtils.a(AndroidUtils.getString("ffmpegkit_copy"));
|
||||
ToastUtils.a("Копирование библиотеки ffmpegkit");
|
||||
copyAssets();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
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;
|
||||
@@ -34,7 +29,7 @@ public class MP3Downloader {
|
||||
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();
|
||||
Toast.makeText(AndroidUtils.getGlobalContext(), "Обновите токен VK Admin в настройках", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
var request = new Request.a()
|
||||
@@ -58,10 +53,12 @@ public class MP3Downloader {
|
||||
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);
|
||||
if (url != null) {
|
||||
if (url.endsWith(".mp3")) {
|
||||
downloadMP3(track.toString(), url);
|
||||
} else if (VKM3UParser.isM3U8(url)) {
|
||||
AudioDownloader.downloadM3U8(track);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,14 +69,13 @@ public class MP3Downloader {
|
||||
});
|
||||
}
|
||||
|
||||
@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(),
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath(),
|
||||
title + ".mp3")
|
||||
.setVisibleInDownloadsUi(true);
|
||||
downloadManager.enqueue(request);
|
||||
|
||||
@@ -24,7 +24,6 @@ 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";
|
||||
@@ -104,7 +103,7 @@ public class Scrobbler {
|
||||
|
||||
public static void auth(String login, String pass) {
|
||||
if (login == null || pass == null) {
|
||||
sendToast(AndroidUtils.getString("lastfm_credentials_empty"));
|
||||
sendToast("Логин или пароль не заданы");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -120,7 +119,7 @@ public class Scrobbler {
|
||||
@Override
|
||||
public void onFailure(NetCall call, IOException e) {
|
||||
Log.d("Scrobbler", "Auth failed", e);
|
||||
sendToast(AndroidUtils.getString("lastfm_auth_error"));
|
||||
sendToast("Ошибка входа");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,7 +155,7 @@ public class Scrobbler {
|
||||
edit().remove("username").apply();
|
||||
edit().remove("sessionKey").apply();
|
||||
scrobbled.clear();
|
||||
sendToast(AndroidUtils.getString("lastfm_logout_success"));
|
||||
sendToast("Вы успешно вышли из учетной записи");
|
||||
}
|
||||
|
||||
public static boolean needToBeScrobble(String uid) {
|
||||
|
||||
@@ -22,8 +22,6 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class LogWriterService extends Service {
|
||||
public LogWriterService() {
|
||||
}
|
||||
@@ -46,12 +44,12 @@ public class LogWriterService extends Service {
|
||||
writeLog(intent, file);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
makeText(getGlobalContext(), AndroidUtils.getString("logfile_error"), LENGTH_SHORT).show();
|
||||
makeText(getGlobalContext(), "Не удалось сохранить лог-файл", LENGTH_SHORT).show();
|
||||
}
|
||||
var notificationId = intent.getIntExtra("notificationId", 1);
|
||||
var manager = (NotificationManager) getGlobalContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
manager.cancel(notificationId);
|
||||
makeText(getGlobalContext(), AndroidUtils.getString("logfile_saved"), LENGTH_SHORT).show();
|
||||
makeText(getGlobalContext(), "Лог-файл был сохранен", LENGTH_SHORT).show();
|
||||
|
||||
stopSelf();
|
||||
return START_NOT_STICKY;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package ru.vtosters.lite.themes;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import com.vk.core.view.TintTextView;
|
||||
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
|
||||
public class Recolor {
|
||||
|
||||
private static int getColor(int original) {
|
||||
var color = VTLColors.getColor(original);
|
||||
if (color != -1) return color;
|
||||
return original;
|
||||
}
|
||||
|
||||
public static void recolorToolbar(Toolbar toolbar) {
|
||||
if (ThemesUtils.isCustomThemeApplied())
|
||||
toolbar.setBackgroundColor(ThemesUtils.getHeaderBackground());
|
||||
}
|
||||
|
||||
public static void recolorIconToAccent(ImageView iv) {
|
||||
if (ThemesUtils.isCustomThemeApplied())
|
||||
iv.setImageTintList(ColorStateList.valueOf(VTLColors.getAccentColor()));
|
||||
}
|
||||
|
||||
public static void recolorTextToAccent(TextView iv) {
|
||||
iv.setTextColor(VTLColors.getAccentColor());
|
||||
}
|
||||
|
||||
public static void recolorTintTextViewToAccent(TintTextView ttv) {
|
||||
ttv.setDrawableTint(VTLColors.getAccentColor());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package ru.vtosters.lite.themes;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.vk.core.ui.themes.VKThemeHelper;
|
||||
import com.vk.core.util.ContextExtKt;
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import ru.vtosters.lite.themes.managers.ThemesManager;
|
||||
import ru.vtosters.lite.themes.models.ThemeModel;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.Preferences;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
|
||||
public class VTLColors {
|
||||
private static final ThemesManager themesManager = ThemesManager.getInstance();
|
||||
private static final ThemeModel currentTheme = themesManager.getCurrentTheme();
|
||||
|
||||
public static int getAccentColor() {
|
||||
return getColor(R.attr.accent, R.attr.accentColor, R.attr.colorAccent, R.attr.vk_accent);
|
||||
}
|
||||
|
||||
public static int getTextPrimaryColor() {
|
||||
return getColor(R.attr.text_primary);
|
||||
}
|
||||
|
||||
public static int getTextSecondaryColor() {
|
||||
return getColor(R.attr.text_secondary);
|
||||
}
|
||||
|
||||
public static int getTabbarBackground() {
|
||||
return getColor(R.attr.tabbar_background);
|
||||
}
|
||||
|
||||
public static int getTabbarActiveColor() {
|
||||
if (ThemesUtils.isCustomThemeApplied())
|
||||
return getColor(R.attr.tabbar_active_icon);
|
||||
return Preferences.dockbar_accent()
|
||||
? getAccentColor()
|
||||
: AndroidUtils.getResources().getColor(ThemesUtils.isDarkTheme() ? R.color.white : R.color.gray_700);
|
||||
}
|
||||
|
||||
public static int getTabbarInactiveColor() {
|
||||
if (ThemesUtils.isCustomThemeApplied())
|
||||
return getColor(R.attr.tabbar_inactive_icon);
|
||||
return AndroidUtils.getResources().getColor(ThemesUtils.isDarkTheme() ? R.color.gray_500 : R.color.vk_steel_gray_300);
|
||||
}
|
||||
|
||||
public static int getBackgroundContent() {
|
||||
return getColor(R.attr.background_content);
|
||||
}
|
||||
|
||||
public static int getBackgroundPage() {
|
||||
return getColor(R.attr.background_page);
|
||||
}
|
||||
|
||||
public static int getHeaderBackground() {
|
||||
return getColor(R.attr.header_background);
|
||||
}
|
||||
|
||||
public static int getHeaderText() {
|
||||
return getColor(R.attr.header_text);
|
||||
}
|
||||
|
||||
//region Hooks
|
||||
|
||||
public static int getColor(int... attrs) {
|
||||
return getColor(attrs[0]);
|
||||
}
|
||||
|
||||
public static int getColor(int attr) {
|
||||
if (ThemesUtils.isCustomThemeApplied()) {
|
||||
int color = currentTheme.getColor(attr);
|
||||
if (color != -1)
|
||||
return color;
|
||||
}
|
||||
return VKThemeHelper.d(attr);
|
||||
}
|
||||
|
||||
public static int getColor(Context context, int colorId) {
|
||||
try {
|
||||
Log.d("VTLColors", "getColor(Landroid/content/Context;I): " + AndroidUtils.getResources().getResourceEntryName(colorId));
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
if (ThemesUtils.isCustomThemeApplied()) {
|
||||
int color = currentTheme.getColor(colorId);
|
||||
if (color != -1)
|
||||
return color;
|
||||
}
|
||||
return ContextExtKt.h(context, colorId);
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package ru.vtosters.lite.themes;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import ru.vtosters.lite.themes.managers.ThemesManager;
|
||||
import ru.vtosters.lite.utils.ReflectionUtils;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
|
||||
public class VTLResources {
|
||||
private static final int STYLE_NUM_ENTRIES = Build.VERSION.SDK_INT >= 29 ? 7 : 6;
|
||||
public static final SparseIntArray forcedAttrs = new SparseIntArray();
|
||||
public static final SparseIntArray otherAttrs = new SparseIntArray();
|
||||
|
||||
private static Field dataField;
|
||||
|
||||
static {
|
||||
try {
|
||||
dataField = ReflectionUtils.getDeclaredField(TypedArray.class, "mData");
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
otherAttrs.put(R.attr.vklib_alv_optionIconTint, R.attr.im_dropdown_icon_color);
|
||||
otherAttrs.put(R.attr.vkim_colorPrimary, R.attr.accent);
|
||||
otherAttrs.put(R.attr.statusBarColorBack, R.attr.statusBarColorBack);
|
||||
otherAttrs.put(R.attr.statusBarColorFront, R.attr.statusBarColorFront);
|
||||
// android attributes
|
||||
otherAttrs.put(android.R.attr.backgroundTint, R.attr.accent);
|
||||
otherAttrs.put(android.R.attr.tint, R.attr.accent);
|
||||
otherAttrs.put(android.R.attr.color, R.attr.accent);
|
||||
|
||||
forcedAttrs.put(-0x8e5515, R.attr.accent);
|
||||
forcedAttrs.put(-0xe6e6e6, R.attr.background_content);
|
||||
}
|
||||
|
||||
public static void prepareTypedArray(TypedArray target, int[] attrs) {
|
||||
if (!ThemesUtils.isCustomThemeApplied() || attrs == null) return;
|
||||
var theme = ThemesManager.getInstance().getCurrentTheme();
|
||||
var data = getData(target);
|
||||
for (int i = 0; i < attrs.length; i++) {
|
||||
//var attr = attrs[i];
|
||||
var off = STYLE_NUM_ENTRIES * i;
|
||||
var type = data[off];
|
||||
var replacement = -1;
|
||||
if (type == TypedValue.TYPE_ATTRIBUTE) {
|
||||
replacement = theme.getColor(data[off + 0x1]);
|
||||
} else if (type == TypedValue.TYPE_INT_COLOR_ARGB8 || type == TypedValue.TYPE_INT_COLOR_RGB8) {
|
||||
replacement = forcedAttrs.get(data[off + 0x1], -1);
|
||||
if (replacement == -1
|
||||
&& ThemesUtils.accentColors.contains(data[off + 0x1]))
|
||||
replacement = ThemesUtils.getAccentColor();
|
||||
}
|
||||
if (replacement == -1) continue;
|
||||
try {
|
||||
data[off] = TypedValue.TYPE_INT_COLOR_RGB8; // type
|
||||
data[off + 0x1] = replacement; // data
|
||||
data[off + 0x2] = 0x0; // asset cookie
|
||||
data[off + 0x3] = 0x0; // resource id
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int[] getData(TypedArray target) {
|
||||
try {
|
||||
return (int[]) dataField.get(target);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
//region Hooks
|
||||
|
||||
public static TypedArray obtainStyledAttributes(Context context, int[] attrs) {
|
||||
var target = context.obtainStyledAttributes(attrs);
|
||||
prepareTypedArray(target, attrs);
|
||||
return target;
|
||||
}
|
||||
|
||||
public static TypedArray obtainStyledAttributes(Context context, int resId, int[] attrs) {
|
||||
var target = context.obtainStyledAttributes(resId, attrs);
|
||||
prepareTypedArray(target, attrs);
|
||||
return target;
|
||||
}
|
||||
|
||||
public static TypedArray obtainStyledAttributes(Context context, AttributeSet set, int[] attrs) {
|
||||
var target = context.obtainStyledAttributes(set, attrs);
|
||||
prepareTypedArray(target, attrs);
|
||||
return target;
|
||||
}
|
||||
|
||||
public static TypedArray obtainStyledAttributes(Context context, AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
|
||||
var target = context.obtainStyledAttributes(set, attrs, defStyleAttr, defStyleRes);
|
||||
prepareTypedArray(target, attrs);
|
||||
return target;
|
||||
}
|
||||
|
||||
public static int getColor(Resources res, int colorId) {
|
||||
return VTLColors.getColor(colorId);//res.getColor(colorId);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public static int getColor(Resources res, int colorId, Resources.Theme theme) {
|
||||
return VTLColors.getColor(colorId);
|
||||
}
|
||||
|
||||
@SuppressLint("UseCompatLoadingForColorStateLists")
|
||||
public static ColorStateList getColorStateList(Resources res, int colorId) {
|
||||
if (ThemesUtils.isCustomThemeApplied()) {
|
||||
int color = VTLColors.getColor(colorId);
|
||||
if (color != -1)
|
||||
return ColorStateList.valueOf(color);
|
||||
}
|
||||
return res.getColorStateList(colorId);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public static ColorStateList getColorStateList(Resources res, int colorId, Resources.Theme theme) {
|
||||
if (ThemesUtils.isCustomThemeApplied()) {
|
||||
int color = VTLColors.getColor(colorId);
|
||||
if (color != -1)
|
||||
return ColorStateList.valueOf(color);
|
||||
}
|
||||
return res.getColorStateList(colorId, theme);
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package ru.vtosters.lite.themes.managers;
|
||||
|
||||
import android.os.Environment;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ru.vtosters.lite.themes.models.PaletteModel;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.IOUtils;
|
||||
|
||||
public class PalettesManager {
|
||||
|
||||
private static PalettesManager instance;
|
||||
|
||||
private static File palettesDir = new File(Environment.getExternalStorageDirectory(), "VTL/themes/palettes");
|
||||
|
||||
private List<PaletteModel> palettes = new ArrayList<>();
|
||||
|
||||
public static PalettesManager getInstance() {
|
||||
if (instance == null)
|
||||
instance = new PalettesManager();
|
||||
return instance;
|
||||
}
|
||||
|
||||
public PalettesManager() {
|
||||
load();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
palettes.clear();
|
||||
if (!palettesDir.exists())
|
||||
palettesDir.mkdirs();
|
||||
final var palettes = palettesDir.listFiles((dir, name) -> name.endsWith(".json"));
|
||||
var check = true;
|
||||
if (palettes == null || palettes.length == 0)
|
||||
check = copyPaletteFromAssets();
|
||||
if (check)
|
||||
parsePalettes();
|
||||
}
|
||||
|
||||
private boolean copyPaletteFromAssets() {
|
||||
try {
|
||||
final var manager = AndroidUtils.getGlobalContext().getAssets();
|
||||
final var assets = manager.list("vtl_themes/palettes/");
|
||||
if (assets == null || assets.length == 0) return false;
|
||||
var i = 0;
|
||||
for (var asset : assets) {
|
||||
try {
|
||||
IOUtils.copyFile(manager.open("vtl_themes/palettes/" + asset), new File(palettesDir, asset));
|
||||
i++;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return i > 0;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void parsePalettes() {
|
||||
var arr = palettesDir.listFiles((dir, name) -> name.endsWith(".json"));
|
||||
if (arr == null || arr.length == 0)
|
||||
throw new RuntimeException("Can't load palettes");
|
||||
for (var file : arr) {
|
||||
try {
|
||||
var json = new JSONObject(IOUtils.readAllLines(file));
|
||||
palettes.add(PaletteModel.fromJson(json));
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PaletteModel getPalette(String id) {
|
||||
for (PaletteModel palette : palettes) {
|
||||
if (id.equals(palette.id))
|
||||
return palette;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public PaletteModel getPalette(int i) {
|
||||
return palettes.get(i);
|
||||
}
|
||||
|
||||
public int getPalettesCount() {
|
||||
return palettes.size();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
package ru.vtosters.lite.themes.managers;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.os.StrictMode;
|
||||
import android.util.Log;
|
||||
|
||||
import com.vtosters.lite.auth.VKAccountManager;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import ru.vtosters.lite.ui.dialogs.ThemesEditorBottomSheetDialog;
|
||||
import ru.vtosters.lite.themes.models.ThemeModel;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.IOUtils;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
|
||||
public class ThemesManager {
|
||||
|
||||
private static File themesDir;
|
||||
private static ThemesManager instance;
|
||||
private static ThemeModel currentTheme = null;
|
||||
private List<ThemeModel> themes = new ArrayList<>();
|
||||
|
||||
public static ThemesManager getInstance() {
|
||||
if (instance == null)
|
||||
instance = new ThemesManager();
|
||||
return instance;
|
||||
}
|
||||
|
||||
public ThemesManager() {
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
themes = new ArrayList<>();
|
||||
currentTheme = new ThemeModel().setName("Тема по умолчанию")
|
||||
.setAuthor("Разработчики ВК")
|
||||
.setDarkMode(ThemesUtils.isDarkTheme())
|
||||
.setId("default");
|
||||
themes.add(currentTheme);
|
||||
themesDir = new File(Environment.getExternalStorageDirectory(), "VTL/themes");
|
||||
if (!themesDir.exists()) {
|
||||
themesDir.mkdirs();
|
||||
return;
|
||||
}
|
||||
// Support themes from Sova V RE (.svt)
|
||||
var files = themesDir.listFiles((dir, name) -> name.endsWith(".vtlt") || name.endsWith(".svt") || name.endsWith(".json"));
|
||||
if (files == null || files.length == 0)
|
||||
return;
|
||||
var currentThemeId = AndroidUtils.getPreferences().getString("vtl_theme_id", "default");
|
||||
for (File file : files) {
|
||||
try {
|
||||
ThemeModel theme;
|
||||
var abs = file.getAbsolutePath();
|
||||
if (abs.endsWith(".svt") || abs.endsWith(".json"))
|
||||
theme = svt2vtlt(file);
|
||||
else
|
||||
theme = read(file);
|
||||
if (theme != null) {
|
||||
Log.d("ThemesManager", theme.toString());
|
||||
if (currentThemeId.equals(theme.id))
|
||||
currentTheme = theme;
|
||||
themes.add(theme);
|
||||
}
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ("default".equals(currentTheme.id))
|
||||
setTheme(currentTheme);
|
||||
}
|
||||
|
||||
private ThemeModel svt2vtlt(File file) {
|
||||
try {
|
||||
var theme = read(file);
|
||||
save(theme);
|
||||
return theme;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
init();
|
||||
}
|
||||
|
||||
public File getThemeFile(ThemeModel theme) throws IOException {
|
||||
if (!themesDir.exists()) {
|
||||
themesDir.mkdirs();
|
||||
throw new FileNotFoundException("theme file not found");
|
||||
}
|
||||
|
||||
var themeFile = new File(themesDir, theme.id + ".svt");
|
||||
if (!themeFile.exists()) {
|
||||
themeFile = new File(themesDir, theme.id + ".vtlt");
|
||||
if (!themeFile.exists())
|
||||
themeFile.createNewFile();
|
||||
}
|
||||
|
||||
return themeFile;
|
||||
}
|
||||
|
||||
public void setTheme(ThemeModel theme) {
|
||||
AndroidUtils.getPreferences()
|
||||
.edit()
|
||||
.putString("vtl_theme_id", theme.id)
|
||||
.commit();
|
||||
}
|
||||
|
||||
public ThemeModel getTheme(int i) {
|
||||
return themes.get(i);
|
||||
}
|
||||
|
||||
public ThemeModel getCurrentTheme() {
|
||||
return currentTheme;
|
||||
}
|
||||
|
||||
public int getThemesCount() {
|
||||
return themes.size();
|
||||
}
|
||||
|
||||
public boolean isCurrentTheme(ThemeModel theme) {
|
||||
return currentTheme.id.equals(theme.id);
|
||||
}
|
||||
|
||||
public boolean hasTheme(ThemeModel theme) {
|
||||
return hasTheme(theme.id);
|
||||
}
|
||||
|
||||
public boolean hasTheme(String id) {
|
||||
for (ThemeModel theme : themes) {
|
||||
if (id.equals(theme.id))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Theme file storing method from Sova V RE is storing json clearly or compressed with gzip.
|
||||
* If first byte byte is 0x1 or 0x2 json has been compressed with gzip,
|
||||
* but if first byte is 0x2 next int is length of json string. */
|
||||
|
||||
private ThemeModel read(InputStream fis) throws IOException, JSONException {
|
||||
InputStream is = fis;
|
||||
var first = is.read();
|
||||
if (first > 0x0 && first < 0x3) {
|
||||
var gzis = new GZIPInputStream(is);
|
||||
var dis = new DataInputStream(gzis);
|
||||
if (first == 0x2)
|
||||
dis.readInt();
|
||||
is = dis;
|
||||
}
|
||||
return ThemeModel.fromJson(IOUtils.readAllLines(is));
|
||||
}
|
||||
|
||||
private ThemeModel read(File file) throws IOException, JSONException {
|
||||
return read(new FileInputStream(file));
|
||||
}
|
||||
|
||||
public void save(ThemeModel theme) throws IOException, JSONException {
|
||||
var buffer = theme.toJson().toString().getBytes(StandardCharsets.UTF_8);
|
||||
var fos = new FileOutputStream(getThemeFile(theme));
|
||||
// writing with data length
|
||||
fos.write(0x2);
|
||||
var gzos = new GZIPOutputStream(fos);
|
||||
var dos = new DataOutputStream(gzos);
|
||||
dos.writeInt(buffer.length);
|
||||
dos.write(buffer);
|
||||
dos.close();
|
||||
}
|
||||
|
||||
public void delete(ThemeModel theme) {
|
||||
try {
|
||||
getThemeFile(theme).delete();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
themes.remove(theme);
|
||||
if (isCurrentTheme(theme)) {
|
||||
setTheme(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void create(Activity activity, String name) throws JSONException, IOException {
|
||||
var id = name.toLowerCase().replace(" ", "-");
|
||||
if (hasTheme(id)) {
|
||||
var i = 1;
|
||||
while (hasTheme(id + "-" + i)) {
|
||||
i++;
|
||||
}
|
||||
id += "-" + i;
|
||||
}
|
||||
var userProfile = VKAccountManager.d().e1();
|
||||
ThemeModel theme = new ThemeModel()
|
||||
.setName(name)
|
||||
.setAuthor(userProfile.c + " " + userProfile.e)
|
||||
.setDarkMode(true)
|
||||
// .setColors(DEFAULT_COLORS)
|
||||
.setId(id);
|
||||
themes.add(theme);
|
||||
ThemesEditorBottomSheetDialog.create(activity, theme, false);
|
||||
save(theme);
|
||||
}
|
||||
|
||||
public void copy(ContentResolver contentResolver, Uri uri) throws IOException, JSONException {
|
||||
var theme = read(contentResolver.openInputStream(uri));
|
||||
if (isCurrentTheme(theme)) {
|
||||
int i = 1;
|
||||
while (hasTheme(theme.id + "-" + i)) {
|
||||
i++;
|
||||
}
|
||||
theme.id += "-" + i;
|
||||
}
|
||||
themes.add(theme);
|
||||
save(theme);
|
||||
}
|
||||
|
||||
public void share(Context context, ThemeModel theme) throws Exception {
|
||||
var vmPolicy = StrictMode.getVmPolicy();
|
||||
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build());
|
||||
var intent = new Intent(Intent.ACTION_SEND)
|
||||
.setType("file/*")
|
||||
.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(getThemeFile(theme)));
|
||||
context.startActivity(Intent.createChooser(intent, ""));
|
||||
StrictMode.setVmPolicy(vmPolicy);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package ru.vtosters.lite.themes.models;
|
||||
|
||||
public class ColorModel {
|
||||
|
||||
public String resName;
|
||||
public int id;
|
||||
public int color;
|
||||
|
||||
public ColorModel(int id, int color) {
|
||||
this.id = id;
|
||||
this.color = color;
|
||||
}
|
||||
public ColorModel(String resName, int id, int color) {
|
||||
this.resName = resName;
|
||||
this.id = id;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public static ColorModel create(int id, int color) {
|
||||
return new ColorModel(id, color);
|
||||
}
|
||||
|
||||
public static ColorModel create(String resName, int id, int color) {
|
||||
return new ColorModel(resName, id, color);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package ru.vtosters.lite.themes.models;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PaletteModel {
|
||||
public String id;
|
||||
public String name;
|
||||
public String author;
|
||||
public List<ColorModel> colors = new ArrayList<>();
|
||||
|
||||
public PaletteModel() {
|
||||
|
||||
}
|
||||
|
||||
public PaletteModel(String id, String name, String author, List<ColorModel> colors) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.author = author;
|
||||
this.colors = colors;
|
||||
}
|
||||
|
||||
public PaletteModel setId(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaletteModel setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaletteModel setAuthor(String author) {
|
||||
this.author = author;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaletteModel setColors(List<ColorModel> colors) {
|
||||
this.colors = colors;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaletteModel setColor(String name, int color) {
|
||||
this.colors.add(new ColorModel(name, 0, color));
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getColor(String name) {
|
||||
for (var item : colors)
|
||||
if (name.equals(item.resName))
|
||||
return item.color;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static PaletteModel fromJson(JSONObject json) throws JSONException {
|
||||
var palette = new PaletteModel()
|
||||
.setId(json.optString("palette_id"))
|
||||
.setName(json.optString("name"))
|
||||
.setAuthor(json.optString("author"));
|
||||
var paletteNode = json.getJSONArray("palette");
|
||||
for (int i = 0; i < paletteNode.length(); i++) {
|
||||
var colorNode = paletteNode.getJSONObject(i);
|
||||
var name = colorNode.getString("name");
|
||||
if (colorNode.has("colors")) {
|
||||
var colorsNode = colorNode.getJSONArray("colors");
|
||||
for (int j = 0; j < colorsNode.length(); j++) {
|
||||
var subColorNode = colorsNode.getJSONObject(j);
|
||||
var index = subColorNode.getString("index");
|
||||
var subColor = subColorNode.getString("color");
|
||||
if (!subColor.startsWith("#")) subColor = "#" + subColor;
|
||||
palette.setColor(name + " " + index, Color.parseColor(subColor));
|
||||
}
|
||||
} else {
|
||||
var color = colorNode.getString("color");
|
||||
if (!color.startsWith("#")) color = "#" + color;
|
||||
palette.setColor(name, Color.parseColor(color));
|
||||
}
|
||||
}
|
||||
return palette;
|
||||
}
|
||||
|
||||
public static PaletteModel valuesOf(String id, String name, String author, List<ColorModel> colors) {
|
||||
return new PaletteModel()
|
||||
.setId(id)
|
||||
.setName(name)
|
||||
.setAuthor(author)
|
||||
.setColors(colors);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package ru.vtosters.lite.themes.models;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ru.vtosters.lite.themes.managers.PalettesManager;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class ThemeModel {
|
||||
|
||||
public String author;
|
||||
public String name;
|
||||
public boolean isDarkMode;
|
||||
public String id;
|
||||
public List<ColorModel> colors = new ArrayList<>();
|
||||
|
||||
public ThemeModel() {
|
||||
}
|
||||
|
||||
public ThemeModel(String author, String name, boolean darkMode, String id, List<ColorModel> colors) {
|
||||
this.author = author;
|
||||
this.name = name;
|
||||
this.isDarkMode = darkMode;
|
||||
this.id = id;
|
||||
this.colors = colors;
|
||||
}
|
||||
|
||||
public ThemeModel setAuthor(String author) {
|
||||
this.author = author;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThemeModel setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThemeModel setDarkMode(boolean b) {
|
||||
this.isDarkMode = b;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThemeModel setId(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThemeModel setColors(List<ColorModel> colors) {
|
||||
this.colors = colors;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ThemeModel setColor(int attrId, int color) {
|
||||
this.colors.add(new ColorModel(attrId, color));
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getColor(int attrId) {
|
||||
for (var item : colors)
|
||||
if (attrId == item.id)
|
||||
return item.color;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static ThemeModel valuesOf(String author, String name, boolean darkMode, String id, List<ColorModel> colors) {
|
||||
var theme = new ThemeModel()
|
||||
.setAuthor(author)
|
||||
.setName(name)
|
||||
.setDarkMode(darkMode)
|
||||
.setId(id)
|
||||
.setColors(colors);
|
||||
return theme;
|
||||
}
|
||||
|
||||
public static ThemeModel fromJson(String json) throws JSONException {
|
||||
return fromJson(new JSONObject(json));
|
||||
}
|
||||
|
||||
public static ThemeModel fromJson(JSONObject json) {
|
||||
List<String> palettes;
|
||||
if (json.has("palettes")) {
|
||||
palettes = new ArrayList<>();
|
||||
var arr = json.optString("palettes")
|
||||
.split("\\||,|&|;");
|
||||
Collections.addAll(palettes, arr);
|
||||
}
|
||||
List<ColorModel> colors = new ArrayList<>();
|
||||
var colorsJson = json.optJSONObject("colors");
|
||||
var names = colorsJson.names();
|
||||
for (int i = 0; i < colorsJson.length(); i++) {
|
||||
var name = names.optString(i);
|
||||
var value = colorsJson.optString(name);
|
||||
int attrId;
|
||||
try {
|
||||
attrId = AndroidUtils.getIdentifier(name, "attr");
|
||||
} catch (Resources.NotFoundException e) {
|
||||
attrId = AndroidUtils.getIdentifier(name, "color");
|
||||
}
|
||||
final int color;
|
||||
if (value.contains(".")) {
|
||||
var paletteId = value.substring(0, value.indexOf("."));
|
||||
var palette = PalettesManager.getInstance().getPalette(paletteId);
|
||||
var paletteColor = value.substring(value.indexOf(".") + 1);
|
||||
color = palette.getColor(paletteColor);
|
||||
} else {
|
||||
color = Color.parseColor(value.startsWith("#") ? value : "#" + value);
|
||||
}
|
||||
colors.add(new ColorModel(name, attrId, color));
|
||||
}
|
||||
return valuesOf(
|
||||
json.optString("author"),
|
||||
json.optString("name"),
|
||||
json.optBoolean("dark"),
|
||||
json.optString("id"),
|
||||
colors
|
||||
);
|
||||
}
|
||||
|
||||
public JSONObject toJson() throws JSONException {
|
||||
var colorsJson = new JSONObject();
|
||||
for (var item : colors)
|
||||
colorsJson.put(item.resName, Integer.toHexString(item.color).toUpperCase());
|
||||
return new JSONObject()
|
||||
.put("author", this.author)
|
||||
.put("name", this.name)
|
||||
.put("dark", this.isDarkMode)
|
||||
.put("id", this.id)
|
||||
.put("colors", colorsJson);
|
||||
}
|
||||
|
||||
public ThemeModel clone() {
|
||||
return new ThemeModel(
|
||||
author,
|
||||
name,
|
||||
isDarkMode,
|
||||
id,
|
||||
colors.stream()
|
||||
.map(colorModel -> new ColorModel(colorModel.resName, colorModel.id, colorModel.color))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package ru.vtosters.lite.themes.models;
|
||||
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ViewModel {
|
||||
|
||||
@IdRes public int id;
|
||||
public List<Pair<Integer, Integer>> attrs = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package ru.vtosters.lite.themes.proxy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.annotation.XmlRes;
|
||||
|
||||
import ru.vtosters.lite.themes.VTLResources;
|
||||
import ru.vtosters.lite.themes.managers.ThemesManager;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
|
||||
public class ProxyResources extends Resources {
|
||||
|
||||
private final Resources mOriginalResource;
|
||||
|
||||
public ProxyResources(Context context, Resources original) {
|
||||
this(original);
|
||||
}
|
||||
|
||||
public ProxyResources(Resources original) {
|
||||
super(original.getAssets(), original.getDisplayMetrics(), original.getConfiguration());
|
||||
mOriginalResource = original;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor(int id, @Nullable Resources.Theme theme) throws Resources.NotFoundException {
|
||||
if (ThemesUtils.isCustomThemeApplied()) {
|
||||
var color = ThemesManager.getInstance().getCurrentTheme().getColor(id);
|
||||
if (color != -1)
|
||||
return color;
|
||||
}
|
||||
return mOriginalResource.getColor(id, theme);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||
@NonNull
|
||||
@Override
|
||||
public ColorStateList getColorStateList(@XmlRes int id, @Nullable Resources.Theme theme)
|
||||
throws Resources.NotFoundException {
|
||||
var target = mOriginalResource.getColorStateList(id, theme);
|
||||
if (ThemesUtils.isCustomThemeApplied() && ThemesUtils.isAccentedColor(target)) {
|
||||
return ColorStateList.valueOf(ThemesUtils.getAccentColor());
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Drawable getDrawableForDensity(int id, int density, @Nullable Resources.Theme theme) {
|
||||
return mOriginalResource.getDrawableForDensity(id, density, theme);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
|
||||
var ta = super.obtainAttributes(set, attrs);
|
||||
VTLResources.prepareTypedArray(ta, attrs);
|
||||
return ta;
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,6 @@ import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class APKInstallActivity extends AppCompatActivity {
|
||||
public static final int REQUEST_INSTALL_PERMISSION = 1;
|
||||
|
||||
@@ -67,7 +65,7 @@ public class APKInstallActivity extends AppCompatActivity {
|
||||
|
||||
startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(this, AndroidUtils.getString("apk_install_error") + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(this, "Ошибка установки обновления " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
finish();
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package ru.vtosters.lite.ui.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuInflater;
|
||||
|
||||
import com.vk.core.ui.themes.ThemableActivity;
|
||||
|
||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
||||
|
||||
public class VTLThemableActivity extends ThemableActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
LifecycleUtils.addActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
LifecycleUtils.removeActivity(this);
|
||||
}
|
||||
}
|
||||
@@ -34,10 +34,10 @@ public class CategorizedAdapter extends RecyclerView.Adapter<CategorizedAdapter.
|
||||
public static final int SELECTED_STATE = -0x1;
|
||||
public static final int DISABLED_STATE = -0x2;
|
||||
|
||||
private final List mSelectedItems;
|
||||
private final List mDisabledItems;
|
||||
private final List mUnmovedItems;
|
||||
private final IViewHolderBinder mBinder;
|
||||
private List mSelectedItems;
|
||||
private List mDisabledItems;
|
||||
private List mUnmovedItems;
|
||||
private IViewHolderBinder mBinder;
|
||||
|
||||
private int mMinSelectedItems = -1;
|
||||
private int mMaxSelectedItems = -1;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package ru.vtosters.lite.ui.adapters;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.vk.core.drawable.BorderDrawable;
|
||||
import com.vk.core.util.Screen;
|
||||
import com.vk.stories.view.StoryCircleImageView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ru.vtosters.lite.themes.models.ColorModel;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
|
||||
public class ColorPickerAdapter extends RecyclerView.Adapter<ColorPickerAdapter.ColorPickerViewHolder> {
|
||||
|
||||
private List<ColorModel> mColors;
|
||||
private OnColorSelectListener mSelectListener;
|
||||
|
||||
public ColorPickerAdapter(List<ColorModel> colors, OnColorSelectListener selectListener) {
|
||||
this.mColors = colors;
|
||||
this.mSelectListener = selectListener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ColorPickerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
var container = LayoutInflater.from(parent.getContext())
|
||||
.inflate(AndroidUtils.getIdentifier("color_picker_item", "layout"), parent, false);
|
||||
return new ColorPickerViewHolder(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ColorPickerViewHolder holder, int pos) {
|
||||
holder.bind(mColors.get(pos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mColors.size();
|
||||
}
|
||||
|
||||
public class ColorPickerViewHolder extends RecyclerView.ViewHolder {
|
||||
private View mContainer;
|
||||
private FrameLayout mColorPreviewBorder;
|
||||
private StoryCircleImageView mColorPreview;
|
||||
private TextView mColorName;
|
||||
private TextView mColorValue;
|
||||
|
||||
public ColorPickerViewHolder(@NonNull View view) {
|
||||
super(view);
|
||||
|
||||
mContainer = view;
|
||||
mColorPreviewBorder = view.findViewById(AndroidUtils.getIdentifier("color_preview_border", "id"));
|
||||
mColorPreview = view.findViewById(AndroidUtils.getIdentifier("color_preview", "id"));
|
||||
mColorName = view.findViewById(AndroidUtils.getIdentifier("color_name", "id"));
|
||||
mColorValue = view.findViewById(AndroidUtils.getIdentifier("color_value", "id"));
|
||||
}
|
||||
|
||||
public void bind(ColorModel item) {
|
||||
mContainer.setOnClickListener(v -> mSelectListener.onColorSelected(ColorPickerAdapter.this, item));
|
||||
mColorPreviewBorder.setBackground(new BorderDrawable(ThemesUtils.isDarkTheme() ? Color.WHITE : Color.BLACK, Screen.c(24.0f), Screen.c(1.0f)));
|
||||
mColorPreview.setPlaceholderColor(item.color);
|
||||
mColorName.setText(item.resName);
|
||||
mColorValue.setText("#" + Integer.toHexString(item.color).toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnColorSelectListener {
|
||||
|
||||
void onColorSelected(ColorPickerAdapter adapter, ColorModel colorModel);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import ru.vtosters.lite.utils.LayoutUtils;
|
||||
public class ImagineArrayAdapter extends ArrayAdapter<ImagineArrayAdapter.ImagineArrayAdapterItem> {
|
||||
|
||||
private List<ImagineArrayAdapterItem> mItems = new ArrayList<>();
|
||||
private final OnClickListener mListener;
|
||||
private OnClickListener mListener;
|
||||
private int mSelectedIndex = -1;
|
||||
|
||||
public ImagineArrayAdapter(@NonNull Context context, OnClickListener listener) {
|
||||
@@ -134,8 +134,8 @@ public class ImagineArrayAdapter extends ArrayAdapter<ImagineArrayAdapter.Imagin
|
||||
}
|
||||
|
||||
public static class ImagineArrayAdapterItem {
|
||||
private final Drawable mIcon;
|
||||
private final String mText;
|
||||
private Drawable mIcon;
|
||||
private String mText;
|
||||
|
||||
public ImagineArrayAdapterItem(Drawable icon, String text) {
|
||||
this.mIcon = icon;
|
||||
@@ -167,6 +167,6 @@ public class ImagineArrayAdapter extends ArrayAdapter<ImagineArrayAdapter.Imagin
|
||||
}
|
||||
|
||||
public interface OnClickListener {
|
||||
void onClick(int i);
|
||||
public void onClick(int i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ import com.vtosters.lite.R;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class MessagesPreviewAdapter extends RecyclerView.Adapter<MessagesPreviewAdapter.MessagePreviewViewHolder> {
|
||||
|
||||
private static final int ME = 0x0;
|
||||
private static final int ANONYMOUS = -0x1;
|
||||
|
||||
private final String[] mMessages = AndroidUtils.getArray("wallpaper_change_dialog");
|
||||
private final String[] mMessages = {
|
||||
"Доброе время", "Доброе утро, день, вечер. ночь", "Как живёшь?", "Не мёртвый, и то хорошо"
|
||||
};
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int i) {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package ru.vtosters.lite.ui.adapters;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import ru.vtosters.lite.themes.managers.PalettesManager;
|
||||
import ru.vtosters.lite.ui.dialogs.PalettesBottomSheetDialog;
|
||||
import ru.vtosters.lite.themes.models.PaletteModel;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class PalettesAdapter extends RecyclerView.Adapter<PalettesAdapter.PaletteViewHolder> {
|
||||
|
||||
private PalettesManager manager = PalettesManager.getInstance();
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PaletteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
var container = LayoutInflater.from(parent.getContext()).inflate(
|
||||
AndroidUtils.getIdentifier("palette_manager_item", "layout"), parent, false
|
||||
);
|
||||
return new PaletteViewHolder(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull PaletteViewHolder holder, int pos) {
|
||||
holder.bind(manager.getPalette(pos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return manager.getPalettesCount();
|
||||
}
|
||||
|
||||
public static class PaletteViewHolder extends RecyclerView.ViewHolder {
|
||||
private View mContainer;
|
||||
private TextView mName;
|
||||
private TextView mAuthor;
|
||||
|
||||
public PaletteViewHolder(@NonNull View view) {
|
||||
super(view);
|
||||
|
||||
mContainer = view;
|
||||
mName = view.findViewById(R.id.name);
|
||||
mAuthor = view.findViewById(AndroidUtils.getIdentifier("author", "id"));
|
||||
}
|
||||
|
||||
public void bind(PaletteModel palette) {
|
||||
mContainer.setOnClickListener(v -> {
|
||||
PalettesBottomSheetDialog.create((Activity) v.getContext(), palette);
|
||||
});
|
||||
mName.setText(palette.name);
|
||||
mAuthor.setText(palette.author);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.recolorDrawable;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.net.Uri;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -29,9 +28,8 @@ import ru.vtosters.lite.tgs.TGPref;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class StickerPackAdapter extends RecyclerView.Adapter<StickerPackAdapter.StickerPackViewHolder> {
|
||||
private static final TelegramStickersService sService = TelegramStickersService.getInstance(getGlobalContext());
|
||||
private static TelegramStickersService sService = TelegramStickersService.getInstance(getGlobalContext());
|
||||
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
@NonNull
|
||||
@Override
|
||||
public StickerPackViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
@@ -63,13 +61,13 @@ public class StickerPackAdapter extends RecyclerView.Adapter<StickerPackAdapter.
|
||||
}
|
||||
|
||||
public class StickerPackViewHolder extends RecyclerView.ViewHolder {
|
||||
private final LinearLayout mContainer;
|
||||
private final ImageView mStickerPreview;
|
||||
private final ImageView mUpdateButton;
|
||||
private final ImageView mDeleteButton;
|
||||
private final TextView mName;
|
||||
private final TextView mStickersCount;
|
||||
private final SwitchCompat mSwitch;
|
||||
private LinearLayout mContainer;
|
||||
private ImageView mStickerPreview;
|
||||
private ImageView mUpdateButton;
|
||||
private ImageView mDeleteButton;
|
||||
private TextView mName;
|
||||
private TextView mStickersCount;
|
||||
private SwitchCompat mSwitch;
|
||||
|
||||
|
||||
public StickerPackViewHolder(@NonNull View view) {
|
||||
@@ -84,7 +82,6 @@ public class StickerPackAdapter extends RecyclerView.Adapter<StickerPackAdapter.
|
||||
mStickersCount = view.findViewWithTag("vkim_cancel_label_text");
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
public void bind(int position) {
|
||||
final TelegramStickersPack pack = sService.getPacksListReference().get(position);
|
||||
if (pack.state != TelegramStickersPack.DOWNLOADED) return;
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
package ru.vtosters.lite.ui.adapters;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.vk.core.drawable.BorderDrawable;
|
||||
import com.vk.core.ui.themes.VKThemeHelper;
|
||||
import com.vk.core.util.Screen;
|
||||
import com.vk.core.util.ToastUtils;
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.vtosters.lite.themes.managers.ThemesManager;
|
||||
import ru.vtosters.lite.ui.dialogs.EditTextDialog;
|
||||
import ru.vtosters.lite.ui.dialogs.ThemesEditorBottomSheetDialog;
|
||||
import ru.vtosters.lite.themes.models.ThemeModel;
|
||||
import ru.vtosters.lite.ui.views.NoTouchRadioButton;
|
||||
import ru.vtosters.lite.ui.vkui.VKUIActionPopup;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
|
||||
public class ThemesAdapter extends RecyclerView.Adapter<ThemesAdapter.ThemeViewHolder> {
|
||||
|
||||
public ThemesManager mManager = ThemesManager.getInstance();
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ThemeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
var container = LayoutInflater.from(parent.getContext()).inflate(
|
||||
AndroidUtils.getIdentifier("theme_manager_item", "layout"), parent, false
|
||||
);
|
||||
return new ThemeViewHolder(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ThemeViewHolder holder, int pos) {
|
||||
holder.bind(mManager.getTheme(pos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mManager.getThemesCount();
|
||||
}
|
||||
|
||||
public class ThemeViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private ConstraintLayout mContainer;
|
||||
private FrameLayout mThemeModePreviewBorder;
|
||||
private ImageView mThemeModePreview;
|
||||
private TextView mName;
|
||||
private TextView mAuthor;
|
||||
private NoTouchRadioButton mRadioButton;
|
||||
|
||||
public ThemeViewHolder(@NonNull View view) {
|
||||
super(view);
|
||||
|
||||
mContainer = (ConstraintLayout) view;
|
||||
mThemeModePreviewBorder = view.findViewById(AndroidUtils.getIdentifier("theme_mode_preview_border", "id"));
|
||||
mThemeModePreview = view.findViewById(AndroidUtils.getIdentifier("theme_mode_preview", "id"));
|
||||
mName = view.findViewById(R.id.name);
|
||||
mAuthor = view.findViewById(AndroidUtils.getIdentifier("author", "id"));
|
||||
mRadioButton = view.findViewById(AndroidUtils.getIdentifier("selection", "id"));
|
||||
}
|
||||
|
||||
public void bind(ThemeModel theme) {
|
||||
var accent = getAccentColorFromCustomTheme(theme);
|
||||
mThemeModePreviewBorder.setBackground(new BorderDrawable(accent, Screen.c(24.0f), Screen.c(1.0f)));
|
||||
mThemeModePreview.setImageResource(AndroidUtils.getIdentifier(
|
||||
"vk_icon_" + (theme.isDarkMode ? "moon" : "sun") + "_outline_28",
|
||||
"drawable"));
|
||||
mThemeModePreview.setImageTintList(ColorStateList.valueOf(accent));
|
||||
var isCurrentTheme = mManager.isCurrentTheme(theme);
|
||||
if (!isCurrentTheme)
|
||||
mContainer.setOnClickListener(v -> {
|
||||
mManager.setTheme(theme);
|
||||
LifecycleUtils.restartApplication();
|
||||
});
|
||||
if (!"default".equals(theme.id))
|
||||
mContainer.setOnLongClickListener(v -> {
|
||||
showActionPopup(v.getContext(), v, isCurrentTheme, theme);
|
||||
return true;
|
||||
});
|
||||
else
|
||||
mContainer.setOnLongClickListener(null);
|
||||
mRadioButton.setChecked(isCurrentTheme);
|
||||
mName.setText(theme.name);
|
||||
mAuthor.setText(theme.author);
|
||||
}
|
||||
|
||||
private void showActionPopup(Context context, View anchorView, boolean isCurrentTheme, ThemeModel theme) {
|
||||
var builder = new VKUIActionPopup(context, anchorView, true, R.color.colorAccent)
|
||||
.setItem("Редактировать название",
|
||||
() -> showEditThemeNameDialog(context, theme))
|
||||
.setItem("Изменить цвета",
|
||||
() -> ThemesEditorBottomSheetDialog.create((Activity) context, theme, isCurrentTheme))
|
||||
.setItem("Поделиться темой", () -> {
|
||||
try {
|
||||
mManager.share(context, theme);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ToastUtils.a("Не удалось поделиться темой");
|
||||
}})
|
||||
.setItem("Удалить тему", () -> {
|
||||
mManager.delete(theme);
|
||||
if (isCurrentTheme)
|
||||
LifecycleUtils.restartApplication();
|
||||
else
|
||||
notifyDataSetChanged();
|
||||
});
|
||||
builder.create().d();
|
||||
}
|
||||
|
||||
private void showEditThemeNameDialog(Context context, ThemeModel theme) {
|
||||
EditTextDialog.create(context, "Редактирование названия темы", "Название темы", theme.name, (dialog, which, editText) -> {
|
||||
var newName = editText.getText().toString();
|
||||
if (TextUtils.isEmpty(newName)) {
|
||||
ToastUtils.a("Название не может быть пустым");
|
||||
return;
|
||||
}
|
||||
if (newName.equals(theme.name)) {
|
||||
ToastUtils.a("Вы не изменили название");
|
||||
return;
|
||||
}
|
||||
theme.setName(newName);
|
||||
try {
|
||||
mManager.save(theme);
|
||||
notifyDataSetChanged();
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
ToastUtils.a("Не удалось изменить название темы");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private int getAccentColorFromCustomTheme(ThemeModel theme) {
|
||||
if (!"default".equals(theme.id)) {
|
||||
int color = theme.getColor(R.attr.accent);
|
||||
if (color != -1)
|
||||
return color;
|
||||
color = theme.getColor(R.attr.colorAccent);
|
||||
if (color != -1)
|
||||
return color;
|
||||
color = theme.getColor(R.attr.vk_accent);
|
||||
if (color != -1)
|
||||
return color;
|
||||
}
|
||||
return VKThemeHelper.d((R.attr.accent));
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.IOUtils;
|
||||
import ru.vtosters.lite.utils.Preferences;
|
||||
|
||||
@@ -43,7 +42,7 @@ public class BackupManager {
|
||||
|
||||
public static void backupOnlines() throws IOException {
|
||||
if (getPrefContent("onlines.xml") == null) {
|
||||
Toast.makeText(getGlobalContext(), AndroidUtils.getString("no_data_to_backup"), LENGTH_SHORT).show();
|
||||
Toast.makeText(getGlobalContext(), "Нет данных для резервного копирования", LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -55,10 +54,10 @@ public class BackupManager {
|
||||
FileWriter out = new FileWriter(file);
|
||||
out.write(getPrefContent("onlines.xml"));
|
||||
out.close();
|
||||
Toast.makeText(getGlobalContext(), AndroidUtils.getString("backup_saved_in") + file.getAbsolutePath(), LENGTH_LONG).show();
|
||||
Toast.makeText(getGlobalContext(), "Сохранено в файл " + file.getAbsolutePath(), LENGTH_LONG).show();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(getGlobalContext(), AndroidUtils.getString("backup_save_error"), LENGTH_SHORT).show();
|
||||
Toast.makeText(getGlobalContext(), "Не удалось сохранить файл", LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,10 +70,10 @@ public class BackupManager {
|
||||
FileWriter out = new FileWriter(file);
|
||||
out.write(getPrefContent("com.vtosters.lite_preferences.xml"));
|
||||
out.close();
|
||||
Toast.makeText(getGlobalContext(), AndroidUtils.getString("backup_saved_in") + file.getAbsolutePath(), LENGTH_LONG).show();
|
||||
Toast.makeText(getGlobalContext(), "Сохранено в файл " + file.getAbsolutePath(), LENGTH_LONG).show();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(getGlobalContext(), AndroidUtils.getString("backup_save_error"), LENGTH_SHORT).show();
|
||||
Toast.makeText(getGlobalContext(), "Не удалось сохранить файл", LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ 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 android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
@@ -58,7 +57,6 @@ public class CrashReporter {
|
||||
var saveLogIntent = new Intent(getGlobalContext(), LogWriterService.class);
|
||||
saveLogIntent.putExtra("log", logString);
|
||||
saveLogIntent.putExtra("notificationId", 1);
|
||||
@SuppressLint("UnspecifiedImmutableFlag")
|
||||
var psaveLogIntent = PendingIntent.getService(getGlobalContext(), 0, saveLogIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
|
||||
var builder = new Notification.Builder(getGlobalContext());
|
||||
@@ -67,8 +65,12 @@ public class CrashReporter {
|
||||
builder.setContentText(logString);
|
||||
builder.setStyle(new Notification.BigTextStyle().bigText(logString));
|
||||
builder.setAutoCancel(true);
|
||||
builder.addAction(new Notification.Action(0, getString("vtl_crash_upload"), PendingIntent.getActivity(getGlobalContext(), (int) (Math.random() * 100.0d), foxbinIntent, PendingIntent.FLAG_CANCEL_CURRENT)));
|
||||
builder.addAction(new Notification.Action(0, getString("vtl_crash_save"), psaveLogIntent));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
|
||||
builder.addAction(new Notification.Action(0, getString("vtl_crash_upload"), PendingIntent.getActivity(getGlobalContext(), (int) (Math.random() * 100.0d), foxbinIntent, PendingIntent.FLAG_CANCEL_CURRENT)));
|
||||
builder.addAction(new Notification.Action(0, getString("vtl_crash_save"), psaveLogIntent));
|
||||
} else {
|
||||
builder.setContentIntent(PendingIntent.getActivity(activity, 0, foxbinIntent, PendingIntent.FLAG_ONE_SHOT));
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
builder.setChannelId("crashes");
|
||||
|
||||
@@ -5,13 +5,10 @@ import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
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 static ru.vtosters.lite.utils.Preferences.vkme_notifs;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import com.vk.apps.AppsFragment;
|
||||
import com.vk.discover.ThemedFeedFragment;
|
||||
import com.vk.fave.fragments.FaveTabFragment;
|
||||
@@ -45,6 +42,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ru.vtosters.lite.ui.fragments.VTSettings;
|
||||
import ru.vtosters.lite.ui.items.DockBarTab;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
@@ -103,28 +101,14 @@ public class DockBarEditorManager {
|
||||
mSelectedTabs.add(getTabByTag(tag));
|
||||
allTags.remove(tag);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
allTags.forEach(tag -> mDisabledTabs.add(getTabByTag(tag)));
|
||||
} else {
|
||||
for (String tag : allTags) {
|
||||
mDisabledTabs.add(getTabByTag(tag));
|
||||
}
|
||||
}
|
||||
allTags.forEach(tag -> mDisabledTabs.add(getTabByTag(tag)));
|
||||
}
|
||||
|
||||
public void save() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
getPreferences().edit().putString("dockbar_tabs", mSelectedTabs.stream()
|
||||
.map(tab -> tab.tag)
|
||||
.collect(Collectors.joining(",")))
|
||||
.commit();
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (DockBarTab tab : mSelectedTabs) {
|
||||
sb.append(tab.tag).append(",");
|
||||
}
|
||||
getPreferences().edit().putString("dockbar_tabs", sb.toString()).commit();
|
||||
}
|
||||
AndroidUtils.getPreferences().edit().putString("dockbar_tabs", mSelectedTabs.stream()
|
||||
.map(tab -> tab.tag)
|
||||
.collect(Collectors.joining(",")))
|
||||
.commit();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
@@ -277,7 +261,7 @@ public class DockBarEditorManager {
|
||||
R.drawable.ic_settings_outline_28,
|
||||
R.string.menu_settings,
|
||||
R.id.menu_settings,
|
||||
useNewSettings());
|
||||
VTSettings.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ru.vtosters.lite.ui.components;
|
||||
|
||||
public interface IItemMovingListener {
|
||||
|
||||
void onItemDismiss(int index);
|
||||
|
||||
boolean onItemMove(int fromPosition, int toPosition);
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package ru.vtosters.lite.ui.components;
|
||||
|
||||
import static ru.vtosters.lite.ui.vkui.VBListBuilder.VBListItem;
|
||||
import static ru.vtosters.lite.ui.vkui.VBListBuilder.buildListOf;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import ru.vtosters.lite.ui.vkui.VBottomSheetBuilder;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class NewsfeedListManager {
|
||||
|
||||
public static void callEditorPopup(Activity activity) {
|
||||
var selectedItems = getDefaultPrefs().getString("news_feed_selected_items", "");
|
||||
var filtersSet = getDefaultPrefs().getStringSet("news_feed_items_set", Collections.synchronizedSet(new LinkedHashSet<>()));
|
||||
var list = new ArrayList<VBListItem>();
|
||||
|
||||
if (filtersSet.size() == 0) {
|
||||
sendToast(AndroidUtils.getString("newsfeed_update_feed"));
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (filtersSet) {
|
||||
for (String item : filtersSet) {
|
||||
var id = item.substring(0, item.indexOf("|"));
|
||||
var title = item.substring(item.indexOf("|") + 1);
|
||||
|
||||
list.add(new VBListItem(id, title, selectedItems.contains(id)));
|
||||
}
|
||||
}
|
||||
|
||||
VBottomSheetBuilder.show(activity, new VBottomSheetBuilder.VBSContent(
|
||||
AndroidUtils.getString("newsfeed_list_choose_to_hide"),
|
||||
buildListOf(activity, list),
|
||||
new VBottomSheetBuilder.VBSContent.VBSButton(
|
||||
AndroidUtils.getString("save"),
|
||||
() -> {
|
||||
var newSelectedItems = "";
|
||||
for (VBListItem item : list)
|
||||
if (item.checked)
|
||||
newSelectedItems += item.id + ",";
|
||||
getDefaultPrefs().edit()
|
||||
.putString("news_feed_selected_items", newSelectedItems)
|
||||
.apply();
|
||||
sendToast(AndroidUtils.getString("newsfeed_list_update_feed_to_work"));
|
||||
}
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
public static void resetHideItems() {
|
||||
getDefaultPrefs().edit()
|
||||
.putString("news_feed_selected_items", "")
|
||||
.apply();
|
||||
sendToast(AndroidUtils.getString("newsfeed_list_hidden_reseted"));
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,11 @@ package ru.vtosters.lite.ui.components;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ru.vtosters.lite.ui.items.DockBarTab;
|
||||
import ru.vtosters.lite.ui.items.SuperAppItem;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
@@ -43,30 +40,15 @@ public class SuperAppEditorManager {
|
||||
mSelectedItems.add(getItemByTag(tag));
|
||||
allTags.remove(tag);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
allTags.forEach(tag -> mDisabledItems.add(getItemByTag(tag)));
|
||||
} else {
|
||||
for (String tag : allTags) {
|
||||
mDisabledItems.add(getItemByTag(tag));
|
||||
}
|
||||
}
|
||||
allTags.forEach(tag -> mDisabledItems.add(getItemByTag(tag)));
|
||||
}
|
||||
|
||||
public void save() {
|
||||
if (mSelectedItems.size() > 0)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
getPreferences().edit().putString("superapp_items", mSelectedItems.stream()
|
||||
.map(item -> item.type)
|
||||
.collect(Collectors.joining(",")))
|
||||
.commit();
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (SuperAppItem item : mSelectedItems) {
|
||||
sb.append(item.type);
|
||||
sb.append(",");
|
||||
}
|
||||
getPreferences().edit().putString("superapp_items", sb.toString()).commit();
|
||||
}
|
||||
getPreferences().edit().putString("superapp_items", mSelectedItems.stream()
|
||||
.map(item -> item.type)
|
||||
.collect(Collectors.joining(",")))
|
||||
.commit();
|
||||
else
|
||||
reset();
|
||||
}
|
||||
@@ -89,33 +71,33 @@ public class SuperAppEditorManager {
|
||||
private SuperAppItem getItemByTag(String tag) {
|
||||
switch (tag) {
|
||||
case "menu":
|
||||
return SuperAppItem.valuesOf("menu", AndroidUtils.getString("superapp_menu"));
|
||||
return SuperAppItem.valuesOf("menu", "Меню приложения");
|
||||
case "miniapps":
|
||||
return SuperAppItem.valuesOf("miniapps", AndroidUtils.getString("superapp_miniapps"));
|
||||
return SuperAppItem.valuesOf("miniapps", "Mini Apps: виджет");
|
||||
case "vkpay_slim":
|
||||
return SuperAppItem.valuesOf("vkpay_slim", AndroidUtils.getString("superapp_vkpay"));
|
||||
return SuperAppItem.valuesOf("vkpay_slim", "VK Pay");
|
||||
case "greeting":
|
||||
return SuperAppItem.valuesOf("greeting", AndroidUtils.getString("superapp_greeting"));
|
||||
return SuperAppItem.valuesOf("greeting", "Приветствие");
|
||||
case "promo":
|
||||
return SuperAppItem.valuesOf("promo", AndroidUtils.getString("superapp_miniapps_promo"));
|
||||
return SuperAppItem.valuesOf("promo", "Mini Apps: промо");
|
||||
case "holiday":
|
||||
return SuperAppItem.valuesOf("holiday", AndroidUtils.getString("superapp_holiday"));
|
||||
return SuperAppItem.valuesOf("holiday", "Дни рождения у друзей");
|
||||
case "weather":
|
||||
return SuperAppItem.valuesOf("weather", AndroidUtils.getString("superapp_weather"));
|
||||
return SuperAppItem.valuesOf("weather", "Погода");
|
||||
case "sport":
|
||||
return SuperAppItem.valuesOf("sport", AndroidUtils.getString("superapp_sport"));
|
||||
return SuperAppItem.valuesOf("sport", "Спортивные события");
|
||||
case "games":
|
||||
return SuperAppItem.valuesOf("games", AndroidUtils.getString("superapp_games"));
|
||||
return SuperAppItem.valuesOf("games", "Игры");
|
||||
case "informer":
|
||||
return SuperAppItem.valuesOf("informer", AndroidUtils.getString("superapp_informer"));
|
||||
return SuperAppItem.valuesOf("informer", "Информер");
|
||||
case "food":
|
||||
return SuperAppItem.valuesOf("food", AndroidUtils.getString("superapp_food"));
|
||||
return SuperAppItem.valuesOf("food", "Еда");
|
||||
case "event":
|
||||
return SuperAppItem.valuesOf("event", AndroidUtils.getString("superapp_event"));
|
||||
return SuperAppItem.valuesOf("event", "Мероприятия");
|
||||
case "music":
|
||||
return SuperAppItem.valuesOf("music", AndroidUtils.getString("superapp_music"));
|
||||
return SuperAppItem.valuesOf("music", "Музыка");
|
||||
case "vk_run":
|
||||
return SuperAppItem.valuesOf("vk_run", AndroidUtils.getString("superapp_vk_run"));
|
||||
return SuperAppItem.valuesOf("vk_run", "VK Run");
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package ru.vtosters.lite.ui.dialogs;
|
||||
|
||||
import static ru.vtosters.lite.themes.VTLColors.getTextSecondaryColor;
|
||||
import static ru.vtosters.lite.themes.VTLColors.getTextPrimaryColor;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||
|
||||
import ru.vtosters.lite.ui.vkui.VKUIEditText;
|
||||
import ru.vtosters.lite.ui.vkui.VKUITextView;
|
||||
import ru.vtosters.lite.utils.LayoutUtils;
|
||||
|
||||
public class EditTextDialog {
|
||||
public static void create(Context context, String title, String hint, String text, OnClickListener clickListener) {
|
||||
var container = new LinearLayout(context);
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
container.setPadding(
|
||||
dp2px(8), dp2px(12), dp2px(8), dp2px(12)
|
||||
);
|
||||
|
||||
if (!TextUtils.isEmpty(hint)) {
|
||||
var hitText = new VKUITextView(context, VKUITextView.STYLE_SUBHEAD_1);
|
||||
hitText.setText(hint);
|
||||
hitText.setPadding(dp2px(8), 0, 0, dp2px(8));
|
||||
container.addView(hitText, LayoutUtils.createLinear(-2, -2));
|
||||
}
|
||||
|
||||
var editText = new VKUIEditText(context);
|
||||
if (!TextUtils.isEmpty(text))
|
||||
editText.setText(text);
|
||||
editText.setTextColor(getTextPrimaryColor());
|
||||
editText.setHintTextColor(getTextSecondaryColor());
|
||||
editText.setPadding(dp2px(8), 0, dp2px(8), 0);
|
||||
|
||||
var editTextParams = LayoutUtils.createLinear(-1, dp2px(44));
|
||||
container.addView(editText, editTextParams);
|
||||
|
||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(context);
|
||||
if (!TextUtils.isEmpty(title))
|
||||
builder.setTitle(title);
|
||||
builder.setPositiveButton("OK", (dialog, which) -> clickListener.onClick(dialog, which, editText));
|
||||
builder.setNegativeButton("Отмена", (dialog, which) -> dialog.cancel());
|
||||
|
||||
var alert = builder.create();
|
||||
alert.setView(container);
|
||||
alert.show();
|
||||
}
|
||||
|
||||
public interface OnClickListener {
|
||||
void onClick(DialogInterface dialog, int which, EditText editText);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ import androidx.appcompat.widget.SwitchCompat;
|
||||
|
||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.LayoutUtils;
|
||||
|
||||
public class MessageSettings {
|
||||
@@ -51,12 +50,12 @@ public class MessageSettings {
|
||||
four.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(14f));
|
||||
five.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(14f));
|
||||
|
||||
zero.setText(AndroidUtils.getString("proxy_disable")); // Отключить
|
||||
one.setText(AndroidUtils.getString("message_self_destruct_15sec"));
|
||||
two.setText(AndroidUtils.getString("message_self_destruct_1min"));
|
||||
three.setText(AndroidUtils.getString("message_self_destruct_5min"));
|
||||
four.setText(AndroidUtils.getString("message_self_destruct_1hour"));
|
||||
five.setText(AndroidUtils.getString("message_self_destruct_24hours"));
|
||||
zero.setText("Отключить");
|
||||
one.setText("15 секунд");
|
||||
two.setText("1 минута");
|
||||
three.setText("5 минут");
|
||||
four.setText("1 час");
|
||||
five.setText("24 часа");
|
||||
|
||||
zero.setTextColor(getTextAttr());
|
||||
one.setTextColor(getTextAttr());
|
||||
@@ -88,7 +87,7 @@ public class MessageSettings {
|
||||
|
||||
@SuppressLint("UseSwitchCompatOrMaterialCode")
|
||||
var silentSwitch = new SwitchCompat(new ContextThemeWrapper(context, com.vtosters.lite.R.style.Widget_AppCompat_CompoundButton_Switch));
|
||||
silentSwitch.setText(AndroidUtils.getString("silent_messages"));
|
||||
silentSwitch.setText("Бесшумные сообщения");
|
||||
silentSwitch.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp2px(14f));
|
||||
silentSwitch.setTextColor(getTextAttr());
|
||||
silentSwitch.setChecked(isSilentEnabled);
|
||||
@@ -105,12 +104,12 @@ public class MessageSettings {
|
||||
mContainer.addView(silentSwitch, LayoutUtils.createLinear(-1, -2));
|
||||
|
||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(context);
|
||||
builder.setTitle(AndroidUtils.getString("message_send_settings_title"));
|
||||
builder.setMessage(AndroidUtils.getString("silent_messages_time_select"));
|
||||
builder.setTitle("Настройки отправки");
|
||||
builder.setMessage("Выберите время исчезновения сообщения");
|
||||
builder.setCancelable(true);
|
||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), null);
|
||||
builder.setNegativeButton("Отмена", null);
|
||||
builder.setView(mContainer);
|
||||
builder.setPositiveButton(AndroidUtils.getString("vtl_confirm"), (dialog, which) -> { // Применить
|
||||
builder.setPositiveButton("Применить", (dialog, which) -> {
|
||||
var checked = rg.getCheckedRadioButtonId();
|
||||
|
||||
if (checked == zero.getId()) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import ru.vtosters.lite.ui.vkui.ModalBottomSheetWrapper;
|
||||
import ru.vtosters.lite.utils.OTAUtils;
|
||||
|
||||
public class OTADialog implements OTAUtils.OTAListener {
|
||||
|
||||
private final Activity mActivity;
|
||||
|
||||
private final OTAUtils mHelper;
|
||||
@@ -20,21 +21,21 @@ public class OTADialog implements OTAUtils.OTAListener {
|
||||
mHelper.loadData();
|
||||
}
|
||||
|
||||
public static void checkUpdates(Activity activity) {
|
||||
new OTADialog(activity);
|
||||
public static OTADialog checkUpdates(Activity activity) {
|
||||
return new OTADialog(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdateApplied() {
|
||||
mActivity.runOnUiThread(() -> {
|
||||
// Toast.makeText(mActivity, "Обновления найдены", Toast.LENGTH_SHORT).show();
|
||||
new ModalBottomSheetWrapper(mActivity)
|
||||
.setTitle(getString("newversion") + " " + mHelper.getNewVersionName())
|
||||
.setUpdateInfoView(mHelper.getUpdateDescription())
|
||||
.setPositiveButton(getString("updateanddownload"), () -> {
|
||||
OTADownloader.downloadBuild(mHelper.getDownloadUrl());
|
||||
})
|
||||
.show();
|
||||
// new ModalBottomSheetWrapper(mActivity)
|
||||
// .setTitle(getString("newversion") + " " + mHelper.getNewVersionName())
|
||||
// // .setUpdateInfoView(mHelper.getUpdateDescription())
|
||||
// .setPositiveButton(getString("updateanddownload"), () -> {
|
||||
// OTADownloader.downloadBuild(mHelper.getDownloadUrl());
|
||||
// })
|
||||
// .show();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package ru.vtosters.lite.ui.dialogs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
|
||||
import com.vk.core.util.ToastUtils;
|
||||
|
||||
import ru.vtosters.lite.ui.adapters.ColorPickerAdapter;
|
||||
import ru.vtosters.lite.themes.models.PaletteModel;
|
||||
|
||||
public class PalettesBottomSheetDialog {
|
||||
|
||||
private static final String TAG = "palettes_copy_color";
|
||||
|
||||
public static void create(Activity activity, PaletteModel palette) {
|
||||
var instance = new VTColorPickerBottomSheetDialog(activity);
|
||||
var colorPickerAdapter = new ColorPickerAdapter(palette.colors, (adapter, color) -> {
|
||||
var manager = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
manager.setPrimaryClip(ClipData.newPlainText("color", Integer.toHexString(color.color).toUpperCase()));
|
||||
ToastUtils.a("Скопировано в буфер обмена");
|
||||
instance.dismiss();
|
||||
});
|
||||
instance.setTitle(palette.name)
|
||||
.setAdapter(colorPickerAdapter, true)
|
||||
.show(TAG, true);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
package ru.vtosters.lite.ui.dialogs;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
@@ -8,10 +9,8 @@ import android.content.Context;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
|
||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.LayoutUtils;
|
||||
|
||||
public class RoundingSeekbarDialog{
|
||||
@@ -26,12 +25,12 @@ public class RoundingSeekbarDialog{
|
||||
mContainer.addView(seek, LayoutUtils.createLinear(-1, -2));
|
||||
|
||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(context);
|
||||
builder.setTitle(AndroidUtils.getString("pic_rounding_title"));
|
||||
builder.setMessage(AndroidUtils.getString("pic_rounding_info"));
|
||||
builder.setTitle("Выберите размер закругления углов");
|
||||
builder.setMessage("Для отключения функции закругления углов введите 0");
|
||||
builder.setCancelable(true);
|
||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), null);
|
||||
builder.setNegativeButton("Отмена", null);
|
||||
builder.setView(mContainer);
|
||||
builder.setPositiveButton(AndroidUtils.getString("vtl_confirm"), (dialog, which) -> {
|
||||
builder.setPositiveButton("Применить", (dialog, which) -> {
|
||||
edit().putInt("pic_rounding", seek.getProgress()).commit();
|
||||
restartApplicationWithTimer();
|
||||
});
|
||||
|
||||
@@ -77,6 +77,8 @@ public class ServerDialog {
|
||||
private static void getResponse(String body) throws Exception {
|
||||
JSONObject jSONObject = new JSONObject(body);
|
||||
|
||||
Log.d("VTLOG", "getResponse: " + jSONObject);
|
||||
|
||||
if (jSONObject.getString("title").equals("")) {
|
||||
showAlert = false;
|
||||
return;
|
||||
@@ -95,18 +97,18 @@ public class ServerDialog {
|
||||
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(() -> {
|
||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(activity);
|
||||
builder.setTitle(title);
|
||||
builder.setMessage(message);
|
||||
builder.setCancelable(cancelable);
|
||||
builder.setPositiveButton(positiveButton, (dialogInterface, i) -> edit().putBoolean(key, false).apply());
|
||||
builder.setNeutralButton(neutralButton, (dialogInterface, i) -> {
|
||||
edit().putBoolean(key, false).apply();
|
||||
activity.startActivity(new Intent("android.intent.action.VIEW").setData(Uri.parse(link)));
|
||||
});
|
||||
if (getBoolValue(key, true) && showForNotVerified() && showAlert) {
|
||||
builder.show();
|
||||
}
|
||||
// VkAlertDialog.Builder builder = new VkAlertDialog.Builder(activity);
|
||||
// builder.setTitle(title);
|
||||
// builder.setMessage(message);
|
||||
// builder.setCancelable(cancelable);
|
||||
// builder.setPositiveButton(positiveButton, (dialogInterface, i) -> edit().putBoolean(key, false).apply());
|
||||
// builder.setNeutralButton(neutralButton, (dialogInterface, i) -> {
|
||||
// edit().putBoolean(key, false).apply();
|
||||
// activity.startActivity(new Intent("android.intent.action.VIEW").setData(Uri.parse(link)));
|
||||
// });
|
||||
// if (getBoolValue(key, true) && showForNotVerified() && showAlert) {
|
||||
// builder.show();
|
||||
// }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
package ru.vtosters.lite.ui.dialogs;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.Gravity;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
|
||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||
import com.vk.core.util.ToastUtils;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.vtosters.lite.themes.VTLColors;
|
||||
import ru.vtosters.lite.themes.managers.PalettesManager;
|
||||
import ru.vtosters.lite.themes.managers.ThemesManager;
|
||||
import ru.vtosters.lite.themes.models.ColorModel;
|
||||
import ru.vtosters.lite.ui.adapters.ColorPickerAdapter;
|
||||
import ru.vtosters.lite.themes.models.PaletteModel;
|
||||
import ru.vtosters.lite.themes.models.ThemeModel;
|
||||
import ru.vtosters.lite.ui.views.flask.builder.ColorPickerDialogBuilder;
|
||||
import ru.vtosters.lite.ui.views.rarepebble.ColorPickerView;
|
||||
import ru.vtosters.lite.utils.LayoutUtils;
|
||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
||||
|
||||
public class ThemesEditorBottomSheetDialog {
|
||||
|
||||
private static final String THEME_EDITOR_TAG = "theme_editor";
|
||||
private static final String PALETTES_EDITOR_TAG = "palettes_editor";
|
||||
private static final String[] COLOR_PICKERS = {
|
||||
"Wheel Color Picker by QuadFlask",
|
||||
"Palettes",
|
||||
"Advanced Color Picker by Martin Stone"
|
||||
};
|
||||
|
||||
public static void create(Activity activity, ThemeModel theme, boolean currentTheme) {
|
||||
var newTheme = theme.clone();
|
||||
var colorPickerAdapter = new ColorPickerAdapter(newTheme.colors, (adapter, color) -> {
|
||||
new VkAlertDialog.Builder(activity)
|
||||
.setItems(COLOR_PICKERS, (dialog, which) -> {
|
||||
if (which == 0) {
|
||||
showQuadFlashWheelColorPicker(activity, adapter, color);
|
||||
} else if (which == 1) {
|
||||
showPaletteChoiceDialog(activity, adapter, color);
|
||||
} else if (which == 2) {
|
||||
showMartinStoneColorPicker(activity, adapter, color);
|
||||
}
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
});
|
||||
var instance = new VTColorPickerBottomSheetDialog(activity);
|
||||
addSwitches(instance.getContainer(), newTheme, colorPickerAdapter);
|
||||
instance.setAdapter(colorPickerAdapter, false)
|
||||
.setTitle("Редактирование " + theme.name)
|
||||
.setPositiveButton("Применить", () -> {
|
||||
String message;
|
||||
try {
|
||||
ThemesManager.getInstance().save(newTheme);
|
||||
message = "Тема изменена";
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
message = "Ошибка при изменении темы";
|
||||
}
|
||||
if (currentTheme) {
|
||||
LifecycleUtils.restartApplication();
|
||||
return;
|
||||
}
|
||||
ToastUtils.a(message);
|
||||
instance.dismiss();
|
||||
})
|
||||
.show(THEME_EDITOR_TAG, true);
|
||||
}
|
||||
|
||||
private static void addSwitches(LinearLayout container, ThemeModel theme, ColorPickerAdapter adapter) {
|
||||
var context = container.getContext();
|
||||
|
||||
var switchesContainer = new LinearLayout(context);
|
||||
switchesContainer.setOrientation(LinearLayout.HORIZONTAL);
|
||||
switchesContainer.setPadding(0, dp2px(5), 0, dp2px(5));
|
||||
container.addView(switchesContainer, LayoutUtils.createLinear(-1, -2));
|
||||
|
||||
var amoledTheme = new SwitchCompat(context);
|
||||
amoledTheme.setTextColor(VTLColors.getTextPrimaryColor());
|
||||
amoledTheme.setTextSize(16.0f);
|
||||
amoledTheme.setText("AMOLED-тема");
|
||||
amoledTheme.setEnabled(theme.isDarkMode);
|
||||
amoledTheme.setGravity(Gravity.CENTER);
|
||||
amoledTheme.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
theme.isDarkMode = isChecked;
|
||||
if (isChecked) {
|
||||
replaceToAmoled(theme, adapter);
|
||||
} else {
|
||||
replaceToLight(theme, adapter);
|
||||
}
|
||||
adapter.notifyDataSetChanged();
|
||||
});
|
||||
|
||||
var darkTheme = new SwitchCompat(context);
|
||||
darkTheme.setChecked(theme.isDarkMode);
|
||||
darkTheme.setTextColor(VTLColors.getTextPrimaryColor());
|
||||
darkTheme.setGravity(Gravity.CENTER);
|
||||
darkTheme.setTextSize(16.0f);
|
||||
darkTheme.setText("Темная тема");
|
||||
darkTheme.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
theme.isDarkMode = isChecked;
|
||||
if (isChecked) {
|
||||
amoledTheme.setEnabled(true);
|
||||
replaceToDark(theme, adapter);
|
||||
} else {
|
||||
amoledTheme.setChecked(false);
|
||||
amoledTheme.setEnabled(false);
|
||||
replaceToLight(theme, adapter);
|
||||
}
|
||||
adapter.notifyDataSetChanged();
|
||||
});
|
||||
var darkThemeParams = LayoutUtils.createLinear(-1, -2);
|
||||
darkThemeParams.weight = 1.0f;
|
||||
switchesContainer.addView(darkTheme, darkThemeParams);
|
||||
var amoledThemeParams = LayoutUtils.createLinear(-1, -2);
|
||||
amoledThemeParams.weight = 1.0f;
|
||||
switchesContainer.addView(amoledTheme, amoledThemeParams);
|
||||
}
|
||||
|
||||
private static void replaceToLight(ThemeModel theme, ColorPickerAdapter adapter) {
|
||||
|
||||
}
|
||||
|
||||
private static void replaceToDark(ThemeModel theme, ColorPickerAdapter adapter) {
|
||||
|
||||
}
|
||||
|
||||
private static void replaceToAmoled(ThemeModel theme, ColorPickerAdapter adapter) {
|
||||
|
||||
}
|
||||
|
||||
private static void showMartinStoneColorPicker(
|
||||
Activity activity,
|
||||
ColorPickerAdapter adapter,
|
||||
ColorModel dest) {
|
||||
var colorPickerView = new ColorPickerView(activity);
|
||||
colorPickerView.setColor(dest.color);
|
||||
var alertDialog = new VkAlertDialog.Builder(activity)
|
||||
.setTitle("Выберите цвет")
|
||||
.setPositiveButton("Выбрать", (dialog, which) -> {
|
||||
dest.color = colorPickerView.getColor();
|
||||
adapter.notifyDataSetChanged();
|
||||
dialog.dismiss();
|
||||
})
|
||||
.create();
|
||||
alertDialog.setView(colorPickerView);
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
private static void showQuadFlashWheelColorPicker(
|
||||
Activity activity,
|
||||
ColorPickerAdapter adapter,
|
||||
ColorModel dest) {
|
||||
ColorPickerDialogBuilder
|
||||
.with(activity)
|
||||
.setTitle("Выберите цвет")
|
||||
.showBorder(true)
|
||||
.setOnColorSelectedListener((dialog, selectedColor) -> {
|
||||
dest.color = selectedColor;
|
||||
adapter.notifyDataSetChanged();
|
||||
dialog.cancel();
|
||||
})
|
||||
.build()
|
||||
.show();
|
||||
}
|
||||
|
||||
private static void showPaletteChoiceDialog(
|
||||
Activity activity,
|
||||
ColorPickerAdapter adapter,
|
||||
ColorModel dest
|
||||
) {
|
||||
var palettesManager = PalettesManager.getInstance();
|
||||
var titles = new String[palettesManager.getPalettesCount()];
|
||||
for (int i = 0; i < titles.length; i++)
|
||||
titles[i] = palettesManager.getPalette(i).name;
|
||||
new VkAlertDialog.Builder(activity)
|
||||
.setItems(titles, (dialog, which) -> createPaletteColorPicker(
|
||||
activity,
|
||||
adapter,
|
||||
dest,
|
||||
palettesManager.getPalette(which)))
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
|
||||
private static void createPaletteColorPicker(
|
||||
Activity activity,
|
||||
ColorPickerAdapter themeEditAdapter,
|
||||
ColorModel dest,
|
||||
PaletteModel palette
|
||||
) {
|
||||
var instance = new VTColorPickerBottomSheetDialog(activity);
|
||||
var colorPickerAdapter = new ColorPickerAdapter(palette.colors, (adapter, color) -> {
|
||||
dest.color = color.color;
|
||||
ToastUtils.a("Цвет был изменён");
|
||||
themeEditAdapter.notifyDataSetChanged();
|
||||
instance.dismiss();
|
||||
});
|
||||
instance.setTitle(palette.name)
|
||||
.setAdapter(colorPickerAdapter, true)
|
||||
.show(PALETTES_EDITOR_TAG, true);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import android.util.Log;
|
||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||
|
||||
import ru.vtosters.lite.translators.BaseTranslator;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class Translate {
|
||||
public static void showTranslatedText(Context context, String text) {
|
||||
@@ -28,16 +27,16 @@ public class Translate {
|
||||
|
||||
private static void showDialog(Context context, String text) {
|
||||
VkAlertDialog.Builder alertDialog = new VkAlertDialog.Builder(context);
|
||||
alertDialog.setTitle(AndroidUtils.getString("translator_title"));
|
||||
alertDialog.setTitle("Переводчик");
|
||||
alertDialog.setMessage(text);
|
||||
alertDialog.setPositiveButton(AndroidUtils.getString("close"), (dialog, which) -> {
|
||||
alertDialog.setPositiveButton("Закрыть", (dialog, which) -> {
|
||||
dialog.cancel();
|
||||
});
|
||||
alertDialog.setNeutralButton(AndroidUtils.getString("copy"), (dialog, which) -> {
|
||||
alertDialog.setNeutralButton("Скопировать", (dialog, which) -> {
|
||||
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
android.content.ClipData clip = android.content.ClipData.newPlainText("Copied Text", text);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
sendToast(AndroidUtils.getString("copied_to_clipboard"));
|
||||
sendToast("Скопировано в буфер обмена");
|
||||
});
|
||||
var alert = alertDialog.create();
|
||||
alert.show();
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package ru.vtosters.lite.ui.dialogs;
|
||||
|
||||
import static ru.vtosters.lite.themes.VTLColors.getTextPrimaryColor;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getString;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import ru.vtosters.lite.downloaders.OTADownloader;
|
||||
import ru.vtosters.lite.ui.vkui.ModalBottomSheetWrapper;
|
||||
import ru.vtosters.lite.utils.OTAUtils;
|
||||
|
||||
public class UpdateBottomSheetDialog extends ModalBottomSheetWrapper<UpdateBottomSheetDialog> {
|
||||
|
||||
private static final String TAG = "ota";
|
||||
|
||||
private Activity mActivity;
|
||||
|
||||
public UpdateBottomSheetDialog(Activity activity) {
|
||||
super(activity);
|
||||
this.mActivity = activity;
|
||||
}
|
||||
|
||||
public UpdateBottomSheetDialog setUpdateDescriptionText(String changelog) {
|
||||
var container = new LinearLayout(mActivity);
|
||||
var changelogView = new TextView(mActivity);
|
||||
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
changelogView.setPadding(0, dp2px(8), 0, 0);
|
||||
changelogView.setText(getString("changelog") + ": \n" + changelog);
|
||||
changelogView.setTextColor(getTextPrimaryColor());
|
||||
container.addView(changelogView, new LinearLayout.LayoutParams(-1, -2));
|
||||
|
||||
return setView(container);
|
||||
}
|
||||
|
||||
public static void create(Activity activity, OTAUtils helper) {
|
||||
new UpdateBottomSheetDialog(activity)
|
||||
.setTitle(getString("newversion") + " " + helper.getNewVersionName())
|
||||
.setUpdateDescriptionText(helper.getUpdateDescription())
|
||||
.setPositiveButton(getString("updateanddownload"), () -> {
|
||||
OTADownloader.downloadBuild(helper.getDownloadUrl());
|
||||
})
|
||||
.show(TAG);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package ru.vtosters.lite.ui.dialogs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import ru.vtosters.lite.ui.adapters.ColorPickerAdapter;
|
||||
import ru.vtosters.lite.ui.vkui.ModalBottomSheetWrapper;
|
||||
import ru.vtosters.lite.utils.LayoutUtils;
|
||||
|
||||
public class VTColorPickerBottomSheetDialog extends ModalBottomSheetWrapper<VTColorPickerBottomSheetDialog> {
|
||||
|
||||
private Activity mActivity;
|
||||
private LinearLayout mContainer;
|
||||
|
||||
public VTColorPickerBottomSheetDialog(Activity activity) {
|
||||
super(activity);
|
||||
this.mActivity = activity;
|
||||
mContainer = new LinearLayout(mActivity);
|
||||
mContainer.setLayoutParams(LayoutUtils.createLinear(-1, -1));
|
||||
mContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
}
|
||||
|
||||
public VTColorPickerBottomSheetDialog setAdapter(ColorPickerAdapter adapter, boolean searchMode) {
|
||||
var recyclerView = new RecyclerView(mActivity);
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
|
||||
var recyclerViewParams = LayoutUtils.createLinear(-1, -1);
|
||||
mContainer.addView(recyclerView, recyclerViewParams);
|
||||
|
||||
mBuilder.a(mContainer);
|
||||
return setView(mContainer);
|
||||
}
|
||||
|
||||
public LinearLayout getContainer() {
|
||||
return mContainer;
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,6 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.vtosters.lite.ui.adapters.CategorizedAdapter;
|
||||
import ru.vtosters.lite.ui.components.DockBarEditorManager;
|
||||
import ru.vtosters.lite.ui.components.ItemMovingCallback;
|
||||
@@ -85,7 +83,7 @@ public class DockBarEditorFragment extends BaseToolbarFragment {
|
||||
});
|
||||
adapter.setMinAndMaxCounts(DockBarEditorManager.MIN_SELECTED_TABS, DockBarEditorManager.MAX_SELECTED_TABS);
|
||||
|
||||
var recyclerView = new RecyclerView(requireContext());
|
||||
var recyclerView = new RecyclerView(getContext());
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
package ru.vtosters.lite.ui.fragments;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPrefsValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.copyright_post;
|
||||
import static ru.vtosters.lite.utils.Preferences.offline;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
@@ -16,9 +14,6 @@ import com.vk.navigation.Navigator;
|
||||
import com.vk.newsfeed.NewsfeedSettingsFragment;
|
||||
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||
|
||||
import ru.vtosters.lite.ui.components.NewsfeedListManager;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class FeedFragment extends MaterialPreferenceToolbarFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
@@ -30,33 +25,6 @@ public class FeedFragment extends MaterialPreferenceToolbarFragment {
|
||||
private void prefs() {
|
||||
findPreference("officialnewssett").setOnPreferenceClickListener(new openofficialsett());
|
||||
findPreference("cringecopyright").setEnabled(!copyright_post());
|
||||
|
||||
findPreference("spamfilters").setSummary(count(getPrefsValue("spamfilters")));
|
||||
findPreference("sourcenamefilter").setSummary(count(getPrefsValue("sourcenamefilter")));
|
||||
findPreference("linkfilter").setSummary(count(getPrefsValue("linkfilter")));
|
||||
findPreference("newsfeedlistmanager").setOnPreferenceClickListener(preference -> {
|
||||
NewsfeedListManager.callEditorPopup(getActivity());
|
||||
return true;
|
||||
});
|
||||
var str = getDefaultPrefs().getString("news_feed_selected_items", "");
|
||||
findPreference("newsfeedlistmanager").setSummary(
|
||||
String.format(AndroidUtils.getString("feed_hidden"), (!TextUtils.isEmpty(str) ? str.split(",").length : 0))
|
||||
);
|
||||
findPreference("newsfeedlistmanager_reset").setOnPreferenceClickListener(preference -> {
|
||||
NewsfeedListManager.resetHideItems();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private String count(String text) {
|
||||
// count comma separated words in string
|
||||
var count = text.split(", ").length;
|
||||
|
||||
if (count < 1 || text.isEmpty()) {
|
||||
return AndroidUtils.getString("feed_no_elements");
|
||||
} else {
|
||||
return String.format(AndroidUtils.getString("feed_elements_count"), count);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,8 +37,6 @@ import androidx.core.content.res.ResourcesCompat;
|
||||
|
||||
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class IconsFragment extends MaterialPreferenceToolbarFragment {
|
||||
@SuppressLint("SetTextI18n")
|
||||
public static void callSelectDialog(Context ctx, String appicon) {
|
||||
@@ -64,7 +62,7 @@ public class IconsFragment extends MaterialPreferenceToolbarFragment {
|
||||
rgVK.setText("VK");
|
||||
rgVK.setTextColor(getTextAttr());
|
||||
|
||||
rgVKontakte.setText(AndroidUtils.getString("app_name_alter"));
|
||||
rgVKontakte.setText("ВКонтакте");
|
||||
rgVKontakte.setTextColor(getTextAttr());
|
||||
|
||||
rgVKontakte.setChecked(isZaboronaEnabled());
|
||||
@@ -72,9 +70,9 @@ public class IconsFragment extends MaterialPreferenceToolbarFragment {
|
||||
rgDefault.setChecked(!isZaboronaEnabled());
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ctx, getAlertStyle());
|
||||
builder.setTitle(AndroidUtils.getString("app_name_select_title"));
|
||||
builder.setTitle("Выберите название приложения");
|
||||
builder.setView(rg);
|
||||
builder.setPositiveButton(AndroidUtils.getString("vtl_confirm"), ((dialog, which) -> {
|
||||
builder.setPositiveButton("Применить", ((dialog, which) -> {
|
||||
var defname = preferences.getString("appname", "vt");
|
||||
var deficon = preferences.getString("selectedicon", "vt");
|
||||
|
||||
@@ -95,7 +93,7 @@ public class IconsFragment extends MaterialPreferenceToolbarFragment {
|
||||
switchComponent(appicon, "vkontakte", deficon, defname);
|
||||
}
|
||||
}));
|
||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), ((dialog, which) -> {
|
||||
builder.setNegativeButton("Отмена", ((dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
}));
|
||||
|
||||
@@ -116,13 +114,13 @@ public class IconsFragment extends MaterialPreferenceToolbarFragment {
|
||||
this.addPreferencesFromResource(vtosterXml);
|
||||
|
||||
if (!hasVerification() && !getBoolValue("dialogrecomm", false)) {
|
||||
addPreference(this, "", AndroidUtils.getString("icons_warning"), AndroidUtils.getString("icons_warning_info"), "ic_about_outline_28", preference -> {
|
||||
addPreference(this, "", "Доступны не все функции!", "Для разблокировки необходимо сделать пожертование от 99р", "ic_about_outline_28", preference -> {
|
||||
getContext().startActivity(new Intent("android.intent.action.VIEW").setData(Uri.parse("https://vtosters.app")));
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
addPreferenceCategory(this, AndroidUtils.getString("icons_title"));
|
||||
addPreferenceCategory(this, "Иконки");
|
||||
|
||||
for (var i = 0; i < icons().size(); i++) {
|
||||
if (icons().get(i) == null || iconsValues().get(i) == null) return;
|
||||
@@ -153,7 +151,7 @@ public class IconsFragment extends MaterialPreferenceToolbarFragment {
|
||||
}
|
||||
|
||||
if (!hasVerification() && !getBoolValue("dialogrecomm", false)) {
|
||||
addPreferenceCategory(this, AndroidUtils.getString("unavailable_icons"));
|
||||
addPreferenceCategory(this, "Недоступные иконки");
|
||||
|
||||
for (var i = 2; i < sIconsPlusNames.size(); i++) {
|
||||
if (sIconsPlusNames.get(i) == null || sIconsPlus.get(i) == null) return;
|
||||
@@ -178,7 +176,7 @@ public class IconsFragment extends MaterialPreferenceToolbarFragment {
|
||||
}
|
||||
|
||||
addPreferenceDrawable(this, icon, iconname, "", drawable, preference -> {
|
||||
sendToast(AndroidUtils.getString("unavailable_icon_warning"));
|
||||
sendToast("Иконка доступна только обладателям верификации");
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package ru.vtosters.lite.ui.fragments;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplicationWithTimer;
|
||||
|
||||
import android.os.Bundle;
|
||||
@@ -10,9 +9,6 @@ import androidx.preference.Preference;
|
||||
|
||||
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||
|
||||
import ru.vtosters.lite.ui.dialogs.RoundingSeekbarDialog;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class InterfaceFragment extends MaterialPreferenceToolbarFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
@@ -25,17 +21,6 @@ public class InterfaceFragment extends MaterialPreferenceToolbarFragment {
|
||||
findPreference("stories").setOnPreferenceClickListener(new restart());
|
||||
findPreference("swipe").setOnPreferenceClickListener(new restart());
|
||||
findPreference("is_likes_on_right").setOnPreferenceClickListener(new restart());
|
||||
|
||||
findPreference("customrounding").setOnPreferenceClickListener(preference -> {
|
||||
RoundingSeekbarDialog.dialog(getContext());
|
||||
return true;
|
||||
});
|
||||
|
||||
if (getPreferences().getInt("pic_rounding", 0) == 0) {
|
||||
findPreference("customrounding").setSummary(AndroidUtils.getString("disabled"));
|
||||
} else {
|
||||
findPreference("customrounding").setSummary(String.format(AndroidUtils.getString("rounding_size"), getPreferences().getInt("pic_rounding", 0)));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean restart(Preference preference) {
|
||||
|
||||
@@ -13,10 +13,8 @@ import static ru.vtosters.lite.utils.ThemesUtils.getAlertStyle;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getSTextAttr;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.getTextAttr;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
@@ -42,16 +40,104 @@ import okhttp3.Request;
|
||||
import ru.vtosters.lite.downloaders.VideoDownloader;
|
||||
import ru.vtosters.lite.music.Scrobbler;
|
||||
import ru.vtosters.lite.ui.adapters.ImagineArrayAdapter;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.FileUriUtils;
|
||||
import ru.vtosters.lite.utils.Preferences;
|
||||
|
||||
public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
||||
private final int REQUEST_CODE_SET_DOWNLOAD_DIRECTORY = 665;
|
||||
private final int REQUEST_CODE_SET_MUSIC_DIRECTORY = 666;
|
||||
private final int REQUEST_CODE_SET_PHOTOS_DIRECTORY = 667;
|
||||
private final int REQUEST_CODE_SET_VIDEOS_DIRECTORY = 668;
|
||||
public static void download(Context ctx) {
|
||||
AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx, getAlertStyle());
|
||||
alertDialog.setTitle("Введите ссылку на видео");
|
||||
|
||||
final EditText input = new EditText(ctx);
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT);
|
||||
input.setLayoutParams(lp);
|
||||
input.setTextColor(getTextAttr());
|
||||
input.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
alertDialog.setView(input);
|
||||
alertDialog.setPositiveButton("Скачать", (dialog, which) -> VideoDownloader.parseVideoLink(input.getText().toString(), ctx));
|
||||
var alert = alertDialog.create();
|
||||
alert.show();
|
||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
||||
}
|
||||
|
||||
private void logout(Context ctx) {
|
||||
VkAlertDialog.Builder alertDialog = new VkAlertDialog.Builder(ctx);
|
||||
alertDialog.setTitle("Вы уверены?");
|
||||
alertDialog.setMessage("Вы действительно хотите выйти из аккаунта?");
|
||||
alertDialog.setPositiveButton("Да", (dialog, which) -> {
|
||||
Scrobbler.logout();
|
||||
});
|
||||
alertDialog.setNeutralButton("Нет", (dialog, which) -> {
|
||||
dialog.cancel();
|
||||
});
|
||||
var alert = alertDialog.create();
|
||||
alert.show();
|
||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
||||
alert.getButton(DialogInterface.BUTTON_NEUTRAL).setTextColor(getResources().getColor(com.vtosters.lite.R.color.red));
|
||||
}
|
||||
|
||||
private void lastfmAuth(Context ctx) {
|
||||
LinearLayout linearLayout = new LinearLayout(ctx);
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
final EditText fn = new EditText(ctx);
|
||||
fn.setHint("Логин");
|
||||
fn.setTextColor(getTextAttr());
|
||||
fn.setHintTextColor(getSTextAttr());
|
||||
fn.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
linearLayout.addView(fn);
|
||||
fn.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) fn.getLayoutParams());
|
||||
margin.setMargins(dp2px(20f), 0, dp2px(20f), 0);
|
||||
fn.setLayoutParams(margin);
|
||||
|
||||
final EditText ln = new EditText(ctx);
|
||||
ln.setHint("Пароль");
|
||||
ln.setTextColor(getTextAttr());
|
||||
ln.setHintTextColor(getSTextAttr());
|
||||
ln.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
linearLayout.addView(ln);
|
||||
ln.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
ln.setLayoutParams(margin);
|
||||
|
||||
AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx, getAlertStyle());
|
||||
alertDialog.setTitle("Введите логин и пароль");
|
||||
|
||||
alertDialog.setView(linearLayout);
|
||||
alertDialog.setPositiveButton("Войти", (dialog, which) -> {
|
||||
String login = fn.getText().toString();
|
||||
String pass = ln.getText().toString();
|
||||
|
||||
Scrobbler.auth(login, pass);
|
||||
});
|
||||
var alert = alertDialog.create();
|
||||
alert.show();
|
||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
||||
}
|
||||
|
||||
public static void deleteVideoHistory() {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
var request = new Request.a()
|
||||
.b("https://api.vk.com/method/" + "video.clearViewingHistoryRecords" + "?https=1" + "&access_token=" + getUserToken() + "&v=5.187")
|
||||
.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("VideoHistory", response);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
thread.start();
|
||||
|
||||
sendToast("История просмотра видео очищена");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
@@ -60,43 +146,6 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
||||
prefs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
var path = data.getData();
|
||||
if (path != null) {
|
||||
var prefs = getPreferences();
|
||||
var editor = prefs.edit();
|
||||
var actualPath = FileUriUtils.getFullPathFromTreeUri(path, getContext());
|
||||
Log.d("MediaFragment", "onActivityResult: " + actualPath);
|
||||
Log.d("MediaFragment", "onActivityResult: " + requestCode);
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_SET_DOWNLOAD_DIRECTORY:
|
||||
editor.putString("downloads_directory", actualPath);
|
||||
break;
|
||||
case REQUEST_CODE_SET_MUSIC_DIRECTORY:
|
||||
editor.putString("music_directory", actualPath);
|
||||
break;
|
||||
case REQUEST_CODE_SET_PHOTOS_DIRECTORY:
|
||||
editor.putString("photos_directory", actualPath);
|
||||
break;
|
||||
case REQUEST_CODE_SET_VIDEOS_DIRECTORY:
|
||||
editor.putString("videos_directory", actualPath);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
prefs();
|
||||
}
|
||||
|
||||
private void prefs() {
|
||||
findPreference("download_video").setOnPreferenceClickListener(new MediaFragment.download());
|
||||
findPreference("clearvideohistory").setOnPreferenceClickListener(preference -> {
|
||||
@@ -113,52 +162,8 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference("downloads_directory").setSummary(
|
||||
AndroidUtils.getString("current_download_folder") + " " + Preferences.getDownloadsDir()
|
||||
);
|
||||
|
||||
findPreference("photos_directory").setSummary(
|
||||
AndroidUtils.getString("current_download_folder") + " " + Preferences.getPhotosDir()
|
||||
);
|
||||
|
||||
findPreference("videos_directory").setSummary(
|
||||
AndroidUtils.getString("current_download_folder") + " " + Preferences.getVideosDir()
|
||||
);
|
||||
|
||||
findPreference("music_directory").setSummary(
|
||||
AndroidUtils.getString("current_download_folder") + " " + Preferences.getMusicDir()
|
||||
);
|
||||
|
||||
findPreference("downloads_directory").setOnPreferenceClickListener(preference -> {
|
||||
var intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
startActivityForResult(intent, REQUEST_CODE_SET_DOWNLOAD_DIRECTORY);
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference("photos_directory").setOnPreferenceClickListener(preference -> {
|
||||
var intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
startActivityForResult(intent, REQUEST_CODE_SET_PHOTOS_DIRECTORY);
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference("videos_directory").setOnPreferenceClickListener(preference -> {
|
||||
var intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
startActivityForResult(intent, REQUEST_CODE_SET_VIDEOS_DIRECTORY);
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference("music_directory").setOnPreferenceClickListener(preference -> {
|
||||
var intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
startActivityForResult(intent, REQUEST_CODE_SET_MUSIC_DIRECTORY);
|
||||
return true;
|
||||
});
|
||||
|
||||
if (isLoggedIn()) {
|
||||
findPreference("lastfm_auth").setSummary(AndroidUtils.getString("lastfm_authorized_as") + Scrobbler.getUserName());
|
||||
findPreference("lastfm_auth").setSummary("Вы авторизованы как " + Scrobbler.getUserName());
|
||||
} else {
|
||||
findPreference("lastfm_enabled").setEnabled(false);
|
||||
}
|
||||
@@ -187,103 +192,6 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
||||
});
|
||||
}
|
||||
|
||||
private void lastfmAuth(Context ctx) {
|
||||
LinearLayout linearLayout = new LinearLayout(ctx);
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
final EditText fn = new EditText(ctx);
|
||||
fn.setHint(AndroidUtils.getString("lastfm_login"));
|
||||
fn.setTextColor(getTextAttr());
|
||||
fn.setHintTextColor(getSTextAttr());
|
||||
fn.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
linearLayout.addView(fn);
|
||||
fn.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) fn.getLayoutParams());
|
||||
margin.setMargins(dp2px(20f), 0, dp2px(20f), 0);
|
||||
fn.setLayoutParams(margin);
|
||||
|
||||
final EditText ln = new EditText(ctx);
|
||||
ln.setHint(AndroidUtils.getString("lastfm_password"));
|
||||
ln.setTextColor(getTextAttr());
|
||||
ln.setHintTextColor(getSTextAttr());
|
||||
ln.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
linearLayout.addView(ln);
|
||||
ln.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
ln.setLayoutParams(margin);
|
||||
|
||||
AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx, getAlertStyle());
|
||||
alertDialog.setTitle(AndroidUtils.getString("lastfm_enter_credentials"));
|
||||
|
||||
alertDialog.setView(linearLayout);
|
||||
alertDialog.setPositiveButton(AndroidUtils.getString("lastfm_enter"), (dialog, which) -> {
|
||||
String login = fn.getText().toString();
|
||||
String pass = ln.getText().toString();
|
||||
|
||||
Scrobbler.auth(login, pass);
|
||||
});
|
||||
var alert = alertDialog.create();
|
||||
alert.show();
|
||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
||||
}
|
||||
|
||||
private void logout(Context ctx) {
|
||||
VkAlertDialog.Builder alertDialog = new VkAlertDialog.Builder(ctx);
|
||||
alertDialog.setTitle(AndroidUtils.getString("lastfm_logout_title"));
|
||||
alertDialog.setMessage(AndroidUtils.getString("lastfm_logout_confirm"));
|
||||
alertDialog.setPositiveButton(AndroidUtils.getString("vkim_yes"), (dialog, which) -> {
|
||||
Scrobbler.logout();
|
||||
});
|
||||
alertDialog.setNeutralButton(AndroidUtils.getString("vkim_no"), (dialog, which) -> {
|
||||
dialog.cancel();
|
||||
});
|
||||
var alert = alertDialog.create();
|
||||
alert.show();
|
||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
||||
alert.getButton(DialogInterface.BUTTON_NEUTRAL).setTextColor(getResources().getColor(com.vtosters.lite.R.color.red));
|
||||
}
|
||||
|
||||
public static void deleteVideoHistory() {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
var request = new Request.a()
|
||||
.b("https://api.vk.com/method/" + "video.clearViewingHistoryRecords" + "?https=1" + "&access_token=" + getUserToken() + "&v=5.187")
|
||||
.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("VideoHistory", response);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
thread.start();
|
||||
|
||||
sendToast(AndroidUtils.getString("video_history_cleaned"));
|
||||
}
|
||||
|
||||
public static void download(Context ctx) {
|
||||
AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx, getAlertStyle());
|
||||
alertDialog.setTitle(AndroidUtils.getString("video_dl_enter_link"));
|
||||
|
||||
final EditText input = new EditText(ctx);
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT);
|
||||
input.setLayoutParams(lp);
|
||||
input.setTextColor(getTextAttr());
|
||||
input.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
alertDialog.setView(input);
|
||||
alertDialog.setPositiveButton(AndroidUtils.getString("download"), (dialog, which) -> VideoDownloader.parseVideoLink(input.getText().toString(), ctx));
|
||||
var alert = alertDialog.create();
|
||||
alert.show();
|
||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
||||
}
|
||||
|
||||
private class download implements Preference.OnPreferenceClickListener {
|
||||
@Override // android.support.v7.preference.Preference.c
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package ru.vtosters.lite.ui.fragments;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.*;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplicationWithTimer;
|
||||
import static ru.vtosters.lite.utils.Preferences.autoalltranslate;
|
||||
import static ru.vtosters.lite.utils.Preferences.vkme;
|
||||
import static ru.vtosters.lite.utils.ThemesUtils.*;
|
||||
import static ru.vtosters.lite.utils.Preferences.offline;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@@ -22,12 +19,9 @@ import com.vk.navigation.Navigator;
|
||||
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.vtosters.lite.ui.adapters.ImagineArrayAdapter;
|
||||
import ru.vtosters.lite.ui.wallpapers.WallpaperMenuFragment;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.ThemesUtils;
|
||||
|
||||
public class MessagesFragment extends MaterialPreferenceToolbarFragment {
|
||||
@Override
|
||||
@@ -37,7 +31,6 @@ public class MessagesFragment extends MaterialPreferenceToolbarFragment {
|
||||
prefs();
|
||||
}
|
||||
|
||||
@SuppressLint("UseCompatLoadingForDrawables")
|
||||
private void prefs() {
|
||||
findPreference("vkme").setOnPreferenceClickListener(new MessagesFragment.restart());
|
||||
findPreference("vkme_notifs").setOnPreferenceClickListener(new MessagesFragment.restart());
|
||||
@@ -57,7 +50,7 @@ public class MessagesFragment extends MaterialPreferenceToolbarFragment {
|
||||
.create();
|
||||
|
||||
var listView = (ListView) LayoutInflater.from(getContext()).inflate(com.vtosters.lite.R.layout.abc_select_dialog_material, null, false);
|
||||
var adapter = new ImagineArrayAdapter(requireContext(), items, i -> {
|
||||
var adapter = new ImagineArrayAdapter(getContext(), items, i -> {
|
||||
getPreferences().edit().putInt("translator", i).apply();
|
||||
alert.dismiss();
|
||||
});
|
||||
@@ -68,20 +61,15 @@ public class MessagesFragment extends MaterialPreferenceToolbarFragment {
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference("vkme_notifs").setEnabled(vkme());
|
||||
findPreference("wallpapers").setIcon(recolorDrawable(getGlobalContext().getDrawable(getIdentifier("ic_media_outline_28", "drawable"))));
|
||||
findPreference("vkme").setIcon(getIdentifier("ic_vkme_28", "drawable"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
findPreference("autotranslate").setEnabled(!autoalltranslate());
|
||||
findPreference("vkme_notifs").setEnabled(vkme());
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
public boolean restart() {
|
||||
public boolean restart(Preference preference) {
|
||||
restartApplicationWithTimer();
|
||||
return true;
|
||||
}
|
||||
@@ -89,14 +77,14 @@ public class MessagesFragment extends MaterialPreferenceToolbarFragment {
|
||||
public class restart implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
return MessagesFragment.this.restart();
|
||||
return MessagesFragment.this.restart(preference);
|
||||
}
|
||||
}
|
||||
|
||||
public class clearCache implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
return MessagesFragment.this.restart();
|
||||
return MessagesFragment.this.restart(preference);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import static ru.vtosters.lite.ui.components.BackupManager.deletePrefs;
|
||||
import static ru.vtosters.lite.ui.components.BackupManager.restoreBackup;
|
||||
import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.CacheUtils.deleteCache;
|
||||
@@ -77,7 +76,7 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
||||
String token = data.getStringExtra("token");
|
||||
AndroidUtils.getPreferences().edit().putString("vk_admin_token", token).apply();
|
||||
Log.d("VkAdminToken", token);
|
||||
Toast.makeText(getContext(), AndroidUtils.getString("token_saved"), LENGTH_SHORT).show();
|
||||
Toast.makeText(getContext(), "Токен успешно сохранён", LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,31 +95,25 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference("resetfolders").setOnPreferenceClickListener(preference -> {
|
||||
edit().remove("photos_directory").remove("videos_directory").remove("audios_directory").remove("downloads_directory").apply();
|
||||
Toast.makeText(getContext(), AndroidUtils.getString("download_folders_reseted"), LENGTH_SHORT).show();
|
||||
return true;
|
||||
});
|
||||
|
||||
var pref = getDefaultPrefs().getString("autoclearcache", "Default");
|
||||
switch (pref) {
|
||||
case "Default":
|
||||
findPreference("autoclearcache").setSummary(AndroidUtils.getString("cache_disabled"));
|
||||
findPreference("autoclearcache").setSummary("Не включено");
|
||||
break;
|
||||
case "100mb":
|
||||
findPreference("autoclearcache").setSummary(AndroidUtils.getString("cache_100mb"));
|
||||
findPreference("autoclearcache").setSummary("Очищать кеш при не менее 100 Мб");
|
||||
break;
|
||||
case "500mb":
|
||||
findPreference("autoclearcache").setSummary(AndroidUtils.getString("cache_500mb"));
|
||||
findPreference("autoclearcache").setSummary("Очищать кеш при не менее 500 Мб");
|
||||
break;
|
||||
case "1gb":
|
||||
findPreference("autoclearcache").setSummary(AndroidUtils.getString("cache_1gb"));
|
||||
findPreference("autoclearcache").setSummary("Очищать кеш при не менее 1 Гб");
|
||||
break;
|
||||
case "2gb":
|
||||
findPreference("autoclearcache").setSummary(AndroidUtils.getString("cache_2gb"));
|
||||
findPreference("autoclearcache").setSummary("Очищать кеш при не менее 2 Гб");
|
||||
break;
|
||||
case "5gb":
|
||||
findPreference("autoclearcache").setSummary(AndroidUtils.getString("cache_5gb"));
|
||||
findPreference("autoclearcache").setSummary("Очищать кеш при не менее 5 Гб");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -192,12 +185,12 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
||||
five.setChecked(val == 5);
|
||||
|
||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(getContext());
|
||||
builder.setTitle(AndroidUtils.getString("cache_clean_title"));
|
||||
builder.setMessage(AndroidUtils.getString("cache_select_size"));
|
||||
builder.setTitle("Очистка кеша");
|
||||
builder.setMessage("Выберите объём кеша для очистки");
|
||||
builder.setCancelable(true);
|
||||
builder.setNegativeButton(AndroidUtils.getString("cancel"), null);
|
||||
builder.setNegativeButton("Отмена", null);
|
||||
builder.setView(rg);
|
||||
builder.setPositiveButton(AndroidUtils.getString("save"), (dialog, which) -> {
|
||||
builder.setPositiveButton("Сохранить", (dialog, which) -> {
|
||||
var pref = getDefaultPrefs().edit();
|
||||
var checked = rg.getCheckedRadioButtonId();
|
||||
|
||||
@@ -228,8 +221,8 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
||||
|
||||
private void cacheCleanDialog() {
|
||||
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(getContext());
|
||||
builder.setTitle(AndroidUtils.getString("select_which_clean"));
|
||||
builder.setItems(AndroidUtils.getArray("cache_cleaner"), (dialog, which) -> {
|
||||
builder.setTitle("Выберите что вы хотите очистить");
|
||||
builder.setItems(new String[]{"Очистить весь кеш", "Очистить кеш стикеров", "Очистить кеш изображений", "Очистить кеш видео", "Очистить кеш сообщений", "Очистить кеш WebView"}, (dialog, which) -> {
|
||||
switch (which) {
|
||||
case 0: {
|
||||
SharedPreferences prefs2 = getContext().getSharedPreferences("stickers_storage", Context.MODE_PRIVATE);
|
||||
@@ -244,6 +237,7 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
||||
ImEngineExt.a(ImEngine1.a());
|
||||
AutoPlayCacheHolder.d.a();
|
||||
MediaStorage.a();
|
||||
deleteCache();
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
@@ -270,7 +264,7 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
||||
break;
|
||||
}
|
||||
|
||||
Toast.makeText(getContext(), AndroidUtils.getString("cache_cleaned"), LENGTH_SHORT).show();
|
||||
Toast.makeText(getContext(), "Кеш очищен", LENGTH_SHORT).show();
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
@@ -289,7 +283,7 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
||||
try {
|
||||
backupOnlines();
|
||||
} catch (IOException e) {
|
||||
Toast.makeText(getContext(), AndroidUtils.getString("no_data_to_backup"), LENGTH_SHORT).show();
|
||||
Toast.makeText(getContext(), "Нет данных для резервного копирования", LENGTH_SHORT).show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -359,14 +353,14 @@ public class OtherFragment extends MaterialPreferenceToolbarFragment {
|
||||
var arr = BackupManager.getBackupsNames();
|
||||
var adapter = new ArrayAdapter(getContext(), android.R.layout.simple_list_item_1, arr);
|
||||
new VkAlertDialog.Builder(getContext())
|
||||
.setTitle(AndroidUtils.getString("select_backup"))
|
||||
.setTitle("Выберите бэкап")
|
||||
.setAdapter(adapter, (dialog, which) -> {
|
||||
try {
|
||||
restoreBackup(arr[which]);
|
||||
Toast.makeText(getContext(), AndroidUtils.getString("backup_success"), LENGTH_LONG).show();
|
||||
Toast.makeText(getContext(), "Настройки восстановлены", LENGTH_LONG).show();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(getContext(), AndroidUtils.getString("backup_error"), LENGTH_LONG).show();
|
||||
Toast.makeText(getContext(), "Ошибка, Настройки не восстановлены", LENGTH_LONG).show();
|
||||
}
|
||||
}).create().show();
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package ru.vtosters.lite.ui.fragments;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import ru.vtosters.lite.themes.managers.PalettesManager;
|
||||
import ru.vtosters.lite.ui.adapters.PalettesAdapter;
|
||||
import ru.vtosters.lite.utils.LayoutUtils;
|
||||
|
||||
public class PalettesManagerFragment extends BaseToolbarFragment {
|
||||
|
||||
private final PalettesManager mManager = PalettesManager.getInstance();
|
||||
|
||||
private PalettesAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
public View onCreateContent(@NonNull LayoutInflater inflater, @Nullable Bundle bundle) {
|
||||
setTitle("Палитры");
|
||||
|
||||
var container = new FrameLayout(getContext());
|
||||
|
||||
mAdapter = new PalettesAdapter();
|
||||
|
||||
var recyclerView = new RecyclerView(getContext());
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
container.addView(recyclerView, LayoutUtils.createFrame(-1, -1));
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.LifecycleUtils.restartApplication;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.Gravity;
|
||||
@@ -47,9 +46,9 @@ public class SuperAppEditorFragment extends BaseToolbarFragment {
|
||||
message.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
||||
message.setTextColor(ThemesUtils.getTextAttr());
|
||||
message.setPadding(
|
||||
dp2px(10),
|
||||
dp2px(10),
|
||||
dp2px(10),
|
||||
AndroidUtils.dp2px(10),
|
||||
AndroidUtils.dp2px(10),
|
||||
AndroidUtils.dp2px(10),
|
||||
0
|
||||
);
|
||||
container.addView(message, LayoutUtils.createLinear(-1, -2));
|
||||
@@ -95,29 +94,16 @@ public class SuperAppEditorFragment extends BaseToolbarFragment {
|
||||
: manager.getDisabledTabs().get(pos - manager.getSelectedTabs().size() - 2);
|
||||
holder.bindMovingItem(item.title);
|
||||
});
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
manager.getSelectedTabs().forEach(item -> {
|
||||
if (item.type.equals("menu"))
|
||||
adapter.addUnmovedItem(item);
|
||||
});
|
||||
manager.getSelectedTabs().forEach(item -> {
|
||||
if (item.type.equals("menu"))
|
||||
adapter.addUnmovedItem(item);
|
||||
});
|
||||
manager.getDisabledTabs().forEach(item -> {
|
||||
if (item.type.equals("menu"))
|
||||
adapter.addUnmovedItem(item);
|
||||
});
|
||||
|
||||
manager.getDisabledTabs().forEach(item -> {
|
||||
if (item.type.equals("menu"))
|
||||
adapter.addUnmovedItem(item);
|
||||
});
|
||||
} else {
|
||||
for (var item : manager.getSelectedTabs()) {
|
||||
if (item.type.equals("menu"))
|
||||
adapter.addUnmovedItem(item);
|
||||
}
|
||||
|
||||
for (var item : manager.getDisabledTabs()) {
|
||||
if (item.type.equals("menu"))
|
||||
adapter.addUnmovedItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
var recyclerView = new RecyclerView(requireContext());
|
||||
var recyclerView = new RecyclerView(getContext());
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
|
||||
@@ -14,9 +14,9 @@ import androidx.preference.Preference;
|
||||
import com.vk.navigation.Navigator;
|
||||
import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||
|
||||
import ru.vtosters.lite.themes.managers.ThemesManager;
|
||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
||||
|
||||
|
||||
public class ThemesFragment extends MaterialPreferenceToolbarFragment {
|
||||
|
||||
@Override
|
||||
@@ -27,6 +27,17 @@ public class ThemesFragment extends MaterialPreferenceToolbarFragment {
|
||||
}
|
||||
|
||||
private void prefs() {
|
||||
var themesPreference = findPreference("themes");
|
||||
var themesManager = ThemesManager.getInstance();
|
||||
// if (themesManager.getThemesCount() > 0)
|
||||
// themesPreference.setSummary(themesManager.getCurrentTheme().name);
|
||||
themesPreference.setOnPreferenceClickListener(preference -> {
|
||||
var intent = new Navigator(ThemesManagerFragment.class).b(getContext());
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getContext().startActivity(intent);
|
||||
return false;
|
||||
});
|
||||
|
||||
findPreference("navbar").setOnPreferenceClickListener(new restart());
|
||||
findPreference("milkshake").setOnPreferenceClickListener(new restart());
|
||||
findPreference("darktheme").setOnPreferenceChangeListener(new restartdark());
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
package ru.vtosters.lite.ui.fragments;
|
||||
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.themes.VTLColors.getAccentColor;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.vk.core.util.ToastUtils;
|
||||
import com.vk.navigation.Navigator;
|
||||
import com.vtosters.lite.R;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.vtosters.lite.themes.managers.ThemesManager;
|
||||
import ru.vtosters.lite.ui.adapters.ThemesAdapter;
|
||||
import ru.vtosters.lite.ui.dialogs.EditTextDialog;
|
||||
import ru.vtosters.lite.utils.LayoutUtils;
|
||||
|
||||
public class ThemesManagerFragment extends BaseToolbarFragment {
|
||||
|
||||
private static final int IMPORT_REQUEST_CODE = 0x1;
|
||||
|
||||
private ThemesAdapter mAdapter;
|
||||
private ThemesManager mManager = ThemesManager.getInstance();
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
super.onActivityResult(requestCode, resultCode, intent);
|
||||
|
||||
switch (requestCode) {
|
||||
case IMPORT_REQUEST_CODE:
|
||||
if (resultCode != Activity.RESULT_OK)
|
||||
return;
|
||||
try {
|
||||
var data = intent.getData();
|
||||
if (data != null) {
|
||||
mManager.copy(getContext().getContentResolver(), data);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
} else {
|
||||
throw new IOException("Error while getting file path");
|
||||
}
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
ToastUtils.a("Не удалось импортировать тему");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateContent(@NonNull LayoutInflater inflater, @Nullable Bundle bundle) {
|
||||
setTitle("Темы");
|
||||
|
||||
var container = new FrameLayout(getContext());
|
||||
|
||||
mAdapter = new ThemesAdapter();
|
||||
|
||||
var recyclerView = new RecyclerView(getContext());
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
container.addView(recyclerView, LayoutUtils.createFrame(-1, -1));
|
||||
|
||||
var buttonsContainer = new LinearLayout(getContext());
|
||||
buttonsContainer.setOrientation(LinearLayout.HORIZONTAL);
|
||||
|
||||
var params = LayoutUtils.createFrame(-2, -2);
|
||||
params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
|
||||
params.setMargins(0, 0, 0, dp2px(12f));
|
||||
container.addView(buttonsContainer, params);
|
||||
|
||||
var addNewTheme = new FloatingActionButton(getContext());
|
||||
addNewTheme.setImageResource(getIdentifier("ic_add_24", "drawable"));
|
||||
addNewTheme.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
addNewTheme.setOnClickListener(v -> {
|
||||
EditTextDialog.create(v.getContext(), "Новая тема", "Название новой темы", null, (dialog, which, editText) -> {
|
||||
var name = editText.getText().toString();
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
ToastUtils.a("Название не может быть пустым");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mManager.create(requireActivity(), name);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
ToastUtils.a("Не удалось изменить название темы");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
buttonsContainer.addView(addNewTheme, LayoutUtils.createLinear(-2, -2));
|
||||
|
||||
buttonsContainer.addView(new View(getContext()), LayoutUtils.createLinear(dp2px(5), 0));
|
||||
|
||||
var importTheme = new FloatingActionButton(getContext());
|
||||
importTheme.setImageResource(getIdentifier("ic_import", "drawable"));
|
||||
importTheme.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
importTheme.setImageTintList(ColorStateList.valueOf(Color.WHITE));
|
||||
importTheme.setOnClickListener(v -> {
|
||||
var intent = new Intent(Intent.ACTION_GET_CONTENT)
|
||||
.setType("*/*")
|
||||
.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
startActivityForResult(Intent.createChooser(intent, "Выберите тему (.vtlt, .svt)"), IMPORT_REQUEST_CODE);
|
||||
ToastUtils.a("Возможен импорт тем из сторонней модификации ВК Sova V RE");
|
||||
});
|
||||
buttonsContainer.addView(importTheme, LayoutUtils.createLinear(-2, -2));
|
||||
|
||||
buttonsContainer.addView(new View(getContext()), LayoutUtils.createLinear(dp2px(5), 0));
|
||||
|
||||
var openPalettes = new FloatingActionButton(getContext());
|
||||
openPalettes.setImageResource(R.drawable.ic_palette_outline_28);
|
||||
openPalettes.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
openPalettes.setOnClickListener(v -> {
|
||||
var intent = new Navigator(PalettesManagerFragment.class, new Bundle()).b(getContext());
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getContext().startActivity(intent);
|
||||
});
|
||||
buttonsContainer.addView(openPalettes, LayoutUtils.createLinear(-2, -2));
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,8 @@ import ru.vtosters.lite.utils.CacheUtils;
|
||||
import ru.vtosters.lite.utils.SSFSUtils;
|
||||
|
||||
public class VTSettings extends MaterialPreferenceToolbarFragment {
|
||||
public int hideitems = 0;
|
||||
|
||||
public static String getValAsString(String stringid, Boolean value) {
|
||||
if (disableSettingsSumms()) return null;
|
||||
|
||||
@@ -114,7 +116,7 @@ public class VTSettings extends MaterialPreferenceToolbarFragment {
|
||||
public static String getSuperappsumm() {
|
||||
if (disableSettingsSumms()) return null;
|
||||
|
||||
return AndroidUtils.getString("elements_hidden_count") + ": " + SuperAppEditorManager.getInstance().getDisabledTabs().size();
|
||||
return "Скрыто элементов" + ": " + SuperAppEditorManager.getInstance().getDisabledTabs().size();
|
||||
}
|
||||
|
||||
public static String getCachesumm() {
|
||||
@@ -330,7 +332,7 @@ public class VTSettings extends MaterialPreferenceToolbarFragment {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
addPreference(this, "", AndroidUtils.getString("debug_warning"), AndroidUtils.getString("vkme_mode_info"), "ic_about_outline_28", preference -> false);
|
||||
addPreference(this, "", "Внимание!", "Некоторые пункты настроек были скрыты из-за режима VK Me \n\nДля отключения режима перейдите в настройки Сообщений", "ic_about_outline_28", preference -> false);
|
||||
}
|
||||
|
||||
addPreference(this, "", AndroidUtils.getString("vtlmedia"), mediasumm, "ic_media_outline_28", preference -> {
|
||||
|
||||
@@ -40,7 +40,6 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.vk.navigation.Navigator;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.vtosters.lite.tgs.TGPref;
|
||||
import ru.vtosters.lite.ui.adapters.StickerPackAdapter;
|
||||
@@ -48,6 +47,7 @@ import ru.vtosters.lite.ui.fragments.BaseToolbarFragment;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
public class StickersFragment extends BaseToolbarFragment {
|
||||
|
||||
public final static String ACTION_RELOAD = "com.vtosters.lite.action.RELOAD_TGS_LIST";
|
||||
|
||||
private final static int TYPE_DIRECT = 0, TYPE_SOCKS = 2;
|
||||
@@ -147,7 +147,7 @@ public class StickersFragment extends BaseToolbarFragment {
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
requireContext().unregisterReceiver(mReceiver);
|
||||
getContext().unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
private void fabClick() {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package ru.vtosters.lite.ui.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatRadioButton;
|
||||
|
||||
public class NoTouchRadioButton extends AppCompatRadioButton {
|
||||
public NoTouchRadioButton(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public NoTouchRadioButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public NoTouchRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package ru.vtosters.lite.ui.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.Checkable;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageButton;
|
||||
|
||||
public class VTLCheckableButton extends AppCompatImageButton implements Checkable {
|
||||
|
||||
private boolean mIsChecked;
|
||||
|
||||
public VTLCheckableButton(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public VTLCheckableButton(Context context, AttributeSet attributeSet) {
|
||||
super(context, attributeSet);
|
||||
}
|
||||
|
||||
public VTLCheckableButton(Context context, AttributeSet attributeSet, int i) {
|
||||
super(context, attributeSet, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
var state = new CustomState(super.onSaveInstanceState());
|
||||
state.setChecked(mIsChecked);
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(Parcelable state) {
|
||||
if (state instanceof CustomState) {
|
||||
var customState = ((CustomState) state);
|
||||
super.onRestoreInstanceState(customState.getSuperState());
|
||||
mIsChecked = customState.isChecked();
|
||||
return;
|
||||
}
|
||||
super.onRestoreInstanceState(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return this.mIsChecked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
mIsChecked = checked;
|
||||
refreshDrawableState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] onCreateDrawableState(int extraSpace) {
|
||||
return mIsChecked
|
||||
? View.mergeDrawableStates(super.onCreateDrawableState(extraSpace + 1), new int[] { android.R.attr.state_checked })
|
||||
: super.onCreateDrawableState(extraSpace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggle() {
|
||||
setChecked(!mIsChecked);
|
||||
}
|
||||
|
||||
static class CustomState extends View.BaseSavedState {
|
||||
private boolean checked;
|
||||
|
||||
public CustomState(Parcelable source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
public CustomState(Parcel source) {
|
||||
super(source);
|
||||
checked = source.readInt() != 0;
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return checked;
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
||||
out.writeInt(checked ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package ru.vtosters.lite.ui.views.flask;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
public class ColorCircle {
|
||||
private float x, y;
|
||||
private float[] hsv = new float[3];
|
||||
private float[] hsvClone;
|
||||
private int color;
|
||||
|
||||
public ColorCircle(float x, float y, float[] hsv) {
|
||||
set(x, y, hsv);
|
||||
}
|
||||
|
||||
public double sqDist(float x, float y) {
|
||||
double dx = this.x - x;
|
||||
double dy = this.y - y;
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public float getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public float[] getHsv() {
|
||||
return hsv;
|
||||
}
|
||||
|
||||
public float[] getHsvWithLightness(float lightness) {
|
||||
if (hsvClone == null)
|
||||
hsvClone = hsv.clone();
|
||||
hsvClone[0] = hsv[0];
|
||||
hsvClone[1] = hsv[1];
|
||||
hsvClone[2] = lightness;
|
||||
return hsvClone;
|
||||
}
|
||||
|
||||
public void set(float x, float y, float[] hsv) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.hsv[0] = hsv[0];
|
||||
this.hsv[1] = hsv[1];
|
||||
this.hsv[2] = hsv[2];
|
||||
this.color = Color.HSVToColor(this.hsv);
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package ru.vtosters.lite.ui.views.flask;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
|
||||
import ru.vtosters.lite.ui.views.flask.builder.PaintBuilder;
|
||||
|
||||
public class ColorCircleDrawable extends ColorDrawable {
|
||||
private float strokeWidth;
|
||||
private Paint strokePaint = PaintBuilder.newPaint().style(Paint.Style.STROKE).stroke(strokeWidth).color(0xff9e9e9e).build();
|
||||
private Paint fillPaint = PaintBuilder.newPaint().style(Paint.Style.FILL).color(0).build();
|
||||
private Paint fillBackPaint = PaintBuilder.newPaint().shader(PaintBuilder.createAlphaPatternShader(26)).build();
|
||||
|
||||
public ColorCircleDrawable(int color) {
|
||||
super(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.drawColor(0);
|
||||
|
||||
int width = canvas.getWidth();
|
||||
float radius = width / 2f;
|
||||
strokeWidth = radius / 8f;
|
||||
|
||||
this.strokePaint.setStrokeWidth(strokeWidth);
|
||||
this.fillPaint.setColor(getColor());
|
||||
canvas.drawCircle(radius, radius, radius - strokeWidth, fillBackPaint);
|
||||
canvas.drawCircle(radius, radius, radius - strokeWidth, fillPaint);
|
||||
canvas.drawCircle(radius, radius, radius - strokeWidth, strokePaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(int color) {
|
||||
super.setColor(color);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
package ru.vtosters.lite.ui.views.flask;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import ru.vtosters.lite.ui.views.flask.builder.PaintBuilder;
|
||||
import ru.vtosters.lite.ui.views.flask.render.ColorWheelRenderOption;
|
||||
import ru.vtosters.lite.ui.views.flask.render.ColorWheelRenderer;
|
||||
import ru.vtosters.lite.ui.views.flask.render.SimpleColorWheelRenderer;
|
||||
|
||||
public class ColorPickerView extends View {
|
||||
private static final float STROKE_RATIO = 1.5f;
|
||||
|
||||
private AlertDialog dialog;
|
||||
private Bitmap colorWheel;
|
||||
private Canvas colorWheelCanvas;
|
||||
private Bitmap currentColor;
|
||||
private Canvas currentColorCanvas;
|
||||
private boolean showBorder;
|
||||
private int density = 8;
|
||||
|
||||
private float lightness = 1;
|
||||
private float alpha = 1;
|
||||
private int backgroundColor = 0x00000000;
|
||||
|
||||
private Integer initialColors[] = new Integer[]{null, null, null, null, null};
|
||||
private int colorSelection = 0;
|
||||
private Integer initialColor;
|
||||
private Paint colorWheelFill = PaintBuilder.newPaint().color(0).build();
|
||||
private Paint selectorStroke = PaintBuilder.newPaint().color(0).build();
|
||||
private Paint alphaPatternPaint = PaintBuilder.newPaint().build();
|
||||
private ColorCircle currentColorCircle;
|
||||
|
||||
private ArrayList<OnColorChangedListener> colorChangedListeners = new ArrayList<>();
|
||||
private ArrayList<OnColorSelectedListener> listeners = new ArrayList<>();
|
||||
|
||||
|
||||
private LinearLayout colorPreview;
|
||||
|
||||
private ColorWheelRenderer renderer;
|
||||
|
||||
public ColorPickerView(Context context) {
|
||||
super(context);
|
||||
initWith();
|
||||
}
|
||||
|
||||
private void initWith() {
|
||||
density = 10;
|
||||
initialColor = 0xffffffff;
|
||||
|
||||
renderer = new SimpleColorWheelRenderer();
|
||||
|
||||
setDensity(density);
|
||||
setInitialColor(initialColor, true);
|
||||
}
|
||||
|
||||
public void setDialog(AlertDialog dialog) {
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasWindowFocus) {
|
||||
super.onWindowFocusChanged(hasWindowFocus);
|
||||
updateColorWheel();
|
||||
currentColorCircle = findNearestByColor(initialColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
updateColorWheel();
|
||||
currentColorCircle = findNearestByColor(initialColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
updateColorWheel();
|
||||
}
|
||||
|
||||
private void updateColorWheel() {
|
||||
int width = getMeasuredWidth();
|
||||
int height = getMeasuredHeight();
|
||||
|
||||
if (height < width)
|
||||
width = height;
|
||||
if (width <= 0)
|
||||
return;
|
||||
if (colorWheel == null || colorWheel.getWidth() != width) {
|
||||
colorWheel = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
|
||||
colorWheelCanvas = new Canvas(colorWheel);
|
||||
alphaPatternPaint.setShader(PaintBuilder.createAlphaPatternShader(26));
|
||||
}
|
||||
if (currentColor == null || currentColor.getWidth() != width) {
|
||||
currentColor = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
|
||||
currentColorCanvas = new Canvas(currentColor);
|
||||
}
|
||||
drawColorWheel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void drawColorWheel() {
|
||||
colorWheelCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
currentColorCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||
|
||||
if (renderer == null) return;
|
||||
|
||||
float half = colorWheelCanvas.getWidth() / 2f;
|
||||
float strokeWidth = STROKE_RATIO * (1f + ColorWheelRenderer.GAP_PERCENTAGE);
|
||||
float maxRadius = half - strokeWidth - half / density;
|
||||
float cSize = maxRadius / (density - 1) / 2;
|
||||
|
||||
ColorWheelRenderOption colorWheelRenderOption = renderer.getRenderOption();
|
||||
colorWheelRenderOption.density = this.density;
|
||||
colorWheelRenderOption.maxRadius = maxRadius;
|
||||
colorWheelRenderOption.cSize = cSize;
|
||||
colorWheelRenderOption.strokeWidth = strokeWidth;
|
||||
colorWheelRenderOption.alpha = alpha;
|
||||
colorWheelRenderOption.lightness = lightness;
|
||||
colorWheelRenderOption.targetCanvas = colorWheelCanvas;
|
||||
|
||||
renderer.initWith(colorWheelRenderOption);
|
||||
renderer.draw();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int width = 0;
|
||||
if (widthMode == MeasureSpec.UNSPECIFIED)
|
||||
width = widthMeasureSpec;
|
||||
else if (widthMode == MeasureSpec.AT_MOST)
|
||||
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
else if (widthMode == MeasureSpec.EXACTLY)
|
||||
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int height = 0;
|
||||
if (heightMode == MeasureSpec.UNSPECIFIED)
|
||||
height = heightMeasureSpec;
|
||||
else if (heightMode == MeasureSpec.AT_MOST)
|
||||
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
else if (heightMode == MeasureSpec.EXACTLY)
|
||||
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
int squareDimen = width;
|
||||
if (height < width)
|
||||
squareDimen = height;
|
||||
setMeasuredDimension(squareDimen, squareDimen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
int lastSelectedColor = getSelectedColor();
|
||||
currentColorCircle = findNearestByPosition(event.getX(), event.getY());
|
||||
int selectedColor = getSelectedColor();
|
||||
|
||||
callOnColorChangedListeners(lastSelectedColor, selectedColor);
|
||||
|
||||
initialColor = selectedColor;
|
||||
updateColorWheel();
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP: {
|
||||
int selectedColor = getSelectedColor();
|
||||
if (listeners != null) {
|
||||
for (OnColorSelectedListener listener : listeners) {
|
||||
try {
|
||||
listener.onColorSelected(dialog, selectedColor);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
setColorPreviewColor(selectedColor);
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void callOnColorChangedListeners(int oldColor, int newColor) {
|
||||
if (colorChangedListeners != null && oldColor != newColor) {
|
||||
for (OnColorChangedListener listener : colorChangedListeners) {
|
||||
try {
|
||||
listener.onColorChanged(newColor);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
canvas.drawColor(backgroundColor);
|
||||
|
||||
float maxRadius = canvas.getWidth() / (1f + ColorWheelRenderer.GAP_PERCENTAGE);
|
||||
float size = maxRadius / density / 2;
|
||||
if (colorWheel != null && currentColorCircle != null) {
|
||||
colorWheelFill.setColor(Color.HSVToColor(currentColorCircle.getHsvWithLightness(this.lightness)));
|
||||
colorWheelFill.setAlpha((int) (alpha * 0xff));
|
||||
|
||||
// a separate canvas is used to erase an issue with the alpha pattern around the edges
|
||||
// draw circle slightly larger than it needs to be, then erase edges to proper dimensions
|
||||
currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + 4, alphaPatternPaint);
|
||||
currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + 4, colorWheelFill);
|
||||
|
||||
selectorStroke = PaintBuilder.newPaint().color(0xffffffff).style(Paint.Style.STROKE).stroke(size * (STROKE_RATIO - 1)).xPerMode(PorterDuff.Mode.CLEAR).build();
|
||||
|
||||
if (showBorder) colorWheelCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + (selectorStroke.getStrokeWidth() / 2f), selectorStroke);
|
||||
canvas.drawBitmap(colorWheel, 0, 0, null);
|
||||
|
||||
currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + (selectorStroke.getStrokeWidth() / 2f), selectorStroke);
|
||||
canvas.drawBitmap(currentColor, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
private ColorCircle findNearestByPosition(float x, float y) {
|
||||
ColorCircle near = null;
|
||||
double minDist = Double.MAX_VALUE;
|
||||
|
||||
for (ColorCircle colorCircle : renderer.getColorCircleList()) {
|
||||
double dist = colorCircle.sqDist(x, y);
|
||||
if (minDist > dist) {
|
||||
minDist = dist;
|
||||
near = colorCircle;
|
||||
}
|
||||
}
|
||||
|
||||
return near;
|
||||
}
|
||||
|
||||
private ColorCircle findNearestByColor(int color) {
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(color, hsv);
|
||||
ColorCircle near = null;
|
||||
double minDiff = Double.MAX_VALUE;
|
||||
double x = hsv[1] * Math.cos(hsv[0] * Math.PI / 180);
|
||||
double y = hsv[1] * Math.sin(hsv[0] * Math.PI / 180);
|
||||
|
||||
for (ColorCircle colorCircle : renderer.getColorCircleList()) {
|
||||
float[] hsv1 = colorCircle.getHsv();
|
||||
double x1 = hsv1[1] * Math.cos(hsv1[0] * Math.PI / 180);
|
||||
double y1 = hsv1[1] * Math.sin(hsv1[0] * Math.PI / 180);
|
||||
double dx = x - x1;
|
||||
double dy = y - y1;
|
||||
double dist = dx * dx + dy * dy;
|
||||
if (dist < minDiff) {
|
||||
minDiff = dist;
|
||||
near = colorCircle;
|
||||
}
|
||||
}
|
||||
|
||||
return near;
|
||||
}
|
||||
|
||||
public int getSelectedColor() {
|
||||
int color = 0;
|
||||
if (currentColorCircle != null)
|
||||
color = Utils.colorAtLightness(currentColorCircle.getColor(), this.lightness);
|
||||
return Utils.adjustAlpha(this.alpha, color);
|
||||
}
|
||||
|
||||
public Integer[] getAllColors() {
|
||||
return initialColors;
|
||||
}
|
||||
|
||||
public void setInitialColors(Integer[] colors, int selectedColor) {
|
||||
this.initialColors = colors;
|
||||
this.colorSelection = selectedColor;
|
||||
Integer initialColor = this.initialColors[this.colorSelection];
|
||||
if (initialColor == null) initialColor = 0xffffffff;
|
||||
setInitialColor(initialColor, true);
|
||||
}
|
||||
|
||||
public void setInitialColor(int color, boolean updateText) {
|
||||
float[] hsv = new float[3];
|
||||
Color.colorToHSV(color, hsv);
|
||||
|
||||
this.alpha = Utils.getAlphaPercent(color);
|
||||
this.lightness = hsv[2];
|
||||
this.initialColors[this.colorSelection] = color;
|
||||
this.initialColor = color;
|
||||
setColorPreviewColor(color);
|
||||
currentColorCircle = findNearestByColor(color);
|
||||
}
|
||||
|
||||
public void setLightness(float lightness) {
|
||||
int lastSelectedColor = getSelectedColor();
|
||||
|
||||
this.lightness = lightness;
|
||||
if (currentColorCircle != null) {
|
||||
this.initialColor = Color.HSVToColor(Utils.alphaValueAsInt(this.alpha), currentColorCircle.getHsvWithLightness(lightness));
|
||||
|
||||
callOnColorChangedListeners(lastSelectedColor, this.initialColor);
|
||||
|
||||
updateColorWheel();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setColor(int color, boolean updateText) {
|
||||
setInitialColor(color, updateText);
|
||||
updateColorWheel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setAlphaValue(float alpha) {
|
||||
int lastSelectedColor = getSelectedColor();
|
||||
|
||||
this.alpha = alpha;
|
||||
this.initialColor = Color.HSVToColor(Utils.alphaValueAsInt(this.alpha), currentColorCircle.getHsvWithLightness(this.lightness));
|
||||
|
||||
callOnColorChangedListeners(lastSelectedColor, this.initialColor);
|
||||
|
||||
updateColorWheel();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void addOnColorChangedListener(OnColorChangedListener listener) {
|
||||
this.colorChangedListeners.add(listener);
|
||||
}
|
||||
|
||||
public void addOnColorSelectedListener(OnColorSelectedListener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
public void setDensity(int density) {
|
||||
this.density = Math.max(2, density);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setColorPreview(LinearLayout colorPreview, Integer selectedColor) {
|
||||
if (colorPreview == null)
|
||||
return;
|
||||
this.colorPreview = colorPreview;
|
||||
if (selectedColor == null)
|
||||
selectedColor = 0;
|
||||
int children = colorPreview.getChildCount();
|
||||
if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < children; i++) {
|
||||
View childView = colorPreview.getChildAt(i);
|
||||
if (!(childView instanceof LinearLayout))
|
||||
continue;
|
||||
LinearLayout childLayout = (LinearLayout) childView;
|
||||
if (i == selectedColor) {
|
||||
childLayout.setBackgroundColor(Color.WHITE);
|
||||
}
|
||||
ImageView childImage = childLayout.findViewWithTag("image_preview");
|
||||
childImage.setClickable(true);
|
||||
childImage.setTag(i);
|
||||
childImage.setOnClickListener(v -> {
|
||||
if (v == null)
|
||||
return;
|
||||
Object tag = v.getTag();
|
||||
if (tag == null || !(tag instanceof Integer))
|
||||
return;
|
||||
setSelectedColor((int) tag);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setSelectedColor(int previewNumber) {
|
||||
if (initialColors == null || initialColors.length < previewNumber)
|
||||
return;
|
||||
this.colorSelection = previewNumber;
|
||||
setHighlightedColor(previewNumber);
|
||||
Integer color = initialColors[previewNumber];
|
||||
if (color == null)
|
||||
return;
|
||||
setColor(color, true);
|
||||
}
|
||||
|
||||
public void setShowBorder(boolean showBorder) {
|
||||
this.showBorder = showBorder;
|
||||
}
|
||||
|
||||
private void setHighlightedColor(int previewNumber) {
|
||||
int children = colorPreview.getChildCount();
|
||||
if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < children; i++) {
|
||||
View childView = colorPreview.getChildAt(i);
|
||||
if (!(childView instanceof LinearLayout))
|
||||
continue;
|
||||
LinearLayout childLayout = (LinearLayout) childView;
|
||||
if (i == previewNumber) {
|
||||
childLayout.setBackgroundColor(Color.WHITE);
|
||||
} else {
|
||||
childLayout.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setColorPreviewColor(int newColor) {
|
||||
if (colorPreview == null || initialColors == null || colorSelection > initialColors.length || initialColors[colorSelection] == null)
|
||||
return;
|
||||
|
||||
int children = colorPreview.getChildCount();
|
||||
if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
|
||||
return;
|
||||
|
||||
View childView = colorPreview.getChildAt(colorSelection);
|
||||
if (!(childView instanceof LinearLayout))
|
||||
return;
|
||||
LinearLayout childLayout = (LinearLayout) childView;
|
||||
ImageView childImage = childLayout.findViewWithTag("image_preview");
|
||||
childImage.setImageDrawable(new ColorCircleDrawable(newColor));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user