mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 11:37:36 +00:00
Compare commits
686 Commits
v26.1
...
canary-270
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0495468d02 | ||
![]() |
300a2a242c | ||
![]() |
33aebb5976 | ||
![]() |
b3d6809c0b | ||
![]() |
461f7e9f89 | ||
![]() |
9cc50b20d8 | ||
![]() |
f488e9df8f | ||
![]() |
0dc596e206 | ||
![]() |
c3bf03190b | ||
![]() |
021ae891a9 | ||
![]() |
9c03514eb1 | ||
![]() |
eb74b266e1 | ||
![]() |
80eb6ff25a | ||
![]() |
7b81e2d2d1 | ||
![]() |
a8789073f1 | ||
![]() |
c8fe0f5524 | ||
![]() |
d33b077a13 | ||
![]() |
2282365cf8 | ||
![]() |
9a00b7b942 | ||
![]() |
d54baadbed | ||
![]() |
0869a90fe3 | ||
![]() |
2754b1dcf8 | ||
![]() |
0db6314661 | ||
![]() |
b5d2ef18e8 | ||
![]() |
6e22476acc | ||
![]() |
b26db8cee6 | ||
![]() |
33cb39c8af | ||
![]() |
f247759a6e | ||
![]() |
de7e5bdfe7 | ||
![]() |
53a8ba8cfe | ||
![]() |
f2d057baba | ||
![]() |
93bcf2cd25 | ||
![]() |
6d82515cfc | ||
![]() |
a177d3b022 | ||
![]() |
92b2e06e57 | ||
![]() |
f919bb0e99 | ||
![]() |
054971e899 | ||
![]() |
93c3d36452 | ||
![]() |
4c38af994d | ||
![]() |
bbb8efe92c | ||
![]() |
659dd09723 | ||
![]() |
4931825912 | ||
![]() |
ef81cdab4f | ||
![]() |
7c0b25cad9 | ||
![]() |
b38ab2a7d6 | ||
![]() |
a97191052b | ||
![]() |
2963d4ca9e | ||
![]() |
6aab856de7 | ||
![]() |
94d1c66f8a | ||
![]() |
7ff4d7608e | ||
![]() |
46ef915c83 | ||
![]() |
63b0a0d96b | ||
![]() |
ea4cabdfc5 | ||
![]() |
0185ddf577 | ||
![]() |
ddae568741 | ||
![]() |
fcb7ebb090 | ||
![]() |
8d446fcc16 | ||
![]() |
881d3b5221 | ||
![]() |
fe9ec3bc6d | ||
![]() |
480198dcd0 | ||
![]() |
4ab7bc0d97 | ||
![]() |
7173693d1b | ||
![]() |
6b81716440 | ||
![]() |
88e8e15607 | ||
![]() |
69181a6b72 | ||
![]() |
b11b81122a | ||
![]() |
648e3ee36b | ||
![]() |
724b94f320 | ||
![]() |
a6e65f9a7e | ||
![]() |
af5c4d09c4 | ||
![]() |
872394cb58 | ||
![]() |
fcbbe9a22e | ||
![]() |
b168163ef0 | ||
![]() |
3e38b8fed1 | ||
![]() |
f90c548f27 | ||
![]() |
c981c40218 | ||
![]() |
dcbf37c5e8 | ||
![]() |
300b233a27 | ||
![]() |
e32cd03d0b | ||
![]() |
a07b9315a5 | ||
![]() |
e9694c6195 | ||
![]() |
4a2a37c87a | ||
![]() |
7dca5b831a | ||
![]() |
be5ff68140 | ||
![]() |
59f40d5fe5 | ||
![]() |
1fbd053a42 | ||
![]() |
966c6314f8 | ||
![]() |
c92204c724 | ||
![]() |
bb9947d4d2 | ||
![]() |
7c8cdb4ad6 | ||
![]() |
bd7f9c9e46 | ||
![]() |
9a33a4dfe2 | ||
![]() |
47e918bc92 | ||
![]() |
c194168d9b | ||
![]() |
cacc60b1ac | ||
![]() |
52063b3652 | ||
![]() |
85a4eaff59 | ||
![]() |
45fa1fce70 | ||
![]() |
2112c916f5 | ||
![]() |
d6e159bff9 | ||
![]() |
2f710a564f | ||
![]() |
27cfc4945c | ||
![]() |
7cdada92c8 | ||
![]() |
8f1e57d4f9 | ||
![]() |
8178666b49 | ||
![]() |
313532dcaa | ||
![]() |
2f8f3dc266 | ||
![]() |
df6ada5ce3 | ||
![]() |
a89b9e6af1 | ||
![]() |
23ed275614 | ||
![]() |
cfd1e0cf22 | ||
![]() |
eb400f19b1 | ||
![]() |
19f15f16f6 | ||
![]() |
e158cfddfa | ||
![]() |
d0cf93a08d | ||
![]() |
08ad0e74dd | ||
![]() |
722374a024 | ||
![]() |
c6f0762510 | ||
![]() |
941a363c5a | ||
![]() |
2afcdc64a0 | ||
![]() |
3c66c4bbc5 | ||
![]() |
9f5cd5e1cc | ||
![]() |
a35f2bb73b | ||
![]() |
6cf00130f4 | ||
![]() |
6c27ba6b88 | ||
![]() |
dd3b9980e7 | ||
![]() |
02e189a029 | ||
![]() |
72b8d12ee4 | ||
![]() |
eed03080c1 | ||
![]() |
090cb4b0f9 | ||
![]() |
6f2c76b898 | ||
![]() |
f61827cbec | ||
![]() |
3f2264f2c7 | ||
![]() |
c1cadf4bdc | ||
![]() |
0e56991369 | ||
![]() |
4dc1c59040 | ||
![]() |
33b7b8b297 | ||
![]() |
e6af5ed460 | ||
![]() |
b678afa4b6 | ||
![]() |
4bac2df4e7 | ||
![]() |
50416eee09 | ||
![]() |
73cf501d33 | ||
![]() |
d2b7907bed | ||
![]() |
99d5dd5ea8 | ||
![]() |
5fdb841fa8 | ||
![]() |
7c88484d64 | ||
![]() |
b22b6a4204 | ||
![]() |
2a3d34c812 | ||
![]() |
c50ee722a1 | ||
![]() |
ffc1e38e48 | ||
![]() |
6219d5fcbf | ||
![]() |
2e4440b702 | ||
![]() |
0d9ec0931b | ||
![]() |
60e8415369 | ||
![]() |
652a26d5d9 | ||
![]() |
f57839379a | ||
![]() |
36bd00a046 | ||
![]() |
fb5ee86615 | ||
![]() |
30bf5c8448 | ||
![]() |
2051836a73 | ||
![]() |
2cb0af1ff3 | ||
![]() |
a1b6568226 | ||
![]() |
1eddbfd72c | ||
![]() |
21ed095601 | ||
![]() |
000a2e4d59 | ||
![]() |
7abe635de9 | ||
![]() |
9a008c17ba | ||
![]() |
08dbf728a4 | ||
![]() |
4670f762d3 | ||
![]() |
efa49567fa | ||
![]() |
0ffc4527a7 | ||
![]() |
dd9d43be96 | ||
![]() |
865fca71a5 | ||
![]() |
6b4baa3bcd | ||
![]() |
a9ee2d7d18 | ||
![]() |
d654b9cb97 | ||
![]() |
4d2921e742 | ||
![]() |
ecc74d45d1 | ||
![]() |
5de597f079 | ||
![]() |
156b0e67ca | ||
![]() |
10069215f4 | ||
![]() |
92b305a389 | ||
![]() |
d20b30c771 | ||
![]() |
83209b21ff | ||
![]() |
81658d45f7 | ||
![]() |
c951b208a1 | ||
![]() |
050a073771 | ||
![]() |
21d374214f | ||
![]() |
19ea25a9d0 | ||
![]() |
dbf6e40dfe | ||
![]() |
d56f4fbc90 | ||
![]() |
73c3d741a7 | ||
![]() |
2b5fc75127 | ||
![]() |
991802ab82 | ||
![]() |
7f6b5305ba | ||
![]() |
825c6c4316 | ||
![]() |
f00408c793 | ||
![]() |
a6ff3672af | ||
![]() |
2290ddeb89 | ||
![]() |
74af79ad03 | ||
![]() |
b6c24a3a8a | ||
![]() |
a8c2ae223a | ||
![]() |
953d44302c | ||
![]() |
24e46a5971 | ||
![]() |
b1297c4192 | ||
![]() |
9ae328fd84 | ||
![]() |
625a1d6f44 | ||
![]() |
987e5f5413 | ||
![]() |
715284b70d | ||
![]() |
62fc7868ac | ||
![]() |
1a70796339 | ||
![]() |
af6965eefa | ||
![]() |
8f7d2e38f7 | ||
![]() |
be433fa667 | ||
![]() |
0ccd6e7381 | ||
![]() |
907bbbda41 | ||
![]() |
4393bc077d | ||
![]() |
365b373480 | ||
![]() |
47e6dd286d | ||
![]() |
0dbaf52566 | ||
![]() |
66f49dfab5 | ||
![]() |
f8967e9274 | ||
![]() |
a4f008fde5 | ||
![]() |
e9980c778b | ||
![]() |
06b6fb0c33 | ||
![]() |
38cb3d4105 | ||
![]() |
db99caf258 | ||
![]() |
39dbffadfe | ||
![]() |
b7505c3c9c | ||
![]() |
3185e5a7ca | ||
![]() |
e0cbe28711 | ||
![]() |
66cee19cea | ||
![]() |
2ec29ade79 | ||
![]() |
c865d4e187 | ||
![]() |
a42a0a53ce | ||
![]() |
6d79de7d71 | ||
![]() |
7e9abe6e90 | ||
![]() |
4d5510be4f | ||
![]() |
b04e1394c0 | ||
![]() |
2aa923191e | ||
![]() |
4bf1c74164 | ||
![]() |
472c7878b2 | ||
![]() |
38ad871e33 | ||
![]() |
c5d34670c4 | ||
![]() |
154121f3dd | ||
![]() |
3d91a561fe | ||
![]() |
2c6adbc69b | ||
![]() |
5280982363 | ||
![]() |
18c45ae289 | ||
![]() |
41fbd2a7be | ||
![]() |
5e45884af4 | ||
![]() |
d78ee171bc | ||
![]() |
356ee1febd | ||
![]() |
cc044ccc4c | ||
![]() |
9c638cc463 | ||
![]() |
df786eb2b6 | ||
![]() |
8e7186eebb | ||
![]() |
74b7b84561 | ||
![]() |
308c9999fa | ||
![]() |
930bb8687f | ||
![]() |
f2c4288d2d | ||
![]() |
b44141ae39 | ||
![]() |
86e0020964 | ||
![]() |
94d3daeadf | ||
![]() |
79334b7702 | ||
![]() |
df66458db6 | ||
![]() |
97705704e2 | ||
![]() |
1206179580 | ||
![]() |
a0b8aa4da6 | ||
![]() |
65207f96c8 | ||
![]() |
062e498bdd | ||
![]() |
1057cb3e3c | ||
![]() |
2dd23b2518 | ||
![]() |
8cab12998c | ||
![]() |
48b1c26dc8 | ||
![]() |
f1e0bc3e4a | ||
![]() |
38527cd58f | ||
![]() |
e94d65b4b2 | ||
![]() |
27ece3c7df | ||
![]() |
06687abffc | ||
![]() |
deedb462a0 | ||
![]() |
c48962bdf7 | ||
![]() |
1ef3f6e13b | ||
![]() |
83a34a9004 | ||
![]() |
e30bda6c8d | ||
![]() |
00e9d76a5a | ||
![]() |
6cda6c2fae | ||
![]() |
6dfda6dc39 | ||
![]() |
f41994cb52 | ||
![]() |
a003336497 | ||
![]() |
401090d6fe | ||
![]() |
90dcc1cd30 | ||
![]() |
2ac464b186 | ||
![]() |
8b7fae278b | ||
![]() |
d73c2daf6d | ||
![]() |
ca25935de3 | ||
![]() |
d7750b7220 | ||
![]() |
98861f0b5a | ||
![]() |
e35925d520 | ||
![]() |
685a2d2101 | ||
![]() |
f7e471616d | ||
![]() |
c013a349af | ||
![]() |
61ea59a27b | ||
![]() |
e55f338367 | ||
![]() |
1425cf4105 | ||
![]() |
b493a985b0 | ||
![]() |
1fe9ede940 | ||
![]() |
1fd49e4987 | ||
![]() |
d49b02b274 | ||
![]() |
d47e70cfaa | ||
![]() |
40cb031af5 | ||
![]() |
1dcf325547 | ||
![]() |
4e99997013 | ||
![]() |
334554697d | ||
![]() |
e77cbd0c15 | ||
![]() |
46ba008b9d | ||
![]() |
58aded31c2 | ||
![]() |
6f6b0ade06 | ||
![]() |
d9b67a207b | ||
![]() |
c7083659aa | ||
![]() |
a6d1803105 | ||
![]() |
66eef75673 | ||
![]() |
367f5f7b44 | ||
![]() |
0edcb03c45 | ||
![]() |
63eef153de | ||
![]() |
68442f38ac | ||
![]() |
8d5b9e5329 | ||
![]() |
6c0966b795 | ||
![]() |
7c2e93d266 | ||
![]() |
1ff7b9055f | ||
![]() |
49f241b77c | ||
![]() |
cfb20b0f86 | ||
![]() |
6d6f14fcb3 | ||
![]() |
977c981265 | ||
![]() |
ef48abf19d | ||
![]() |
65c18f9c09 | ||
![]() |
ecb31eed40 | ||
![]() |
a80cadf587 | ||
![]() |
fce1bf2365 | ||
![]() |
cbc6d40b2c | ||
![]() |
9fbd079560 | ||
![]() |
42eb928054 | ||
![]() |
577483fde1 | ||
![]() |
aa6c7c15cc | ||
![]() |
6c807d35b2 | ||
![]() |
8ca8cdae97 | ||
![]() |
75e37be6f3 | ||
![]() |
4985314ca6 | ||
![]() |
ac5ceb18c8 | ||
![]() |
72b39594d3 | ||
![]() |
16ae4aedf1 | ||
![]() |
3ba00858e6 | ||
![]() |
489100c755 | ||
![]() |
da766f2a4e | ||
![]() |
c81d7ff76c | ||
![]() |
a6e50d3648 | ||
![]() |
a177846044 | ||
![]() |
19a4e11645 | ||
![]() |
67cc36268e | ||
![]() |
28770b9a32 | ||
![]() |
9f92e1bf15 | ||
![]() |
23fe5d5a19 | ||
![]() |
9088b584f6 | ||
![]() |
beaf636415 | ||
![]() |
09bb2fe8dc | ||
![]() |
1d6747d90e | ||
![]() |
efadd94de3 | ||
![]() |
8c0b4e444a | ||
![]() |
32c7106e40 | ||
![]() |
d2f2a9e4c8 | ||
![]() |
985454afd4 | ||
![]() |
9e1322de25 | ||
![]() |
4e4ec73d94 | ||
![]() |
bb39a524d0 | ||
![]() |
196d9af099 | ||
![]() |
1eeb2a34a1 | ||
![]() |
cf43c56218 | ||
![]() |
e6c1aec443 | ||
![]() |
43fd1c4c1b | ||
![]() |
022caca979 | ||
![]() |
0352ea2cca | ||
![]() |
e483d6befe | ||
![]() |
678c07fff5 | ||
![]() |
91c92051f1 | ||
![]() |
4b8a0388e7 | ||
![]() |
66788dc58c | ||
![]() |
dd8c28b1cb | ||
![]() |
32c5153e8e | ||
![]() |
36de62873a | ||
![]() |
51e37880c6 | ||
![]() |
4b83c1e76c | ||
![]() |
b0b04690d5 | ||
![]() |
6d1e8d86cb | ||
![]() |
eda8c70a80 | ||
![]() |
587b6cfd41 | ||
![]() |
e774408782 | ||
![]() |
187f583c95 | ||
![]() |
f5d3a71478 | ||
![]() |
d868ff3080 | ||
![]() |
f80198a669 | ||
![]() |
6076b52c48 | ||
![]() |
79a1c39b30 | ||
![]() |
5c92d39498 | ||
![]() |
6e7a995716 | ||
![]() |
a55d570213 | ||
![]() |
5d07d0b964 | ||
![]() |
ec115cd7e3 | ||
![]() |
9b3896fd3d | ||
![]() |
a3f5918d25 | ||
![]() |
b28326198c | ||
![]() |
46275b90c2 | ||
![]() |
15e13a8d8b | ||
![]() |
b750c89c87 | ||
![]() |
8d7c7c3dfb | ||
![]() |
8e1a91509c | ||
![]() |
927cd571f8 | ||
![]() |
5fbd3e5c65 | ||
![]() |
877aeb66cb | ||
![]() |
8a88d8465a | ||
![]() |
dda8cc85c9 | ||
![]() |
6a59939d9a | ||
![]() |
4745e86c1b | ||
![]() |
9aa466c773 | ||
![]() |
0243610c09 | ||
![]() |
0a2a590ab7 | ||
![]() |
89aee6ffa7 | ||
![]() |
4eaf701cb7 | ||
![]() |
4fff2aa7d8 | ||
![]() |
35b3c8ba5c | ||
![]() |
1d7cff7703 | ||
![]() |
8d81bd0e33 | ||
![]() |
7826d7527f | ||
![]() |
d4e552d08b | ||
![]() |
5a16418543 | ||
![]() |
7297aba15a | ||
![]() |
bc5d5f9502 | ||
![]() |
1761986c1b | ||
![]() |
1e034e3e0e | ||
![]() |
bbf9756bfa | ||
![]() |
96e559fb0e | ||
![]() |
4c45775131 | ||
![]() |
c072b4254d | ||
![]() |
2dbb812126 | ||
![]() |
be50f17f55 | ||
![]() |
6f77f190f2 | ||
![]() |
6bdc57cbe4 | ||
![]() |
de00f1d5a9 | ||
![]() |
e9b9bf987b | ||
![]() |
f4b6385f9f | ||
![]() |
75d905a56d | ||
![]() |
b1363ee479 | ||
![]() |
51afe43a30 | ||
![]() |
189c03c047 | ||
![]() |
ae9d270a32 | ||
![]() |
e47e869f6b | ||
![]() |
c39038a439 | ||
![]() |
69174e2c13 | ||
![]() |
474268a0af | ||
![]() |
eadb0307fa | ||
![]() |
5a5d0d5d72 | ||
![]() |
a1273bc467 | ||
![]() |
0c28a916be | ||
![]() |
0ba573b789 | ||
![]() |
ec42ee152c | ||
![]() |
abcb487361 | ||
![]() |
d12d9e82f1 | ||
![]() |
275208e81b | ||
![]() |
41226c12b8 | ||
![]() |
f86c66c99d | ||
![]() |
93876b5fd3 | ||
![]() |
b5b14ce343 | ||
![]() |
350d0d600c | ||
![]() |
f924ffcbf3 | ||
![]() |
0f5963f231 | ||
![]() |
1961ff2c40 | ||
![]() |
40003691d6 | ||
![]() |
8290358241 | ||
![]() |
ee34f775c3 | ||
![]() |
feb47cd88c | ||
![]() |
c6efb51f61 | ||
![]() |
a5acf33ccd | ||
![]() |
ab9ee449e4 | ||
![]() |
9571b6f9be | ||
![]() |
207d7fd3f6 | ||
![]() |
bcdcfa1104 | ||
![]() |
e0a4230dac | ||
![]() |
17ba5cba3e | ||
![]() |
f2e109ad7d | ||
![]() |
c83e141a1c | ||
![]() |
6089cc36de | ||
![]() |
9638dc0a66 | ||
![]() |
b191a14a23 | ||
![]() |
cf1bc82537 | ||
![]() |
6141bb5bb3 | ||
![]() |
4d2b62da0d | ||
![]() |
39383229d1 | ||
![]() |
08bfbb154a | ||
![]() |
d390ca2fdf | ||
![]() |
7ad77a14ae | ||
![]() |
f33343b4e6 | ||
![]() |
af65d07456 | ||
![]() |
16d728f379 | ||
![]() |
c97ab690b6 | ||
![]() |
4caed73fe0 | ||
![]() |
4856da1584 | ||
![]() |
0a07018fec | ||
![]() |
64c82e1f2c | ||
![]() |
e8e8afa6c2 | ||
![]() |
af2207433d | ||
![]() |
75ba62d588 | ||
![]() |
606d97ae4d | ||
![]() |
d778b0b0a7 | ||
![]() |
5ee6daf126 | ||
![]() |
43b9a09c9b | ||
![]() |
8475a2bb94 | ||
![]() |
d8692de2f4 | ||
![]() |
33a9abc946 | ||
![]() |
ee943afbc9 | ||
![]() |
1f7c3e9f14 | ||
![]() |
46770db18b | ||
![]() |
92f980601c | ||
![]() |
d0b8c16651 | ||
![]() |
a470ee6f93 | ||
![]() |
ff1c56683d | ||
![]() |
4ee4cbada6 | ||
![]() |
dbc2236dd2 | ||
![]() |
a8c4a33e91 | ||
![]() |
279f955a84 | ||
![]() |
fbd1dbb20c | ||
![]() |
6c09fc2e64 | ||
![]() |
f3304b482c | ||
![]() |
0a85ef61c3 | ||
![]() |
dc26ad7125 | ||
![]() |
24b1c607f3 | ||
![]() |
732a161b67 | ||
![]() |
9c7cf340a1 | ||
![]() |
399b9e5eba | ||
![]() |
5805573625 | ||
![]() |
a6b1149b9f | ||
![]() |
51e985ae7f | ||
![]() |
9929b25339 | ||
![]() |
2359cfc480 | ||
![]() |
81493475f9 | ||
![]() |
0493829231 | ||
![]() |
e2d1952ad9 | ||
![]() |
7450965458 | ||
![]() |
f45384685b | ||
![]() |
8abcccc262 | ||
![]() |
a9c89cbbbb | ||
![]() |
d2eaa6e6c1 | ||
![]() |
53257b6ea1 | ||
![]() |
c874391be4 | ||
![]() |
7e8e013832 | ||
![]() |
037f46f7f0 | ||
![]() |
d3e1c496ca | ||
![]() |
d7d0a44693 | ||
![]() |
9d6f6764cb | ||
![]() |
cb3ab63815 | ||
![]() |
caae932117 | ||
![]() |
e9cf27eb5a | ||
![]() |
6ee6685f4c | ||
![]() |
d15017b777 | ||
![]() |
a9387e63e1 | ||
![]() |
23c1f0111b | ||
![]() |
866386e21f | ||
![]() |
bf10496fa9 | ||
![]() |
607e6547a7 | ||
![]() |
6b21091fe2 | ||
![]() |
e58f98e844 | ||
![]() |
b8cb9cd84d | ||
![]() |
c1038ac6f9 | ||
![]() |
c556dd0aac | ||
![]() |
d2fbcd07b7 | ||
![]() |
bf6359abaa | ||
![]() |
d1621845b8 | ||
![]() |
f33f1d25d0 | ||
![]() |
40f25f4d56 | ||
![]() |
e13775ec2c | ||
![]() |
ee4dad7a13 | ||
![]() |
5e2ef1b7f4 | ||
![]() |
f8c38eab74 | ||
![]() |
305e8b3d14 | ||
![]() |
2a654e5d7f | ||
![]() |
57afae3425 | ||
![]() |
feb44f875e | ||
![]() |
7eebe62bb6 | ||
![]() |
9ea9f01933 | ||
![]() |
665c6bdc4b | ||
![]() |
c79bc83275 | ||
![]() |
c30fbdf145 | ||
![]() |
f12951bd1d | ||
![]() |
52f2e8c4a0 | ||
![]() |
1b2af1ed6d | ||
![]() |
0f9b2a7df8 | ||
![]() |
f2846694e1 | ||
![]() |
e668dbf6f7 | ||
![]() |
d77a368176 | ||
![]() |
ad0da08610 | ||
![]() |
0c52385ad4 | ||
![]() |
5b8b48ccc1 | ||
![]() |
659b9c6fee | ||
![]() |
ec31cab5a7 | ||
![]() |
dd93556ad8 | ||
![]() |
533aeadd38 | ||
![]() |
18d0cedbe2 | ||
![]() |
5a94ef9106 | ||
![]() |
8e8f01f8b5 | ||
![]() |
7087badf87 | ||
![]() |
47d2d4e3a5 | ||
![]() |
6c47d8f556 | ||
![]() |
8c9d0314fb | ||
![]() |
69144942e3 | ||
![]() |
5627053b74 | ||
![]() |
0f666de5e6 | ||
![]() |
eddc862fa3 | ||
![]() |
4327682120 | ||
![]() |
af5bdee78f | ||
![]() |
0e36e86dbf | ||
![]() |
f95478f1f1 | ||
![]() |
9fe8741a02 | ||
![]() |
a5768e02ea | ||
![]() |
f5aaff2b1e | ||
![]() |
655f778171 | ||
![]() |
2e77a426b2 | ||
![]() |
2bcf2e76f1 | ||
![]() |
57bd450798 | ||
![]() |
582cad1b8d | ||
![]() |
6ca2a3d841 | ||
![]() |
91773c3311 | ||
![]() |
dc61033b2c | ||
![]() |
f8d62a4b6c | ||
![]() |
1d2145b1b7 | ||
![]() |
1f7f84b74a | ||
![]() |
cd7a335d0f | ||
![]() |
17569005a4 | ||
![]() |
f36b21bae5 | ||
![]() |
fe1ca52f6d | ||
![]() |
1be647a279 | ||
![]() |
2ea1a47bec | ||
![]() |
2d799dae0d | ||
![]() |
c6408babac | ||
![]() |
a8c1ed8795 | ||
![]() |
e3cb5f8ddd | ||
![]() |
e160e211dd | ||
![]() |
22d05ca399 | ||
![]() |
bd2651057d | ||
![]() |
1610092ec4 | ||
![]() |
b9e6937996 | ||
![]() |
a207f03952 | ||
![]() |
851153dd7c | ||
![]() |
583ffc8177 | ||
![]() |
7518092ad2 | ||
![]() |
8c2ad3883a | ||
![]() |
d364554425 | ||
![]() |
726ffdcd98 | ||
![]() |
f9d22cf8ee | ||
![]() |
ee50da566f | ||
![]() |
9f7d410959 | ||
![]() |
bc94ea4334 | ||
![]() |
c0c9204848 | ||
![]() |
c0d1bf63bc | ||
![]() |
bbda0cdffe | ||
![]() |
7b5ff99cd1 | ||
![]() |
21ddb26db8 | ||
![]() |
7bf2e3875f | ||
![]() |
b136aba1e2 | ||
![]() |
0d84f80b3c | ||
![]() |
af45aeb771 | ||
![]() |
1c5a435e1f | ||
![]() |
0ea1257dcd | ||
![]() |
4c92677b5a | ||
![]() |
979260bd62 | ||
![]() |
f7de649a36 | ||
![]() |
0cf0d2b821 | ||
![]() |
3733c9a091 | ||
![]() |
e9f32e4f68 | ||
![]() |
68c2817d40 | ||
![]() |
83d837d868 | ||
![]() |
093eb15ee1 | ||
![]() |
c6412c1b1b | ||
![]() |
1151393d74 | ||
![]() |
468f3efb13 | ||
![]() |
d6b19b9d4c | ||
![]() |
709f25f600 | ||
![]() |
4b16e4b026 | ||
![]() |
cdfbc02922 |
44
.github/actions/setup/action.yml
vendored
Normal file
44
.github/actions/setup/action.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
name: Magisk Setup
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: "temurin"
|
||||||
|
java-version: "17"
|
||||||
|
|
||||||
|
- name: Set up Python 3
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.x"
|
||||||
|
|
||||||
|
- name: Set up sccache
|
||||||
|
uses: hendrikmuhs/ccache-action@v1.2
|
||||||
|
with:
|
||||||
|
variant: sccache
|
||||||
|
key: ${{ runner.os }}-${{ github.sha }}
|
||||||
|
restore-keys: ${{ runner.os }}
|
||||||
|
max-size: 10000M
|
||||||
|
|
||||||
|
- name: Cache Gradle dependencies
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
|
!~/.gradle/caches/build-cache-*
|
||||||
|
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||||
|
restore-keys: ${{ runner.os }}-gradle-
|
||||||
|
|
||||||
|
- name: Cache build cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.gradle/caches/build-cache-*
|
||||||
|
key: ${{ runner.os }}-build-cache-${{ github.sha }}
|
||||||
|
restore-keys: ${{ runner.os }}-build-cache-
|
||||||
|
|
||||||
|
- name: Set up NDK
|
||||||
|
run: python build.py -v ndk
|
||||||
|
shell: bash
|
241
.github/workflows/build.yml
vendored
241
.github/workflows/build.yml
vendored
@@ -2,107 +2,194 @@ name: Magisk Build
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches: [master]
|
||||||
paths:
|
paths:
|
||||||
- 'app/**'
|
- "app/**"
|
||||||
- 'native/**'
|
- "native/**"
|
||||||
- 'stub/**'
|
- "buildSrc/**"
|
||||||
- 'buildSrc/**'
|
- "build.py"
|
||||||
- 'build.py'
|
- "gradle.properties"
|
||||||
- 'gradle.properties'
|
- ".github/workflows/build.yml"
|
||||||
- '.github/workflows/build.yml'
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master ]
|
branches: [master]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build on ${{ matrix.os }}
|
name: Build Magisk artifacts
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
SCCACHE_DIRECT: false
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
|
||||||
env:
|
|
||||||
NDK_CCACHE: ccache
|
|
||||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
|
||||||
CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
|
|
||||||
RUSTC_WRAPPER: sccache
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out
|
- name: Check out
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: "recursive"
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up JDK 17
|
- name: Setup environment
|
||||||
uses: actions/setup-java@v3
|
uses: ./.github/actions/setup
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: '17'
|
|
||||||
|
|
||||||
- name: Set up Python 3
|
|
||||||
uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: '3.x'
|
|
||||||
|
|
||||||
- name: Set up ccache
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
|
||||||
with:
|
|
||||||
key: ${{ runner.os }}-${{ github.sha }}
|
|
||||||
restore-keys: ${{ runner.os }}
|
|
||||||
|
|
||||||
- name: Set up sccache
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
|
||||||
with:
|
|
||||||
variant: sccache
|
|
||||||
key: ${{ runner.os }}-${{ github.sha }}
|
|
||||||
restore-keys: ${{ runner.os }}
|
|
||||||
|
|
||||||
- name: Cache Gradle dependencies
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches
|
|
||||||
~/.gradle/wrapper
|
|
||||||
!~/.gradle/caches/build-cache-*
|
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
|
|
||||||
restore-keys: ${{ runner.os }}-gradle-
|
|
||||||
|
|
||||||
- name: Cache build cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/caches/build-cache-*
|
|
||||||
key: ${{ runner.os }}-build-cache-${{ github.sha }}
|
|
||||||
restore-keys: ${{ runner.os }}-build-cache-
|
|
||||||
|
|
||||||
- name: Set up NDK
|
|
||||||
run: python build.py -v ndk
|
|
||||||
|
|
||||||
- name: Build release
|
- name: Build release
|
||||||
run: |
|
run: ./build.py -vr all
|
||||||
python build.py -vr all
|
|
||||||
|
|
||||||
- name: Build debug
|
- name: Build debug
|
||||||
run: |
|
run: ./build.py -v all
|
||||||
python build.py -v all
|
|
||||||
|
|
||||||
- name: Stop gradle daemon
|
- name: Stop gradle daemon
|
||||||
run: ./gradlew --stop
|
run: ./gradlew --stop
|
||||||
|
|
||||||
# Only upload artifacts built on Linux
|
|
||||||
- name: Upload build artifact
|
- name: Upload build artifact
|
||||||
if: runner.os == 'Linux'
|
uses: actions/upload-artifact@v4
|
||||||
uses: actions/upload-artifact@v3
|
with:
|
||||||
|
name: ${{ github.sha }}
|
||||||
|
path: out
|
||||||
|
compression-level: 9
|
||||||
|
|
||||||
|
- name: Upload mapping and native debug symbols
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ github.sha }}-symbols
|
||||||
|
path: app/apk/build/outputs
|
||||||
|
compression-level: 9
|
||||||
|
|
||||||
|
test-build:
|
||||||
|
name: Test building on ${{ matrix.os }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
env:
|
||||||
|
SCCACHE_DIRECT: false
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [windows-latest, macos-14]
|
||||||
|
steps:
|
||||||
|
- name: Check out
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: "recursive"
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup environment
|
||||||
|
uses: ./.github/actions/setup
|
||||||
|
|
||||||
|
- name: Build debug
|
||||||
|
run: python build.py -v all
|
||||||
|
|
||||||
|
- name: Stop gradle daemon
|
||||||
|
run: ./gradlew --stop
|
||||||
|
|
||||||
|
avd-test:
|
||||||
|
name: Test API ${{ matrix.version }} (x86_64)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
version: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]
|
||||||
|
type: [""]
|
||||||
|
include:
|
||||||
|
- version: 35
|
||||||
|
type: "google_apis"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Download build artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ github.sha }}
|
name: ${{ github.sha }}
|
||||||
path: out
|
path: out
|
||||||
|
|
||||||
- name: Upload mapping and native debug symbols
|
- name: Enable KVM group perms
|
||||||
if: runner.os == 'Linux'
|
run: |
|
||||||
uses: actions/upload-artifact@v3
|
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
|
||||||
|
sudo udevadm control --reload-rules
|
||||||
|
sudo udevadm trigger --name-match=kvm
|
||||||
|
|
||||||
|
- name: Run AVD test
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
AVD_TEST_VERBOSE: 1
|
||||||
|
run: scripts/avd_test.sh ${{ matrix.version }} ${{ matrix.type }}
|
||||||
|
|
||||||
|
avd-test-32:
|
||||||
|
name: Test API ${{ matrix.version }} (x86)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
version: [23, 24, 25, 26, 27, 28, 29, 30]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out
|
||||||
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ github.sha }}-symbols
|
fetch-depth: 0
|
||||||
path: app/build/outputs
|
|
||||||
|
- name: Download build artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ github.sha }}
|
||||||
|
path: out
|
||||||
|
|
||||||
|
- name: Enable KVM group perms
|
||||||
|
run: |
|
||||||
|
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
|
||||||
|
sudo udevadm control --reload-rules
|
||||||
|
sudo udevadm trigger --name-match=kvm
|
||||||
|
|
||||||
|
- name: Run AVD test
|
||||||
|
timeout-minutes: 10
|
||||||
|
env:
|
||||||
|
FORCE_32_BIT: 1
|
||||||
|
AVD_TEST_VERBOSE: 1
|
||||||
|
run: scripts/avd_test.sh ${{ matrix.version }}
|
||||||
|
|
||||||
|
cf_test:
|
||||||
|
name: Test ${{ matrix.branch }} (${{ matrix.target }})
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
needs: build
|
||||||
|
env:
|
||||||
|
CF_HOME: /home/runner/aosp_cf_phone
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- branch: "aosp-main"
|
||||||
|
target: "aosp_cf_x86_64_phone-trunk_staging-userdebug"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Download build artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ github.sha }}
|
||||||
|
path: out
|
||||||
|
|
||||||
|
- name: Setup Cuttlefish environment
|
||||||
|
run: |
|
||||||
|
scripts/cuttlefish.sh setup
|
||||||
|
scripts/cuttlefish.sh download ${{ matrix.branch }} ${{ matrix.target }}
|
||||||
|
|
||||||
|
- name: Run Cuttlefish test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: su $USER -c 'scripts/cuttlefish.sh test'
|
||||||
|
|
||||||
|
- name: Upload logs on error
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: "cvd-logs"
|
||||||
|
path: |
|
||||||
|
/home/runner/aosp_cf_phone/cuttlefish/instances/cvd-1/logs
|
||||||
|
/home/runner/aosp_cf_phone/cuttlefish/instances/cvd-1/cuttlefish_config.json
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,8 +3,9 @@ out
|
|||||||
*.jks
|
*.jks
|
||||||
*.apk
|
*.apk
|
||||||
/config.prop
|
/config.prop
|
||||||
|
/notes.md
|
||||||
/update.sh
|
/update.sh
|
||||||
/dict.txt
|
/app/dict.txt
|
||||||
|
|
||||||
# Built binaries
|
# Built binaries
|
||||||
native/out
|
native/out
|
||||||
|
24
.gitmodules
vendored
24
.gitmodules
vendored
@@ -1,12 +1,6 @@
|
|||||||
[submodule "selinux"]
|
[submodule "selinux"]
|
||||||
path = native/src/external/selinux
|
path = native/src/external/selinux
|
||||||
url = https://github.com/topjohnwu/selinux.git
|
url = https://github.com/topjohnwu/selinux.git
|
||||||
[submodule "busybox"]
|
|
||||||
path = native/src/external/busybox
|
|
||||||
url = https://github.com/topjohnwu/ndk-busybox.git
|
|
||||||
[submodule "dtc"]
|
|
||||||
path = native/src/external/dtc
|
|
||||||
url = https://github.com/dgibson/dtc.git
|
|
||||||
[submodule "lz4"]
|
[submodule "lz4"]
|
||||||
path = native/src/external/lz4
|
path = native/src/external/lz4
|
||||||
url = https://github.com/lz4/lz4.git
|
url = https://github.com/lz4/lz4.git
|
||||||
@@ -16,24 +10,12 @@
|
|||||||
[submodule "xz"]
|
[submodule "xz"]
|
||||||
path = native/src/external/xz
|
path = native/src/external/xz
|
||||||
url = https://github.com/xz-mirror/xz.git
|
url = https://github.com/xz-mirror/xz.git
|
||||||
[submodule "nanopb"]
|
|
||||||
path = native/src/external/nanopb
|
|
||||||
url = https://github.com/nanopb/nanopb.git
|
|
||||||
[submodule "mincrypt"]
|
|
||||||
path = native/src/external/mincrypt
|
|
||||||
url = https://github.com/topjohnwu/mincrypt.git
|
|
||||||
[submodule "pcre"]
|
|
||||||
path = native/src/external/pcre
|
|
||||||
url = https://android.googlesource.com/platform/external/pcre
|
|
||||||
[submodule "libcxx"]
|
[submodule "libcxx"]
|
||||||
path = native/src/external/libcxx
|
path = native/src/external/libcxx
|
||||||
url = https://github.com/topjohnwu/libcxx.git
|
url = https://github.com/topjohnwu/libcxx.git
|
||||||
[submodule "zlib"]
|
[submodule "zlib"]
|
||||||
path = native/src/external/zlib
|
path = native/src/external/zlib
|
||||||
url = https://android.googlesource.com/platform/external/zlib
|
url = https://android.googlesource.com/platform/external/zlib
|
||||||
[submodule "parallel-hashmap"]
|
|
||||||
path = native/src/external/parallel-hashmap
|
|
||||||
url = https://github.com/greg7mdp/parallel-hashmap.git
|
|
||||||
[submodule "zopfli"]
|
[submodule "zopfli"]
|
||||||
path = native/src/external/zopfli
|
path = native/src/external/zopfli
|
||||||
url = https://github.com/google/zopfli.git
|
url = https://github.com/google/zopfli.git
|
||||||
@@ -43,6 +25,12 @@
|
|||||||
[submodule "lsplt"]
|
[submodule "lsplt"]
|
||||||
path = native/src/external/lsplt
|
path = native/src/external/lsplt
|
||||||
url = https://github.com/LSPosed/LSPlt.git
|
url = https://github.com/LSPosed/LSPlt.git
|
||||||
|
[submodule "system_properties"]
|
||||||
|
path = native/src/external/system_properties
|
||||||
|
url = https://github.com/topjohnwu/system_properties.git
|
||||||
|
[submodule "crt0"]
|
||||||
|
path = native/src/external/crt0
|
||||||
|
url = https://github.com/topjohnwu/crt0.git
|
||||||
[submodule "termux-elf-cleaner"]
|
[submodule "termux-elf-cleaner"]
|
||||||
path = tools/termux-elf-cleaner
|
path = tools/termux-elf-cleaner
|
||||||
url = https://github.com/termux/termux-elf-cleaner.git
|
url = https://github.com/termux/termux-elf-cleaner.git
|
||||||
|
39
README.MD
39
README.MD
@@ -18,15 +18,18 @@ Some highlight features:
|
|||||||
|
|
||||||
[Github](https://github.com/topjohnwu/Magisk/) is the only source where you can get official Magisk information and downloads.
|
[Github](https://github.com/topjohnwu/Magisk/) is the only source where you can get official Magisk information and downloads.
|
||||||
|
|
||||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v25.2)
|
Click the icon below to download Magisk apk.
|
||||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v26.0)
|
|
||||||
[](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-release.apk)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
|
||||||
[](https://raw.githubusercontent.com/topjohnwu/magisk-files/canary/app-debug.apk)
|
[](https://github.com/topjohnwu/Magisk/releases/tag/v27.0)
|
||||||
|
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-27006)
|
||||||
|
|
||||||
## Useful Links
|
## Useful Links
|
||||||
|
|
||||||
- [Installation Instruction](https://topjohnwu.github.io/Magisk/install.html)
|
- [Installation Instruction](https://topjohnwu.github.io/Magisk/install.html)
|
||||||
|
- [Building and Development](https://topjohnwu.github.io/Magisk/build.html)
|
||||||
- [Magisk Documentation](https://topjohnwu.github.io/Magisk/)
|
- [Magisk Documentation](https://topjohnwu.github.io/Magisk/)
|
||||||
|
- [Zygisk module sample](https://github.com/topjohnwu/zygisk-module-sample)
|
||||||
|
|
||||||
## Bug Reports
|
## Bug Reports
|
||||||
|
|
||||||
@@ -36,36 +39,12 @@ For installation issues, upload both boot image and install logs.<br>
|
|||||||
For Magisk issues, upload boot logcat or dmesg.<br>
|
For Magisk issues, upload boot logcat or dmesg.<br>
|
||||||
For Magisk app crashes, record and upload the logcat when the crash occurs.
|
For Magisk app crashes, record and upload the logcat when the crash occurs.
|
||||||
|
|
||||||
## Building and Development
|
|
||||||
|
|
||||||
- Magisk builds on any OS Android Studio supports. Install Android Studio and do the initial setups.
|
|
||||||
- Clone sources: `git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git`
|
|
||||||
- Install Python 3.8+ \
|
|
||||||
(Windows only: select **'Add Python to PATH'** in installer, and run `pip install colorama` after install)
|
|
||||||
- Configure to use the JDK bundled in Android Studio:
|
|
||||||
- macOS: `export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/Contents/Home"`
|
|
||||||
- Linux: `export PATH="/path/to/androidstudio/jre/bin:$PATH"`
|
|
||||||
- Windows: Add `C:\Path\To\Android Studio\jre\bin` to environment variable `PATH`
|
|
||||||
- Set environment variable `ANDROID_SDK_ROOT` to the Android SDK folder (can be found in Android Studio settings)
|
|
||||||
- Run `./build.py ndk` to let the script download and install NDK for you
|
|
||||||
- To start building, run `build.py` to see your options. \
|
|
||||||
For each action, use `-h` to access help (e.g. `./build.py all -h`)
|
|
||||||
- To start development, open the project with Android Studio. The IDE can be used for both app (Kotlin/Java) and native sources.
|
|
||||||
- Optionally, set custom configs with `config.prop`. A sample `config.prop.sample` is provided.
|
|
||||||
|
|
||||||
## Signing and Distribution
|
|
||||||
|
|
||||||
- The certificate of the key used to sign the final Magisk APK product is also directly embedded into some executables. In release builds, Magisk's root daemon will enforce this certificate check and reject and forcefully uninstall any non-matching Magisk apps to protect users from malicious and unverified Magisk APKs.
|
|
||||||
- To do any development on Magisk itself, switch to an **official debug build and reinstall Magisk** to bypass the signature check.
|
|
||||||
- To distribute your own Magisk builds signed with your own keys, set your signing configs in `config.prop`.
|
|
||||||
- Check [Google's Documentation](https://developer.android.com/studio/publish/app-signing.html#generate-key) for more details on generating your own key.
|
|
||||||
|
|
||||||
## Translation Contributions
|
## Translation Contributions
|
||||||
|
|
||||||
Default string resources for the Magisk app and its stub APK are located here:
|
Default string resources for the Magisk app and its stub APK are located here:
|
||||||
|
|
||||||
- `app/src/main/res/values/strings.xml`
|
- `app/core/src/main/res/values/strings.xml`
|
||||||
- `stub/src/main/res/values/strings.xml`
|
- `app/stub/src/main/res/values/strings.xml`
|
||||||
|
|
||||||
Translate each and place them in the respective locations (`[module]/src/main/res/values-[lang]/strings.xml`).
|
Translate each and place them in the respective locations (`[module]/src/main/res/values-[lang]/strings.xml`).
|
||||||
|
|
||||||
|
11
app/.gitignore
vendored
11
app/.gitignore
vendored
@@ -1,11 +0,0 @@
|
|||||||
*.iml
|
|
||||||
.gradle
|
|
||||||
/local.properties
|
|
||||||
.idea/
|
|
||||||
/build
|
|
||||||
*.hprof
|
|
||||||
.externalNativeBuild/
|
|
||||||
*.apk
|
|
||||||
src/*/assets
|
|
||||||
src/*/jniLibs
|
|
||||||
src/*/resources
|
|
1
app/apk/.gitignore
vendored
Normal file
1
app/apk/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/build
|
69
app/apk/build.gradle.kts
Normal file
69
app/apk/build.gradle.kts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
plugins {
|
||||||
|
id("com.android.application")
|
||||||
|
kotlin("android")
|
||||||
|
kotlin("plugin.parcelize")
|
||||||
|
kotlin("kapt")
|
||||||
|
id("androidx.navigation.safeargs.kotlin")
|
||||||
|
}
|
||||||
|
|
||||||
|
setupAppCommon()
|
||||||
|
|
||||||
|
kapt {
|
||||||
|
correctErrorTypes = true
|
||||||
|
useBuildCache = true
|
||||||
|
mapDiagnosticLocations = true
|
||||||
|
javacOptions {
|
||||||
|
option("-Xmaxerrs", 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "com.topjohnwu.magisk"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId = "com.topjohnwu.magisk"
|
||||||
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
versionName = Config.version
|
||||||
|
versionCode = Config.versionCode
|
||||||
|
ndk {
|
||||||
|
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64", "riscv64")
|
||||||
|
debugSymbolLevel = "FULL"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = true
|
||||||
|
isShrinkResources = true
|
||||||
|
proguardFiles("proguard-rules.pro")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
dataBinding = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":app:core"))
|
||||||
|
|
||||||
|
implementation("com.github.topjohnwu:indeterminate-checkbox:1.0.7")
|
||||||
|
implementation("dev.rikka.rikkax.layoutinflater:layoutinflater:1.3.0")
|
||||||
|
implementation("dev.rikka.rikkax.insets:insets:1.3.0")
|
||||||
|
implementation("dev.rikka.rikkax.recyclerview:recyclerview-ktx:1.3.2")
|
||||||
|
|
||||||
|
val vNav = "2.7.7"
|
||||||
|
implementation("androidx.navigation:navigation-fragment-ktx:${vNav}")
|
||||||
|
implementation("androidx.navigation:navigation-ui-ktx:${vNav}")
|
||||||
|
|
||||||
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
|
implementation("androidx.recyclerview:recyclerview:1.3.2")
|
||||||
|
implementation("androidx.transition:transition:1.5.1")
|
||||||
|
implementation("androidx.fragment:fragment-ktx:1.8.2")
|
||||||
|
implementation("androidx.appcompat:appcompat:1.7.0")
|
||||||
|
implementation("com.google.android.material:material:1.12.0")
|
||||||
|
|
||||||
|
// Make sure kapt runs with a proper kotlin-stdlib
|
||||||
|
kapt(kotlin("stdlib"))
|
||||||
|
}
|
33
app/apk/src/main/AndroidManifest.xml
Normal file
33
app/apk/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<application android:localeConfig="@xml/locale_config">
|
||||||
|
<activity
|
||||||
|
android:name=".ui.MainActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:theme="@style/SplashTheme">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".ui.surequest.SuRequestActivity"
|
||||||
|
android:directBootAware="true"
|
||||||
|
android:exported="false"
|
||||||
|
android:taskAffinity=""
|
||||||
|
tools:ignore="AppLinkUrlError">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
@@ -10,6 +10,7 @@ import androidx.databinding.DataBindingUtil
|
|||||||
import androidx.databinding.OnRebindCallback
|
import androidx.databinding.OnRebindCallback
|
||||||
import androidx.databinding.ViewDataBinding
|
import androidx.databinding.ViewDataBinding
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.navigation.NavDirections
|
import androidx.navigation.NavDirections
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
|
|
||||||
@@ -37,6 +38,9 @@ abstract class BaseFragment<Binding : ViewDataBinding> : Fragment(), ViewModelHo
|
|||||||
it.setVariable(BR.viewModel, viewModel)
|
it.setVariable(BR.viewModel, viewModel)
|
||||||
it.lifecycleOwner = viewLifecycleOwner
|
it.lifecycleOwner = viewLifecycleOwner
|
||||||
}
|
}
|
||||||
|
if (this is MenuProvider) {
|
||||||
|
activity?.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.STARTED)
|
||||||
|
}
|
||||||
savedInstanceState?.let { viewModel.onRestoreState(it) }
|
savedInstanceState?.let { viewModel.onRestoreState(it) }
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
@@ -66,8 +70,6 @@ abstract class BaseFragment<Binding : ViewDataBinding> : Fragment(), ViewModelHo
|
|||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
if (this is MenuProvider)
|
|
||||||
activity?.addMenuProvider(this, viewLifecycleOwner)
|
|
||||||
binding.addOnRebindCallback(object : OnRebindCallback<Binding>() {
|
binding.addOnRebindCallback(object : OnRebindCallback<Binding>() {
|
||||||
override fun onPreBind(binding: Binding): Boolean {
|
override fun onPreBind(binding: Binding): Boolean {
|
||||||
this@BaseFragment.onPreBind(binding)
|
this@BaseFragment.onPreBind(binding)
|
||||||
@@ -91,5 +93,4 @@ abstract class BaseFragment<Binding : ViewDataBinding> : Fragment(), ViewModelHo
|
|||||||
fun NavDirections.navigate() {
|
fun NavDirections.navigate() {
|
||||||
navigation?.currentDestination?.getAction(actionId)?.let { navigation!!.navigate(this) }
|
navigation?.currentDestination?.getAction(actionId)?.let { navigation!!.navigate(this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -1,6 +1,8 @@
|
|||||||
package com.topjohnwu.magisk.arch
|
package com.topjohnwu.magisk.arch
|
||||||
|
|
||||||
import android.Manifest.permission.*
|
import android.Manifest.permission.POST_NOTIFICATIONS
|
||||||
|
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
||||||
|
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.databinding.PropertyChangeRegistry
|
import androidx.databinding.PropertyChangeRegistry
|
||||||
@@ -8,7 +10,7 @@ import androidx.lifecycle.LiveData
|
|||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.navigation.NavDirections
|
import androidx.navigation.NavDirections
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.databinding.ObservableHost
|
import com.topjohnwu.magisk.databinding.ObservableHost
|
||||||
import com.topjohnwu.magisk.events.BackPressEvent
|
import com.topjohnwu.magisk.events.BackPressEvent
|
||||||
import com.topjohnwu.magisk.events.DialogBuilder
|
import com.topjohnwu.magisk.events.DialogBuilder
|
@@ -1,11 +1,13 @@
|
|||||||
package com.topjohnwu.magisk.arch
|
package com.topjohnwu.magisk.arch
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.content.res.use
|
import androidx.core.content.res.use
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
@@ -18,14 +20,20 @@ import com.google.android.material.snackbar.Snackbar
|
|||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
import com.topjohnwu.magisk.core.base.ActivityExtension
|
||||||
|
import com.topjohnwu.magisk.core.base.IActivityExtension
|
||||||
|
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||||
|
import com.topjohnwu.magisk.core.ktx.reflectField
|
||||||
|
import com.topjohnwu.magisk.core.wrap
|
||||||
import rikka.insets.WindowInsetsHelper
|
import rikka.insets.WindowInsetsHelper
|
||||||
import rikka.layoutinflater.view.LayoutInflaterFactory
|
import rikka.layoutinflater.view.LayoutInflaterFactory
|
||||||
|
|
||||||
abstract class UIActivity<Binding : ViewDataBinding> : BaseActivity(), ViewModelHolder {
|
abstract class UIActivity<Binding : ViewDataBinding>
|
||||||
|
: AppCompatActivity(), ViewModelHolder, IActivityExtension {
|
||||||
|
|
||||||
protected lateinit var binding: Binding
|
protected lateinit var binding: Binding
|
||||||
protected abstract val layoutRes: Int
|
protected abstract val layoutRes: Int
|
||||||
|
override val extension = ActivityExtension(this)
|
||||||
|
|
||||||
protected val binded get() = ::binding.isInitialized
|
protected val binded get() = ::binding.isInitialized
|
||||||
|
|
||||||
@@ -36,10 +44,23 @@ abstract class UIActivity<Binding : ViewDataBinding> : BaseActivity(), ViewModel
|
|||||||
AppCompatDelegate.setDefaultNightMode(Config.darkTheme)
|
AppCompatDelegate.setDefaultNightMode(Config.darkTheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun attachBaseContext(base: Context) {
|
||||||
|
super.attachBaseContext(base.wrap())
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
layoutInflater.factory2 = LayoutInflaterFactory(delegate)
|
layoutInflater.factory2 = LayoutInflaterFactory(delegate)
|
||||||
.addOnViewCreatedListener(WindowInsetsHelper.LISTENER)
|
.addOnViewCreatedListener(WindowInsetsHelper.LISTENER)
|
||||||
|
|
||||||
|
extension.onCreate(savedInstanceState)
|
||||||
|
if (isRunningAsStub) {
|
||||||
|
// Overwrite private members to avoid nasty "false" stack traces being logged
|
||||||
|
val delegate = delegate
|
||||||
|
val clz = delegate.javaClass
|
||||||
|
clz.reflectField("mActivityHandlesConfigFlagsChecked").set(delegate, true)
|
||||||
|
clz.reflectField("mActivityHandlesConfigFlags").set(delegate, 0)
|
||||||
|
}
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
startObserveLiveData()
|
startObserveLiveData()
|
||||||
@@ -70,6 +91,11 @@ abstract class UIActivity<Binding : ViewDataBinding> : BaseActivity(), ViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
extension.onSaveInstanceState(outState)
|
||||||
|
}
|
||||||
|
|
||||||
fun setContentView() {
|
fun setContentView() {
|
||||||
binding = DataBindingUtil.setContentView<Binding>(this, layoutRes).also {
|
binding = DataBindingUtil.setContentView<Binding>(this, layoutRes).also {
|
||||||
it.setVariable(BR.viewModel, viewModel)
|
it.setVariable(BR.viewModel, viewModel)
|
@@ -8,7 +8,12 @@ import android.text.Spanned
|
|||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.*
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.ProgressBar
|
||||||
|
import android.widget.Spinner
|
||||||
|
import android.widget.TextView
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
@@ -20,7 +25,11 @@ import androidx.databinding.BindingAdapter
|
|||||||
import androidx.databinding.InverseBindingAdapter
|
import androidx.databinding.InverseBindingAdapter
|
||||||
import androidx.databinding.InverseBindingListener
|
import androidx.databinding.InverseBindingListener
|
||||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
|
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
|
||||||
import androidx.recyclerview.widget.*
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
@@ -3,7 +3,7 @@ package com.topjohnwu.magisk.databinding
|
|||||||
import androidx.databinding.ListChangeRegistry
|
import androidx.databinding.ListChangeRegistry
|
||||||
import androidx.databinding.ObservableList
|
import androidx.databinding.ObservableList
|
||||||
import androidx.databinding.ObservableList.OnListChangedCallback
|
import androidx.databinding.ObservableList.OnListChangedCallback
|
||||||
import java.util.*
|
import java.util.AbstractList
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
class MergeObservableList<T> : AbstractList<T>(), ObservableList<T> {
|
class MergeObservableList<T> : AbstractList<T>(), ObservableList<T> {
|
@@ -7,26 +7,27 @@ import com.topjohnwu.magisk.arch.UIActivity
|
|||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.events.DialogBuilder
|
import com.topjohnwu.magisk.events.DialogBuilder
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class DarkThemeDialog : DialogBuilder {
|
class DarkThemeDialog : DialogBuilder {
|
||||||
|
|
||||||
override fun build(dialog: MagiskDialog) {
|
override fun build(dialog: MagiskDialog) {
|
||||||
val activity = dialog.ownerActivity!!
|
val activity = dialog.ownerActivity!!
|
||||||
dialog.apply {
|
dialog.apply {
|
||||||
setTitle(R.string.settings_dark_mode_title)
|
setTitle(CoreR.string.settings_dark_mode_title)
|
||||||
setMessage(R.string.settings_dark_mode_message)
|
setMessage(CoreR.string.settings_dark_mode_message)
|
||||||
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||||
text = R.string.settings_dark_mode_light
|
text = CoreR.string.settings_dark_mode_light
|
||||||
icon = R.drawable.ic_day
|
icon = R.drawable.ic_day
|
||||||
onClick { selectTheme(AppCompatDelegate.MODE_NIGHT_NO, activity) }
|
onClick { selectTheme(AppCompatDelegate.MODE_NIGHT_NO, activity) }
|
||||||
}
|
}
|
||||||
setButton(MagiskDialog.ButtonType.NEUTRAL) {
|
setButton(MagiskDialog.ButtonType.NEUTRAL) {
|
||||||
text = R.string.settings_dark_mode_system
|
text = CoreR.string.settings_dark_mode_system
|
||||||
icon = R.drawable.ic_day_night
|
icon = R.drawable.ic_day_night
|
||||||
onClick { selectTheme(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, activity) }
|
onClick { selectTheme(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, activity) }
|
||||||
}
|
}
|
||||||
setButton(MagiskDialog.ButtonType.NEGATIVE) {
|
setButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||||
text = R.string.settings_dark_mode_dark
|
text = CoreR.string.settings_dark_mode_dark
|
||||||
icon = R.drawable.ic_night
|
icon = R.drawable.ic_night
|
||||||
onClick { selectTheme(AppCompatDelegate.MODE_NIGHT_YES, activity) }
|
onClick { selectTheme(AppCompatDelegate.MODE_NIGHT_YES, activity) }
|
||||||
}
|
}
|
@@ -1,10 +1,9 @@
|
|||||||
package com.topjohnwu.magisk.dialog
|
package com.topjohnwu.magisk.dialog
|
||||||
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
import com.topjohnwu.magisk.core.BuildConfig
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||||
import com.topjohnwu.magisk.events.DialogBuilder
|
import com.topjohnwu.magisk.events.DialogBuilder
|
||||||
import com.topjohnwu.magisk.ui.home.HomeViewModel
|
import com.topjohnwu.magisk.ui.home.HomeViewModel
|
||||||
@@ -27,7 +26,7 @@ class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : Dialo
|
|||||||
resetButtons()
|
resetButtons()
|
||||||
setCancelable(false)
|
setCancelable(false)
|
||||||
}
|
}
|
||||||
(dialog.ownerActivity as BaseActivity).lifecycleScope.launch {
|
dialog.activity.lifecycleScope.launch {
|
||||||
MagiskInstaller.FixEnv {
|
MagiskInstaller.FixEnv {
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}.exec()
|
}.exec()
|
||||||
@@ -40,8 +39,8 @@ class EnvFixDialog(private val vm: HomeViewModel, private val code: Int) : Dialo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (code == 2 || // No rules block, module policy not loaded
|
if (code == 2 || // No rules block, module policy not loaded
|
||||||
Info.env.versionCode != BuildConfig.VERSION_CODE ||
|
Info.env.versionCode != BuildConfig.APP_VERSION_CODE ||
|
||||||
Info.env.versionString != BuildConfig.VERSION_NAME) {
|
Info.env.versionString != BuildConfig.APP_VERSION_NAME) {
|
||||||
dialog.setMessage(R.string.env_full_fix_msg)
|
dialog.setMessage(R.string.env_full_fix_msg)
|
||||||
dialog.setButton(MagiskDialog.ButtonType.POSITIVE) {
|
dialog.setButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||||
text = android.R.string.ok
|
text = android.R.string.ok
|
@@ -2,8 +2,8 @@ package com.topjohnwu.magisk.dialog
|
|||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.topjohnwu.magisk.MainDirections
|
import com.topjohnwu.magisk.MainDirections
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.events.DialogBuilder
|
import com.topjohnwu.magisk.events.DialogBuilder
|
||||||
import com.topjohnwu.magisk.ui.module.ModuleViewModel
|
import com.topjohnwu.magisk.ui.module.ModuleViewModel
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
@@ -1,10 +1,10 @@
|
|||||||
package com.topjohnwu.magisk.dialog
|
package com.topjohnwu.magisk.dialog
|
||||||
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.core.AppContext
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.di.AppContext
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
import com.topjohnwu.magisk.core.di.ServiceLocator
|
||||||
import com.topjohnwu.magisk.core.download.DownloadService
|
import com.topjohnwu.magisk.core.download.DownloadEngine
|
||||||
import com.topjohnwu.magisk.core.download.Subject
|
import com.topjohnwu.magisk.core.download.Subject
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -29,7 +29,7 @@ class ManagerInstallDialog : MarkDownDialog() {
|
|||||||
setCancelable(true)
|
setCancelable(true)
|
||||||
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||||
text = R.string.install
|
text = R.string.install
|
||||||
onClick { DownloadService.start(activity, Subject.App()) }
|
onClick { DownloadEngine.startWithActivity(activity, Subject.App()) }
|
||||||
}
|
}
|
||||||
setButton(MagiskDialog.ButtonType.NEGATIVE) {
|
setButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||||
text = android.R.string.cancel
|
text = android.R.string.cancel
|
@@ -13,6 +13,7 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
abstract class MarkDownDialog : DialogBuilder {
|
abstract class MarkDownDialog : DialogBuilder {
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ abstract class MarkDownDialog : DialogBuilder {
|
|||||||
ServiceLocator.markwon.setMarkdown(tv, text)
|
ServiceLocator.markwon.setMarkdown(tv, text)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
Timber.e(e)
|
Timber.e(e)
|
||||||
tv.setText(R.string.download_file_error)
|
tv.setText(CoreR.string.download_file_error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,11 +1,11 @@
|
|||||||
package com.topjohnwu.magisk.dialog
|
package com.topjohnwu.magisk.dialog
|
||||||
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
import com.topjohnwu.magisk.core.di.ServiceLocator
|
||||||
import com.topjohnwu.magisk.core.download.Action
|
import com.topjohnwu.magisk.core.download.DownloadEngine
|
||||||
import com.topjohnwu.magisk.core.download.DownloadService
|
|
||||||
import com.topjohnwu.magisk.core.download.Subject
|
import com.topjohnwu.magisk.core.download.Subject
|
||||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||||
|
import com.topjohnwu.magisk.ui.flash.FlashFragment
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
|
|
||||||
class OnlineModuleInstallDialog(private val item: OnlineModule) : MarkDownDialog() {
|
class OnlineModuleInstallDialog(private val item: OnlineModule) : MarkDownDialog() {
|
||||||
@@ -22,9 +22,9 @@ class OnlineModuleInstallDialog(private val item: OnlineModule) : MarkDownDialog
|
|||||||
dialog.apply {
|
dialog.apply {
|
||||||
|
|
||||||
fun download(install: Boolean) {
|
fun download(install: Boolean) {
|
||||||
val action = if (install) Action.Flash else Action.Download
|
val module = Subject.Module(item, install)
|
||||||
val subject = Subject.Module(item, action)
|
module.piCreator = FlashFragment::installIntent
|
||||||
DownloadService.start(activity, subject)
|
DownloadEngine.startWithActivity(activity, module)
|
||||||
}
|
}
|
||||||
|
|
||||||
val title = context.getString(R.string.repo_install_title,
|
val title = context.getString(R.string.repo_install_title,
|
@@ -1,6 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.dialog
|
package com.topjohnwu.magisk.dialog
|
||||||
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.events.DialogBuilder
|
import com.topjohnwu.magisk.events.DialogBuilder
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
|
|
@@ -1,6 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.dialog
|
package com.topjohnwu.magisk.dialog
|
||||||
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.events.DialogBuilder
|
import com.topjohnwu.magisk.events.DialogBuilder
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
|
|
@@ -3,8 +3,8 @@ package com.topjohnwu.magisk.dialog
|
|||||||
import android.app.ProgressDialog
|
import android.app.ProgressDialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
import com.topjohnwu.magisk.arch.NavigationActivity
|
import com.topjohnwu.magisk.arch.NavigationActivity
|
||||||
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.core.ktx.toast
|
import com.topjohnwu.magisk.core.ktx.toast
|
||||||
import com.topjohnwu.magisk.events.DialogBuilder
|
import com.topjohnwu.magisk.events.DialogBuilder
|
||||||
import com.topjohnwu.magisk.ui.flash.FlashFragment
|
import com.topjohnwu.magisk.ui.flash.FlashFragment
|
@@ -11,6 +11,7 @@ import com.topjohnwu.magisk.arch.NavigationActivity
|
|||||||
import com.topjohnwu.magisk.arch.UIActivity
|
import com.topjohnwu.magisk.arch.UIActivity
|
||||||
import com.topjohnwu.magisk.arch.ViewEvent
|
import com.topjohnwu.magisk.arch.ViewEvent
|
||||||
import com.topjohnwu.magisk.core.base.ContentResultCallback
|
import com.topjohnwu.magisk.core.base.ContentResultCallback
|
||||||
|
import com.topjohnwu.magisk.core.base.relaunch
|
||||||
import com.topjohnwu.magisk.utils.TextHolder
|
import com.topjohnwu.magisk.utils.TextHolder
|
||||||
import com.topjohnwu.magisk.utils.asText
|
import com.topjohnwu.magisk.utils.asText
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
@@ -47,7 +48,16 @@ class ShowUIEvent(private val delegate: View.AccessibilityDelegate?)
|
|||||||
|
|
||||||
class RecreateEvent : ViewEvent(), ActivityExecutor {
|
class RecreateEvent : ViewEvent(), ActivityExecutor {
|
||||||
override fun invoke(activity: UIActivity<*>) {
|
override fun invoke(activity: UIActivity<*>) {
|
||||||
activity.recreate()
|
activity.relaunch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AuthEvent(
|
||||||
|
private val callback: () -> Unit
|
||||||
|
) : ViewEvent(), ActivityExecutor {
|
||||||
|
|
||||||
|
override fun invoke(activity: UIActivity<*>) {
|
||||||
|
activity.withAuthentication { if (it) callback() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@@ -1,6 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.ui
|
package com.topjohnwu.magisk.ui
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
@@ -8,6 +9,7 @@ import android.os.Bundle
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
@@ -17,29 +19,35 @@ import androidx.navigation.NavDirections
|
|||||||
import com.topjohnwu.magisk.MainDirections
|
import com.topjohnwu.magisk.MainDirections
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||||
|
import com.topjohnwu.magisk.arch.NavigationActivity
|
||||||
import com.topjohnwu.magisk.arch.startAnimations
|
import com.topjohnwu.magisk.arch.startAnimations
|
||||||
import com.topjohnwu.magisk.arch.viewModel
|
import com.topjohnwu.magisk.arch.viewModel
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
|
import com.topjohnwu.magisk.core.base.SplashController
|
||||||
|
import com.topjohnwu.magisk.core.base.SplashScreenHost
|
||||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||||
|
import com.topjohnwu.magisk.core.ktx.toast
|
||||||
import com.topjohnwu.magisk.core.model.module.LocalModule
|
import com.topjohnwu.magisk.core.model.module.LocalModule
|
||||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
import com.topjohnwu.magisk.core.tasks.AppMigration
|
||||||
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
|
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
|
||||||
import com.topjohnwu.magisk.ui.home.HomeFragmentDirections
|
import com.topjohnwu.magisk.ui.home.HomeFragmentDirections
|
||||||
|
import com.topjohnwu.magisk.ui.theme.Theme
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
import com.topjohnwu.magisk.view.Shortcuts
|
import com.topjohnwu.magisk.view.Shortcuts
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class MainViewModel : BaseViewModel()
|
class MainViewModel : BaseViewModel()
|
||||||
|
|
||||||
class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
class MainActivity : NavigationActivity<ActivityMainMd2Binding>(), SplashScreenHost {
|
||||||
|
|
||||||
override val layoutRes = R.layout.activity_main_md2
|
override val layoutRes = R.layout.activity_main_md2
|
||||||
override val viewModel by viewModel<MainViewModel>()
|
override val viewModel by viewModel<MainViewModel>()
|
||||||
override val navHostId: Int = R.id.main_nav_host
|
override val navHostId: Int = R.id.main_nav_host
|
||||||
|
override val splashController = SplashController(this)
|
||||||
override val snackbarView: View
|
override val snackbarView: View
|
||||||
get() {
|
get() {
|
||||||
val fragmentOverride = currentFragment?.snackbarView
|
val fragmentOverride = currentFragment?.snackbarView
|
||||||
@@ -57,12 +65,23 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
|||||||
|
|
||||||
private var isRootFragment = true
|
private var isRootFragment = true
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
setTheme(Theme.selected.themeRes)
|
||||||
|
splashController.preOnCreate()
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
splashController.onCreate(savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
splashController.onResume()
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
override fun showMainUI(savedInstanceState: Bundle?) {
|
override fun onCreateUi(savedInstanceState: Bundle?) {
|
||||||
setContentView()
|
setContentView()
|
||||||
showUnsupportedMessage()
|
showUnsupportedMessage()
|
||||||
askForHomeShortcut()
|
askForHomeShortcut()
|
||||||
checkStubComponent()
|
|
||||||
|
|
||||||
// Ask permission to post notifications for background update check
|
// Ask permission to post notifications for background update check
|
||||||
if (Config.checkUpdate) {
|
if (Config.checkUpdate) {
|
||||||
@@ -169,11 +188,36 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("InlinedApi")
|
||||||
|
override fun showInvalidStateMessage(): Unit = runOnUiThread {
|
||||||
|
MagiskDialog(this).apply {
|
||||||
|
setTitle(CoreR.string.unsupport_nonroot_stub_title)
|
||||||
|
setMessage(CoreR.string.unsupport_nonroot_stub_msg)
|
||||||
|
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||||
|
text = CoreR.string.install
|
||||||
|
onClick {
|
||||||
|
withPermission(REQUEST_INSTALL_PACKAGES) {
|
||||||
|
if (!it) {
|
||||||
|
toast(CoreR.string.install_unknown_denied, Toast.LENGTH_SHORT)
|
||||||
|
showInvalidStateMessage()
|
||||||
|
} else {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
AppMigration.restore(this@MainActivity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCancelable(false)
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun showUnsupportedMessage() {
|
private fun showUnsupportedMessage() {
|
||||||
if (Info.env.isUnsupported) {
|
if (Info.env.isUnsupported) {
|
||||||
MagiskDialog(this).apply {
|
MagiskDialog(this).apply {
|
||||||
setTitle(R.string.unsupport_magisk_title)
|
setTitle(CoreR.string.unsupport_magisk_title)
|
||||||
setMessage(R.string.unsupport_magisk_msg, Const.Version.MIN_VERSION)
|
setMessage(CoreR.string.unsupport_magisk_msg, Const.Version.MIN_VERSION)
|
||||||
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
|
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
|
||||||
setCancelable(false)
|
setCancelable(false)
|
||||||
}.show()
|
}.show()
|
||||||
@@ -184,8 +228,8 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
|||||||
?.filterNot { File("$it/magisk").exists() }
|
?.filterNot { File("$it/magisk").exists() }
|
||||||
?.any { File("$it/su").exists() } == true) {
|
?.any { File("$it/su").exists() } == true) {
|
||||||
MagiskDialog(this).apply {
|
MagiskDialog(this).apply {
|
||||||
setTitle(R.string.unsupport_general_title)
|
setTitle(CoreR.string.unsupport_general_title)
|
||||||
setMessage(R.string.unsupport_other_su_msg)
|
setMessage(CoreR.string.unsupport_other_su_msg)
|
||||||
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
|
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
|
||||||
setCancelable(false)
|
setCancelable(false)
|
||||||
}.show()
|
}.show()
|
||||||
@@ -193,8 +237,8 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
|||||||
|
|
||||||
if (applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0) {
|
if (applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0) {
|
||||||
MagiskDialog(this).apply {
|
MagiskDialog(this).apply {
|
||||||
setTitle(R.string.unsupport_general_title)
|
setTitle(CoreR.string.unsupport_general_title)
|
||||||
setMessage(R.string.unsupport_system_app_msg)
|
setMessage(CoreR.string.unsupport_system_app_msg)
|
||||||
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
|
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
|
||||||
setCancelable(false)
|
setCancelable(false)
|
||||||
}.show()
|
}.show()
|
||||||
@@ -202,8 +246,8 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
|||||||
|
|
||||||
if (applicationInfo.flags and ApplicationInfo.FLAG_EXTERNAL_STORAGE != 0) {
|
if (applicationInfo.flags and ApplicationInfo.FLAG_EXTERNAL_STORAGE != 0) {
|
||||||
MagiskDialog(this).apply {
|
MagiskDialog(this).apply {
|
||||||
setTitle(R.string.unsupport_general_title)
|
setTitle(CoreR.string.unsupport_general_title)
|
||||||
setMessage(R.string.unsupport_external_storage_msg)
|
setMessage(CoreR.string.unsupport_external_storage_msg)
|
||||||
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
|
setButton(MagiskDialog.ButtonType.POSITIVE) { text = android.R.string.ok }
|
||||||
setCancelable(false)
|
setCancelable(false)
|
||||||
}.show()
|
}.show()
|
||||||
@@ -216,8 +260,8 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
|||||||
// Ask and show dialog
|
// Ask and show dialog
|
||||||
Config.askedHome = true
|
Config.askedHome = true
|
||||||
MagiskDialog(this).apply {
|
MagiskDialog(this).apply {
|
||||||
setTitle(R.string.add_shortcut_title)
|
setTitle(CoreR.string.add_shortcut_title)
|
||||||
setMessage(R.string.add_shortcut_msg)
|
setMessage(CoreR.string.add_shortcut_msg)
|
||||||
setButton(MagiskDialog.ButtonType.NEGATIVE) {
|
setButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||||
text = android.R.string.cancel
|
text = android.R.string.cancel
|
||||||
}
|
}
|
||||||
@@ -231,22 +275,4 @@ class MainActivity : SplashActivity<ActivityMainMd2Binding>() {
|
|||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
|
||||||
private fun checkStubComponent() {
|
|
||||||
if (intent.component?.className?.contains(HideAPK.PLACEHOLDER) == true) {
|
|
||||||
// The stub APK was not properly patched, re-apply our changes
|
|
||||||
withPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES) { granted ->
|
|
||||||
if (granted) {
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
val apk = File(applicationInfo.sourceDir)
|
|
||||||
HideAPK.upgrade(this@MainActivity, apk)?.let {
|
|
||||||
startActivity(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@@ -4,15 +4,20 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.ComponentInfo
|
import android.content.pm.ComponentInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.pm.PackageManager.*
|
import android.content.pm.PackageManager.GET_ACTIVITIES
|
||||||
|
import android.content.pm.PackageManager.GET_PROVIDERS
|
||||||
|
import android.content.pm.PackageManager.GET_RECEIVERS
|
||||||
|
import android.content.pm.PackageManager.GET_SERVICES
|
||||||
|
import android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS
|
||||||
|
import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES
|
||||||
import android.content.pm.ServiceInfo
|
import android.content.pm.ServiceInfo
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Build.VERSION.SDK_INT
|
import android.os.Build.VERSION.SDK_INT
|
||||||
import androidx.core.os.ProcessCompat
|
import androidx.core.os.ProcessCompat
|
||||||
import com.topjohnwu.magisk.core.ktx.getLabel
|
import com.topjohnwu.magisk.core.ktx.getLabel
|
||||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
import java.util.Locale
|
||||||
import java.util.*
|
import java.util.TreeSet
|
||||||
|
|
||||||
class CmdlineListItem(line: String) {
|
class CmdlineListItem(line: String) {
|
||||||
val packageName: String
|
val packageName: String
|
||||||
@@ -97,7 +102,7 @@ class AppProcessInfo(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val comparator = compareBy<AppProcessInfo>(
|
private val comparator = compareBy<AppProcessInfo>(
|
||||||
{ it.label.lowercase(currentLocale) },
|
{ it.label.lowercase(Locale.ROOT) },
|
||||||
{ it.info.packageName }
|
{ it.info.packageName }
|
||||||
)
|
)
|
||||||
}
|
}
|
@@ -16,6 +16,7 @@ import com.topjohnwu.magisk.databinding.FragmentDenyMd2Binding
|
|||||||
import rikka.recyclerview.addEdgeSpacing
|
import rikka.recyclerview.addEdgeSpacing
|
||||||
import rikka.recyclerview.addItemSpacing
|
import rikka.recyclerview.addItemSpacing
|
||||||
import rikka.recyclerview.fixEdgeEffect
|
import rikka.recyclerview.fixEdgeEffect
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class DenyListFragment : BaseFragment<FragmentDenyMd2Binding>(), MenuProvider {
|
class DenyListFragment : BaseFragment<FragmentDenyMd2Binding>(), MenuProvider {
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ class DenyListFragment : BaseFragment<FragmentDenyMd2Binding>(), MenuProvider {
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
activity?.setTitle(R.string.denylist)
|
activity?.setTitle(CoreR.string.denylist)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
@@ -58,7 +59,7 @@ class DenyListFragment : BaseFragment<FragmentDenyMd2Binding>(), MenuProvider {
|
|||||||
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
inflater.inflate(R.menu.menu_deny_md2, menu)
|
inflater.inflate(R.menu.menu_deny_md2, menu)
|
||||||
searchView = menu.findItem(R.id.action_search).actionView as SearchView
|
searchView = menu.findItem(R.id.action_search).actionView as SearchView
|
||||||
searchView.queryHint = searchView.context.getString(R.string.hide_filter_hint)
|
searchView.queryHint = searchView.context.getString(CoreR.string.hide_filter_hint)
|
||||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||||
viewModel.query = query ?: ""
|
viewModel.query = query ?: ""
|
@@ -6,7 +6,7 @@ import androidx.databinding.Bindable
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
||||||
import com.topjohnwu.magisk.core.di.AppContext
|
import com.topjohnwu.magisk.core.AppContext
|
||||||
import com.topjohnwu.magisk.core.ktx.concurrentMap
|
import com.topjohnwu.magisk.core.ktx.concurrentMap
|
||||||
import com.topjohnwu.magisk.databinding.bindExtra
|
import com.topjohnwu.magisk.databinding.bindExtra
|
||||||
import com.topjohnwu.magisk.databinding.filterList
|
import com.topjohnwu.magisk.databinding.filterList
|
@@ -5,7 +5,11 @@ import android.content.Context
|
|||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.view.KeyEvent
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.navigation.NavDeepLinkBuilder
|
import androidx.navigation.NavDeepLinkBuilder
|
||||||
@@ -17,6 +21,7 @@ import com.topjohnwu.magisk.core.Const
|
|||||||
import com.topjohnwu.magisk.core.cmp
|
import com.topjohnwu.magisk.core.cmp
|
||||||
import com.topjohnwu.magisk.databinding.FragmentFlashMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentFlashMd2Binding
|
||||||
import com.topjohnwu.magisk.ui.MainActivity
|
import com.topjohnwu.magisk.ui.MainActivity
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class FlashFragment : BaseFragment<FragmentFlashMd2Binding>(), MenuProvider {
|
class FlashFragment : BaseFragment<FragmentFlashMd2Binding>(), MenuProvider {
|
||||||
|
|
||||||
@@ -35,14 +40,14 @@ class FlashFragment : BaseFragment<FragmentFlashMd2Binding>(), MenuProvider {
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
activity?.setTitle(R.string.flash_screen_title)
|
activity?.setTitle(CoreR.string.flash_screen_title)
|
||||||
|
|
||||||
viewModel.state.observe(this) {
|
viewModel.state.observe(this) {
|
||||||
activity?.supportActionBar?.setSubtitle(
|
activity?.supportActionBar?.setSubtitle(
|
||||||
when (it) {
|
when (it) {
|
||||||
FlashViewModel.State.FLASHING -> R.string.flashing
|
FlashViewModel.State.FLASHING -> CoreR.string.flashing
|
||||||
FlashViewModel.State.SUCCESS -> R.string.done
|
FlashViewModel.State.SUCCESS -> CoreR.string.done
|
||||||
FlashViewModel.State.FAILED -> R.string.failure
|
FlashViewModel.State.FAILED -> CoreR.string.failure
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (it == FlashViewModel.State.SUCCESS && viewModel.showReboot) {
|
if (it == FlashViewModel.State.SUCCESS && viewModel.showReboot) {
|
@@ -5,7 +5,7 @@ import androidx.databinding.Bindable
|
|||||||
import androidx.databinding.ObservableArrayList
|
import androidx.databinding.ObservableArrayList
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.Transformations
|
import androidx.lifecycle.map
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
@@ -34,7 +34,7 @@ class FlashViewModel : BaseViewModel() {
|
|||||||
|
|
||||||
private val _state = MutableLiveData(State.FLASHING)
|
private val _state = MutableLiveData(State.FLASHING)
|
||||||
val state: LiveData<State> get() = _state
|
val state: LiveData<State> get() = _state
|
||||||
val flashing = Transformations.map(state) { it == State.FLASHING }
|
val flashing = state.map { it == State.FLASHING }
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var showReboot = Info.isRooted
|
var showReboot = Info.isRooted
|
||||||
@@ -72,6 +72,7 @@ class FlashViewModel : BaseViewModel() {
|
|||||||
MagiskInstaller.Direct(outItems, logItems).exec()
|
MagiskInstaller.Direct(outItems, logItems).exec()
|
||||||
}
|
}
|
||||||
Const.Value.FLASH_INACTIVE_SLOT -> {
|
Const.Value.FLASH_INACTIVE_SLOT -> {
|
||||||
|
showReboot = false
|
||||||
MagiskInstaller.SecondSlot(outItems, logItems).exec()
|
MagiskInstaller.SecondSlot(outItems, logItems).exec()
|
||||||
}
|
}
|
||||||
Const.Value.PATCH_FILE -> {
|
Const.Value.PATCH_FILE -> {
|
||||||
@@ -104,7 +105,7 @@ class FlashViewModel : BaseViewModel() {
|
|||||||
val name = "magisk_install_log_%s.log".format(
|
val name = "magisk_install_log_%s.log".format(
|
||||||
System.currentTimeMillis().toTime(timeFormatStandard)
|
System.currentTimeMillis().toTime(timeFormatStandard)
|
||||||
)
|
)
|
||||||
val file = MediaStoreUtils.getFile(name, true)
|
val file = MediaStoreUtils.getFile(name)
|
||||||
file.uri.outputStream().bufferedWriter().use { writer ->
|
file.uri.outputStream().bufferedWriter().use { writer ->
|
||||||
synchronized(logItems) {
|
synchronized(logItems) {
|
||||||
logItems.forEach {
|
logItems.forEach {
|
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.home
|
|||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.databinding.RvItem
|
import com.topjohnwu.magisk.databinding.RvItem
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
interface Dev {
|
interface Dev {
|
||||||
val name: String
|
val name: String
|
||||||
@@ -24,6 +25,10 @@ private interface RikkaImpl : Dev {
|
|||||||
override val name get() = "RikkaW"
|
override val name get() = "RikkaW"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private interface CanyieImpl : Dev {
|
||||||
|
override val name get() = "canyie"
|
||||||
|
}
|
||||||
|
|
||||||
sealed class DeveloperItem : Dev {
|
sealed class DeveloperItem : Dev {
|
||||||
|
|
||||||
abstract val items: List<IconLink>
|
abstract val items: List<IconLink>
|
||||||
@@ -61,6 +66,14 @@ sealed class DeveloperItem : Dev {
|
|||||||
object : IconLink.Github.User(), RikkaImpl {}
|
object : IconLink.Github.User(), RikkaImpl {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Canyie : DeveloperItem(), CanyieImpl {
|
||||||
|
override val items =
|
||||||
|
listOf<IconLink>(
|
||||||
|
object : IconLink.Twitter() { override val name = "canyie2977" },
|
||||||
|
object : IconLink.Github.User(), CanyieImpl {}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class IconLink : RvItem() {
|
sealed class IconLink : RvItem() {
|
||||||
@@ -72,8 +85,8 @@ sealed class IconLink : RvItem() {
|
|||||||
override val layoutRes get() = R.layout.item_icon_link
|
override val layoutRes get() = R.layout.item_icon_link
|
||||||
|
|
||||||
abstract class PayPal : IconLink(), Dev {
|
abstract class PayPal : IconLink(), Dev {
|
||||||
override val icon get() = R.drawable.ic_paypal
|
override val icon get() = CoreR.drawable.ic_paypal
|
||||||
override val title get() = R.string.paypal
|
override val title get() = CoreR.string.paypal
|
||||||
override val link get() = "https://paypal.me/$name"
|
override val link get() = "https://paypal.me/$name"
|
||||||
|
|
||||||
object Project : PayPal() {
|
object Project : PayPal() {
|
||||||
@@ -82,20 +95,20 @@ sealed class IconLink : RvItem() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Patreon : IconLink() {
|
object Patreon : IconLink() {
|
||||||
override val icon get() = R.drawable.ic_patreon
|
override val icon get() = CoreR.drawable.ic_patreon
|
||||||
override val title get() = R.string.patreon
|
override val title get() = CoreR.string.patreon
|
||||||
override val link get() = Const.Url.PATREON_URL
|
override val link get() = Const.Url.PATREON_URL
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Twitter : IconLink(), Dev {
|
abstract class Twitter : IconLink(), Dev {
|
||||||
override val icon get() = R.drawable.ic_twitter
|
override val icon get() = CoreR.drawable.ic_twitter
|
||||||
override val title get() = R.string.twitter
|
override val title get() = CoreR.string.twitter
|
||||||
override val link get() = "https://twitter.com/$name"
|
override val link get() = "https://twitter.com/$name"
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Github : IconLink() {
|
abstract class Github : IconLink() {
|
||||||
override val icon get() = R.drawable.ic_github
|
override val icon get() = CoreR.drawable.ic_github
|
||||||
override val title get() = R.string.github
|
override val title get() = CoreR.string.github
|
||||||
|
|
||||||
abstract class User : Github(), Dev {
|
abstract class User : Github(), Dev {
|
||||||
override val link get() = "https://github.com/$name"
|
override val link get() = "https://github.com/$name"
|
||||||
@@ -107,8 +120,8 @@ sealed class IconLink : RvItem() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class Sponsor : IconLink(), Dev {
|
abstract class Sponsor : IconLink(), Dev {
|
||||||
override val icon get() = R.drawable.ic_favorite
|
override val icon get() = CoreR.drawable.ic_favorite
|
||||||
override val title get() = R.string.github
|
override val title get() = CoreR.string.github
|
||||||
override val link get() = "https://github.com/sponsors/$name"
|
override val link get() = "https://github.com/sponsors/$name"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -14,8 +14,9 @@ import com.topjohnwu.magisk.R
|
|||||||
import com.topjohnwu.magisk.arch.BaseFragment
|
import com.topjohnwu.magisk.arch.BaseFragment
|
||||||
import com.topjohnwu.magisk.arch.viewModel
|
import com.topjohnwu.magisk.arch.viewModel
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.download.DownloadService
|
import com.topjohnwu.magisk.core.download.DownloadEngine
|
||||||
import com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
|
class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
|
||||||
|
|
||||||
@@ -24,8 +25,8 @@ class HomeFragment : BaseFragment<FragmentHomeMd2Binding>(), MenuProvider {
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
activity?.setTitle(R.string.section_home)
|
activity?.setTitle(CoreR.string.section_home)
|
||||||
DownloadService.observeProgress(this, viewModel::onProgressUpdate)
|
DownloadEngine.observeProgress(this, viewModel::onProgressUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkTitle(text: TextView, icon: ImageView) {
|
private fun checkTitle(text: TextView, icon: ImageView) {
|
@@ -7,13 +7,13 @@ import android.widget.Toast
|
|||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.arch.ActivityExecutor
|
import com.topjohnwu.magisk.arch.ActivityExecutor
|
||||||
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
||||||
import com.topjohnwu.magisk.arch.ContextExecutor
|
import com.topjohnwu.magisk.arch.ContextExecutor
|
||||||
import com.topjohnwu.magisk.arch.UIActivity
|
import com.topjohnwu.magisk.arch.UIActivity
|
||||||
import com.topjohnwu.magisk.arch.ViewEvent
|
import com.topjohnwu.magisk.arch.ViewEvent
|
||||||
|
import com.topjohnwu.magisk.core.BuildConfig
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.download.Subject
|
import com.topjohnwu.magisk.core.download.Subject
|
||||||
@@ -30,6 +30,7 @@ import com.topjohnwu.magisk.events.SnackbarEvent
|
|||||||
import com.topjohnwu.magisk.utils.asText
|
import com.topjohnwu.magisk.utils.asText
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class HomeViewModel(
|
class HomeViewModel(
|
||||||
private val svc: NetworkService
|
private val svc: NetworkService
|
||||||
@@ -52,7 +53,7 @@ class HomeViewModel(
|
|||||||
get() = when {
|
get() = when {
|
||||||
Info.isRooted && Info.env.isUnsupported -> State.OUTDATED
|
Info.isRooted && Info.env.isUnsupported -> State.OUTDATED
|
||||||
!Info.env.isActive -> State.INVALID
|
!Info.env.isActive -> State.INVALID
|
||||||
Info.env.versionCode < BuildConfig.VERSION_CODE -> State.OUTDATED
|
Info.env.versionCode < BuildConfig.APP_VERSION_CODE -> State.OUTDATED
|
||||||
else -> State.UP_TO_DATE
|
else -> State.UP_TO_DATE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,15 +66,15 @@ class HomeViewModel(
|
|||||||
if (isActive)
|
if (isActive)
|
||||||
("$versionString ($versionCode)" + if (isDebug) " (D)" else "").asText()
|
("$versionString ($versionCode)" + if (isDebug) " (D)" else "").asText()
|
||||||
else
|
else
|
||||||
R.string.not_available.asText()
|
CoreR.string.not_available.asText()
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var managerRemoteVersion = R.string.loading.asText()
|
var managerRemoteVersion = CoreR.string.loading.asText()
|
||||||
set(value) = set(value, field, { field = it }, BR.managerRemoteVersion)
|
set(value) = set(value, field, { field = it }, BR.managerRemoteVersion)
|
||||||
|
|
||||||
val managerInstalledVersion
|
val managerInstalledVersion
|
||||||
get() = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})" +
|
get() = "${BuildConfig.APP_VERSION_NAME} (${BuildConfig.APP_VERSION_CODE})" +
|
||||||
if (BuildConfig.DEBUG) " (D)" else ""
|
if (BuildConfig.DEBUG) " (D)" else ""
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
@@ -92,7 +93,7 @@ class HomeViewModel(
|
|||||||
appState = State.LOADING
|
appState = State.LOADING
|
||||||
Info.getRemote(svc)?.apply {
|
Info.getRemote(svc)?.apply {
|
||||||
appState = when {
|
appState = when {
|
||||||
BuildConfig.VERSION_CODE < magisk.versionCode -> State.OUTDATED
|
BuildConfig.APP_VERSION_CODE < magisk.versionCode -> State.OUTDATED
|
||||||
else -> State.UP_TO_DATE
|
else -> State.UP_TO_DATE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +103,7 @@ class HomeViewModel(
|
|||||||
if (isDebug) " (D)" else "").asText()
|
if (isDebug) " (D)" else "").asText()
|
||||||
} ?: run {
|
} ?: run {
|
||||||
appState = State.INVALID
|
appState = State.INVALID
|
||||||
managerRemoteVersion = R.string.not_available.asText()
|
managerRemoteVersion = CoreR.string.not_available.asText()
|
||||||
}
|
}
|
||||||
ensureEnv()
|
ensureEnv()
|
||||||
}
|
}
|
||||||
@@ -121,7 +122,7 @@ class HomeViewModel(
|
|||||||
try {
|
try {
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: ActivityNotFoundException) {
|
||||||
context.toast(R.string.open_link_failed_toast, Toast.LENGTH_SHORT)
|
context.toast(CoreR.string.open_link_failed_toast, Toast.LENGTH_SHORT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.publish()
|
}.publish()
|
||||||
@@ -129,8 +130,8 @@ class HomeViewModel(
|
|||||||
fun onDeletePressed() = UninstallDialog().show()
|
fun onDeletePressed() = UninstallDialog().show()
|
||||||
|
|
||||||
fun onManagerPressed() = when (appState) {
|
fun onManagerPressed() = when (appState) {
|
||||||
State.LOADING -> SnackbarEvent(R.string.loading).publish()
|
State.LOADING -> SnackbarEvent(CoreR.string.loading).publish()
|
||||||
State.INVALID -> SnackbarEvent(R.string.no_connection).publish()
|
State.INVALID -> SnackbarEvent(CoreR.string.no_connection).publish()
|
||||||
else -> withExternalRW {
|
else -> withExternalRW {
|
||||||
withInstallPermission {
|
withInstallPermission {
|
||||||
ManagerInstallDialog().show()
|
ManagerInstallDialog().show()
|
@@ -1,5 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.ui.home
|
package com.topjohnwu.magisk.ui.home
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import android.view.ContextThemeWrapper
|
import android.view.ContextThemeWrapper
|
||||||
@@ -7,7 +8,8 @@ import android.view.MenuItem
|
|||||||
import android.widget.PopupMenu
|
import android.widget.PopupMenu
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.ktx.reboot as systemReboot
|
import com.topjohnwu.magisk.core.ktx.reboot as systemReboot
|
||||||
|
|
||||||
object RebootMenu {
|
object RebootMenu {
|
||||||
@@ -20,19 +22,30 @@ object RebootMenu {
|
|||||||
R.id.action_reboot_download -> systemReboot("download")
|
R.id.action_reboot_download -> systemReboot("download")
|
||||||
R.id.action_reboot_edl -> systemReboot("edl")
|
R.id.action_reboot_edl -> systemReboot("edl")
|
||||||
R.id.action_reboot_recovery -> systemReboot("recovery")
|
R.id.action_reboot_recovery -> systemReboot("recovery")
|
||||||
|
R.id.action_reboot_safe_mode -> {
|
||||||
|
val status = !item.isChecked
|
||||||
|
item.isChecked = status
|
||||||
|
Config.bootloop = if (status) 2 else 0
|
||||||
|
}
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun inflate(activity: BaseActivity): PopupMenu {
|
fun inflate(activity: Activity): PopupMenu {
|
||||||
val themeWrapper = ContextThemeWrapper(activity, R.style.Foundation_PopupMenu)
|
val themeWrapper = ContextThemeWrapper(activity, R.style.Foundation_PopupMenu)
|
||||||
val menu = PopupMenu(themeWrapper, activity.findViewById(R.id.action_reboot))
|
val menu = PopupMenu(themeWrapper, activity.findViewById(R.id.action_reboot))
|
||||||
activity.menuInflater.inflate(R.menu.menu_reboot, menu.menu)
|
activity.menuInflater.inflate(R.menu.menu_reboot, menu.menu)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
|
|
||||||
activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true)
|
|
||||||
menu.menu.findItem(R.id.action_reboot_userspace).isVisible = true
|
|
||||||
menu.setOnMenuItemClickListener(RebootMenu::reboot)
|
menu.setOnMenuItemClickListener(RebootMenu::reboot)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
|
||||||
|
activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true) {
|
||||||
|
menu.menu.findItem(R.id.action_reboot_userspace).isVisible = true
|
||||||
|
}
|
||||||
|
if (Const.Version.isCanary()) {
|
||||||
|
menu.menu.findItem(R.id.action_reboot_safe_mode).isChecked = Config.bootloop >= 2
|
||||||
|
} else {
|
||||||
|
menu.menu.findItem(R.id.action_reboot_safe_mode).isVisible = false
|
||||||
|
}
|
||||||
return menu
|
return menu
|
||||||
}
|
}
|
||||||
|
|
@@ -4,6 +4,7 @@ import com.topjohnwu.magisk.R
|
|||||||
import com.topjohnwu.magisk.arch.BaseFragment
|
import com.topjohnwu.magisk.arch.BaseFragment
|
||||||
import com.topjohnwu.magisk.arch.viewModel
|
import com.topjohnwu.magisk.arch.viewModel
|
||||||
import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class InstallFragment : BaseFragment<FragmentInstallMd2Binding>() {
|
class InstallFragment : BaseFragment<FragmentInstallMd2Binding>() {
|
||||||
|
|
||||||
@@ -12,6 +13,6 @@ class InstallFragment : BaseFragment<FragmentInstallMd2Binding>() {
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
requireActivity().setTitle(R.string.install)
|
requireActivity().setTitle(CoreR.string.install)
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -11,14 +11,14 @@ import androidx.lifecycle.LiveData
|
|||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||||
|
import com.topjohnwu.magisk.core.AppContext
|
||||||
|
import com.topjohnwu.magisk.core.BuildConfig
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.base.ContentResultCallback
|
import com.topjohnwu.magisk.core.base.ContentResultCallback
|
||||||
import com.topjohnwu.magisk.core.di.AppContext
|
|
||||||
import com.topjohnwu.magisk.core.ktx.toast
|
import com.topjohnwu.magisk.core.ktx.toast
|
||||||
import com.topjohnwu.magisk.core.repository.NetworkService
|
import com.topjohnwu.magisk.core.repository.NetworkService
|
||||||
import com.topjohnwu.magisk.databinding.set
|
import com.topjohnwu.magisk.databinding.set
|
||||||
@@ -33,12 +33,12 @@ import kotlinx.parcelize.Parcelize
|
|||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel() {
|
class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel() {
|
||||||
|
|
||||||
val isRooted get() = Info.isRooted
|
val isRooted get() = Info.isRooted
|
||||||
val hideVbmeta = Info.vbmeta || Info.isSamsung || Info.isAB
|
val skipOptions = Info.isEmulator || (Info.isSAR && !Info.isFDE && Info.ramdisk)
|
||||||
val skipOptions = Info.isEmulator || (Info.isSAR && !Info.isFDE && hideVbmeta && Info.ramdisk)
|
|
||||||
val noSecondSlot = !isRooted || !Info.isAB || Info.isEmulator
|
val noSecondSlot = !isRooted || !Info.isAB || Info.isEmulator
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
@@ -70,7 +70,7 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
|
|||||||
init {
|
init {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val file = File(AppContext.cacheDir, "${BuildConfig.VERSION_CODE}.md")
|
val file = File(AppContext.cacheDir, "${BuildConfig.APP_VERSION_CODE}.md")
|
||||||
val text = when {
|
val text = when {
|
||||||
file.exists() -> file.readText()
|
file.exists() -> file.readText()
|
||||||
Const.Url.CHANGELOG_URL.isEmpty() -> ""
|
Const.Url.CHANGELOG_URL.isEmpty() -> ""
|
||||||
@@ -105,7 +105,6 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
|
|||||||
step,
|
step,
|
||||||
Config.keepVerity,
|
Config.keepVerity,
|
||||||
Config.keepEnc,
|
Config.keepEnc,
|
||||||
Config.patchVbmeta,
|
|
||||||
Config.recovery
|
Config.recovery
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -116,7 +115,6 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
|
|||||||
step = it.step
|
step = it.step
|
||||||
Config.keepVerity = it.keepVerity
|
Config.keepVerity = it.keepVerity
|
||||||
Config.keepEnc = it.keepEnc
|
Config.keepEnc = it.keepEnc
|
||||||
Config.patchVbmeta = it.patchVbmeta
|
|
||||||
Config.recovery = it.recovery
|
Config.recovery = it.recovery
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +122,7 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
|
|||||||
@Parcelize
|
@Parcelize
|
||||||
class UriCallback : ContentResultCallback {
|
class UriCallback : ContentResultCallback {
|
||||||
override fun onActivityLaunch() {
|
override fun onActivityLaunch() {
|
||||||
AppContext.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
|
AppContext.toast(CoreR.string.patch_file_msg, Toast.LENGTH_LONG)
|
||||||
}
|
}
|
||||||
override fun onActivityResult(result: Uri) {
|
override fun onActivityResult(result: Uri) {
|
||||||
uri.value = result
|
uri.value = result
|
||||||
@@ -137,7 +135,6 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
|
|||||||
val step: Int,
|
val step: Int,
|
||||||
val keepVerity: Boolean,
|
val keepVerity: Boolean,
|
||||||
val keepEnc: Boolean,
|
val keepEnc: Boolean,
|
||||||
val patchVbmeta: Boolean,
|
|
||||||
val recovery: Boolean,
|
val recovery: Boolean,
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
@@ -16,6 +16,7 @@ import com.topjohnwu.magisk.utils.MotionRevealHelper
|
|||||||
import rikka.recyclerview.addEdgeSpacing
|
import rikka.recyclerview.addEdgeSpacing
|
||||||
import rikka.recyclerview.addItemSpacing
|
import rikka.recyclerview.addItemSpacing
|
||||||
import rikka.recyclerview.fixEdgeEffect
|
import rikka.recyclerview.fixEdgeEffect
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class LogFragment : BaseFragment<FragmentLogMd2Binding>(), MenuProvider {
|
class LogFragment : BaseFragment<FragmentLogMd2Binding>(), MenuProvider {
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ class LogFragment : BaseFragment<FragmentLogMd2Binding>(), MenuProvider {
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
activity?.setTitle(R.string.logs)
|
activity?.setTitle(CoreR.string.logs)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
@@ -4,10 +4,10 @@ import android.system.Os
|
|||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
||||||
|
import com.topjohnwu.magisk.core.BuildConfig
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.core.ktx.timeFormatStandard
|
import com.topjohnwu.magisk.core.ktx.timeFormatStandard
|
||||||
import com.topjohnwu.magisk.core.ktx.toTime
|
import com.topjohnwu.magisk.core.ktx.toTime
|
||||||
import com.topjohnwu.magisk.core.repository.LogRepository
|
import com.topjohnwu.magisk.core.repository.LogRepository
|
||||||
@@ -69,7 +69,7 @@ class LogViewModel(
|
|||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val filename = "magisk_log_%s.log".format(
|
val filename = "magisk_log_%s.log".format(
|
||||||
System.currentTimeMillis().toTime(timeFormatStandard))
|
System.currentTimeMillis().toTime(timeFormatStandard))
|
||||||
val logFile = MediaStoreUtils.getFile(filename, true)
|
val logFile = MediaStoreUtils.getFile(filename)
|
||||||
logFile.uri.outputStream().bufferedWriter().use { file ->
|
logFile.uri.outputStream().bufferedWriter().use { file ->
|
||||||
file.write("---Detected Device Info---\n\n")
|
file.write("---Detected Device Info---\n\n")
|
||||||
file.write("isAB=${Info.isAB}\n")
|
file.write("isAB=${Info.isAB}\n")
|
||||||
@@ -93,7 +93,7 @@ class LogViewModel(
|
|||||||
if (Info.env.isActive) file.write(magiskLogRaw)
|
if (Info.env.isActive) file.write(magiskLogRaw)
|
||||||
|
|
||||||
file.write("\n---Manager Logs---\n")
|
file.write("\n---Manager Logs---\n")
|
||||||
file.write("${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})\n\n")
|
file.write("${BuildConfig.APP_VERSION_NAME} (${BuildConfig.APP_VERSION_CODE})\n\n")
|
||||||
ProcessBuilder("logcat", "-d").start()
|
ProcessBuilder("logcat", "-d").start()
|
||||||
.inputStream.reader().use { it.copyTo(file) }
|
.inputStream.reader().use { it.copyTo(file) }
|
||||||
}
|
}
|
@@ -0,0 +1,54 @@
|
|||||||
|
package com.topjohnwu.magisk.ui.log
|
||||||
|
|
||||||
|
import androidx.databinding.Bindable
|
||||||
|
import com.topjohnwu.magisk.BR
|
||||||
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.AppContext
|
||||||
|
import com.topjohnwu.magisk.core.ktx.timeDateFormat
|
||||||
|
import com.topjohnwu.magisk.core.ktx.toTime
|
||||||
|
import com.topjohnwu.magisk.core.model.su.SuLog
|
||||||
|
import com.topjohnwu.magisk.databinding.DiffItem
|
||||||
|
import com.topjohnwu.magisk.databinding.ObservableRvItem
|
||||||
|
import com.topjohnwu.magisk.databinding.set
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
|
class SuLogRvItem(val log: SuLog) : ObservableRvItem(), DiffItem<SuLogRvItem> {
|
||||||
|
|
||||||
|
override val layoutRes = R.layout.item_log_access_md2
|
||||||
|
|
||||||
|
val info = genInfo()
|
||||||
|
|
||||||
|
@get:Bindable
|
||||||
|
var isTop = false
|
||||||
|
set(value) = set(value, field, { field = it }, BR.top)
|
||||||
|
|
||||||
|
@get:Bindable
|
||||||
|
var isBottom = false
|
||||||
|
set(value) = set(value, field, { field = it }, BR.bottom)
|
||||||
|
|
||||||
|
override fun itemSameAs(other: SuLogRvItem) = log.appName == other.log.appName
|
||||||
|
|
||||||
|
private fun genInfo(): String {
|
||||||
|
val res = AppContext.resources
|
||||||
|
val sb = StringBuilder()
|
||||||
|
val date = log.time.toTime(timeDateFormat)
|
||||||
|
val toUid = res.getString(CoreR.string.target_uid, log.toUid)
|
||||||
|
val fromPid = res.getString(CoreR.string.pid, log.fromPid)
|
||||||
|
sb.append("$date\n$toUid $fromPid")
|
||||||
|
if (log.target != -1) {
|
||||||
|
val pid = if (log.target == 0) "magiskd" else log.target.toString()
|
||||||
|
val target = res.getString(CoreR.string.target_pid, pid)
|
||||||
|
sb.append(" $target")
|
||||||
|
}
|
||||||
|
if (log.context.isNotEmpty()) {
|
||||||
|
val context = res.getString(CoreR.string.selinux_context, log.context)
|
||||||
|
sb.append("\n$context")
|
||||||
|
}
|
||||||
|
if (log.gids.isNotEmpty()) {
|
||||||
|
val gids = res.getString(CoreR.string.supp_group, log.gids)
|
||||||
|
sb.append("\n$gids")
|
||||||
|
}
|
||||||
|
sb.append("\n${log.command}")
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
}
|
@@ -11,6 +11,7 @@ import rikka.recyclerview.addEdgeSpacing
|
|||||||
import rikka.recyclerview.addInvalidateItemDecorationsObserver
|
import rikka.recyclerview.addInvalidateItemDecorationsObserver
|
||||||
import rikka.recyclerview.addItemSpacing
|
import rikka.recyclerview.addItemSpacing
|
||||||
import rikka.recyclerview.fixEdgeEffect
|
import rikka.recyclerview.fixEdgeEffect
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class ModuleFragment : BaseFragment<FragmentModuleMd2Binding>() {
|
class ModuleFragment : BaseFragment<FragmentModuleMd2Binding>() {
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ class ModuleFragment : BaseFragment<FragmentModuleMd2Binding>() {
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
activity?.title = resources.getString(R.string.modules)
|
activity?.title = resources.getString(CoreR.string.modules)
|
||||||
viewModel.data.observe(this) {
|
viewModel.data.observe(this) {
|
||||||
it ?: return@observe
|
it ?: return@observe
|
||||||
val displayName = runCatching { it.displayName }.getOrNull() ?: return@observe
|
val displayName = runCatching { it.displayName }.getOrNull() ?: return@observe
|
@@ -12,6 +12,7 @@ import com.topjohnwu.magisk.databinding.RvItem
|
|||||||
import com.topjohnwu.magisk.databinding.set
|
import com.topjohnwu.magisk.databinding.set
|
||||||
import com.topjohnwu.magisk.utils.TextHolder
|
import com.topjohnwu.magisk.utils.TextHolder
|
||||||
import com.topjohnwu.magisk.utils.asText
|
import com.topjohnwu.magisk.utils.asText
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
object InstallModule : RvItem(), DiffItem<InstallModule> {
|
object InstallModule : RvItem(), DiffItem<InstallModule> {
|
||||||
override val layoutRes = R.layout.item_module_download
|
override val layoutRes = R.layout.item_module_download
|
||||||
@@ -36,9 +37,9 @@ class LocalModuleRvItem(
|
|||||||
(!Info.isZygiskEnabled && isZygisk)
|
(!Info.isZygiskEnabled && isZygisk)
|
||||||
noticeText =
|
noticeText =
|
||||||
when {
|
when {
|
||||||
zygiskUnloaded -> R.string.zygisk_module_unloaded.asText()
|
zygiskUnloaded -> CoreR.string.zygisk_module_unloaded.asText()
|
||||||
isRiru -> R.string.suspend_text_riru.asText(R.string.zygisk.asText())
|
isRiru -> CoreR.string.suspend_text_riru.asText(CoreR.string.zygisk.asText())
|
||||||
else -> R.string.suspend_text_zygisk.asText(R.string.zygisk.asText())
|
else -> CoreR.string.suspend_text_zygisk.asText(CoreR.string.zygisk.asText())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@@ -22,6 +22,7 @@ import com.topjohnwu.magisk.events.SnackbarEvent
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class ModuleViewModel : AsyncLoadViewModel() {
|
class ModuleViewModel : AsyncLoadViewModel() {
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ class ModuleViewModel : AsyncLoadViewModel() {
|
|||||||
if (item != null && Info.isConnected.value == true) {
|
if (item != null && Info.isConnected.value == true) {
|
||||||
withExternalRW { OnlineModuleInstallDialog(item).show() }
|
withExternalRW { OnlineModuleInstallDialog(item).show() }
|
||||||
} else {
|
} else {
|
||||||
SnackbarEvent(R.string.no_connection).publish()
|
SnackbarEvent(CoreR.string.no_connection).publish()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun installPressed() = withExternalRW {
|
fun installPressed() = withExternalRW {
|
@@ -14,29 +14,34 @@ import com.topjohnwu.magisk.view.MagiskDialog
|
|||||||
|
|
||||||
sealed class BaseSettingsItem : ObservableRvItem() {
|
sealed class BaseSettingsItem : ObservableRvItem() {
|
||||||
|
|
||||||
|
interface Handler {
|
||||||
|
fun onItemPressed(view: View, item: BaseSettingsItem, andThen: () -> Unit)
|
||||||
|
fun onItemAction(view: View, item: BaseSettingsItem)
|
||||||
|
}
|
||||||
|
|
||||||
override val layoutRes get() = R.layout.item_settings
|
override val layoutRes get() = R.layout.item_settings
|
||||||
|
|
||||||
open val icon: Int get() = 0
|
open val icon: Int get() = 0
|
||||||
open val title: TextHolder get() = TextHolder.EMPTY
|
open val title: TextHolder get() = TextHolder.EMPTY
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
open val description: TextHolder get() = TextHolder.EMPTY
|
open val description: TextHolder get() = TextHolder.EMPTY
|
||||||
open val showSwitch get() = false
|
|
||||||
@get:Bindable
|
|
||||||
open val isChecked get() = false
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var isEnabled = true
|
var isEnabled = true
|
||||||
set(value) = set(value, field, { field = it }, BR.enabled, BR.description)
|
set(value) = set(value, field, { field = it }, BR.enabled, BR.description)
|
||||||
|
|
||||||
open fun onToggle(view: View, handler: Handler, checked: Boolean) {}
|
|
||||||
open fun onPressed(view: View, handler: Handler) {
|
open fun onPressed(view: View, handler: Handler) {
|
||||||
handler.onItemPressed(view, this)
|
handler.onItemPressed(view, this) {
|
||||||
|
handler.onItemAction(view, this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
open fun refresh() {}
|
open fun refresh() {}
|
||||||
|
|
||||||
interface Handler {
|
// Only for toggle
|
||||||
fun onItemPressed(view: View, item: BaseSettingsItem, andThen: () -> Unit = {})
|
open val showSwitch get() = false
|
||||||
fun onItemAction(view: View, item: BaseSettingsItem)
|
@get:Bindable
|
||||||
}
|
open val isChecked get() = false
|
||||||
|
fun onToggle(view: View, handler: Handler, checked: Boolean) =
|
||||||
|
set(checked, isChecked, { onPressed(view, handler) })
|
||||||
|
|
||||||
abstract class Value<T> : BaseSettingsItem() {
|
abstract class Value<T> : BaseSettingsItem() {
|
||||||
|
|
||||||
@@ -54,9 +59,6 @@ sealed class BaseSettingsItem : ObservableRvItem() {
|
|||||||
override val showSwitch get() = true
|
override val showSwitch get() = true
|
||||||
override val isChecked get() = value
|
override val isChecked get() = value
|
||||||
|
|
||||||
override fun onToggle(view: View, handler: Handler, checked: Boolean) =
|
|
||||||
set(checked, value, { onPressed(view, handler) })
|
|
||||||
|
|
||||||
override fun onPressed(view: View, handler: Handler) {
|
override fun onPressed(view: View, handler: Handler) {
|
||||||
// Make sure the checked state is synced
|
// Make sure the checked state is synced
|
||||||
notifyPropertyChanged(BR.checked)
|
notifyPropertyChanged(BR.checked)
|
||||||
@@ -140,5 +142,4 @@ sealed class BaseSettingsItem : ObservableRvItem() {
|
|||||||
abstract class Section : BaseSettingsItem() {
|
abstract class Section : BaseSettingsItem() {
|
||||||
override val layoutRes = R.layout.item_settings_section
|
override val layoutRes = R.layout.item_settings_section
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -9,6 +9,7 @@ import com.topjohnwu.magisk.databinding.FragmentSettingsMd2Binding
|
|||||||
import rikka.recyclerview.addEdgeSpacing
|
import rikka.recyclerview.addEdgeSpacing
|
||||||
import rikka.recyclerview.addItemSpacing
|
import rikka.recyclerview.addItemSpacing
|
||||||
import rikka.recyclerview.fixEdgeEffect
|
import rikka.recyclerview.fixEdgeEffect
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class SettingsFragment : BaseFragment<FragmentSettingsMd2Binding>() {
|
class SettingsFragment : BaseFragment<FragmentSettingsMd2Binding>() {
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsMd2Binding>() {
|
|||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
|
|
||||||
activity?.title = resources.getString(R.string.settings)
|
activity?.title = resources.getString(CoreR.string.settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
@@ -7,82 +7,70 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.core.BuildConfig
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.ktx.activity
|
import com.topjohnwu.magisk.core.ktx.activity
|
||||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
import com.topjohnwu.magisk.core.tasks.AppMigration
|
||||||
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
import com.topjohnwu.magisk.core.utils.LocaleSetting
|
||||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||||
import com.topjohnwu.magisk.core.utils.availableLocales
|
|
||||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
|
||||||
import com.topjohnwu.magisk.databinding.DialogSettingsAppNameBinding
|
import com.topjohnwu.magisk.databinding.DialogSettingsAppNameBinding
|
||||||
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
|
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
|
||||||
import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
|
import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
|
||||||
import com.topjohnwu.magisk.databinding.set
|
import com.topjohnwu.magisk.databinding.set
|
||||||
|
import com.topjohnwu.magisk.utils.TextHolder
|
||||||
import com.topjohnwu.magisk.utils.asText
|
import com.topjohnwu.magisk.utils.asText
|
||||||
import com.topjohnwu.magisk.view.MagiskDialog
|
import com.topjohnwu.magisk.view.MagiskDialog
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
// --- Customization
|
// --- Customization
|
||||||
|
|
||||||
object Customization : BaseSettingsItem.Section() {
|
object Customization : BaseSettingsItem.Section() {
|
||||||
override val title = R.string.settings_customization.asText()
|
override val title = CoreR.string.settings_customization.asText()
|
||||||
}
|
}
|
||||||
|
|
||||||
object Language : BaseSettingsItem.Selector() {
|
object Language : BaseSettingsItem.Selector() {
|
||||||
|
private val names: Array<String> get() = LocaleSetting.available.names
|
||||||
|
private val tags: Array<String> get() = LocaleSetting.available.tags
|
||||||
|
|
||||||
override var value
|
override var value
|
||||||
get() = index
|
get() = tags.indexOf(Config.locale)
|
||||||
set(value) {
|
set(value) {
|
||||||
index = value
|
Config.locale = tags[value]
|
||||||
Config.locale = entryValues[value]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val title = R.string.language.asText()
|
override val title = CoreR.string.language.asText()
|
||||||
|
|
||||||
private var entries = emptyArray<String>()
|
override fun entries(res: Resources) = names
|
||||||
private var entryValues = emptyArray<String>()
|
override fun descriptions(res: Resources) = names
|
||||||
private var index = -1
|
}
|
||||||
|
|
||||||
override fun entries(res: Resources) = entries
|
object LanguageSystem : BaseSettingsItem.Blank() {
|
||||||
override fun descriptions(res: Resources) = entries
|
override val title = CoreR.string.language.asText()
|
||||||
|
override val description: TextHolder
|
||||||
override fun onPressed(view: View, handler: Handler) {
|
get() {
|
||||||
if (entries.isNotEmpty())
|
val locale = LocaleSetting.instance.appLocale
|
||||||
super.onPressed(view, handler)
|
return locale?.getDisplayName(locale)?.asText() ?: CoreR.string.system_default.asText()
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun loadLanguages(scope: CoroutineScope) {
|
|
||||||
scope.launch {
|
|
||||||
availableLocales().let { (names, values) ->
|
|
||||||
entries = names
|
|
||||||
entryValues = values
|
|
||||||
val selectedLocale = currentLocale.getDisplayName(currentLocale)
|
|
||||||
index = names.indexOfFirst { it == selectedLocale }.let { if (it == -1) 0 else it }
|
|
||||||
notifyPropertyChanged(BR.description)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object Theme : BaseSettingsItem.Blank() {
|
object Theme : BaseSettingsItem.Blank() {
|
||||||
override val icon = R.drawable.ic_paint
|
override val icon = R.drawable.ic_paint
|
||||||
override val title = R.string.section_theme.asText()
|
override val title = CoreR.string.section_theme.asText()
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- App
|
// --- App
|
||||||
|
|
||||||
object AppSettings : BaseSettingsItem.Section() {
|
object AppSettings : BaseSettingsItem.Section() {
|
||||||
override val title = R.string.home_app_title.asText()
|
override val title = CoreR.string.home_app_title.asText()
|
||||||
}
|
}
|
||||||
|
|
||||||
object Hide : BaseSettingsItem.Input() {
|
object Hide : BaseSettingsItem.Input() {
|
||||||
override val title = R.string.settings_hide_app_title.asText()
|
override val title = CoreR.string.settings_hide_app_title.asText()
|
||||||
override val description = R.string.settings_hide_app_summary.asText()
|
override val description = CoreR.string.settings_hide_app_summary.asText()
|
||||||
override var value = ""
|
override var value = ""
|
||||||
|
|
||||||
override val inputResult
|
override val inputResult
|
||||||
@@ -93,7 +81,7 @@ object Hide : BaseSettingsItem.Input() {
|
|||||||
set(value) = set(value, field, { field = it }, BR.result, BR.error)
|
set(value) = set(value, field, { field = it }, BR.result, BR.error)
|
||||||
|
|
||||||
val maxLength
|
val maxLength
|
||||||
get() = HideAPK.MAX_LABEL_LENGTH
|
get() = AppMigration.MAX_LABEL_LENGTH
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
val isError
|
val isError
|
||||||
@@ -104,14 +92,14 @@ object Hide : BaseSettingsItem.Input() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Restore : BaseSettingsItem.Blank() {
|
object Restore : BaseSettingsItem.Blank() {
|
||||||
override val title = R.string.settings_restore_app_title.asText()
|
override val title = CoreR.string.settings_restore_app_title.asText()
|
||||||
override val description = R.string.settings_restore_app_summary.asText()
|
override val description = CoreR.string.settings_restore_app_summary.asText()
|
||||||
|
|
||||||
override fun onPressed(view: View, handler: Handler) {
|
override fun onPressed(view: View, handler: Handler) {
|
||||||
handler.onItemPressed(view, this) {
|
handler.onItemPressed(view, this) {
|
||||||
MagiskDialog(view.activity).apply {
|
MagiskDialog(view.activity).apply {
|
||||||
setTitle(R.string.settings_restore_app_title)
|
setTitle(CoreR.string.settings_restore_app_title)
|
||||||
setMessage(R.string.restore_app_confirmation)
|
setMessage(CoreR.string.restore_app_confirmation)
|
||||||
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
setButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||||
text = android.R.string.ok
|
text = android.R.string.ok
|
||||||
onClick {
|
onClick {
|
||||||
@@ -129,8 +117,8 @@ object Restore : BaseSettingsItem.Blank() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object AddShortcut : BaseSettingsItem.Blank() {
|
object AddShortcut : BaseSettingsItem.Blank() {
|
||||||
override val title = R.string.add_shortcut_title.asText()
|
override val title = CoreR.string.add_shortcut_title.asText()
|
||||||
override val description = R.string.setting_add_shortcut_summary.asText()
|
override val description = CoreR.string.setting_add_shortcut_summary.asText()
|
||||||
}
|
}
|
||||||
|
|
||||||
object DownloadPath : BaseSettingsItem.Input() {
|
object DownloadPath : BaseSettingsItem.Input() {
|
||||||
@@ -141,7 +129,7 @@ object DownloadPath : BaseSettingsItem.Input() {
|
|||||||
notifyPropertyChanged(BR.description)
|
notifyPropertyChanged(BR.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val title = R.string.settings_download_path_title.asText()
|
override val title = CoreR.string.settings_download_path_title.asText()
|
||||||
override val description get() = MediaStoreUtils.fullPath(value).asText()
|
override val description get() = MediaStoreUtils.fullPath(value).asText()
|
||||||
|
|
||||||
override var inputResult: String = value
|
override var inputResult: String = value
|
||||||
@@ -162,9 +150,9 @@ object UpdateChannel : BaseSettingsItem.Selector() {
|
|||||||
Info.remote = Info.EMPTY_REMOTE
|
Info.remote = Info.EMPTY_REMOTE
|
||||||
}
|
}
|
||||||
|
|
||||||
override val title = R.string.settings_update_channel_title.asText()
|
override val title = CoreR.string.settings_update_channel_title.asText()
|
||||||
|
|
||||||
override val entryRes = R.array.update_channel
|
override val entryRes = CoreR.array.update_channel
|
||||||
override fun entries(res: Resources): Array<String> {
|
override fun entries(res: Resources): Array<String> {
|
||||||
return super.entries(res).let {
|
return super.entries(res).let {
|
||||||
if (!Const.APP_IS_CANARY && !BuildConfig.DEBUG)
|
if (!Const.APP_IS_CANARY && !BuildConfig.DEBUG)
|
||||||
@@ -175,7 +163,7 @@ object UpdateChannel : BaseSettingsItem.Selector() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object UpdateChannelUrl : BaseSettingsItem.Input() {
|
object UpdateChannelUrl : BaseSettingsItem.Input() {
|
||||||
override val title = R.string.settings_update_custom.asText()
|
override val title = CoreR.string.settings_update_custom.asText()
|
||||||
override val description get() = value.asText()
|
override val description get() = value.asText()
|
||||||
override var value
|
override var value
|
||||||
get() = Config.customChannelUrl
|
get() = Config.customChannelUrl
|
||||||
@@ -197,56 +185,51 @@ object UpdateChannelUrl : BaseSettingsItem.Input() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object UpdateChecker : BaseSettingsItem.Toggle() {
|
object UpdateChecker : BaseSettingsItem.Toggle() {
|
||||||
override val title = R.string.settings_check_update_title.asText()
|
override val title = CoreR.string.settings_check_update_title.asText()
|
||||||
override val description = R.string.settings_check_update_summary.asText()
|
override val description = CoreR.string.settings_check_update_summary.asText()
|
||||||
override var value by Config::checkUpdate
|
override var value by Config::checkUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
object DoHToggle : BaseSettingsItem.Toggle() {
|
object DoHToggle : BaseSettingsItem.Toggle() {
|
||||||
override val title = R.string.settings_doh_title.asText()
|
override val title = CoreR.string.settings_doh_title.asText()
|
||||||
override val description = R.string.settings_doh_description.asText()
|
override val description = CoreR.string.settings_doh_description.asText()
|
||||||
override var value by Config::doh
|
override var value by Config::doh
|
||||||
}
|
}
|
||||||
|
|
||||||
object SystemlessHosts : BaseSettingsItem.Blank() {
|
object SystemlessHosts : BaseSettingsItem.Blank() {
|
||||||
override val title = R.string.settings_hosts_title.asText()
|
override val title = CoreR.string.settings_hosts_title.asText()
|
||||||
override val description = R.string.settings_hosts_summary.asText()
|
override val description = CoreR.string.settings_hosts_summary.asText()
|
||||||
|
}
|
||||||
|
|
||||||
|
object RandNameToggle : BaseSettingsItem.Toggle() {
|
||||||
|
override val title = CoreR.string.settings_random_name_title.asText()
|
||||||
|
override val description = CoreR.string.settings_random_name_description.asText()
|
||||||
|
override var value by Config::randName
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Magisk
|
// --- Magisk
|
||||||
|
|
||||||
object Magisk : BaseSettingsItem.Section() {
|
object Magisk : BaseSettingsItem.Section() {
|
||||||
override val title = R.string.magisk.asText()
|
override val title = CoreR.string.magisk.asText()
|
||||||
}
|
}
|
||||||
|
|
||||||
object Zygisk : BaseSettingsItem.Toggle() {
|
object Zygisk : BaseSettingsItem.Toggle() {
|
||||||
override val title = R.string.zygisk.asText()
|
override val title = CoreR.string.zygisk.asText()
|
||||||
override val description get() =
|
override val description get() =
|
||||||
if (mismatch) R.string.reboot_apply_change.asText()
|
if (mismatch) CoreR.string.reboot_apply_change.asText()
|
||||||
else R.string.settings_zygisk_summary.asText()
|
else CoreR.string.settings_zygisk_summary.asText()
|
||||||
override var value
|
override var value
|
||||||
get() = Config.zygisk
|
get() = Config.zygisk
|
||||||
set(value) {
|
set(value) {
|
||||||
Config.zygisk = value
|
Config.zygisk = value
|
||||||
DenyList.isEnabled = value
|
|
||||||
DenyListConfig.isEnabled = value
|
|
||||||
notifyPropertyChanged(BR.description)
|
notifyPropertyChanged(BR.description)
|
||||||
DenyList.notifyPropertyChanged(BR.description)
|
|
||||||
}
|
}
|
||||||
val mismatch get() = value != Info.isZygiskEnabled
|
val mismatch get() = value != Info.isZygiskEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
object DenyList : BaseSettingsItem.Toggle() {
|
object DenyList : BaseSettingsItem.Toggle() {
|
||||||
override val title = R.string.settings_denylist_title.asText()
|
override val title = CoreR.string.settings_denylist_title.asText()
|
||||||
override val description get() =
|
override val description get() = CoreR.string.settings_denylist_summary.asText()
|
||||||
if (isEnabled) {
|
|
||||||
if (Zygisk.mismatch)
|
|
||||||
R.string.reboot_apply_change.asText()
|
|
||||||
else
|
|
||||||
R.string.settings_denylist_summary.asText()
|
|
||||||
} else {
|
|
||||||
R.string.settings_denylist_error.asText(R.string.zygisk.asText())
|
|
||||||
}
|
|
||||||
|
|
||||||
override var value = Config.denyList
|
override var value = Config.denyList
|
||||||
set(value) {
|
set(value) {
|
||||||
@@ -261,57 +244,48 @@ object DenyList : BaseSettingsItem.Toggle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun refresh() {
|
|
||||||
isEnabled = Zygisk.value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object DenyListConfig : BaseSettingsItem.Blank() {
|
object DenyListConfig : BaseSettingsItem.Blank() {
|
||||||
override val title = R.string.settings_denylist_config_title.asText()
|
override val title = CoreR.string.settings_denylist_config_title.asText()
|
||||||
override val description = R.string.settings_denylist_config_summary.asText()
|
override val description = CoreR.string.settings_denylist_config_summary.asText()
|
||||||
override fun refresh() {
|
|
||||||
isEnabled = Zygisk.value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Superuser
|
// --- Superuser
|
||||||
|
|
||||||
object Tapjack : BaseSettingsItem.Toggle() {
|
object Tapjack : BaseSettingsItem.Toggle() {
|
||||||
override val title = R.string.settings_su_tapjack_title.asText()
|
override val title = CoreR.string.settings_su_tapjack_title.asText()
|
||||||
override val description = R.string.settings_su_tapjack_summary.asText()
|
override val description = CoreR.string.settings_su_tapjack_summary.asText()
|
||||||
override var value by Config::suTapjack
|
override var value by Config::suTapjack
|
||||||
}
|
}
|
||||||
|
|
||||||
object Biometrics : BaseSettingsItem.Toggle() {
|
object Authentication : BaseSettingsItem.Toggle() {
|
||||||
override val title = R.string.settings_su_biometric_title.asText()
|
override val title = CoreR.string.settings_su_auth_title.asText()
|
||||||
override var description = R.string.settings_su_biometric_summary.asText()
|
override var description = CoreR.string.settings_su_auth_summary.asText()
|
||||||
override var value by Config::suBiometric
|
override var value by Config::suAuth
|
||||||
|
|
||||||
override fun refresh() {
|
override fun refresh() {
|
||||||
isEnabled = BiometricHelper.isSupported
|
isEnabled = Info.isDeviceSecure
|
||||||
if (!isEnabled) {
|
if (!isEnabled) {
|
||||||
value = false
|
description = CoreR.string.settings_su_auth_insecure.asText()
|
||||||
description = R.string.no_biometric.asText()
|
|
||||||
notifyPropertyChanged(BR.checked)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Superuser : BaseSettingsItem.Section() {
|
object Superuser : BaseSettingsItem.Section() {
|
||||||
override val title = R.string.superuser.asText()
|
override val title = CoreR.string.superuser.asText()
|
||||||
}
|
}
|
||||||
|
|
||||||
object AccessMode : BaseSettingsItem.Selector() {
|
object AccessMode : BaseSettingsItem.Selector() {
|
||||||
override val title = R.string.superuser_access.asText()
|
override val title = CoreR.string.superuser_access.asText()
|
||||||
override val entryRes = R.array.su_access
|
override val entryRes = CoreR.array.su_access
|
||||||
override var value by Config::rootMode
|
override var value by Config::rootMode
|
||||||
}
|
}
|
||||||
|
|
||||||
object MultiuserMode : BaseSettingsItem.Selector() {
|
object MultiuserMode : BaseSettingsItem.Selector() {
|
||||||
override val title = R.string.multiuser_mode.asText()
|
override val title = CoreR.string.multiuser_mode.asText()
|
||||||
override val entryRes = R.array.multiuser_mode
|
override val entryRes = CoreR.array.multiuser_mode
|
||||||
override val descriptionRes = R.array.multiuser_summary
|
override val descriptionRes = CoreR.array.multiuser_summary
|
||||||
override var value by Config::suMultiuserMode
|
override var value by Config::suMultiuserMode
|
||||||
|
|
||||||
override fun refresh() {
|
override fun refresh() {
|
||||||
@@ -320,21 +294,21 @@ object MultiuserMode : BaseSettingsItem.Selector() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object MountNamespaceMode : BaseSettingsItem.Selector() {
|
object MountNamespaceMode : BaseSettingsItem.Selector() {
|
||||||
override val title = R.string.mount_namespace_mode.asText()
|
override val title = CoreR.string.mount_namespace_mode.asText()
|
||||||
override val entryRes = R.array.namespace
|
override val entryRes = CoreR.array.namespace
|
||||||
override val descriptionRes = R.array.namespace_summary
|
override val descriptionRes = CoreR.array.namespace_summary
|
||||||
override var value by Config::suMntNamespaceMode
|
override var value by Config::suMntNamespaceMode
|
||||||
}
|
}
|
||||||
|
|
||||||
object AutomaticResponse : BaseSettingsItem.Selector() {
|
object AutomaticResponse : BaseSettingsItem.Selector() {
|
||||||
override val title = R.string.auto_response.asText()
|
override val title = CoreR.string.auto_response.asText()
|
||||||
override val entryRes = R.array.auto_response
|
override val entryRes = CoreR.array.auto_response
|
||||||
override var value by Config::suAutoResponse
|
override var value by Config::suAutoResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
object RequestTimeout : BaseSettingsItem.Selector() {
|
object RequestTimeout : BaseSettingsItem.Selector() {
|
||||||
override val title = R.string.request_timeout.asText()
|
override val title = CoreR.string.request_timeout.asText()
|
||||||
override val entryRes = R.array.request_timeout
|
override val entryRes = CoreR.array.request_timeout
|
||||||
|
|
||||||
private val entryValues = listOf(10, 15, 20, 30, 45, 60)
|
private val entryValues = listOf(10, 15, 20, 30, 45, 60)
|
||||||
override var value = entryValues.indexOfFirst { it == Config.suDefaultTimeout }
|
override var value = entryValues.indexOfFirst { it == Config.suDefaultTimeout }
|
||||||
@@ -345,14 +319,14 @@ object RequestTimeout : BaseSettingsItem.Selector() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object SUNotification : BaseSettingsItem.Selector() {
|
object SUNotification : BaseSettingsItem.Selector() {
|
||||||
override val title = R.string.superuser_notification.asText()
|
override val title = CoreR.string.superuser_notification.asText()
|
||||||
override val entryRes = R.array.su_notification
|
override val entryRes = CoreR.array.su_notification
|
||||||
override var value by Config::suNotification
|
override var value by Config::suNotification
|
||||||
}
|
}
|
||||||
|
|
||||||
object Reauthenticate : BaseSettingsItem.Toggle() {
|
object Reauthenticate : BaseSettingsItem.Toggle() {
|
||||||
override val title = R.string.settings_su_reauth_title.asText()
|
override val title = CoreR.string.settings_su_reauth_title.asText()
|
||||||
override val description = R.string.settings_su_reauth_summary.asText()
|
override val description = CoreR.string.settings_su_reauth_summary.asText()
|
||||||
override var value by Config::suReAuth
|
override var value by Config::suReAuth
|
||||||
|
|
||||||
override fun refresh() {
|
override fun refresh() {
|
@@ -1,24 +1,29 @@
|
|||||||
package com.topjohnwu.magisk.ui.settings
|
package com.topjohnwu.magisk.ui.settings
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.provider.Settings
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||||
|
import com.topjohnwu.magisk.core.AppContext
|
||||||
|
import com.topjohnwu.magisk.core.BuildConfig
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.di.AppContext
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||||
import com.topjohnwu.magisk.core.ktx.activity
|
import com.topjohnwu.magisk.core.ktx.activity
|
||||||
import com.topjohnwu.magisk.core.ktx.toast
|
import com.topjohnwu.magisk.core.ktx.toast
|
||||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
import com.topjohnwu.magisk.core.tasks.AppMigration
|
||||||
|
import com.topjohnwu.magisk.core.utils.LocaleSetting
|
||||||
import com.topjohnwu.magisk.databinding.bindExtra
|
import com.topjohnwu.magisk.databinding.bindExtra
|
||||||
import com.topjohnwu.magisk.events.AddHomeIconEvent
|
import com.topjohnwu.magisk.events.AddHomeIconEvent
|
||||||
import com.topjohnwu.magisk.events.BiometricEvent
|
import com.topjohnwu.magisk.events.AuthEvent
|
||||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -30,20 +35,14 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
|||||||
it.put(BR.handler, this)
|
it.put(BR.handler, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
viewModelScope.launch {
|
|
||||||
Language.loadLanguages(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createItems(): List<BaseSettingsItem> {
|
private fun createItems(): List<BaseSettingsItem> {
|
||||||
val context = AppContext
|
val context = AppContext
|
||||||
val hidden = context.packageName != BuildConfig.APPLICATION_ID
|
val hidden = context.packageName != BuildConfig.APP_PACKAGE_NAME
|
||||||
|
|
||||||
// Customization
|
// Customization
|
||||||
val list = mutableListOf(
|
val list = mutableListOf(
|
||||||
Customization,
|
Customization,
|
||||||
Theme, Language
|
Theme, if (LocaleSetting.useLocaleManager) LanguageSystem else Language
|
||||||
)
|
)
|
||||||
if (isRunningAsStub && ShortcutManagerCompat.isRequestPinShortcutSupported(context))
|
if (isRunningAsStub && ShortcutManagerCompat.isRequestPinShortcutSupported(context))
|
||||||
list.add(AddShortcut)
|
list.add(AddShortcut)
|
||||||
@@ -51,7 +50,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
|||||||
// Manager
|
// Manager
|
||||||
list.addAll(listOf(
|
list.addAll(listOf(
|
||||||
AppSettings,
|
AppSettings,
|
||||||
UpdateChannel, UpdateChannelUrl, DoHToggle, UpdateChecker, DownloadPath
|
UpdateChannel, UpdateChannelUrl, DoHToggle, UpdateChecker, DownloadPath, RandNameToggle
|
||||||
))
|
))
|
||||||
if (Info.env.isActive && Const.USER_ID == 0) {
|
if (Info.env.isActive && Const.USER_ID == 0) {
|
||||||
if (hidden) list.add(Restore) else list.add(Hide)
|
if (hidden) list.add(Restore) else list.add(Hide)
|
||||||
@@ -72,7 +71,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
|||||||
if (Info.showSuperUser) {
|
if (Info.showSuperUser) {
|
||||||
list.addAll(listOf(
|
list.addAll(listOf(
|
||||||
Superuser,
|
Superuser,
|
||||||
Tapjack, Biometrics, AccessMode, MultiuserMode, MountNamespaceMode,
|
Tapjack, Authentication, AccessMode, MultiuserMode, MountNamespaceMode,
|
||||||
AutomaticResponse, RequestTimeout, SUNotification
|
AutomaticResponse, RequestTimeout, SUNotification
|
||||||
))
|
))
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||||
@@ -88,30 +87,37 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemPressed(view: View, item: BaseSettingsItem, andThen: () -> Unit) {
|
override fun onItemPressed(view: View, item: BaseSettingsItem, doAction: () -> Unit) {
|
||||||
when (item) {
|
when (item) {
|
||||||
DownloadPath -> withExternalRW(andThen)
|
DownloadPath -> withExternalRW(doAction)
|
||||||
UpdateChecker -> withPostNotificationPermission(andThen)
|
UpdateChecker -> withPostNotificationPermission(doAction)
|
||||||
Biometrics -> authenticate(andThen)
|
Authentication -> AuthEvent(doAction).publish()
|
||||||
Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().navigate()
|
Hide, Restore -> withInstallPermission(doAction)
|
||||||
DenyListConfig -> SettingsFragmentDirections.actionSettingsFragmentToDenyFragment().navigate()
|
else -> doAction()
|
||||||
SystemlessHosts -> createHosts()
|
|
||||||
Hide, Restore -> withInstallPermission(andThen)
|
|
||||||
AddShortcut -> AddHomeIconEvent().publish()
|
|
||||||
else -> andThen()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemAction(view: View, item: BaseSettingsItem) {
|
override fun onItemAction(view: View, item: BaseSettingsItem) {
|
||||||
when (item) {
|
when (item) {
|
||||||
|
Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().navigate()
|
||||||
|
LanguageSystem -> launchAppLocaleSettings(view.activity)
|
||||||
|
AddShortcut -> AddHomeIconEvent().publish()
|
||||||
|
SystemlessHosts -> createHosts()
|
||||||
|
DenyListConfig -> SettingsFragmentDirections.actionSettingsFragmentToDenyFragment().navigate()
|
||||||
UpdateChannel -> openUrlIfNecessary(view)
|
UpdateChannel -> openUrlIfNecessary(view)
|
||||||
is Hide -> viewModelScope.launch { HideAPK.hide(view.activity, item.value) }
|
is Hide -> viewModelScope.launch { AppMigration.hide(view.activity, item.value) }
|
||||||
Restore -> viewModelScope.launch { HideAPK.restore(view.activity) }
|
Restore -> viewModelScope.launch { AppMigration.restore(view.activity) }
|
||||||
Zygisk -> if (Zygisk.mismatch) SnackbarEvent(R.string.reboot_apply_change).publish()
|
Zygisk -> if (Zygisk.mismatch) SnackbarEvent(R.string.reboot_apply_change).publish()
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun launchAppLocaleSettings(activity: Activity) {
|
||||||
|
val intent = Intent(Settings.ACTION_APP_LOCALE_SETTINGS)
|
||||||
|
intent.data = Uri.fromParts("package", activity.packageName, null)
|
||||||
|
activity.startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
private fun openUrlIfNecessary(view: View) {
|
private fun openUrlIfNecessary(view: View) {
|
||||||
UpdateChannelUrl.refresh()
|
UpdateChannelUrl.refresh()
|
||||||
if (UpdateChannelUrl.isEnabled && UpdateChannelUrl.value.isBlank()) {
|
if (UpdateChannelUrl.isEnabled && UpdateChannelUrl.value.isBlank()) {
|
||||||
@@ -119,13 +125,6 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun authenticate(callback: () -> Unit) {
|
|
||||||
BiometricEvent {
|
|
||||||
// allow the change on success
|
|
||||||
onSuccess { callback() }
|
|
||||||
}.publish()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createHosts() {
|
private fun createHosts() {
|
||||||
Shell.cmd("add_hosts_module").submit {
|
Shell.cmd("add_hosts_module").submit {
|
||||||
AppContext.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT)
|
AppContext.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT)
|
@@ -73,6 +73,8 @@ class PolicyRvItem(
|
|||||||
viewModel.deletePressed(this)
|
viewModel.deletePressed(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun itemSameAs(other: PolicyRvItem) = item.uid == other.item.uid
|
override fun itemSameAs(other: PolicyRvItem) = packageName == other.packageName
|
||||||
|
|
||||||
|
override fun contentSameAs(other: PolicyRvItem) = item.policy == other.item.policy
|
||||||
|
|
||||||
}
|
}
|
@@ -9,6 +9,7 @@ import com.topjohnwu.magisk.databinding.FragmentSuperuserMd2Binding
|
|||||||
import rikka.recyclerview.addEdgeSpacing
|
import rikka.recyclerview.addEdgeSpacing
|
||||||
import rikka.recyclerview.addItemSpacing
|
import rikka.recyclerview.addItemSpacing
|
||||||
import rikka.recyclerview.fixEdgeEffect
|
import rikka.recyclerview.fixEdgeEffect
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class SuperuserFragment : BaseFragment<FragmentSuperuserMd2Binding>() {
|
class SuperuserFragment : BaseFragment<FragmentSuperuserMd2Binding>() {
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ class SuperuserFragment : BaseFragment<FragmentSuperuserMd2Binding>() {
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
activity?.title = resources.getString(R.string.superuser)
|
activity?.title = resources.getString(CoreR.string.superuser)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
@@ -8,24 +8,28 @@ import androidx.databinding.Bindable
|
|||||||
import androidx.databinding.ObservableArrayList
|
import androidx.databinding.ObservableArrayList
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
||||||
|
import com.topjohnwu.magisk.core.AppContext
|
||||||
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao
|
import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao
|
||||||
import com.topjohnwu.magisk.core.di.AppContext
|
|
||||||
import com.topjohnwu.magisk.core.ktx.getLabel
|
import com.topjohnwu.magisk.core.ktx.getLabel
|
||||||
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
||||||
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
import com.topjohnwu.magisk.databinding.MergeObservableList
|
||||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
import com.topjohnwu.magisk.databinding.RvItem
|
||||||
import com.topjohnwu.magisk.databinding.*
|
import com.topjohnwu.magisk.databinding.bindExtra
|
||||||
|
import com.topjohnwu.magisk.databinding.diffList
|
||||||
|
import com.topjohnwu.magisk.databinding.set
|
||||||
import com.topjohnwu.magisk.dialog.SuperuserRevokeDialog
|
import com.topjohnwu.magisk.dialog.SuperuserRevokeDialog
|
||||||
import com.topjohnwu.magisk.events.BiometricEvent
|
import com.topjohnwu.magisk.events.AuthEvent
|
||||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||||
import com.topjohnwu.magisk.utils.asText
|
import com.topjohnwu.magisk.utils.asText
|
||||||
import com.topjohnwu.magisk.view.TextItem
|
import com.topjohnwu.magisk.view.TextItem
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
class SuperuserViewModel(
|
class SuperuserViewModel(
|
||||||
private val db: PolicyDao
|
private val db: PolicyDao
|
||||||
@@ -88,7 +92,7 @@ class SuperuserViewModel(
|
|||||||
policies.addAll(map)
|
policies.addAll(map)
|
||||||
}
|
}
|
||||||
policies.sortWith(compareBy(
|
policies.sortWith(compareBy(
|
||||||
{ it.appName.lowercase(currentLocale) },
|
{ it.appName.lowercase(Locale.ROOT) },
|
||||||
{ it.packageName }
|
{ it.packageName }
|
||||||
))
|
))
|
||||||
itemsPolicies.update(policies)
|
itemsPolicies.update(policies)
|
||||||
@@ -106,17 +110,15 @@ class SuperuserViewModel(
|
|||||||
fun updateState() = viewModelScope.launch {
|
fun updateState() = viewModelScope.launch {
|
||||||
db.delete(item.item.uid)
|
db.delete(item.item.uid)
|
||||||
val list = ArrayList(itemsPolicies)
|
val list = ArrayList(itemsPolicies)
|
||||||
list.removeAll { it.itemSameAs(item) }
|
list.removeAll { it.item.uid == item.item.uid }
|
||||||
itemsPolicies.update(list)
|
itemsPolicies.update(list)
|
||||||
if (list.isEmpty() && itemsHelpers.isEmpty()) {
|
if (list.isEmpty() && itemsHelpers.isEmpty()) {
|
||||||
itemsHelpers.add(itemNoData)
|
itemsHelpers.add(itemNoData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BiometricHelper.isEnabled) {
|
if (Config.suAuth) {
|
||||||
BiometricEvent {
|
AuthEvent { updateState() }.publish()
|
||||||
onSuccess { updateState() }
|
|
||||||
}.publish()
|
|
||||||
} else {
|
} else {
|
||||||
SuperuserRevokeDialog(item.title) { updateState() }.show()
|
SuperuserRevokeDialog(item.title) { updateState() }.show()
|
||||||
}
|
}
|
||||||
@@ -155,24 +157,21 @@ class SuperuserViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun togglePolicy(item: PolicyRvItem, enable: Boolean) {
|
fun togglePolicy(item: PolicyRvItem, enable: Boolean) {
|
||||||
|
val items = itemsPolicies.filter { it.item.uid == item.item.uid }
|
||||||
fun updateState() {
|
fun updateState() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val res = if (enable) R.string.su_snack_grant else R.string.su_snack_deny
|
val res = if (enable) R.string.su_snack_grant else R.string.su_snack_deny
|
||||||
item.item.policy = if (enable) SuPolicy.ALLOW else SuPolicy.DENY
|
item.item.policy = if (enable) SuPolicy.ALLOW else SuPolicy.DENY
|
||||||
db.update(item.item)
|
db.update(item.item)
|
||||||
itemsPolicies.forEach {
|
items.forEach {
|
||||||
if (it.item.uid == item.item.uid) {
|
it.notifyPropertyChanged(BR.enabled)
|
||||||
it.notifyPropertyChanged(BR.enabled)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SnackbarEvent(res.asText(item.appName)).publish()
|
SnackbarEvent(res.asText(item.appName)).publish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BiometricHelper.isEnabled) {
|
if (Config.suAuth) {
|
||||||
BiometricEvent {
|
AuthEvent { updateState() }.publish()
|
||||||
onSuccess { updateState() }
|
|
||||||
}.publish()
|
|
||||||
} else {
|
} else {
|
||||||
updateState()
|
updateState()
|
||||||
}
|
}
|
@@ -11,6 +11,7 @@ import androidx.lifecycle.lifecycleScope
|
|||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.arch.UIActivity
|
import com.topjohnwu.magisk.arch.UIActivity
|
||||||
import com.topjohnwu.magisk.arch.viewModel
|
import com.topjohnwu.magisk.arch.viewModel
|
||||||
|
import com.topjohnwu.magisk.core.base.UntrackedActivity
|
||||||
import com.topjohnwu.magisk.core.su.SuCallbackHandler
|
import com.topjohnwu.magisk.core.su.SuCallbackHandler
|
||||||
import com.topjohnwu.magisk.core.su.SuCallbackHandler.REQUEST
|
import com.topjohnwu.magisk.core.su.SuCallbackHandler.REQUEST
|
||||||
import com.topjohnwu.magisk.databinding.ActivityRequestBinding
|
import com.topjohnwu.magisk.databinding.ActivityRequestBinding
|
||||||
@@ -19,7 +20,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
open class SuRequestActivity : UIActivity<ActivityRequestBinding>() {
|
open class SuRequestActivity : UIActivity<ActivityRequestBinding>(), UntrackedActivity {
|
||||||
|
|
||||||
override val layoutRes: Int = R.layout.activity_request
|
override val layoutRes: Int = R.layout.activity_request
|
||||||
override val viewModel: SuRequestViewModel by viewModel()
|
override val viewModel: SuRequestViewModel by viewModel()
|
@@ -17,22 +17,22 @@ import android.widget.Toast
|
|||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||||
|
import com.topjohnwu.magisk.core.AppContext
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
|
import com.topjohnwu.magisk.core.R
|
||||||
import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao
|
import com.topjohnwu.magisk.core.data.magiskdb.PolicyDao
|
||||||
import com.topjohnwu.magisk.core.di.AppContext
|
|
||||||
import com.topjohnwu.magisk.core.ktx.getLabel
|
import com.topjohnwu.magisk.core.ktx.getLabel
|
||||||
import com.topjohnwu.magisk.core.ktx.toast
|
import com.topjohnwu.magisk.core.ktx.toast
|
||||||
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.ALLOW
|
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.ALLOW
|
||||||
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.DENY
|
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.DENY
|
||||||
import com.topjohnwu.magisk.core.su.SuRequestHandler
|
import com.topjohnwu.magisk.core.su.SuRequestHandler
|
||||||
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
|
||||||
import com.topjohnwu.magisk.databinding.set
|
import com.topjohnwu.magisk.databinding.set
|
||||||
import com.topjohnwu.magisk.events.BiometricEvent
|
import com.topjohnwu.magisk.events.AuthEvent
|
||||||
import com.topjohnwu.magisk.events.DieEvent
|
import com.topjohnwu.magisk.events.DieEvent
|
||||||
import com.topjohnwu.magisk.events.ShowUIEvent
|
import com.topjohnwu.magisk.events.ShowUIEvent
|
||||||
import com.topjohnwu.magisk.utils.TextHolder
|
import com.topjohnwu.magisk.utils.TextHolder
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.concurrent.TimeUnit.SECONDS
|
import java.util.concurrent.TimeUnit.SECONDS
|
||||||
|
|
||||||
@@ -70,17 +70,14 @@ class SuRequestViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val handler = SuRequestHandler(AppContext.packageManager, policyDB)
|
private val handler = SuRequestHandler(AppContext.packageManager, policyDB)
|
||||||
private lateinit var timer: CountDownTimer
|
private val millis = SECONDS.toMillis(Config.suDefaultTimeout.toLong())
|
||||||
|
private var timer = SuTimer(millis, 1000)
|
||||||
private var initialized = false
|
private var initialized = false
|
||||||
|
|
||||||
fun grantPressed() {
|
fun grantPressed() {
|
||||||
cancelTimer()
|
cancelTimer()
|
||||||
if (BiometricHelper.isEnabled) {
|
if (Config.suAuth) {
|
||||||
BiometricEvent {
|
AuthEvent { respond(ALLOW) }.publish()
|
||||||
onSuccess {
|
|
||||||
respond(ALLOW)
|
|
||||||
}
|
|
||||||
}.publish()
|
|
||||||
} else {
|
} else {
|
||||||
respond(ALLOW)
|
respond(ALLOW)
|
||||||
}
|
}
|
||||||
@@ -96,7 +93,7 @@ class SuRequestViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun handleRequest(intent: Intent) {
|
fun handleRequest(intent: Intent) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.Default) {
|
||||||
if (handler.start(intent))
|
if (handler.start(intent))
|
||||||
showDialog()
|
showDialog()
|
||||||
else
|
else
|
||||||
@@ -125,8 +122,7 @@ class SuRequestViewModel(
|
|||||||
selectedItemPosition = timeoutPrefs.getInt(packageName, 0)
|
selectedItemPosition = timeoutPrefs.getInt(packageName, 0)
|
||||||
|
|
||||||
// Set timer
|
// Set timer
|
||||||
val millis = SECONDS.toMillis(Config.suDefaultTimeout.toLong())
|
timer.start()
|
||||||
timer = SuTimer(millis, 1000).apply { start() }
|
|
||||||
|
|
||||||
// Actually show the UI
|
// Actually show the UI
|
||||||
ShowUIEvent(if (Config.suTapjack) EmptyAccessibilityDelegate else null).publish()
|
ShowUIEvent(if (Config.suTapjack) EmptyAccessibilityDelegate else null).publish()
|
@@ -12,6 +12,7 @@ import com.topjohnwu.magisk.arch.BaseFragment
|
|||||||
import com.topjohnwu.magisk.arch.viewModel
|
import com.topjohnwu.magisk.arch.viewModel
|
||||||
import com.topjohnwu.magisk.databinding.FragmentThemeMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentThemeMd2Binding
|
||||||
import com.topjohnwu.magisk.databinding.ItemThemeBindingImpl
|
import com.topjohnwu.magisk.databinding.ItemThemeBindingImpl
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
class ThemeFragment : BaseFragment<FragmentThemeMd2Binding>() {
|
class ThemeFragment : BaseFragment<FragmentThemeMd2Binding>() {
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ class ThemeFragment : BaseFragment<FragmentThemeMd2Binding>() {
|
|||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
|
|
||||||
activity?.title = getString(R.string.section_theme)
|
activity?.title = getString(CoreR.string.section_theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -14,7 +14,7 @@ import androidx.interpolator.view.animation.FastOutSlowInInterpolator
|
|||||||
import com.google.android.material.circularreveal.CircularRevealCompat
|
import com.google.android.material.circularreveal.CircularRevealCompat
|
||||||
import com.google.android.material.circularreveal.CircularRevealWidget
|
import com.google.android.material.circularreveal.CircularRevealWidget
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
import com.topjohnwu.magisk.core.utils.LocaleSetting
|
||||||
import kotlin.math.hypot
|
import kotlin.math.hypot
|
||||||
|
|
||||||
object MotionRevealHelper {
|
object MotionRevealHelper {
|
||||||
@@ -63,7 +63,9 @@ object MotionRevealHelper {
|
|||||||
it.interpolator = FastOutSlowInInterpolator()
|
it.interpolator = FastOutSlowInInterpolator()
|
||||||
it.addListener(onStart = { show() }, onEnd = { if (revealInfo.radius != 0f) hide() })
|
it.addListener(onStart = { show() }, onEnd = { if (revealInfo.radius != 0f) hide() })
|
||||||
|
|
||||||
val rtlMod = if (currentLocale.layoutDirection == View.LAYOUT_DIRECTION_RTL) 1f else -1f
|
val rtlMod =
|
||||||
|
if (LocaleSetting.instance.currentLocale.layoutDirection == View.LAYOUT_DIRECTION_RTL)
|
||||||
|
1f else -1f
|
||||||
val maxX = revealInfo.centerX - marginEnd - measuredWidth / 2f
|
val maxX = revealInfo.centerX - marginEnd - measuredWidth / 2f
|
||||||
val targetX = if (revealInfo.radius == 0f) 0f else maxX * rtlMod
|
val targetX = if (revealInfo.radius == 0f) 0f else maxX * rtlMod
|
||||||
val moveX = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, targetX)
|
val moveX = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, targetX)
|
@@ -21,7 +21,7 @@ import com.google.android.material.color.MaterialColors
|
|||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
import com.topjohnwu.magisk.arch.UIActivity
|
||||||
import com.topjohnwu.magisk.databinding.DialogMagiskBaseBinding
|
import com.topjohnwu.magisk.databinding.DialogMagiskBaseBinding
|
||||||
import com.topjohnwu.magisk.databinding.DiffItem
|
import com.topjohnwu.magisk.databinding.DiffItem
|
||||||
import com.topjohnwu.magisk.databinding.ItemWrapper
|
import com.topjohnwu.magisk.databinding.ItemWrapper
|
||||||
@@ -42,7 +42,7 @@ class MagiskDialog(
|
|||||||
DialogMagiskBaseBinding.inflate(LayoutInflater.from(context))
|
DialogMagiskBaseBinding.inflate(LayoutInflater.from(context))
|
||||||
private val data = Data()
|
private val data = Data()
|
||||||
|
|
||||||
val activity: BaseActivity get() = ownerActivity as BaseActivity
|
val activity: UIActivity<*> get() = ownerActivity as UIActivity<*>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
binding.setVariable(BR.data, data)
|
binding.setVariable(BR.data, data)
|
@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.view
|
|||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.databinding.DiffItem
|
import com.topjohnwu.magisk.databinding.DiffItem
|
||||||
import com.topjohnwu.magisk.databinding.RvItem
|
import com.topjohnwu.magisk.databinding.RvItem
|
||||||
|
import com.topjohnwu.magisk.core.R as CoreR
|
||||||
|
|
||||||
sealed class TappableHeadlineItem : RvItem(), DiffItem<TappableHeadlineItem> {
|
sealed class TappableHeadlineItem : RvItem(), DiffItem<TappableHeadlineItem> {
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ sealed class TappableHeadlineItem : RvItem(), DiffItem<TappableHeadlineItem> {
|
|||||||
// --- objects
|
// --- objects
|
||||||
|
|
||||||
object ThemeMode : TappableHeadlineItem() {
|
object ThemeMode : TappableHeadlineItem() {
|
||||||
override val title = R.string.settings_dark_mode_title
|
override val title = CoreR.string.settings_dark_mode_title
|
||||||
override val icon = R.drawable.ic_day_night
|
override val icon = R.drawable.ic_day_night
|
||||||
}
|
}
|
||||||
|
|
@@ -18,7 +18,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="300"
|
android:duration="300"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 20 8 L 20 8 L 17.19 8 C 16.74 7.22 16.12 6.55 15.37 6.04 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.49 5 12 5 C 11.51 5 11.04 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6.04 C 7.88 6.55 7.26 7.22 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.04 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.04 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 7.85 19.79 9.78 21 12 21 C 14.22 21 16.15 19.79 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.96 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.96 10.33 17.91 10 L 20 10 L 20 8 M 14 16 C 14 15.43 14 14.859 14 14.289 L 14 14 C 13.869 14 13.739 14 13.608 14 C 12.405 14 11.203 14 10 14 C 10 14.509 10 15.017 10 15.526 C 10 15.684 10 15.842 10 16 L 10.33 16 C 10.392 16 10.454 16 10.515 16 C 11.677 16 12.838 16 14 16 C 14 16 14 16 14 16 M 14 10 L 14 12 L 14 12 L 10 12 L 10 10 L 14 10 M 12 15 L 12 15 L 12 15 L 12 15 L 12 15 L 12 15"
|
android:valueFrom="M 20 8 L 20 8 L 17.19 8 C 16.74 7.22 16.12 6.55 15.37 6.04 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.49 5 12 5 C 11.51 5 11.04 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6.04 C 7.88 6.55 7.26 7.22 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.04 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.04 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 7.85 19.79 9.78 21 12 21 C 14.22 21 16.15 19.79 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.96 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.96 10.33 17.91 10 L 20 10 L 20 8 M 14 16 C 14 15.43 14 14.859 14 14.289 L 14 14 C 13.869 14 13.739 14 13.608 14 C 12.405 14 11.203 14 10 14 C 10 14.509 10 15.017 10 15.526 C 10 15.684 10 15.842 10 16 L 10.33 16 C 10.392 16 10.454 16 10.515 16 C 11.677 16 12.838 16 14 16 C 14 16 14 16 14 16 M 14 10 L 14 12 L 14 12 L 10 12 L 10 10 L 14 10 M 12 15 L 12 15 L 12 15 L 12 15 L 12 15 L 12 15"
|
||||||
android:valueTo="M 20 8 L 18.595 8 L 17.19 8 C 16.74 7.2 16.12 6.5 15.37 6 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.5 5 12 5 C 11.5 5 11.05 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6 C 7.87 6.5 7.26 7.21 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.03 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.03 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 8.47 20.87 12.14 21.84 15 20.18 C 15.91 19.66 16.67 18.9 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.97 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.97 10.33 17.91 10 L 20 10 L 20 8 M 14.828 17.828 C 15.578 17.079 16 16.06 16 15 L 16 11 C 16 9.94 15.578 8.921 14.828 8.172 C 14.079 7.422 13.06 7 12 7 C 10.94 7 9.921 7.422 9.172 8.172 C 8.422 8.921 8 9.94 8 11 L 8 15 C 8 16.06 8.422 17.079 9.172 17.828 C 9.921 18.578 10.94 19 12 19 C 13.06 19 14.079 18.578 14.828 17.828 M 14 10 L 14 11 L 14 12 L 10 12 L 10 10 L 14 10 M 10 14 L 14 14 L 14 16 L 10 16 L 10 14 L 10 14"
|
android:valueTo="M 20 8 L 18.595 8 L 17.19 8 C 16.74 7.2 16.12 6.5 15.37 6 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.5 5 12 5 C 11.5 5 11.05 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6 C 7.87 6.5 7.26 7.21 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.03 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.03 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 8.47 20.87 12.14 21.84 15 20.18 C 15.91 19.66 16.67 18.9 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.97 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.97 10.33 17.91 10 L 20 10 L 20 8 M 14.828 17.828 C 15.578 17.079 16 16.06 16 15 L 16 11 C 16 9.94 15.578 8.921 14.828 8.172 C 14.079 7.422 13.06 7 12 7 C 10.94 7 9.921 7.422 9.172 8.172 C 8.422 8.921 8 9.94 8 11 L 8 15 C 8 16.06 8.422 17.079 9.172 17.828 C 9.921 18.578 10.94 19 12 19 C 13.06 19 14.079 18.578 14.828 17.828 M 14 10 L 14 11 L 14 12 L 10 12 L 10 10 L 14 10 M 10 14 L 14 14 L 14 16 L 10 16 L 10 14 L 10 14"
|
@@ -18,7 +18,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="300"
|
android:duration="300"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 20 8 L 18.595 8 L 17.19 8 C 16.74 7.2 16.12 6.5 15.37 6 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.5 5 12 5 C 11.5 5 11.05 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6 C 7.87 6.5 7.26 7.21 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.03 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.03 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 8.47 20.87 12.14 21.84 15 20.18 C 15.91 19.66 16.67 18.9 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.97 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.97 10.33 17.91 10 L 20 10 L 20 8 M 14.828 17.828 C 15.578 17.079 16 16.06 16 15 L 16 11 C 16 9.94 15.578 8.921 14.828 8.172 C 14.079 7.422 13.06 7 12 7 C 10.94 7 9.921 7.422 9.172 8.172 C 8.422 8.921 8 9.94 8 11 L 8 15 C 8 16.06 8.422 17.079 9.172 17.828 C 9.921 18.578 10.94 19 12 19 C 13.06 19 14.079 18.578 14.828 17.828 M 14 10 L 14 11 L 14 12 L 10 12 L 10 10 L 14 10 M 10 14 L 14 14 L 14 16 L 10 16 L 10 14 L 10 14"
|
android:valueFrom="M 20 8 L 18.595 8 L 17.19 8 C 16.74 7.2 16.12 6.5 15.37 6 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.5 5 12 5 C 11.5 5 11.05 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6 C 7.87 6.5 7.26 7.21 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.03 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.03 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 8.47 20.87 12.14 21.84 15 20.18 C 15.91 19.66 16.67 18.9 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.97 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.97 10.33 17.91 10 L 20 10 L 20 8 M 14.828 17.828 C 15.578 17.079 16 16.06 16 15 L 16 11 C 16 9.94 15.578 8.921 14.828 8.172 C 14.079 7.422 13.06 7 12 7 C 10.94 7 9.921 7.422 9.172 8.172 C 8.422 8.921 8 9.94 8 11 L 8 15 C 8 16.06 8.422 17.079 9.172 17.828 C 9.921 18.578 10.94 19 12 19 C 13.06 19 14.079 18.578 14.828 17.828 M 14 10 L 14 11 L 14 12 L 10 12 L 10 10 L 14 10 M 10 14 L 14 14 L 14 16 L 10 16 L 10 14 L 10 14"
|
||||||
android:valueTo="M 20 8 L 20 8 L 17.19 8 C 16.74 7.22 16.12 6.55 15.37 6.04 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.49 5 12 5 C 11.51 5 11.04 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6.04 C 7.88 6.55 7.26 7.22 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.04 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.04 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 7.85 19.79 9.78 21 12 21 C 14.22 21 16.15 19.79 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.96 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.96 10.33 17.91 10 L 20 10 L 20 8 M 14 16 C 14 15.43 14 14.859 14 14.289 L 14 14 C 13.869 14 13.739 14 13.608 14 C 12.405 14 11.203 14 10 14 C 10 14.509 10 15.017 10 15.526 C 10 15.684 10 15.842 10 16 L 10.33 16 C 10.392 16 10.454 16 10.515 16 C 11.677 16 12.838 16 14 16 C 14 16 14 16 14 16 M 14 10 L 14 12 L 14 12 L 10 12 L 10 10 L 14 10 M 12 15 L 12 15 L 12 15 L 12 15 L 12 15 L 12 15"
|
android:valueTo="M 20 8 L 20 8 L 17.19 8 C 16.74 7.22 16.12 6.55 15.37 6.04 L 17 4.41 L 15.59 3 L 13.42 5.17 C 12.96 5.06 12.49 5 12 5 C 11.51 5 11.04 5.06 10.59 5.17 L 8.41 3 L 7 4.41 L 8.62 6.04 C 7.88 6.55 7.26 7.22 6.81 8 L 4 8 L 4 10 L 6.09 10 C 6.04 10.33 6 10.66 6 11 L 6 12 L 4 12 L 4 14 L 6 14 L 6 15 C 6 15.34 6.04 15.67 6.09 16 L 4 16 L 4 18 L 6.81 18 C 7.85 19.79 9.78 21 12 21 C 14.22 21 16.15 19.79 17.19 18 L 20 18 L 20 16 L 17.91 16 C 17.96 15.67 18 15.34 18 15 L 18 14 L 20 14 L 20 12 L 18 12 L 18 11 C 18 10.66 17.96 10.33 17.91 10 L 20 10 L 20 8 M 14 16 C 14 15.43 14 14.859 14 14.289 L 14 14 C 13.869 14 13.739 14 13.608 14 C 12.405 14 11.203 14 10 14 C 10 14.509 10 15.017 10 15.526 C 10 15.684 10 15.842 10 16 L 10.33 16 C 10.392 16 10.454 16 10.515 16 C 11.677 16 12.838 16 14 16 C 14 16 14 16 14 16 M 14 10 L 14 12 L 14 12 L 10 12 L 10 10 L 14 10 M 12 15 L 12 15 L 12 15 L 12 15 L 12 15 L 12 15"
|
@@ -17,7 +17,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="500"
|
android:duration="500"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 12 2 C 9.217 2 6.689 3.152 4.872 5.004 C 3.098 6.811 2 9.283 2 12 C 2 14.744 3.12 17.24 4.927 19.052 C 6.74 20.87 9.244 22 12 22 C 13.911 22 15.701 21.457 17.224 20.517 C 18.628 19.651 19.804 18.448 20.638 17.024 C 21.503 15.545 22 13.828 22 12 C 22 10.2 21.518 8.507 20.677 7.044 C 19.755 5.441 18.402 4.114 16.779 3.224 C 15.357 2.444 13.728 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 6 13 L 10 17 L 18 9 L 16.59 7.58 L 16.59 7.58 L 10 14.17 L 7.41 11.59 L 6 13"
|
android:valueFrom="M 12 2 C 9.217 2 6.689 3.152 4.872 5.004 C 3.098 6.811 2 9.283 2 12 C 2 14.744 3.12 17.24 4.927 19.052 C 6.74 20.87 9.244 22 12 22 C 13.911 22 15.701 21.457 17.224 20.517 C 18.628 19.651 19.804 18.448 20.638 17.024 C 21.503 15.545 22 13.828 22 12 C 22 10.2 21.518 8.507 20.677 7.044 C 19.755 5.441 18.402 4.114 16.779 3.224 C 15.357 2.444 13.728 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 6 13 L 10 17 L 18 9 L 16.59 7.58 L 16.59 7.58 L 10 14.17 L 7.41 11.59 L 6 13"
|
||||||
android:valueTo="M 12 2 C 9.349 2 6.804 3.054 4.929 4.929 C 3.054 6.804 2 9.349 2 12 C 2 14.651 3.054 17.196 4.929 19.071 C 6.804 20.946 9.349 22 12 22 C 13.755 22 15.48 21.538 17 20.66 C 18.52 19.783 19.783 18.52 20.66 17 C 21.538 15.48 22 13.755 22 12 C 22 10.245 21.538 8.52 20.66 7 C 19.783 5.48 18.52 4.217 17 3.34 C 15.48 2.462 13.755 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 7 13 L 7 13 L 17 13 L 17 11 L 17 11 L 7 11 L 7 11 L 7 11"
|
android:valueTo="M 12 2 C 9.349 2 6.804 3.054 4.929 4.929 C 3.054 6.804 2 9.349 2 12 C 2 14.651 3.054 17.196 4.929 19.071 C 6.804 20.946 9.349 22 12 22 C 13.755 22 15.48 21.538 17 20.66 C 18.52 19.783 19.783 18.52 20.66 17 C 21.538 15.48 22 13.755 22 12 C 22 10.245 21.538 8.52 20.66 7 C 19.783 5.48 18.52 4.217 17 3.34 C 15.48 2.462 13.755 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 7 13 L 7 13 L 17 13 L 17 11 L 17 11 L 7 11 L 7 11 L 7 11"
|
@@ -17,7 +17,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="500"
|
android:duration="500"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 12 2 C 9.349 2 6.804 3.054 4.929 4.929 C 3.054 6.804 2 9.349 2 12 C 2 14.651 3.054 17.196 4.929 19.071 C 6.804 20.946 9.349 22 12 22 C 13.755 22 15.48 21.538 17 20.66 C 18.52 19.783 19.783 18.52 20.66 17 C 21.538 15.48 22 13.755 22 12 C 22 10.245 21.538 8.52 20.66 7 C 19.783 5.48 18.52 4.217 17 3.34 C 15.48 2.462 13.755 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 7 13 L 7 13 L 17 13 L 17 11 L 17 11 L 7 11 L 7 11 L 7 11"
|
android:valueFrom="M 12 2 C 9.349 2 6.804 3.054 4.929 4.929 C 3.054 6.804 2 9.349 2 12 C 2 14.651 3.054 17.196 4.929 19.071 C 6.804 20.946 9.349 22 12 22 C 13.755 22 15.48 21.538 17 20.66 C 18.52 19.783 19.783 18.52 20.66 17 C 21.538 15.48 22 13.755 22 12 C 22 10.245 21.538 8.52 20.66 7 C 19.783 5.48 18.52 4.217 17 3.34 C 15.48 2.462 13.755 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 7 13 L 7 13 L 17 13 L 17 11 L 17 11 L 7 11 L 7 11 L 7 11"
|
||||||
android:valueTo="M 12 2 C 9.217 2 6.689 3.152 4.872 5.004 C 3.098 6.811 2 9.283 2 12 C 2 14.856 3.213 17.442 5.149 19.268 C 6.942 20.96 9.356 22 12 22 C 14.061 22 15.982 21.368 17.578 20.288 C 19.114 19.249 20.349 17.796 21.119 16.092 C 21.685 14.841 22 13.456 22 12 C 22 10.122 21.475 8.361 20.566 6.856 C 19.691 5.408 18.46 4.197 16.997 3.347 C 15.524 2.491 13.817 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 6 13 L 10 17 L 18 9 L 16.59 7.58 L 16.59 7.58 L 10 14.17 L 7.41 11.59 L 6 13"
|
android:valueTo="M 12 2 C 9.217 2 6.689 3.152 4.872 5.004 C 3.098 6.811 2 9.283 2 12 C 2 14.856 3.213 17.442 5.149 19.268 C 6.942 20.96 9.356 22 12 22 C 14.061 22 15.982 21.368 17.578 20.288 C 19.114 19.249 20.349 17.796 21.119 16.092 C 21.685 14.841 22 13.456 22 12 C 22 10.122 21.475 8.361 20.566 6.856 C 19.691 5.408 18.46 4.197 16.997 3.347 C 15.524 2.491 13.817 2 12 2 M 12 20 C 7.59 20 4 16.41 4 12 C 4 7.59 7.59 4 12 4 C 16.41 4 20 7.59 20 12 C 20 16.41 16.41 20 12 20 M 6 13 L 10 17 L 18 9 L 16.59 7.58 L 16.59 7.58 L 10 14.17 L 7.41 11.59 L 6 13"
|
@@ -19,7 +19,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="300"
|
android:duration="300"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 9 14 L 9 21 L 4 21 L 4 9 L 12 3 L 12 3 L 20 9 L 20 21 L 15 21 L 15 14 L 9 14 M 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4"
|
android:valueFrom="M 9 14 L 9 21 L 4 21 L 4 9 L 12 3 L 12 3 L 20 9 L 20 21 L 15 21 L 15 14 L 9 14 M 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4"
|
||||||
android:valueTo="M 9 13 L 9 19 L 6 19 L 6 10 L 12 5.5 L 15 7.75 L 18 10 L 18 19 L 15 19 L 15 13 L 9 13 M 4 21 L 4 9 L 12 3 L 20 9 L 20 21 L 4 21 L 4 21"
|
android:valueTo="M 9 13 L 9 19 L 6 19 L 6 10 L 12 5.5 L 15 7.75 L 18 10 L 18 19 L 15 19 L 15 13 L 9 13 M 4 21 L 4 9 L 12 3 L 20 9 L 20 21 L 4 21 L 4 21"
|
@@ -19,7 +19,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="300"
|
android:duration="300"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 9 13 L 9 19 L 6 19 L 6 10 L 12 5.5 L 15 7.75 L 18 10 L 18 19 L 15 19 L 15 13 L 9 13 M 4 21 L 4 9 L 12 3 L 20 9 L 20 21 L 4 21 L 4 21"
|
android:valueFrom="M 9 13 L 9 19 L 6 19 L 6 10 L 12 5.5 L 15 7.75 L 18 10 L 18 19 L 15 19 L 15 13 L 9 13 M 4 21 L 4 9 L 12 3 L 20 9 L 20 21 L 4 21 L 4 21"
|
||||||
android:valueTo="M 9 14 L 9 21 L 4 21 L 4 9 L 12 3 L 12 3 L 20 9 L 20 21 L 15 21 L 15 14 L 9 14 M 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4"
|
android:valueTo="M 9 14 L 9 21 L 4 21 L 4 9 L 12 3 L 12 3 L 20 9 L 20 21 L 15 21 L 15 14 L 9 14 M 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4 L 12 13.4"
|
@@ -18,7 +18,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="300"
|
android:duration="300"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 23 13.5 C 23 14.163 22.736 14.799 22.268 15.268 C 21.799 15.736 21.163 16 20.5 16 C 20 16 19.5 16 19 16 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 15.1 22 L 13.2 22 C 13.2 21.5 13.2 21 13.2 20.5 C 13.2 19 12 17.8 10.5 17.8 C 9 17.8 7.8 19 7.8 20.5 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 3.5 16.2 C 5 16.2 6.2 15 6.2 13.5 C 6.2 12 5 10.8 3.5 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 8 5 C 8 4.5 8 4 8 3.5 C 8 2.837 8.264 2.201 8.732 1.732 C 9.201 1.264 9.837 1 10.5 1 C 11.163 1 11.799 1.264 12.268 1.732 C 12.736 2.201 13 2.837 13 3.5 C 13 4 13 4.5 13 5 L 17 5 C 17.55 5 18.05 5.223 18.413 5.584 C 18.775 5.945 19 6.445 19 7 L 19 11 C 19.5 11 20 11 20.5 11 C 20.5 11 20.5 11 20.5 11 C 21.163 11 21.799 11.264 22.268 11.732 C 22.736 12.201 23 12.837 23 13.5 M 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12"
|
android:valueFrom="M 23 13.5 C 23 14.163 22.736 14.799 22.268 15.268 C 21.799 15.736 21.163 16 20.5 16 C 20 16 19.5 16 19 16 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 15.1 22 L 13.2 22 C 13.2 21.5 13.2 21 13.2 20.5 C 13.2 19 12 17.8 10.5 17.8 C 9 17.8 7.8 19 7.8 20.5 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 3.5 16.2 C 5 16.2 6.2 15 6.2 13.5 C 6.2 12 5 10.8 3.5 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 8 5 C 8 4.5 8 4 8 3.5 C 8 2.837 8.264 2.201 8.732 1.732 C 9.201 1.264 9.837 1 10.5 1 C 11.163 1 11.799 1.264 12.268 1.732 C 12.736 2.201 13 2.837 13 3.5 C 13 4 13 4.5 13 5 L 17 5 C 17.55 5 18.05 5.223 18.413 5.584 C 18.775 5.945 19 6.445 19 7 L 19 11 C 19.5 11 20 11 20.5 11 C 20.5 11 20.5 11 20.5 11 C 21.163 11 21.799 11.264 22.268 11.732 C 22.736 12.201 23 12.837 23 13.5 M 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12"
|
||||||
android:valueTo="M 22 13.5 C 22 14.087 21.856 14.64 21.6 15.126 C 21.344 15.612 20.978 16.03 20.533 16.347 C 20.089 16.664 19.567 16.88 19 16.96 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 13.2 22 L 13.2 21.7 C 13.2 20.984 12.915 20.297 12.409 19.791 C 11.903 19.285 11.216 19 10.5 19 C 9 19 7.8 20.21 7.8 21.7 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 2.3 16.2 C 3.79 16.2 5 15 5 13.5 C 5 12 3.79 10.8 2.3 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 7.04 5 C 7.12 4.433 7.336 3.911 7.653 3.467 C 7.97 3.022 8.388 2.656 8.874 2.4 C 9.36 2.144 9.913 2 10.5 2 C 11.087 2 11.64 2.144 12.126 2.4 C 12.612 2.656 13.03 3.022 13.347 3.467 C 13.664 3.911 13.88 4.433 13.96 5 L 17 5 C 17.53 5 18.039 5.211 18.414 5.586 C 18.789 5.961 19 6.47 19 7 L 19 10.04 C 19.425 10.1 19.825 10.236 20.186 10.434 C 20.547 10.633 20.869 10.893 21.137 11.2 C 21.406 11.508 21.622 11.863 21.77 12.251 C 21.919 12.639 22 13.06 22 13.5 M 17 12 L 18.5 12 C 18.898 12 19.279 12.158 19.561 12.439 C 19.842 12.721 20 13.102 20 13.5 C 20 13.898 19.842 14.279 19.561 14.561 C 19.279 14.842 18.898 15 18.5 15 L 17 15 L 17 15 L 17 20 L 14.88 20 C 14.2 18.25 12.5 17 10.5 17 C 8.5 17 6.8 18.25 6.12 20 L 4 20 L 4 17.88 C 5.75 17.2 7 15.5 7 13.5 C 7 11.5 5.76 9.8 4 9.12 L 4 7 L 9 7 L 9 5.5 C 9 5.102 9.158 4.721 9.439 4.439 C 9.721 4.158 10.102 4 10.5 4 C 10.898 4 11.279 4.158 11.561 4.439 C 11.842 4.721 12 5.102 12 5.5 L 12 7 L 17 7 L 17 12"
|
android:valueTo="M 22 13.5 C 22 14.087 21.856 14.64 21.6 15.126 C 21.344 15.612 20.978 16.03 20.533 16.347 C 20.089 16.664 19.567 16.88 19 16.96 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 13.2 22 L 13.2 21.7 C 13.2 20.984 12.915 20.297 12.409 19.791 C 11.903 19.285 11.216 19 10.5 19 C 9 19 7.8 20.21 7.8 21.7 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 2.3 16.2 C 3.79 16.2 5 15 5 13.5 C 5 12 3.79 10.8 2.3 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 7.04 5 C 7.12 4.433 7.336 3.911 7.653 3.467 C 7.97 3.022 8.388 2.656 8.874 2.4 C 9.36 2.144 9.913 2 10.5 2 C 11.087 2 11.64 2.144 12.126 2.4 C 12.612 2.656 13.03 3.022 13.347 3.467 C 13.664 3.911 13.88 4.433 13.96 5 L 17 5 C 17.53 5 18.039 5.211 18.414 5.586 C 18.789 5.961 19 6.47 19 7 L 19 10.04 C 19.425 10.1 19.825 10.236 20.186 10.434 C 20.547 10.633 20.869 10.893 21.137 11.2 C 21.406 11.508 21.622 11.863 21.77 12.251 C 21.919 12.639 22 13.06 22 13.5 M 17 12 L 18.5 12 C 18.898 12 19.279 12.158 19.561 12.439 C 19.842 12.721 20 13.102 20 13.5 C 20 13.898 19.842 14.279 19.561 14.561 C 19.279 14.842 18.898 15 18.5 15 L 17 15 L 17 15 L 17 20 L 14.88 20 C 14.2 18.25 12.5 17 10.5 17 C 8.5 17 6.8 18.25 6.12 20 L 4 20 L 4 17.88 C 5.75 17.2 7 15.5 7 13.5 C 7 11.5 5.76 9.8 4 9.12 L 4 7 L 9 7 L 9 5.5 C 9 5.102 9.158 4.721 9.439 4.439 C 9.721 4.158 10.102 4 10.5 4 C 10.898 4 11.279 4.158 11.561 4.439 C 11.842 4.721 12 5.102 12 5.5 L 12 7 L 17 7 L 17 12"
|
@@ -18,7 +18,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="300"
|
android:duration="300"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 22 13.5 C 22 14.087 21.856 14.64 21.6 15.126 C 21.344 15.612 20.978 16.03 20.533 16.347 C 20.089 16.664 19.567 16.88 19 16.96 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 13.2 22 L 13.2 21.7 C 13.2 20.984 12.915 20.297 12.409 19.791 C 11.903 19.285 11.216 19 10.5 19 C 9 19 7.8 20.21 7.8 21.7 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 2.3 16.2 C 3.79 16.2 5 15 5 13.5 C 5 12 3.79 10.8 2.3 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 7.04 5 C 7.12 4.433 7.336 3.911 7.653 3.467 C 7.97 3.022 8.388 2.656 8.874 2.4 C 9.36 2.144 9.913 2 10.5 2 C 11.087 2 11.64 2.144 12.126 2.4 C 12.612 2.656 13.03 3.022 13.347 3.467 C 13.664 3.911 13.88 4.433 13.96 5 L 17 5 C 17.53 5 18.039 5.211 18.414 5.586 C 18.789 5.961 19 6.47 19 7 L 19 10.04 C 19.425 10.1 19.825 10.236 20.186 10.434 C 20.547 10.633 20.869 10.893 21.137 11.2 C 21.406 11.508 21.622 11.863 21.77 12.251 C 21.919 12.639 22 13.06 22 13.5 M 17 12 L 18.5 12 C 18.898 12 19.279 12.158 19.561 12.439 C 19.842 12.721 20 13.102 20 13.5 C 20 13.898 19.842 14.279 19.561 14.561 C 19.279 14.842 18.898 15 18.5 15 L 17 15 L 17 15 L 17 20 L 14.88 20 C 14.2 18.25 12.5 17 10.5 17 C 8.5 17 6.8 18.25 6.12 20 L 4 20 L 4 17.88 C 5.75 17.2 7 15.5 7 13.5 C 7 11.5 5.76 9.8 4 9.12 L 4 7 L 9 7 L 9 5.5 C 9 5.102 9.158 4.721 9.439 4.439 C 9.721 4.158 10.102 4 10.5 4 C 10.898 4 11.279 4.158 11.561 4.439 C 11.842 4.721 12 5.102 12 5.5 L 12 7 L 17 7 L 17 12"
|
android:valueFrom="M 22 13.5 C 22 14.087 21.856 14.64 21.6 15.126 C 21.344 15.612 20.978 16.03 20.533 16.347 C 20.089 16.664 19.567 16.88 19 16.96 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 13.2 22 L 13.2 21.7 C 13.2 20.984 12.915 20.297 12.409 19.791 C 11.903 19.285 11.216 19 10.5 19 C 9 19 7.8 20.21 7.8 21.7 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 2.3 16.2 C 3.79 16.2 5 15 5 13.5 C 5 12 3.79 10.8 2.3 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 7.04 5 C 7.12 4.433 7.336 3.911 7.653 3.467 C 7.97 3.022 8.388 2.656 8.874 2.4 C 9.36 2.144 9.913 2 10.5 2 C 11.087 2 11.64 2.144 12.126 2.4 C 12.612 2.656 13.03 3.022 13.347 3.467 C 13.664 3.911 13.88 4.433 13.96 5 L 17 5 C 17.53 5 18.039 5.211 18.414 5.586 C 18.789 5.961 19 6.47 19 7 L 19 10.04 C 19.425 10.1 19.825 10.236 20.186 10.434 C 20.547 10.633 20.869 10.893 21.137 11.2 C 21.406 11.508 21.622 11.863 21.77 12.251 C 21.919 12.639 22 13.06 22 13.5 M 17 12 L 18.5 12 C 18.898 12 19.279 12.158 19.561 12.439 C 19.842 12.721 20 13.102 20 13.5 C 20 13.898 19.842 14.279 19.561 14.561 C 19.279 14.842 18.898 15 18.5 15 L 17 15 L 17 15 L 17 20 L 14.88 20 C 14.2 18.25 12.5 17 10.5 17 C 8.5 17 6.8 18.25 6.12 20 L 4 20 L 4 17.88 C 5.75 17.2 7 15.5 7 13.5 C 7 11.5 5.76 9.8 4 9.12 L 4 7 L 9 7 L 9 5.5 C 9 5.102 9.158 4.721 9.439 4.439 C 9.721 4.158 10.102 4 10.5 4 C 10.898 4 11.279 4.158 11.561 4.439 C 11.842 4.721 12 5.102 12 5.5 L 12 7 L 17 7 L 17 12"
|
||||||
android:valueTo="M 23 13.5 C 23 14.163 22.736 14.799 22.268 15.268 C 21.799 15.736 21.163 16 20.5 16 C 20 16 19.5 16 19 16 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 15.1 22 L 13.2 22 C 13.2 21.5 13.2 21 13.2 20.5 C 13.2 19 12 17.8 10.5 17.8 C 9 17.8 7.8 19 7.8 20.5 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 3.5 16.2 C 5 16.2 6.2 15 6.2 13.5 C 6.2 12 5 10.8 3.5 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 8 5 C 8 4.5 8 4 8 3.5 C 8 2.837 8.264 2.201 8.732 1.732 C 9.201 1.264 9.837 1 10.5 1 C 11.163 1 11.799 1.264 12.268 1.732 C 12.736 2.201 13 2.837 13 3.5 C 13 4 13 4.5 13 5 L 17 5 C 17.55 5 18.05 5.223 18.413 5.584 C 18.775 5.945 19 6.445 19 7 L 19 11 C 19.5 11 20 11 20.5 11 C 20.5 11 20.5 11 20.5 11 C 21.163 11 21.799 11.264 22.268 11.732 C 22.736 12.201 23 12.837 23 13.5 M 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12"
|
android:valueTo="M 23 13.5 C 23 14.163 22.736 14.799 22.268 15.268 C 21.799 15.736 21.163 16 20.5 16 C 20 16 19.5 16 19 16 L 19 20 C 19 20.53 18.789 21.039 18.414 21.414 C 18.039 21.789 17.53 22 17 22 L 15.1 22 L 13.2 22 C 13.2 21.5 13.2 21 13.2 20.5 C 13.2 19 12 17.8 10.5 17.8 C 9 17.8 7.8 19 7.8 20.5 L 7.8 22 L 4 22 C 3.47 22 2.961 21.789 2.586 21.414 C 2.211 21.039 2 20.53 2 20 L 2 16.2 L 3.5 16.2 C 5 16.2 6.2 15 6.2 13.5 C 6.2 12 5 10.8 3.5 10.8 L 2 10.8 L 2 7 C 2 6.47 2.211 5.961 2.586 5.586 C 2.961 5.211 3.47 5 4 5 L 8 5 C 8 4.5 8 4 8 3.5 C 8 2.837 8.264 2.201 8.732 1.732 C 9.201 1.264 9.837 1 10.5 1 C 11.163 1 11.799 1.264 12.268 1.732 C 12.736 2.201 13 2.837 13 3.5 C 13 4 13 4.5 13 5 L 17 5 C 17.55 5 18.05 5.223 18.413 5.584 C 18.775 5.945 19 6.445 19 7 L 19 11 C 19.5 11 20 11 20.5 11 C 20.5 11 20.5 11 20.5 11 C 21.163 11 21.799 11.264 22.268 11.732 C 22.736 12.201 23 12.837 23 13.5 M 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12"
|
@@ -18,7 +18,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="300"
|
android:duration="300"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.53 11.34 4.5 11.67 4.5 12 C 4.5 12.33 4.53 12.65 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.67 16.04 18.34 16.56 17.94 L 19.05 18.95 C 19.27 19.03 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.78 15.05 21.73 14.78 21.54 14.63 L 19.43 12.97 L 19.43 12.97 C 19.47 12.65 19.5 12.33 19.5 12 C 19.5 11.67 19.47 11.34 19.43 11 L 21.54 9.37 C 21.73 9.22 21.78 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8.5 C 12.614 8.5 13.218 8.662 13.75 8.969 C 14.282 9.276 14.724 9.718 15.031 10.25 C 15.338 10.782 15.5 11.386 15.5 12 C 15.5 12.614 15.338 13.218 15.031 13.75 C 14.724 14.282 14.282 14.724 13.75 15.031 C 13.218 15.338 12.614 15.5 12 15.5 C 11.072 15.5 10.181 15.131 9.525 14.475 C 8.869 13.819 8.5 12.928 8.5 12 C 8.5 11.072 8.869 10.181 9.525 9.525 C 10.181 8.869 11.072 8.5 12 8.5 M 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 M 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12"
|
android:valueFrom="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.53 11.34 4.5 11.67 4.5 12 C 4.5 12.33 4.53 12.65 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.67 16.04 18.34 16.56 17.94 L 19.05 18.95 C 19.27 19.03 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.78 15.05 21.73 14.78 21.54 14.63 L 19.43 12.97 L 19.43 12.97 C 19.47 12.65 19.5 12.33 19.5 12 C 19.5 11.67 19.47 11.34 19.43 11 L 21.54 9.37 C 21.73 9.22 21.78 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8.5 C 12.614 8.5 13.218 8.662 13.75 8.969 C 14.282 9.276 14.724 9.718 15.031 10.25 C 15.338 10.782 15.5 11.386 15.5 12 C 15.5 12.614 15.338 13.218 15.031 13.75 C 14.724 14.282 14.282 14.724 13.75 15.031 C 13.218 15.338 12.614 15.5 12 15.5 C 11.072 15.5 10.181 15.131 9.525 14.475 C 8.869 13.819 8.5 12.928 8.5 12 C 8.5 11.072 8.869 10.181 9.525 9.525 C 10.181 8.869 11.072 8.5 12 8.5 M 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 M 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12"
|
||||||
android:valueTo="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.547 11.333 4.523 11.667 4.5 12 C 4.523 12.323 4.547 12.647 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.68 16.04 18.34 16.56 17.95 L 19.05 18.95 C 19.27 19.04 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.79 15.05 21.73 14.78 21.54 14.63 L 19.43 13 L 19.465 12.499 C 19.477 12.333 19.488 12.166 19.5 12 C 19.477 11.667 19.453 11.333 19.43 11 L 21.54 9.37 C 21.73 9.22 21.79 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8 C 12.53 8 13.05 8.105 13.531 8.305 C 14.011 8.504 14.454 8.797 14.828 9.172 C 15.578 9.921 16 10.94 16 12 C 16 12.53 15.895 13.05 15.695 13.531 C 15.496 14.011 15.203 14.454 14.828 14.828 C 14.079 15.578 13.06 16 12 16 C 10.94 16 9.921 15.578 9.172 14.828 C 8.422 14.079 8 13.06 8 12 C 8 10.94 8.422 9.921 9.172 9.172 C 9.921 8.422 10.94 8 12 8 M 12 10 C 11.912 10 11.824 10.006 11.737 10.017 C 11.651 10.029 11.565 10.046 11.481 10.069 C 11.397 10.091 11.315 10.119 11.235 10.152 C 11.155 10.186 11.077 10.224 11.001 10.267 C 10.926 10.311 10.854 10.359 10.784 10.412 C 10.715 10.466 10.649 10.524 10.586 10.586 C 10.524 10.649 10.466 10.715 10.412 10.784 C 10.359 10.854 10.311 10.926 10.267 11.001 C 10.224 11.077 10.186 11.155 10.152 11.235 C 10.119 11.315 10.091 11.397 10.069 11.481 C 10.046 11.565 10.029 11.651 10.017 11.737 C 10.006 11.824 10 11.912 10 12 C 10 12.088 10.006 12.176 10.017 12.263 C 10.029 12.349 10.046 12.435 10.069 12.519 C 10.091 12.603 10.119 12.685 10.152 12.765 C 10.186 12.845 10.224 12.923 10.267 12.999 C 10.311 13.074 10.359 13.146 10.412 13.216 C 10.466 13.285 10.524 13.351 10.586 13.414 C 10.649 13.476 10.715 13.534 10.784 13.588 C 10.854 13.641 10.926 13.689 11.001 13.733 C 11.077 13.776 11.155 13.814 11.235 13.848 C 11.315 13.881 11.397 13.909 11.481 13.931 C 11.565 13.954 11.651 13.971 11.737 13.983 C 11.824 13.994 11.912 14 12 14 C 12.53 14 13.039 13.789 13.414 13.414 C 13.468 13.36 13.518 13.304 13.565 13.245 C 13.611 13.187 13.655 13.126 13.694 13.062 C 13.734 12.999 13.77 12.934 13.802 12.867 C 13.834 12.8 13.863 12.731 13.887 12.661 C 13.912 12.591 13.933 12.519 13.949 12.447 C 13.966 12.374 13.979 12.3 13.987 12.226 C 13.996 12.151 14 12.076 14 12 C 14 11.912 13.994 11.824 13.983 11.737 C 13.971 11.651 13.954 11.565 13.931 11.481 C 13.909 11.397 13.881 11.315 13.848 11.235 C 13.814 11.155 13.776 11.077 13.733 11.001 C 13.689 10.926 13.641 10.854 13.588 10.784 C 13.534 10.715 13.476 10.649 13.414 10.586 C 13.039 10.211 12.53 10 12 10 M 11.25 4 L 11.25 4 L 12.75 4 L 13.12 6.62 C 14.32 6.86 15.38 7.5 16.15 8.39 L 18.56 7.35 L 19.31 8.65 L 17.2 10.2 C 17.6 11.37 17.6 12.64 17.2 13.81 L 19.32 15.36 L 18.57 16.66 L 16.14 15.62 C 15.37 16.5 14.32 17.14 13.13 17.39 L 12.76 20 L 11.24 20 L 10.87 17.38 C 9.68 17.14 8.63 16.5 7.86 15.62 L 5.43 16.66 L 4.68 15.36 L 6.8 13.8 C 6.4 12.64 6.4 11.37 6.8 10.2 L 4.69 8.65 L 5.44 7.35 L 7.85 8.39 C 8.62 7.5 9.68 6.86 10.88 6.61 L 11.25 4"
|
android:valueTo="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.547 11.333 4.523 11.667 4.5 12 C 4.523 12.323 4.547 12.647 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.68 16.04 18.34 16.56 17.95 L 19.05 18.95 C 19.27 19.04 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.79 15.05 21.73 14.78 21.54 14.63 L 19.43 13 L 19.465 12.499 C 19.477 12.333 19.488 12.166 19.5 12 C 19.477 11.667 19.453 11.333 19.43 11 L 21.54 9.37 C 21.73 9.22 21.79 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8 C 12.53 8 13.05 8.105 13.531 8.305 C 14.011 8.504 14.454 8.797 14.828 9.172 C 15.578 9.921 16 10.94 16 12 C 16 12.53 15.895 13.05 15.695 13.531 C 15.496 14.011 15.203 14.454 14.828 14.828 C 14.079 15.578 13.06 16 12 16 C 10.94 16 9.921 15.578 9.172 14.828 C 8.422 14.079 8 13.06 8 12 C 8 10.94 8.422 9.921 9.172 9.172 C 9.921 8.422 10.94 8 12 8 M 12 10 C 11.912 10 11.824 10.006 11.737 10.017 C 11.651 10.029 11.565 10.046 11.481 10.069 C 11.397 10.091 11.315 10.119 11.235 10.152 C 11.155 10.186 11.077 10.224 11.001 10.267 C 10.926 10.311 10.854 10.359 10.784 10.412 C 10.715 10.466 10.649 10.524 10.586 10.586 C 10.524 10.649 10.466 10.715 10.412 10.784 C 10.359 10.854 10.311 10.926 10.267 11.001 C 10.224 11.077 10.186 11.155 10.152 11.235 C 10.119 11.315 10.091 11.397 10.069 11.481 C 10.046 11.565 10.029 11.651 10.017 11.737 C 10.006 11.824 10 11.912 10 12 C 10 12.088 10.006 12.176 10.017 12.263 C 10.029 12.349 10.046 12.435 10.069 12.519 C 10.091 12.603 10.119 12.685 10.152 12.765 C 10.186 12.845 10.224 12.923 10.267 12.999 C 10.311 13.074 10.359 13.146 10.412 13.216 C 10.466 13.285 10.524 13.351 10.586 13.414 C 10.649 13.476 10.715 13.534 10.784 13.588 C 10.854 13.641 10.926 13.689 11.001 13.733 C 11.077 13.776 11.155 13.814 11.235 13.848 C 11.315 13.881 11.397 13.909 11.481 13.931 C 11.565 13.954 11.651 13.971 11.737 13.983 C 11.824 13.994 11.912 14 12 14 C 12.53 14 13.039 13.789 13.414 13.414 C 13.468 13.36 13.518 13.304 13.565 13.245 C 13.611 13.187 13.655 13.126 13.694 13.062 C 13.734 12.999 13.77 12.934 13.802 12.867 C 13.834 12.8 13.863 12.731 13.887 12.661 C 13.912 12.591 13.933 12.519 13.949 12.447 C 13.966 12.374 13.979 12.3 13.987 12.226 C 13.996 12.151 14 12.076 14 12 C 14 11.912 13.994 11.824 13.983 11.737 C 13.971 11.651 13.954 11.565 13.931 11.481 C 13.909 11.397 13.881 11.315 13.848 11.235 C 13.814 11.155 13.776 11.077 13.733 11.001 C 13.689 10.926 13.641 10.854 13.588 10.784 C 13.534 10.715 13.476 10.649 13.414 10.586 C 13.039 10.211 12.53 10 12 10 M 11.25 4 L 11.25 4 L 12.75 4 L 13.12 6.62 C 14.32 6.86 15.38 7.5 16.15 8.39 L 18.56 7.35 L 19.31 8.65 L 17.2 10.2 C 17.6 11.37 17.6 12.64 17.2 13.81 L 19.32 15.36 L 18.57 16.66 L 16.14 15.62 C 15.37 16.5 14.32 17.14 13.13 17.39 L 12.76 20 L 11.24 20 L 10.87 17.38 C 9.68 17.14 8.63 16.5 7.86 15.62 L 5.43 16.66 L 4.68 15.36 L 6.8 13.8 C 6.4 12.64 6.4 11.37 6.8 10.2 L 4.69 8.65 L 5.44 7.35 L 7.85 8.39 C 8.62 7.5 9.68 6.86 10.88 6.61 L 11.25 4"
|
@@ -18,7 +18,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="300"
|
android:duration="300"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.547 11.333 4.523 11.667 4.5 12 C 4.523 12.323 4.547 12.647 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.68 16.04 18.34 16.56 17.95 L 19.05 18.95 C 19.27 19.04 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.79 15.05 21.73 14.78 21.54 14.63 L 19.43 13 L 19.465 12.499 C 19.477 12.333 19.488 12.166 19.5 12 C 19.477 11.667 19.453 11.333 19.43 11 L 21.54 9.37 C 21.73 9.22 21.79 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8 C 12.53 8 13.05 8.105 13.531 8.305 C 14.011 8.504 14.454 8.797 14.828 9.172 C 15.578 9.921 16 10.94 16 12 C 16 12.53 15.895 13.05 15.695 13.531 C 15.496 14.011 15.203 14.454 14.828 14.828 C 14.079 15.578 13.06 16 12 16 C 10.94 16 9.921 15.578 9.172 14.828 C 8.422 14.079 8 13.06 8 12 C 8 10.94 8.422 9.921 9.172 9.172 C 9.921 8.422 10.94 8 12 8 M 12 10 C 11.912 10 11.824 10.006 11.737 10.017 C 11.651 10.029 11.565 10.046 11.481 10.069 C 11.397 10.091 11.315 10.119 11.235 10.152 C 11.155 10.186 11.077 10.224 11.001 10.267 C 10.926 10.311 10.854 10.359 10.784 10.412 C 10.715 10.466 10.649 10.524 10.586 10.586 C 10.524 10.649 10.466 10.715 10.412 10.784 C 10.359 10.854 10.311 10.926 10.267 11.001 C 10.224 11.077 10.186 11.155 10.152 11.235 C 10.119 11.315 10.091 11.397 10.069 11.481 C 10.046 11.565 10.029 11.651 10.017 11.737 C 10.006 11.824 10 11.912 10 12 C 10 12.088 10.006 12.176 10.017 12.263 C 10.029 12.349 10.046 12.435 10.069 12.519 C 10.091 12.603 10.119 12.685 10.152 12.765 C 10.186 12.845 10.224 12.923 10.267 12.999 C 10.311 13.074 10.359 13.146 10.412 13.216 C 10.466 13.285 10.524 13.351 10.586 13.414 C 10.649 13.476 10.715 13.534 10.784 13.588 C 10.854 13.641 10.926 13.689 11.001 13.733 C 11.077 13.776 11.155 13.814 11.235 13.848 C 11.315 13.881 11.397 13.909 11.481 13.931 C 11.565 13.954 11.651 13.971 11.737 13.983 C 11.824 13.994 11.912 14 12 14 C 12.53 14 13.039 13.789 13.414 13.414 C 13.468 13.36 13.518 13.304 13.565 13.245 C 13.611 13.187 13.655 13.126 13.694 13.062 C 13.734 12.999 13.77 12.934 13.802 12.867 C 13.834 12.8 13.863 12.731 13.887 12.661 C 13.912 12.591 13.933 12.519 13.949 12.447 C 13.966 12.374 13.979 12.3 13.987 12.226 C 13.996 12.151 14 12.076 14 12 C 14 11.912 13.994 11.824 13.983 11.737 C 13.971 11.651 13.954 11.565 13.931 11.481 C 13.909 11.397 13.881 11.315 13.848 11.235 C 13.814 11.155 13.776 11.077 13.733 11.001 C 13.689 10.926 13.641 10.854 13.588 10.784 C 13.534 10.715 13.476 10.649 13.414 10.586 C 13.039 10.211 12.53 10 12 10 M 11.25 4 L 11.25 4 L 12.75 4 L 13.12 6.62 C 14.32 6.86 15.38 7.5 16.15 8.39 L 18.56 7.35 L 19.31 8.65 L 17.2 10.2 C 17.6 11.37 17.6 12.64 17.2 13.81 L 19.32 15.36 L 18.57 16.66 L 16.14 15.62 C 15.37 16.5 14.32 17.14 13.13 17.39 L 12.76 20 L 11.24 20 L 10.87 17.38 C 9.68 17.14 8.63 16.5 7.86 15.62 L 5.43 16.66 L 4.68 15.36 L 6.8 13.8 C 6.4 12.64 6.4 11.37 6.8 10.2 L 4.69 8.65 L 5.44 7.35 L 7.85 8.39 C 8.62 7.5 9.68 6.86 10.88 6.61 L 11.25 4"
|
android:valueFrom="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.547 11.333 4.523 11.667 4.5 12 C 4.523 12.323 4.547 12.647 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.68 16.04 18.34 16.56 17.95 L 19.05 18.95 C 19.27 19.04 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.79 15.05 21.73 14.78 21.54 14.63 L 19.43 13 L 19.465 12.499 C 19.477 12.333 19.488 12.166 19.5 12 C 19.477 11.667 19.453 11.333 19.43 11 L 21.54 9.37 C 21.73 9.22 21.79 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8 C 12.53 8 13.05 8.105 13.531 8.305 C 14.011 8.504 14.454 8.797 14.828 9.172 C 15.578 9.921 16 10.94 16 12 C 16 12.53 15.895 13.05 15.695 13.531 C 15.496 14.011 15.203 14.454 14.828 14.828 C 14.079 15.578 13.06 16 12 16 C 10.94 16 9.921 15.578 9.172 14.828 C 8.422 14.079 8 13.06 8 12 C 8 10.94 8.422 9.921 9.172 9.172 C 9.921 8.422 10.94 8 12 8 M 12 10 C 11.912 10 11.824 10.006 11.737 10.017 C 11.651 10.029 11.565 10.046 11.481 10.069 C 11.397 10.091 11.315 10.119 11.235 10.152 C 11.155 10.186 11.077 10.224 11.001 10.267 C 10.926 10.311 10.854 10.359 10.784 10.412 C 10.715 10.466 10.649 10.524 10.586 10.586 C 10.524 10.649 10.466 10.715 10.412 10.784 C 10.359 10.854 10.311 10.926 10.267 11.001 C 10.224 11.077 10.186 11.155 10.152 11.235 C 10.119 11.315 10.091 11.397 10.069 11.481 C 10.046 11.565 10.029 11.651 10.017 11.737 C 10.006 11.824 10 11.912 10 12 C 10 12.088 10.006 12.176 10.017 12.263 C 10.029 12.349 10.046 12.435 10.069 12.519 C 10.091 12.603 10.119 12.685 10.152 12.765 C 10.186 12.845 10.224 12.923 10.267 12.999 C 10.311 13.074 10.359 13.146 10.412 13.216 C 10.466 13.285 10.524 13.351 10.586 13.414 C 10.649 13.476 10.715 13.534 10.784 13.588 C 10.854 13.641 10.926 13.689 11.001 13.733 C 11.077 13.776 11.155 13.814 11.235 13.848 C 11.315 13.881 11.397 13.909 11.481 13.931 C 11.565 13.954 11.651 13.971 11.737 13.983 C 11.824 13.994 11.912 14 12 14 C 12.53 14 13.039 13.789 13.414 13.414 C 13.468 13.36 13.518 13.304 13.565 13.245 C 13.611 13.187 13.655 13.126 13.694 13.062 C 13.734 12.999 13.77 12.934 13.802 12.867 C 13.834 12.8 13.863 12.731 13.887 12.661 C 13.912 12.591 13.933 12.519 13.949 12.447 C 13.966 12.374 13.979 12.3 13.987 12.226 C 13.996 12.151 14 12.076 14 12 C 14 11.912 13.994 11.824 13.983 11.737 C 13.971 11.651 13.954 11.565 13.931 11.481 C 13.909 11.397 13.881 11.315 13.848 11.235 C 13.814 11.155 13.776 11.077 13.733 11.001 C 13.689 10.926 13.641 10.854 13.588 10.784 C 13.534 10.715 13.476 10.649 13.414 10.586 C 13.039 10.211 12.53 10 12 10 M 11.25 4 L 11.25 4 L 12.75 4 L 13.12 6.62 C 14.32 6.86 15.38 7.5 16.15 8.39 L 18.56 7.35 L 19.31 8.65 L 17.2 10.2 C 17.6 11.37 17.6 12.64 17.2 13.81 L 19.32 15.36 L 18.57 16.66 L 16.14 15.62 C 15.37 16.5 14.32 17.14 13.13 17.39 L 12.76 20 L 11.24 20 L 10.87 17.38 C 9.68 17.14 8.63 16.5 7.86 15.62 L 5.43 16.66 L 4.68 15.36 L 6.8 13.8 C 6.4 12.64 6.4 11.37 6.8 10.2 L 4.69 8.65 L 5.44 7.35 L 7.85 8.39 C 8.62 7.5 9.68 6.86 10.88 6.61 L 11.25 4"
|
||||||
android:valueTo="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.53 11.34 4.5 11.67 4.5 12 C 4.5 12.33 4.53 12.65 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.67 16.04 18.34 16.56 17.94 L 19.05 18.95 C 19.27 19.03 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.78 15.05 21.73 14.78 21.54 14.63 L 19.43 12.97 L 19.43 12.97 C 19.47 12.65 19.5 12.33 19.5 12 C 19.5 11.67 19.47 11.34 19.43 11 L 21.54 9.37 C 21.73 9.22 21.78 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8.5 C 12.614 8.5 13.218 8.662 13.75 8.969 C 14.282 9.276 14.724 9.718 15.031 10.25 C 15.338 10.782 15.5 11.386 15.5 12 C 15.5 12.614 15.338 13.218 15.031 13.75 C 14.724 14.282 14.282 14.724 13.75 15.031 C 13.218 15.338 12.614 15.5 12 15.5 C 11.072 15.5 10.181 15.131 9.525 14.475 C 8.869 13.819 8.5 12.928 8.5 12 C 8.5 11.072 8.869 10.181 9.525 9.525 C 10.181 8.869 11.072 8.5 12 8.5 M 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 M 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12"
|
android:valueTo="M 14.87 5.07 L 14.5 2.42 C 14.46 2.18 14.25 2 14 2 L 10 2 C 9.75 2 9.54 2.18 9.5 2.42 L 9.13 5.07 C 8.5 5.32 7.96 5.66 7.44 6.05 L 4.95 5.05 C 4.73 4.96 4.46 5.05 4.34 5.27 L 2.34 8.73 C 2.21 8.95 2.27 9.22 2.46 9.37 L 4.57 11 C 4.53 11.34 4.5 11.67 4.5 12 C 4.5 12.33 4.53 12.65 4.57 12.97 L 2.46 14.63 C 2.27 14.78 2.21 15.05 2.34 15.27 L 4.34 18.73 C 4.46 18.95 4.73 19.03 4.95 18.95 L 7.44 17.94 C 7.96 18.34 8.5 18.68 9.13 18.93 L 9.5 21.58 C 9.54 21.82 9.75 22 10 22 L 14 22 C 14.25 22 14.46 21.82 14.5 21.58 L 14.87 18.93 C 15.5 18.67 16.04 18.34 16.56 17.94 L 19.05 18.95 C 19.27 19.03 19.54 18.95 19.66 18.73 L 21.66 15.27 C 21.78 15.05 21.73 14.78 21.54 14.63 L 19.43 12.97 L 19.43 12.97 C 19.47 12.65 19.5 12.33 19.5 12 C 19.5 11.67 19.47 11.34 19.43 11 L 21.54 9.37 C 21.73 9.22 21.78 8.95 21.66 8.73 L 19.66 5.27 C 19.54 5.05 19.27 4.96 19.05 5.05 L 16.56 6.05 C 16.04 5.66 15.5 5.32 14.87 5.07 M 12 8.5 C 12.614 8.5 13.218 8.662 13.75 8.969 C 14.282 9.276 14.724 9.718 15.031 10.25 C 15.338 10.782 15.5 11.386 15.5 12 C 15.5 12.614 15.338 13.218 15.031 13.75 C 14.724 14.282 14.282 14.724 13.75 15.031 C 13.218 15.338 12.614 15.5 12 15.5 C 11.072 15.5 10.181 15.131 9.525 14.475 C 8.869 13.819 8.5 12.928 8.5 12 C 8.5 11.072 8.869 10.181 9.525 9.525 C 10.181 8.869 11.072 8.5 12 8.5 M 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 C 11.982 12 11.982 12 11.982 12 M 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12 L 12 12 L 12 12 C 12 12 12 12 12 12 L 12 12"
|
@@ -18,7 +18,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="300"
|
android:duration="300"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 12 1 L 12 1 L 21 5 L 21 11 M 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18"
|
android:valueFrom="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 12 1 L 12 1 L 21 5 L 21 11 M 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18"
|
||||||
android:valueTo="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 7.5 3 L 12 1 L 21 5 L 21 11 M 12 21 L 12 21 C 8.25 20 5 15.54 5 11.22 L 5 6.3 L 12 3.18 L 19 6.3 L 19 11.22 C 19 15.54 15.75 20 12 21"
|
android:valueTo="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 7.5 3 L 12 1 L 21 5 L 21 11 M 12 21 L 12 21 C 8.25 20 5 15.54 5 11.22 L 5 6.3 L 12 3.18 L 19 6.3 L 19 11.22 C 19 15.54 15.75 20 12 21"
|
@@ -18,7 +18,7 @@
|
|||||||
<aapt:attr name="android:animation">
|
<aapt:attr name="android:animation">
|
||||||
<objectAnimator
|
<objectAnimator
|
||||||
android:duration="300"
|
android:duration="300"
|
||||||
android:interpolator="@interpolator/fast_out_slow_in"
|
android:interpolator="@android:interpolator/fast_out_slow_in"
|
||||||
android:propertyName="pathData"
|
android:propertyName="pathData"
|
||||||
android:valueFrom="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 7.5 3 L 12 1 L 21 5 L 21 11 M 12 21 L 12 21 C 8.25 20 5 15.54 5 11.22 L 5 6.3 L 12 3.18 L 19 6.3 L 19 11.22 C 19 15.54 15.75 20 12 21"
|
android:valueFrom="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 7.5 3 L 12 1 L 21 5 L 21 11 M 12 21 L 12 21 C 8.25 20 5 15.54 5 11.22 L 5 6.3 L 12 3.18 L 19 6.3 L 19 11.22 C 19 15.54 15.75 20 12 21"
|
||||||
android:valueTo="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 12 1 L 12 1 L 21 5 L 21 11 M 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18"
|
android:valueTo="M 21 11 C 21 16.55 17.16 21.74 12 23 C 6.84 21.74 3 16.55 3 11 L 3 5 L 12 1 L 12 1 L 21 5 L 21 11 M 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 L 12 10.18 C 12 10.18 12 10.18 12 10.18"
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user