Compare commits

...

217 Commits

Author SHA1 Message Date
Grishka
19759023a4 Bump version 2023-11-21 22:34:51 +03:00
Grishka
714d3399ce Merge branch 'l10n_master' 2023-11-21 22:34:30 +03:00
Grishka
e1850e5282 Validate timezone and locale against what server supports
closes #654, AND-118
2023-11-21 22:31:26 +03:00
Grishka
a05c917b2c Assorted crash fixes 2023-11-21 21:46:41 +03:00
Grishka
8f3a9c265c Fix a rare crash when opening a notification 2023-11-21 21:27:43 +03:00
Grishka
6f1a33b76e Fix #741 2023-11-21 21:17:30 +03:00
Eugen Rochko
8f0451175f New translations strings.xml (Japanese) 2023-11-21 13:38:37 +01:00
Eugen Rochko
37a3a4f1c0 New translations strings.xml (Chinese Simplified) 2023-11-21 05:53:58 +01:00
Eugen Rochko
bd85746726 New translations strings.xml (Chinese Simplified) 2023-11-21 04:58:34 +01:00
Grishka
96265010bf Merge branch 'l10n_master' 2023-11-20 17:40:05 +03:00
Eugen Rochko
4209951ce3 New translations strings.xml (Armenian) 2023-11-19 11:46:47 +01:00
Eugen Rochko
f1cbd95439 New translations strings.xml (Thai) 2023-11-18 10:24:17 +01:00
Eugen Rochko
d63382c6d9 New translations strings.xml (Thai) 2023-11-18 09:18:16 +01:00
Grishka
20697fb334 Show bio instead of fields in non-mutual pre-reply sheet 2023-11-18 10:58:09 +03:00
Eugen Rochko
1090d1ca42 New translations strings.xml (Thai) 2023-11-17 21:37:58 +01:00
Eugen Rochko
bec4acdf51 New translations strings.xml (Japanese) 2023-11-17 17:27:10 +01:00
Eugen Rochko
800b78bfd8 New translations strings.xml (Vietnamese) 2023-11-17 16:15:13 +01:00
Eugen Rochko
52b01b7bbe New translations strings.xml (Slovenian) 2023-11-17 16:15:12 +01:00
Eugen Rochko
8b71764207 New translations strings.xml (Japanese) 2023-11-17 14:56:57 +01:00
Eugen Rochko
a5d7a75f32 New translations strings.xml (Slovenian) 2023-11-17 14:00:00 +01:00
Eugen Rochko
8839bcb7aa New translations strings.xml (Slovenian) 2023-11-17 12:03:35 +01:00
Eugen Rochko
bcaf71760d New translations strings.xml (Chinese Traditional) 2023-11-17 08:51:19 +01:00
Eugen Rochko
1d95204648 New translations strings.xml (Russian) 2023-11-17 07:26:31 +01:00
Eugen Rochko
83bf2a808f New translations strings.xml (Russian) 2023-11-17 06:19:30 +01:00
Eugen Rochko
7ffb0a01c6 New translations strings.xml (Italian) 2023-11-16 22:09:36 +01:00
Eugen Rochko
0710113148 New translations strings.xml (Thai) 2023-11-16 20:31:10 +01:00
Eugen Rochko
7c43e9a1af New translations strings.xml (Norwegian) 2023-11-16 20:31:08 +01:00
Eugen Rochko
f9e768c378 New translations strings.xml (Thai) 2023-11-16 19:20:56 +01:00
Grishka
2063dbd0b0 Copy app version when tapped 2023-11-16 18:15:59 +03:00
Eugen Rochko
057683c72f New translations strings.xml (Kabyle) 2023-11-16 12:47:38 +01:00
Eugen Rochko
4963a0e722 New translations strings.xml (Occitan) 2023-11-16 12:47:36 +01:00
Eugen Rochko
1d66d288bd New translations strings.xml (Scottish Gaelic) 2023-11-16 12:47:35 +01:00
Eugen Rochko
b8f49157c3 New translations strings.xml (Bosnian) 2023-11-16 12:47:33 +01:00
Eugen Rochko
d77a62ef6f New translations strings.xml (Filipino) 2023-11-16 12:47:32 +01:00
Eugen Rochko
c531150483 New translations strings.xml (Burmese) 2023-11-16 12:47:31 +01:00
Eugen Rochko
991f41c531 New translations strings.xml (Croatian) 2023-11-16 12:47:30 +01:00
Eugen Rochko
b5fb7dd2ec New translations strings.xml (Thai) 2023-11-16 12:47:29 +01:00
Eugen Rochko
4fe8532971 New translations strings.xml (Bengali) 2023-11-16 12:47:27 +01:00
Eugen Rochko
4ae1e7d33e New translations strings.xml (Indonesian) 2023-11-16 12:47:26 +01:00
Eugen Rochko
43fa4526a4 New translations strings.xml (Portuguese, Brazilian) 2023-11-16 12:47:25 +01:00
Eugen Rochko
fc4b1da323 New translations strings.xml (Galician) 2023-11-16 12:47:24 +01:00
Eugen Rochko
843755f4e4 New translations strings.xml (Chinese Traditional) 2023-11-16 12:47:23 +01:00
Eugen Rochko
80e02f7520 New translations strings.xml (Chinese Simplified) 2023-11-16 12:47:22 +01:00
Eugen Rochko
af8f52e589 New translations strings.xml (Swedish) 2023-11-16 12:47:21 +01:00
Eugen Rochko
bc3f48dec9 New translations strings.xml (Russian) 2023-11-16 12:47:20 +01:00
Eugen Rochko
74ee832507 New translations strings.xml (Portuguese) 2023-11-16 12:47:18 +01:00
Eugen Rochko
da1b2d09b1 New translations strings.xml (Polish) 2023-11-16 12:47:17 +01:00
Eugen Rochko
99f8607211 New translations strings.xml (Norwegian) 2023-11-16 12:47:16 +01:00
Eugen Rochko
ef293088e1 New translations strings.xml (Dutch) 2023-11-16 12:47:15 +01:00
Eugen Rochko
e08e72ccb0 New translations strings.xml (Korean) 2023-11-16 12:47:14 +01:00
Eugen Rochko
b692440bab New translations strings.xml (Japanese) 2023-11-16 12:47:13 +01:00
Eugen Rochko
7061abc64b New translations strings.xml (Italian) 2023-11-16 12:47:12 +01:00
Eugen Rochko
0dd5064abb New translations strings.xml (Hungarian) 2023-11-16 12:47:11 +01:00
Eugen Rochko
a1aafff6ce New translations strings.xml (Hebrew) 2023-11-16 12:47:09 +01:00
Eugen Rochko
1f88f154af New translations strings.xml (German) 2023-11-16 12:47:08 +01:00
Eugen Rochko
3d1e0364c6 New translations strings.xml (Danish) 2023-11-16 12:47:06 +01:00
Eugen Rochko
0f1b5431bb New translations strings.xml (Czech) 2023-11-16 12:47:05 +01:00
Eugen Rochko
0369d3fa62 New translations strings.xml (Catalan) 2023-11-16 12:47:04 +01:00
Eugen Rochko
154e3a732a New translations strings.xml (Belarusian) 2023-11-16 12:47:03 +01:00
Eugen Rochko
9c979db043 New translations strings.xml (Arabic) 2023-11-16 12:47:02 +01:00
Eugen Rochko
0af089db89 New translations strings.xml (Spanish) 2023-11-16 12:47:00 +01:00
Eugen Rochko
1335613860 New translations strings.xml (Vietnamese) 2023-11-16 12:46:58 +01:00
Eugen Rochko
cb86bfd8dc New translations strings.xml (Persian) 2023-11-16 12:46:57 +01:00
Eugen Rochko
a0d32ae493 New translations strings.xml (Turkish) 2023-11-16 12:46:56 +01:00
Eugen Rochko
f7e56a6c40 New translations strings.xml (Slovenian) 2023-11-16 12:46:55 +01:00
Eugen Rochko
56613c75f7 New translations strings.xml (Armenian) 2023-11-16 12:46:54 +01:00
Eugen Rochko
fb3c35c0a0 New translations strings.xml (Basque) 2023-11-16 12:46:53 +01:00
Eugen Rochko
4b3dc0a59f New translations strings.xml (French) 2023-11-16 12:46:52 +01:00
Eugen Rochko
7855615a7b New translations strings.xml (Icelandic) 2023-11-16 12:46:50 +01:00
Eugen Rochko
ff6576f4da New translations strings.xml (Ukrainian) 2023-11-16 12:46:49 +01:00
Eugen Rochko
931fa9a9b0 New translations strings.xml (Finnish) 2023-11-16 12:46:48 +01:00
Eugen Rochko
77a70967f2 New translations strings.xml (Greek) 2023-11-16 12:46:47 +01:00
Grishka
e5506d952c Onboarding: replace fields with discoverability toggle (AND-100) 2023-11-16 12:15:17 +03:00
Eugen Rochko
2c2dbd0761 New translations strings.xml (Kabyle) 2023-11-16 09:56:39 +01:00
Eugen Rochko
e6f5ecd496 New translations strings.xml (Scottish Gaelic) 2023-11-16 09:56:37 +01:00
Eugen Rochko
73cea2d83c New translations strings.xml (Filipino) 2023-11-16 09:56:34 +01:00
Eugen Rochko
835a576f44 New translations strings.xml (Thai) 2023-11-16 09:56:31 +01:00
Eugen Rochko
0a090341cc New translations strings.xml (Indonesian) 2023-11-16 09:56:29 +01:00
Eugen Rochko
453671abfb New translations strings.xml (Portuguese, Brazilian) 2023-11-16 09:56:27 +01:00
Eugen Rochko
cfa7daa984 New translations strings.xml (Galician) 2023-11-16 09:56:26 +01:00
Eugen Rochko
88f913f586 New translations strings.xml (Chinese Traditional) 2023-11-16 09:56:25 +01:00
Eugen Rochko
5b4aeb4923 New translations strings.xml (Chinese Simplified) 2023-11-16 09:56:24 +01:00
Eugen Rochko
19133a2913 New translations strings.xml (Swedish) 2023-11-16 09:56:23 +01:00
Eugen Rochko
293035b7c8 New translations strings.xml (Russian) 2023-11-16 09:56:22 +01:00
Eugen Rochko
d06723de5c New translations strings.xml (Portuguese) 2023-11-16 09:56:20 +01:00
Eugen Rochko
bc45d0c499 New translations strings.xml (Polish) 2023-11-16 09:56:19 +01:00
Eugen Rochko
c320cccf6f New translations strings.xml (Norwegian) 2023-11-16 09:56:18 +01:00
Eugen Rochko
e3aebbd145 New translations strings.xml (Dutch) 2023-11-16 09:56:17 +01:00
Eugen Rochko
e15d378e46 New translations strings.xml (Korean) 2023-11-16 09:56:16 +01:00
Eugen Rochko
b6720d10fb New translations strings.xml (Japanese) 2023-11-16 09:56:15 +01:00
Eugen Rochko
83a2dbe8a1 New translations strings.xml (Italian) 2023-11-16 09:56:13 +01:00
Eugen Rochko
5b8592a99d New translations strings.xml (Hungarian) 2023-11-16 09:56:12 +01:00
Eugen Rochko
18a094c06c New translations strings.xml (German) 2023-11-16 09:56:10 +01:00
Eugen Rochko
a319ff3dc0 New translations strings.xml (Danish) 2023-11-16 09:56:08 +01:00
Eugen Rochko
0cb46eca1a New translations strings.xml (Czech) 2023-11-16 09:56:07 +01:00
Eugen Rochko
d85c814cba New translations strings.xml (Catalan) 2023-11-16 09:56:06 +01:00
Eugen Rochko
f49e660f29 New translations strings.xml (Belarusian) 2023-11-16 09:56:05 +01:00
Eugen Rochko
afa407e7d1 New translations strings.xml (Arabic) 2023-11-16 09:56:04 +01:00
Eugen Rochko
37e0f5ecea New translations strings.xml (Spanish) 2023-11-16 09:56:02 +01:00
Eugen Rochko
5000fdcfea New translations strings.xml (Vietnamese) 2023-11-16 09:56:00 +01:00
Eugen Rochko
2ec7489dbf New translations strings.xml (Persian) 2023-11-16 09:55:59 +01:00
Eugen Rochko
05965cea6e New translations strings.xml (Turkish) 2023-11-16 09:55:58 +01:00
Eugen Rochko
279e22ccb3 New translations strings.xml (Slovenian) 2023-11-16 09:55:57 +01:00
Eugen Rochko
6a6fc1ca8b New translations strings.xml (Armenian) 2023-11-16 09:55:56 +01:00
Eugen Rochko
b6b5426297 New translations strings.xml (Basque) 2023-11-16 09:55:55 +01:00
Eugen Rochko
e332ddda74 New translations strings.xml (French) 2023-11-16 09:55:54 +01:00
Eugen Rochko
2cd4cfb883 New translations strings.xml (Icelandic) 2023-11-16 09:55:52 +01:00
Eugen Rochko
ef12d09d35 New translations strings.xml (Ukrainian) 2023-11-16 09:55:51 +01:00
Eugen Rochko
1e365a8a7c New translations strings.xml (Finnish) 2023-11-16 09:55:50 +01:00
Eugen Rochko
e9363b41fd New translations strings.xml (Greek) 2023-11-16 09:55:49 +01:00
Grishka
5e99df137a Remove unused resources 2023-11-16 11:44:27 +03:00
Grishka
c0d0b45e24 Replace boost icons 2023-11-16 11:38:18 +03:00
Eugen Rochko
3340b4cdfa New translations strings.xml (Norwegian) 2023-11-15 22:47:52 +01:00
Eugen Rochko
d4afcc3383 New translations strings.xml (Norwegian) 2023-11-15 21:19:47 +01:00
Eugen Rochko
dad423eb04 New translations strings.xml (German) 2023-11-15 20:06:02 +01:00
Eugen Rochko
7b275d7e3d New translations strings.xml (Chinese Traditional) 2023-11-15 19:10:30 +01:00
Eugen Rochko
5274ecb721 New translations strings.xml (Chinese Traditional) 2023-11-15 18:12:43 +01:00
Eugen Rochko
e45367a482 New translations strings.xml (Japanese) 2023-11-15 18:12:42 +01:00
Eugen Rochko
83532edaab New translations strings.xml (Urdu (India)) 2023-11-15 16:43:17 +01:00
Eugen Rochko
793d28da6a New translations strings.xml (Kabyle) 2023-11-15 16:43:16 +01:00
Eugen Rochko
a8e575f680 New translations strings.xml (Igbo) 2023-11-15 16:43:15 +01:00
Eugen Rochko
98b0b3f9dd New translations strings.xml (Occitan) 2023-11-15 16:43:14 +01:00
Eugen Rochko
2e6d9c296a New translations strings.xml (Scottish Gaelic) 2023-11-15 16:43:13 +01:00
Eugen Rochko
a07dc96ef9 New translations strings.xml (Sinhala) 2023-11-15 16:43:12 +01:00
Eugen Rochko
8ba097a68a New translations strings.xml (Bosnian) 2023-11-15 16:43:11 +01:00
Eugen Rochko
b1dd990fea New translations strings.xml (Filipino) 2023-11-15 16:43:09 +01:00
Eugen Rochko
ba7864b910 New translations strings.xml (Burmese) 2023-11-15 16:43:08 +01:00
Eugen Rochko
5d8fa343cd New translations strings.xml (Hindi) 2023-11-15 16:43:07 +01:00
Eugen Rochko
3fc49c431b New translations strings.xml (Croatian) 2023-11-15 16:43:06 +01:00
Eugen Rochko
79b6e65ce3 New translations strings.xml (Thai) 2023-11-15 16:43:05 +01:00
Eugen Rochko
9f457d0d76 New translations strings.xml (Bengali) 2023-11-15 16:43:03 +01:00
Eugen Rochko
aa2ff62db4 New translations strings.xml (Indonesian) 2023-11-15 16:43:02 +01:00
Eugen Rochko
73fffca569 New translations strings.xml (Portuguese, Brazilian) 2023-11-15 16:43:01 +01:00
Eugen Rochko
45589fc033 New translations strings.xml (Galician) 2023-11-15 16:42:59 +01:00
Eugen Rochko
79b81ed932 New translations strings.xml (Chinese Traditional) 2023-11-15 16:42:58 +01:00
Eugen Rochko
d1242870df New translations strings.xml (Chinese Simplified) 2023-11-15 16:42:57 +01:00
Eugen Rochko
e0dbbc4bc0 New translations strings.xml (Swedish) 2023-11-15 16:42:56 +01:00
Eugen Rochko
bf89791817 New translations strings.xml (Russian) 2023-11-15 16:42:55 +01:00
Eugen Rochko
e3197f6dc1 New translations strings.xml (Portuguese) 2023-11-15 16:42:54 +01:00
Eugen Rochko
e6317aa898 New translations strings.xml (Polish) 2023-11-15 16:42:52 +01:00
Eugen Rochko
c73dc326fd New translations strings.xml (Norwegian) 2023-11-15 16:42:51 +01:00
Eugen Rochko
287e250357 New translations strings.xml (Dutch) 2023-11-15 16:42:50 +01:00
Eugen Rochko
9673a14420 New translations strings.xml (Korean) 2023-11-15 16:42:49 +01:00
Eugen Rochko
3333fdc8d7 New translations strings.xml (Japanese) 2023-11-15 16:42:48 +01:00
Eugen Rochko
9fb4b8bb6e New translations strings.xml (Italian) 2023-11-15 16:42:47 +01:00
Eugen Rochko
7b10ed13f4 New translations strings.xml (Hungarian) 2023-11-15 16:42:45 +01:00
Eugen Rochko
c528bd797d New translations strings.xml (Hebrew) 2023-11-15 16:42:44 +01:00
Eugen Rochko
264529705c New translations strings.xml (Irish) 2023-11-15 16:42:43 +01:00
Eugen Rochko
4669e3dfc7 New translations strings.xml (German) 2023-11-15 16:42:42 +01:00
Eugen Rochko
eff3798964 New translations strings.xml (Danish) 2023-11-15 16:42:41 +01:00
Eugen Rochko
78c526c25b New translations strings.xml (Czech) 2023-11-15 16:42:40 +01:00
Eugen Rochko
ec13415d1f New translations strings.xml (Catalan) 2023-11-15 16:42:39 +01:00
Eugen Rochko
96622184ae New translations strings.xml (Belarusian) 2023-11-15 16:42:38 +01:00
Eugen Rochko
3742c1c862 New translations strings.xml (Arabic) 2023-11-15 16:42:37 +01:00
Eugen Rochko
a0c7757428 New translations strings.xml (Spanish) 2023-11-15 16:42:36 +01:00
Eugen Rochko
15f9f4906a New translations strings.xml (Romanian) 2023-11-15 16:42:34 +01:00
Eugen Rochko
d577cd9b21 New translations strings.xml (Vietnamese) 2023-11-15 16:42:33 +01:00
Eugen Rochko
cf610cbb87 New translations strings.xml (Persian) 2023-11-15 16:42:32 +01:00
Eugen Rochko
1e1095204d New translations strings.xml (Turkish) 2023-11-15 16:42:31 +01:00
Eugen Rochko
3fb6a13a3a New translations strings.xml (Slovenian) 2023-11-15 16:42:30 +01:00
Eugen Rochko
2826655fe2 New translations strings.xml (Armenian) 2023-11-15 16:42:29 +01:00
Eugen Rochko
0ccf450b28 New translations strings.xml (Basque) 2023-11-15 16:42:28 +01:00
Eugen Rochko
d28b9460af New translations strings.xml (French) 2023-11-15 16:42:26 +01:00
Eugen Rochko
3e1bdf98c2 New translations strings.xml (Icelandic) 2023-11-15 16:42:25 +01:00
Eugen Rochko
3f87764230 New translations strings.xml (Ukrainian) 2023-11-15 16:42:24 +01:00
Eugen Rochko
25e8e2e9e1 New translations strings.xml (Finnish) 2023-11-15 16:42:23 +01:00
Eugen Rochko
3faf2ce9b9 New translations strings.xml (Greek) 2023-11-15 16:42:22 +01:00
Grishka
cbe243fc9e Open link in browser when a post/account links to itself
closes #739
2023-11-15 18:17:08 +03:00
Grishka
a438f633be Pre-reply sheets 2023-11-15 18:05:38 +03:00
Eugen Rochko
37ef67d7ac New translations strings.xml (Italian) 2023-11-15 13:33:31 +01:00
Eugen Rochko
67d631b0f0 New translations strings.xml (Russian) 2023-11-15 07:59:18 +01:00
Eugen Rochko
fc302ffa5f New translations strings.xml (Belarusian) 2023-11-15 03:27:35 +01:00
Eugen Rochko
8c28556a94 New translations strings.xml (Chinese Traditional) 2023-11-14 20:53:35 +01:00
Grishka
45cc531eec Thread fragment tweaks part 2 2023-11-14 21:27:15 +03:00
Grishka
5c9ad9286d Thread fragment tweaks part 1 2023-11-14 19:23:42 +03:00
Eugen Rochko
ad1c9486d7 New translations short_description.txt (Hungarian) 2023-11-14 15:33:01 +01:00
Eugen Rochko
ad6a03b712 New translations strings.xml (Hungarian) 2023-11-14 15:33:00 +01:00
Eugen Rochko
36bb8010bc New translations strings.xml (Swedish) 2023-11-14 13:43:32 +01:00
Eugen Rochko
2200da7a16 New translations strings.xml (Hungarian) 2023-11-14 13:43:31 +01:00
Grishka
688c0e2e85 Use sp units in more places
#723
2023-11-14 09:54:55 +03:00
Eugen Rochko
714345a65d New translations strings.xml (French) 2023-11-13 19:16:10 +01:00
Gregory K
34a1c7e408 Merge pull request #736 from alex-vit/alexv/fix/delete_account_shared_pref
Delete `id.xml` shared pref from the correct dir
2023-11-13 18:07:24 +03:00
Aleksandrs Vitjukovs
6255221d6a Delete id.xml shared pref from the correct dir 2023-11-13 16:54:10 +02:00
Eugen Rochko
58364de72a New translations strings.xml (Armenian) 2023-11-13 05:28:24 +01:00
Eugen Rochko
6d64df4ee4 New translations strings.xml (Turkish) 2023-11-11 15:16:48 +01:00
Gregory K
7bac2f206b Merge pull request #734 from FineFindus/feat/translate-media-upstream
Allow translation of attachments, spoilers and polls
2023-11-11 08:01:13 +03:00
FineFindus
75e1a17a2c fix: add args in correct order 2023-11-10 22:05:21 +01:00
FineFindus
47b13384a8 feat(status/translation): support translating spoiler 2023-11-10 22:04:07 +01:00
FineFindus
77b9efa7d1 feat(status/translation): support translating spoiler 2023-11-10 22:01:24 +01:00
FineFindus
be5f3b18af feat(status): translate poll options 2023-11-10 22:00:47 +01:00
FineFindus
d5d12a7ce5 fix(status/translation): do not require all fields 2023-11-10 22:00:47 +01:00
Eugen Rochko
d7726d7755 New translations strings.xml (Norwegian) 2023-11-10 21:26:30 +01:00
FineFindus
0cd0d37eff feat(status): translate media attachments 2023-11-10 21:07:24 +01:00
Eugen Rochko
4521def103 New translations strings.xml (Norwegian) 2023-11-10 20:08:28 +01:00
Eugen Rochko
5c70f0a758 New translations strings.xml (Arabic) 2023-11-09 23:12:18 +01:00
Eugen Rochko
c12c2c0416 New translations strings.xml (Arabic) 2023-11-09 22:09:22 +01:00
Eugen Rochko
db45c422e7 New translations strings.xml (Arabic) 2023-11-09 21:07:57 +01:00
Eugen Rochko
affd9a95c5 New translations strings.xml (Hungarian) 2023-11-09 15:25:20 +01:00
Gregory K
7baf25869a Merge pull request #732 from FineFindus/fix/invisible-menu
fix: disable group divider on EMUI
2023-11-08 22:35:22 +03:00
FineFindus
12096fb427 fix: disable group divider on EMUI 2023-11-08 20:25:25 +01:00
Gregory K
ef7136cb81 Merge pull request #731 from FineFindus/fix/edit-history-crash
fix: edit history crash
2023-11-08 22:00:48 +03:00
FineFindus
3c4baf0126 fix(status/edit-history): set fake poll fields 2023-11-08 19:45:49 +01:00
FineFindus
f0b87c62a5 fix(status/edit-history): check for negative array index 2023-11-08 19:36:24 +01:00
Eugen Rochko
a319435e91 New translations strings.xml (Belarusian) 2023-11-08 12:18:27 +00:00
Eugen Rochko
5bd0e988e3 New translations strings.xml (Belarusian) 2023-11-08 11:22:42 +00:00
Eugen Rochko
b2be669b9e New translations strings.xml (Belarusian) 2023-11-08 09:22:28 +00:00
Eugen Rochko
51952b0485 New translations strings.xml (Portuguese, Brazilian) 2023-11-05 10:47:44 +00:00
Eugen Rochko
2b0c5e7fac New translations strings.xml (Basque) 2023-11-04 19:16:42 +00:00
Eugen Rochko
3e6cea1a6a New translations strings.xml (Basque) 2023-11-04 17:29:35 +00:00
Eugen Rochko
1aec7c0999 New translations strings.xml (Russian) 2023-11-03 08:28:42 +00:00
Eugen Rochko
5da98809a5 New translations strings.xml (Russian) 2023-11-03 06:34:07 +00:00
Eugen Rochko
49695614b7 New translations strings.xml (Russian) 2023-11-03 05:25:21 +00:00
Eugen Rochko
3fbbc104b7 New translations strings.xml (Galician) 2023-11-02 08:42:01 +00:00
Eugen Rochko
2fe7c0b85e New translations strings.xml (Slovenian) 2023-11-02 00:28:09 +00:00
Grishka
09d0e82216 Fix video player state after app resumption 2023-11-02 02:21:11 +03:00
Eugen Rochko
d208fcea7d New translations strings.xml (Persian) 2023-11-01 21:16:18 +00:00
Eugen Rochko
cc0674db34 New translations strings.xml (Persian) 2023-11-01 20:07:40 +00:00
142 changed files with 2803 additions and 1311 deletions

View File

@@ -1 +1 @@
Decentralizált szociális hálózat
Decentralizált közösségi hálózat

View File

@@ -9,8 +9,8 @@ android {
applicationId "org.joinmastodon.android"
minSdk 23
targetSdk 33
versionCode 76
versionName "2.2.1"
versionCode 79
versionName "2.2.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resConfigs "ar-rSA", "be-rBY", "bn-rBD", "bs-rBA", "ca-rES", "cs-rCZ", "da-rDK", "de-rDE", "el-rGR", "es-rES", "eu-rES", "fa-rIR", "fi-rFI", "fil-rPH", "fr-rFR", "ga-rIE", "gd-rGB", "gl-rES", "hi-rIN", "hr-rHR", "hu-rHU", "hy-rAM", "ig-rNG", "in-rID", "is-rIS", "it-rIT", "iw-rIL", "ja-rJP", "kab", "ko-rKR", "my-rMM", "nl-rNL", "no-rNO", "oc-rFR", "pl-rPL", "pt-rBR", "pt-rPT", "ro-rRO", "ru-rRU", "si-rLK", "sl-rSI", "sv-rSE", "th-rTH", "tr-rTR", "uk-rUA", "ur-rIN", "vi-rVN", "zh-rCN", "zh-rTW"
}

View File

@@ -3,6 +3,9 @@ package org.joinmastodon.android;
import android.content.Context;
import android.content.SharedPreferences;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Account;
public class GlobalUserPreferences{
public static boolean playGifs;
public static boolean useCustomTabs;
@@ -13,6 +16,10 @@ public class GlobalUserPreferences{
return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE);
}
private static SharedPreferences getPreReplyPrefs(){
return MastodonApp.context.getSharedPreferences("pre_reply_sheets", Context.MODE_PRIVATE);
}
public static void load(){
SharedPreferences prefs=getPrefs();
playGifs=prefs.getBoolean("playGifs", true);
@@ -36,9 +43,42 @@ public class GlobalUserPreferences{
.apply();
}
public static boolean isOptedOutOfPreReplySheet(PreReplySheetType type, Account account, String accountID){
if(getPreReplyPrefs().getBoolean("opt_out_"+type, false))
return true;
if(account==null)
return false;
String accountKey=account.acct;
if(!accountKey.contains("@"))
accountKey+="@"+AccountSessionManager.get(accountID).domain;
return getPreReplyPrefs().getBoolean("opt_out_"+type+"_"+accountKey.toLowerCase(), false);
}
public static void optOutOfPreReplySheet(PreReplySheetType type, Account account, String accountID){
String key;
if(account==null){
key="opt_out_"+type;
}else{
String accountKey=account.acct;
if(!accountKey.contains("@"))
accountKey+="@"+AccountSessionManager.get(accountID).domain;
key="opt_out_"+type+"_"+accountKey.toLowerCase();
}
getPreReplyPrefs().edit().putBoolean(key, true).apply();
}
public static void resetPreReplySheets(){
getPreReplyPrefs().edit().clear().apply();
}
public enum ThemePreference{
AUTO,
LIGHT,
DARK
}
public enum PreReplySheetType{
OLD_POST,
NON_MUTUAL
}
}

View File

@@ -6,6 +6,7 @@ import android.app.Fragment;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.BadParcelableException;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
@@ -36,6 +37,8 @@ import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
public class MainActivity extends FragmentStackActivity{
private static final String TAG="MainActivity";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState){
UiUtils.setUserPreferredTheme(this);
@@ -193,8 +196,14 @@ public class MainActivity extends FragmentStackActivity{
fragment.setArguments(args);
showFragmentClearingBackStack(fragment);
if(intent.getBooleanExtra("fromNotification", false) && intent.hasExtra("notification")){
Notification notification=Parcels.unwrap(intent.getParcelableExtra("notification"));
showFragmentForNotification(notification, session.getID());
// Parcelables might not be compatible across app versions so this protects against possible crashes
// when a notification was received, then the app was updated, and then the user opened the notification
try{
Notification notification=Parcels.unwrap(intent.getParcelableExtra("notification"));
showFragmentForNotification(notification, session.getID());
}catch(BadParcelableException x){
Log.w(TAG, x);
}
}else if(intent.getBooleanExtra("compose", false)){
showCompose();
}else if(Intent.ACTION_VIEW.equals(intent.getAction())){

View File

@@ -22,6 +22,7 @@ public class UpdateAccountCredentials extends MastodonAPIRequest<Account>{
private Uri avatar, cover;
private File avatarFile, coverFile;
private List<AccountField> fields;
private Boolean discoverable, indexable;
public UpdateAccountCredentials(String displayName, String bio, Uri avatar, Uri cover, List<AccountField> fields){
super(HttpMethod.PATCH, "/accounts/update_credentials", Account.class);
@@ -41,6 +42,12 @@ public class UpdateAccountCredentials extends MastodonAPIRequest<Account>{
this.fields=fields;
}
public UpdateAccountCredentials setDiscoverableIndexable(boolean discoverable, boolean indexable){
this.discoverable=discoverable;
this.indexable=indexable;
return this;
}
@Override
public RequestBody getRequestBody() throws IOException{
MultipartBody.Builder bldr=new MultipartBody.Builder()
@@ -58,15 +65,21 @@ public class UpdateAccountCredentials extends MastodonAPIRequest<Account>{
}else if(coverFile!=null){
bldr.addFormDataPart("header", coverFile.getName(), new ResizedImageRequestBody(Uri.fromFile(coverFile), 1500*500, null));
}
if(fields.isEmpty()){
bldr.addFormDataPart("fields_attributes[0][name]", "").addFormDataPart("fields_attributes[0][value]", "");
}else{
int i=0;
for(AccountField field:fields){
bldr.addFormDataPart("fields_attributes["+i+"][name]", field.name).addFormDataPart("fields_attributes["+i+"][value]", field.value);
i++;
if(fields!=null){
if(fields.isEmpty()){
bldr.addFormDataPart("fields_attributes[0][name]", "").addFormDataPart("fields_attributes[0][value]", "");
}else{
int i=0;
for(AccountField field:fields){
bldr.addFormDataPart("fields_attributes["+i+"][name]", field.name).addFormDataPart("fields_attributes["+i+"][value]", field.value);
i++;
}
}
}
if(discoverable!=null)
bldr.addFormDataPart("discoverable", discoverable.toString());
if(indexable!=null)
bldr.addFormDataPart("indexable", indexable.toString());
return bldr.build();
}

View File

@@ -26,6 +26,11 @@ public class GetStatusEditHistory extends MastodonAPIRequest<List<Status>>{
s.visibility=StatusPrivacy.PUBLIC;
s.mentions=Collections.emptyList();
s.tags=Collections.emptyList();
if(s.poll!=null){
s.poll.id="fakeID"+i;
s.poll.emojis=Collections.emptyList();
s.poll.ownVotes=Collections.emptyList();
}
i++;
}
super.validateAndPostprocessResponse(respObj, httpResponse);

View File

@@ -181,7 +181,11 @@ public class AccountSessionManager{
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
MastodonApp.context.deleteSharedPreferences(id);
}else{
new File(MastodonApp.context.getDir("shared_prefs", Context.MODE_PRIVATE), id+".xml").delete();
String dataDir=MastodonApp.context.getApplicationInfo().dataDir;
if(dataDir!=null){
File prefsDir=new File(dataDir, "shared_prefs");
new File(prefsDir, id+".xml").delete();
}
}
sessions.remove(id);
if(lastActiveAccountID.equals(id)){

View File

@@ -14,10 +14,12 @@ import android.view.WindowInsets;
import android.widget.Toolbar;
import org.joinmastodon.android.E;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
import org.joinmastodon.android.api.requests.polls.SubmitPollVote;
import org.joinmastodon.android.api.requests.statuses.TranslateStatus;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.PollUpdatedEvent;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.DisplayItemsParent;
@@ -27,6 +29,8 @@ import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.Translation;
import org.joinmastodon.android.ui.BetterItemAnimator;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.NonMutualPreReplySheet;
import org.joinmastodon.android.ui.OldPostPreReplySheet;
import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
@@ -43,6 +47,8 @@ import org.joinmastodon.android.ui.utils.MediaAttachmentViewController;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.utils.TypedObjectPool;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -106,6 +112,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
for(T s:items){
displayItems.addAll(buildDisplayItems(s));
}
loadRelationships(items.stream().map(DisplayItemsParent::getAccountID).filter(Objects::nonNull).collect(Collectors.toSet()));
}
@Override
@@ -127,6 +134,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
if(notify)
adapter.notifyItemRangeInserted(0, offset);
loadRelationships(items.stream().map(DisplayItemsParent::getAccountID).filter(Objects::nonNull).collect(Collectors.toSet()));
}
protected String getMaxID(){
@@ -240,6 +248,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
@Override
public void photoViewerDismissed(){
currentPhotoViewer=null;
gridHolder.itemView.setHasTransientState(false);
}
@Override
@@ -251,6 +260,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
return gridHolder.getViewController(index);
}
});
gridHolder.itemView.setHasTransientState(true);
}
@Override
@@ -357,7 +367,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
List<StatusDisplayItem> pollItems=displayItems.subList(firstOptionIndex, footerIndex+1);
int prevSize=pollItems.size();
pollItems.clear();
StatusDisplayItem.buildPollItems(itemID, this, poll, pollItems);
StatusDisplayItem.buildPollItems(itemID, this, poll, status, pollItems);
if(prevSize!=pollItems.size()){
adapter.notifyItemRangeRemoved(firstOptionIndex, prevSize);
adapter.notifyItemRangeInserted(firstOptionIndex, pollItems.size());
@@ -455,6 +465,9 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
protected void loadRelationships(Set<String> ids){
if(ids.isEmpty())
return;
ids=ids.stream().filter(id->!relationships.containsKey(id)).collect(Collectors.toSet());
if(ids.isEmpty())
return;
// TODO somehow manage these and cancel outstanding requests on refresh
@@ -586,11 +599,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
return;
status.translation=result;
status.translationState=Status.TranslationState.SHOWN;
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
if(text!=null){
text.updateTranslation(true);
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
}
updateTranslation(itemID);
}
@Override
@@ -598,10 +607,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
if(getActivity()==null)
return;
status.translationState=Status.TranslationState.HIDDEN;
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
if(text!=null){
text.updateTranslation(true);
}
updateTranslation(itemID);
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.error)
.setMessage(R.string.translation_failed)
@@ -613,11 +619,31 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
}
}
updateTranslation(itemID);
}
private void updateTranslation(String itemID) {
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
if(text!=null){
text.updateTranslation(true);
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
}
SpoilerStatusDisplayItem.Holder spoiler=findHolderOfType(itemID, SpoilerStatusDisplayItem.Holder.class);
if(spoiler!=null){
spoiler.rebind();
}
MediaGridStatusDisplayItem.Holder media=findHolderOfType(itemID, MediaGridStatusDisplayItem.Holder.class);
if (media!=null) {
media.rebind();
}
for(int i=0;i<list.getChildCount();i++){
if(list.getChildViewHolder(list.getChildAt(i)) instanceof PollOptionStatusDisplayItem.Holder item){
item.rebind();
}
}
}
public void rebuildAllDisplayItems(){
@@ -628,6 +654,26 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
adapter.notifyDataSetChanged();
}
public void maybeShowPreReplySheet(Status status, Runnable proceed){
Relationship rel=getRelationship(status.account.id);
if(!GlobalUserPreferences.isOptedOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.NON_MUTUAL, status.account, accountID) &&
!status.account.id.equals(AccountSessionManager.get(accountID).self.id) && rel!=null && !rel.followedBy && status.account.followingCount>=1){
new NonMutualPreReplySheet(getActivity(), notAgain->{
GlobalUserPreferences.optOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.NON_MUTUAL, notAgain ? null : status.account, accountID);
proceed.run();
}, status.account).show();
}else if(!GlobalUserPreferences.isOptedOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.OLD_POST, null, null) &&
status.createdAt.isBefore(Instant.now().minus(90, ChronoUnit.DAYS))){
new OldPostPreReplySheet(getActivity(), notAgain->{
if(notAgain)
GlobalUserPreferences.optOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.OLD_POST, null, null);
proceed.run();
}, status).show();
}else{
proceed.run();
}
}
protected void onModifyItemViewHolder(BindableViewHolder<StatusDisplayItem> holder){}
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
@@ -700,7 +746,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
// Do not draw dividers between hashtag and/or account rows
if((ih instanceof HashtagStatusDisplayItem.Holder || ih instanceof AccountStatusDisplayItem.Holder) && (sh instanceof HashtagStatusDisplayItem.Holder || sh instanceof AccountStatusDisplayItem.Holder))
return false;
return (!ih.getItemID().equals(sh.getItemID()) || sh instanceof ExtendedFooterStatusDisplayItem.Holder) && ih.getItem().getType()!=StatusDisplayItem.Type.GAP;
return !ih.getItemID().equals(sh.getItemID()) && ih.getItem().getType()!=StatusDisplayItem.Type.GAP;
}
return false;
}

View File

@@ -1,5 +1,8 @@
package org.joinmastodon.android.fragments;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ClipData;
@@ -90,12 +93,14 @@ import java.util.stream.Collectors;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.CustomTransitionsFragment;
import me.grishka.appkit.fragments.OnBackPressedListener;
import me.grishka.appkit.imageloader.ViewImageLoader;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.CubicBezierInterpolator;
import me.grishka.appkit.utils.V;
public class ComposeFragment extends MastodonToolbarFragment implements OnBackPressedListener, ComposeEditText.SelectionListener{
public class ComposeFragment extends MastodonToolbarFragment implements OnBackPressedListener, ComposeEditText.SelectionListener, CustomTransitionsFragment{
private static final int MEDIA_RESULT=717;
public static final int IMAGE_DESCRIPTION_RESULT=363;
@@ -1124,4 +1129,35 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private void setPostLanguage(ComposeLanguageAlertViewController.SelectedOption language){
postLang=language;
}
@Override
public Animator onCreateEnterTransition(View prev, View container){
AnimatorSet anim=new AnimatorSet();
if(getArguments().getBoolean("fromThreadFragment")){
anim.playTogether(
ObjectAnimator.ofFloat(container, View.ALPHA, 0f, 1f),
ObjectAnimator.ofFloat(container, View.TRANSLATION_Y, V.dp(200), 0)
);
}else{
anim.playTogether(
ObjectAnimator.ofFloat(container, View.ALPHA, 0f, 1f),
ObjectAnimator.ofFloat(container, View.TRANSLATION_X, V.dp(100), 0)
);
}
anim.setDuration(300);
anim.setInterpolator(CubicBezierInterpolator.DEFAULT);
return anim;
}
@Override
public Animator onCreateExitTransition(View prev, View container){
AnimatorSet anim=new AnimatorSet();
anim.playTogether(
ObjectAnimator.ofFloat(container, View.TRANSLATION_X, V.dp(100)),
ObjectAnimator.ofFloat(container, View.ALPHA, 0)
);
anim.setDuration(200);
anim.setInterpolator(CubicBezierInterpolator.DEFAULT);
return anim;
}
}

View File

@@ -314,6 +314,8 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
}
private void markAsRead(){
if(data.isEmpty())
return;
String id=data.get(0).id;
if(ObjectIdComparator.INSTANCE.compare(id, realUnreadMarker)>0){
new SaveMarkers(null, id).exec(accountID);

View File

@@ -516,7 +516,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
// noinspection SetTextI18n
username.setText('@'+account.acct+(isSelf ? ('@'+AccountSessionManager.getInstance().getAccount(accountID).domain) : ""));
}
CharSequence parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
CharSequence parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID, account);
if(TextUtils.isEmpty(parsedBio)){
bio.setVisibility(View.GONE);
}else{
@@ -551,7 +551,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
fields.add(joined);
for(AccountField field:account.fields){
field.parsedValue=ssb=HtmlParser.parse(field.value, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
field.parsedValue=ssb=HtmlParser.parse(field.value, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID, account);
field.valueEmojis=ssb.getSpans(0, ssb.length(), CustomEmojiSpan.class);
ssb=new SpannableStringBuilder(field.name);
HtmlParser.parseCustomEmoji(ssb, account.emojis);

View File

@@ -2,19 +2,24 @@ package org.joinmastodon.android.fragments;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.statuses.GetStatusContext;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.StatusCreatedEvent;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.FilterContext;
import org.joinmastodon.android.model.LegacyFilter;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.StatusContext;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.SpoilerStatusDisplayItem;
@@ -26,10 +31,12 @@ import org.parceler.Parcels;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.imageloader.ViewImageLoader;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.MergeRecyclerAdapter;
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
import me.grishka.appkit.utils.V;
@@ -37,10 +44,16 @@ import me.grishka.appkit.utils.V;
public class ThreadFragment extends StatusListFragment{
private Status mainStatus;
private ImageView endMark;
private FrameLayout replyContainer;
private LinearLayout replyButton;
private ImageView replyButtonAva;
private TextView replyButtonText;
private int lastBottomInset;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setLayout(R.layout.fragment_thread);
mainStatus=Parcels.unwrap(getArguments().getParcelable("status"));
Account inReplyToAccount=Parcels.unwrap(getArguments().getParcelable("inReplyToAccount"));
if(inReplyToAccount!=null)
@@ -69,7 +82,7 @@ public class ThreadFragment extends StatusListFragment{
}
}
}
items.add(new ExtendedFooterStatusDisplayItem(s.id, this, s.getContentStatus()));
items.add(items.size()-1, new ExtendedFooterStatusDisplayItem(s.id, this, s.getContentStatus()));
}
return items;
}
@@ -126,6 +139,20 @@ public class ThreadFragment extends StatusListFragment{
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
replyContainer=view.findViewById(R.id.reply_button_wrapper);
replyButton=replyContainer.findViewById(R.id.reply_button);
replyButtonText=replyButton.findViewById(R.id.reply_btn_text);
replyButtonAva=replyButton.findViewById(R.id.avatar);
replyButton.setOutlineProvider(OutlineProviders.roundedRect(20));
replyButton.setClipToOutline(true);
replyButtonText.setText(getString(R.string.reply_to_user, mainStatus.account.displayName));
replyButtonAva.setOutlineProvider(OutlineProviders.OVAL);
replyButtonAva.setClipToOutline(true);
replyButton.setOnClickListener(v->openReply());
Account self=AccountSessionManager.get(accountID).self;
if(!TextUtils.isEmpty(self.avatar)){
ViewImageLoader.loadWithoutAnimation(replyButtonAva, getResources().getDrawable(R.drawable.image_placeholder), new UrlImageLoaderRequest(self.avatar, V.dp(24), V.dp(24)));
}
UiUtils.loadCustomEmojiInTextView(toolbarTitleView);
showContent();
if(!loaded)
@@ -175,4 +202,24 @@ public class ThreadFragment extends StatusListFragment{
}
super.onErrorRetryClick();
}
@Override
public void onApplyWindowInsets(WindowInsets insets){
lastBottomInset=insets.getSystemWindowInsetBottom();
super.onApplyWindowInsets(UiUtils.applyBottomInsetToFixedView(replyContainer, insets));
}
private void openReply(){
maybeShowPreReplySheet(mainStatus, ()->{
Bundle args=new Bundle();
args.putString("account", accountID);
args.putParcelable("replyTo", Parcels.wrap(mainStatus));
args.putBoolean("fromThreadFragment", true);
Nav.go(getActivity(), ComposeFragment.class, args);
});
}
public int getSnackbarOffset(){
return replyContainer.getHeight()-lastBottomInset;
}
}

View File

@@ -381,63 +381,6 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
onNextClick(v);
}
// private String getEmojiForCategory(String category){
// return switch(category){
// case "all" -> "💬";
// case "academia" -> "📚";
// case "activism" -> "✊";
// case "food" -> "🍕";
// case "furry" -> "🦁";
// case "games" -> "🕹";
// case "general" -> "🐘";
// case "journalism" -> "📰";
// case "lgbt" -> "🏳️‍🌈";
// case "regional" -> "📍";
// case "art" -> "🎨";
// case "music" -> "🎼";
// case "tech" -> "📱";
// default -> "❓";
// };
// }
private int getEmojiForCategory(String category){
return switch(category){
case "all" -> R.drawable.ic_category_all;
case "academia" -> R.drawable.ic_category_academia;
case "activism" -> R.drawable.ic_category_activism;
case "food" -> R.drawable.ic_category_food;
case "furry" -> R.drawable.ic_category_furry;
case "games" -> R.drawable.ic_category_games;
case "general" -> R.drawable.ic_category_general;
case "journalism" -> R.drawable.ic_category_journalism;
case "lgbt" -> R.drawable.ic_category_lgbt;
case "regional" -> R.drawable.ic_category_regional;
case "art" -> R.drawable.ic_category_art;
case "music" -> R.drawable.ic_category_music;
case "tech" -> R.drawable.ic_category_tech;
default -> R.drawable.ic_category_unknown;
};
}
private int getTitleForCategory(String category){
return switch(category){
case "all" -> R.string.category_all;
case "academia" -> R.string.category_academia;
case "activism" -> R.string.category_activism;
case "food" -> R.string.category_food;
case "furry" -> R.string.category_furry;
case "games" -> R.string.category_games;
case "general" -> R.string.category_general;
case "journalism" -> R.string.category_journalism;
case "lgbt" -> R.string.category_lgbt;
case "regional" -> R.string.category_regional;
case "art" -> R.string.category_art;
case "music" -> R.string.category_music;
case "tech" -> R.string.category_tech;
default -> 0;
};
}
@Override
protected void updateFilteredList(){
ArrayList<CatalogInstance> prevData=new ArrayList<>(filteredData);

View File

@@ -12,6 +12,7 @@ import android.view.WindowInsets;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import org.joinmastodon.android.R;
@@ -20,12 +21,17 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.HomeFragment;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.AccountField;
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.adapters.GenericListItemsAdapter;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.viewholders.ListItemViewHolder;
import org.joinmastodon.android.ui.views.ReorderableLinearLayout;
import org.joinmastodon.android.utils.ElevationOnScrollListener;
import java.util.ArrayList;
import java.util.List;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
@@ -36,7 +42,7 @@ import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
public class OnboardingProfileSetupFragment extends ToolbarFragment implements ReorderableLinearLayout.OnDragListener{
public class OnboardingProfileSetupFragment extends ToolbarFragment{
private Button btn;
private View buttonBar;
private String accountID;
@@ -44,9 +50,9 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
private ScrollView scroller;
private EditText nameEdit, bioEdit;
private ImageView avaImage, coverImage;
private Button addRow;
private ReorderableLinearLayout profileFieldsLayout;
private Uri avatarUri, coverUri;
private LinearLayout scrollContent;
private CheckableListItem<Void> discoverableItem;
private static final int AVATAR_RESULT=348;
private static final int COVER_RESULT=183;
@@ -74,8 +80,6 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
bioEdit=view.findViewById(R.id.bio);
avaImage=view.findViewById(R.id.avatar);
coverImage=view.findViewById(R.id.header);
addRow=view.findViewById(R.id.add_row);
profileFieldsLayout=view.findViewById(R.id.profile_fields);
btn=view.findViewById(R.id.btn_next);
btn.setOnClickListener(v->onButtonClick());
@@ -87,31 +91,20 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
Account account=AccountSessionManager.getInstance().getAccount(accountID).self;
if(savedInstanceState==null){
nameEdit.setText(account.displayName);
makeFieldsRow();
}else{
ArrayList<String> fieldTitles=savedInstanceState.getStringArrayList("fieldTitles");
ArrayList<String> fieldValues=savedInstanceState.getStringArrayList("fieldValues");
for(int i=0;i<fieldTitles.size();i++){
View row=makeFieldsRow();
EditText title=row.findViewById(R.id.title);
EditText content=row.findViewById(R.id.content);
title.setText(fieldTitles.get(i));
content.setText(fieldValues.get(i));
}
if(fieldTitles.size()==4)
addRow.setVisibility(View.GONE);
}
addRow.setOnClickListener(v->{
makeFieldsRow();
if(profileFieldsLayout.getChildCount()==4){
addRow.setVisibility(View.GONE);
}
});
profileFieldsLayout.setDragListener(this);
avaImage.setOnClickListener(v->startActivityForResult(UiUtils.getMediaPickerIntent(new String[]{"image/*"}, 1), AVATAR_RESULT));
coverImage.setOnClickListener(v->startActivityForResult(UiUtils.getMediaPickerIntent(new String[]{"image/*"}, 1), COVER_RESULT));
scrollContent=view.findViewById(R.id.scrollable_content);
discoverableItem=new CheckableListItem<>(R.string.make_profile_discoverable, 0, CheckableListItem.Style.SWITCH_SEPARATED, true, R.drawable.ic_campaign_24px, item->showDiscoverabilityAlert());
GenericListItemsAdapter<Void> fakeAdapter=new GenericListItemsAdapter<>(List.of(discoverableItem));
ListItemViewHolder<?> holder=fakeAdapter.onCreateViewHolder(scrollContent, fakeAdapter.getItemViewType(0));
fakeAdapter.bindViewHolder(holder, 0);
holder.itemView.setBackground(UiUtils.getThemeDrawable(getActivity(), android.R.attr.selectableItemBackground));
holder.itemView.setOnClickListener(v->holder.onClick());
scrollContent.addView(holder.itemView);
return view;
}
@@ -130,17 +123,8 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
}
protected void onButtonClick(){
ArrayList<AccountField> fields=new ArrayList<>();
for(int i=0;i<profileFieldsLayout.getChildCount();i++){
View row=profileFieldsLayout.getChildAt(i);
EditText title=row.findViewById(R.id.title);
EditText content=row.findViewById(R.id.content);
AccountField fld=new AccountField();
fld.name=title.getText().toString();
fld.value=content.getText().toString();
fields.add(fld);
}
new UpdateAccountCredentials(nameEdit.getText().toString(), bioEdit.getText().toString(), avatarUri, coverUri, fields)
new UpdateAccountCredentials(nameEdit.getText().toString(), bioEdit.getText().toString(), avatarUri, coverUri, null)
.setDiscoverableIndexable(discoverableItem.checked, discoverableItem.checked)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Account result){
@@ -164,39 +148,6 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
super.onApplyWindowInsets(UiUtils.applyBottomInsetToFixedView(buttonBar, insets));
}
private View makeFieldsRow(){
View view=LayoutInflater.from(getActivity()).inflate(R.layout.onboarding_profile_field, profileFieldsLayout, false);
profileFieldsLayout.addView(view);
view.findViewById(R.id.dragger_thingy).setOnLongClickListener(v->{
profileFieldsLayout.startDragging(view);
return true;
});
view.findViewById(R.id.delete).setOnClickListener(v->{
profileFieldsLayout.removeView(view);
if(addRow.getVisibility()==View.GONE)
addRow.setVisibility(View.VISIBLE);
});
return view;
}
@Override
public void onSwapItems(int oldIndex, int newIndex){}
@Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
ArrayList<String> fieldTitles=new ArrayList<>(), fieldValues=new ArrayList<>();
for(int i=0;i<profileFieldsLayout.getChildCount();i++){
View row=profileFieldsLayout.getChildAt(i);
EditText title=row.findViewById(R.id.title);
EditText content=row.findViewById(R.id.content);
fieldTitles.add(title.getText().toString());
fieldValues.add(content.getText().toString());
}
outState.putStringArrayList("fieldTitles", fieldTitles);
outState.putStringArrayList("fieldValues", fieldValues);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(resultCode!=Activity.RESULT_OK)
@@ -216,4 +167,12 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
img.setForeground(null);
ViewImageLoader.load(img, null, new UrlImageLoaderRequest(uri, size, size));
}
private void showDiscoverabilityAlert(){
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.discoverability)
.setMessage(R.string.discoverability_help)
.setPositiveButton(R.string.ok, null)
.show();
}
}

View File

@@ -1,18 +1,15 @@
package org.joinmastodon.android.fragments.onboarding;
import android.app.ProgressDialog;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.os.LocaleList;
import android.text.Editable;
import android.text.Html;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -46,10 +43,13 @@ import org.jsoup.select.NodeVisitor;
import org.parceler.Parcels;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import androidx.annotation.Nullable;
@@ -58,7 +58,6 @@ import me.grishka.appkit.api.APIRequest;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.ToolbarFragment;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
public class SignupFragment extends ToolbarFragment{
@@ -79,6 +78,7 @@ public class SignupFragment extends ToolbarFragment{
private ProgressDialog progressDialog;
private HashSet<EditText> errorFields=new HashSet<>();
private ElevationOnScrollListener onScrollListener;
private Set<String> serverSupportedTimezones, serverSupportedLocales;
@Override
public void onCreate(Bundle savedInstanceState){
@@ -87,6 +87,8 @@ public class SignupFragment extends ToolbarFragment{
instance=Parcels.unwrap(getArguments().getParcelable("instance"));
createAppAndGetToken();
setTitle(R.string.signup_title);
serverSupportedTimezones=Arrays.stream(getResources().getStringArray(R.array.server_supported_timezones)).collect(Collectors.toSet());
serverSupportedLocales=Arrays.stream(getResources().getStringArray(R.array.server_supported_locales)).collect(Collectors.toSet());
}
@Nullable
@@ -190,7 +192,34 @@ public class SignupFragment extends ToolbarFragment{
edit.setError(null);
}
errorFields.clear();
new RegisterAccount(username, email, password.getText().toString(), getResources().getConfiguration().locale.getLanguage(), reason.getText().toString(), ZoneId.systemDefault().getId())
String locale=null;
String timezone=ZoneId.systemDefault().getId();
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
LocaleList localeList=getResources().getConfiguration().getLocales();
for(int i=0;i<localeList.size();i++){
Locale l=localeList.get(i);
if(serverSupportedLocales.contains(l.toLanguageTag())){
locale=l.toLanguageTag();
break;
}else if(serverSupportedLocales.contains(l.getLanguage())){
locale=l.getLanguage();
break;
}
}
}else{
Locale l=getResources().getConfiguration().locale;
if(serverSupportedLocales.contains(l.toLanguageTag())){
locale=l.toLanguageTag();
}else if(serverSupportedLocales.contains(l.getLanguage())){
locale=l.getLanguage();
}
}
if(!serverSupportedTimezones.contains(timezone))
timezone=null;
new RegisterAccount(username, email, password.getText().toString(), locale, reason.getText().toString(), timezone)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Token result){
@@ -271,7 +300,7 @@ public class SignupFragment extends ToolbarFragment{
@Override
public void tail(Node node, int depth){
if(node instanceof Element){
ssb.setSpan(new LinkSpan("", SignupFragment.this::onGoBackLinkClick, LinkSpan.Type.CUSTOM, null, null), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new LinkSpan("", SignupFragment.this::onGoBackLinkClick, LinkSpan.Type.CUSTOM, null, null, null), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new TypefaceSpan("sans-serif-medium"), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}

View File

@@ -1,6 +1,9 @@
package org.joinmastodon.android.fragments.settings;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
import android.view.ViewGroup;
@@ -13,6 +16,7 @@ import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.Snackbar;
import org.joinmastodon.android.ui.utils.UiUtils;
import java.util.List;
@@ -57,6 +61,14 @@ public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
versionInfo.setTextColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Outline));
versionInfo.setGravity(Gravity.CENTER);
versionInfo.setText(getString(R.string.settings_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
versionInfo.setOnClickListener(v->{
getActivity().getSystemService(ClipboardManager.class).setPrimaryClip(ClipData.newPlainText("", BuildConfig.VERSION_NAME+" ("+BuildConfig.VERSION_CODE+")"));
if(Build.VERSION.SDK_INT<=Build.VERSION_CODES.S_V2){
new Snackbar.Builder(getActivity())
.setText(R.string.app_version_copied)
.show();
}
});
adapter.addAdapter(new SingleViewRecyclerAdapter(versionInfo));
return adapter;

View File

@@ -1,10 +1,9 @@
package org.joinmastodon.android.fragments.settings;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Toast;
import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.api.session.AccountActivationInfo;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
@@ -28,7 +27,8 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
new ListItem<>("Test email confirmation flow", null, this::onTestEmailConfirmClick),
selfUpdateItem=new ListItem<>("Force self-update", null, this::onForceSelfUpdateClick),
resetUpdateItem=new ListItem<>("Reset self-updater", null, this::onResetUpdaterClick),
new ListItem<>("Reset search info banners", null, this::onResetDiscoverBannersClick)
new ListItem<>("Reset search info banners", null, this::onResetDiscoverBannersClick),
new ListItem<>("Reset pre-reply sheets", null, this::onResetPreReplySheetsClick)
));
if(!GithubSelfUpdater.needSelfUpdating()){
resetUpdateItem.isEnabled=selfUpdateItem.isEnabled=false;
@@ -65,6 +65,11 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
restartUI();
}
private void onResetPreReplySheetsClick(ListItem<?> item){
GlobalUserPreferences.resetPreReplySheets();
Toast.makeText(getActivity(), "Pre-reply sheets were reset", Toast.LENGTH_SHORT).show();
}
private void restartUI(){
Bundle args=new Bundle();
args.putString("account", accountID);

View File

@@ -153,7 +153,7 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
}
private void onManageAccountsClick(ListItem<?> item){
new AccountSwitcherSheet(getActivity(), null).show();
new AccountSwitcherSheet(getActivity(), null).setOnLoggedOutCallback(()->loggedOut=true).show();
}
private void onLogOutClick(ListItem<?> item_){

View File

@@ -5,4 +5,8 @@ package org.joinmastodon.android.model;
*/
public interface DisplayItemsParent{
String getID();
default String getAccountID(){
return null;
}
}

View File

@@ -34,6 +34,11 @@ public class Notification extends BaseModel implements DisplayItemsParent{
return id;
}
@Override
public String getAccountID(){
return status!=null ? account.id : null;
}
public enum Type{
@SerializedName("follow")
FOLLOW,

View File

@@ -34,10 +34,18 @@ public class SearchResult extends BaseModel implements DisplayItemsParent{
generateID();
}
@Override
public String getID(){
return id;
}
@Override
public String getAccountID(){
if(type==Type.STATUS)
return status.getAccountID();
return null;
}
@Override
public void postprocess() throws ObjectValidationException{
super.postprocess();

View File

@@ -143,6 +143,11 @@ public class Status extends BaseModel implements DisplayItemsParent{
return id;
}
@Override
public String getAccountID(){
return getContentStatus().account.id;
}
public void update(StatusCountersUpdatedEvent ev){
favouritesCount=ev.favorites;
reblogsCount=ev.reblogs;

View File

@@ -1,10 +1,30 @@
package org.joinmastodon.android.model;
import org.joinmastodon.android.api.AllFieldsAreRequired;
@AllFieldsAreRequired
import org.joinmastodon.android.api.RequiredField;
public class Translation extends BaseModel{
@RequiredField
public String content;
@RequiredField
public String detectedSourceLanguage;
@RequiredField
public String provider;
public String spoilerText;
public MediaAttachment[] mediaAttachments;
public PollTranslation poll;
public static class MediaAttachment {
public String id;
public String description;
}
public static class PollTranslation {
public String id;
public PollOption[] options;
}
public static class PollOption {
public String title;
}
}

View File

@@ -30,7 +30,7 @@ public class AccountViewModel{
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
else
parsedName=account.displayName;
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID, account);
SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName);
ssb.append(parsedBio);
emojiHelper.setText(ssb);

View File

@@ -55,6 +55,7 @@ public class CheckableListItem<T> extends ListItem<T>{
case CHECKBOX -> R.id.list_item_checkbox;
case RADIO -> R.id.list_item_radio;
case SWITCH -> R.id.list_item_switch;
case SWITCH_SEPARATED -> R.id.list_item_switch_separated;
};
}
@@ -69,6 +70,7 @@ public class CheckableListItem<T> extends ListItem<T>{
public enum Style{
CHECKBOX,
RADIO,
SWITCH
SWITCH,
SWITCH_SEPARATED
}
}

View File

@@ -60,6 +60,7 @@ public class AccountSwitcherSheet extends BottomSheet{
private UsableRecyclerView list;
private List<WrappedAccount> accounts;
private ListImageLoaderWrapper imgLoader;
private Runnable onLoggedOutCallback;
public AccountSwitcherSheet(@NonNull Activity activity, @Nullable HomeFragment fragment){
super(activity);
@@ -95,6 +96,11 @@ public class AccountSwitcherSheet extends BottomSheet{
UiUtils.getThemeColor(activity, R.attr.colorM3Primary), 0.05f)), !UiUtils.isDarkTheme());
}
public AccountSwitcherSheet setOnLoggedOutCallback(Runnable onLoggedOutCallback){
this.onLoggedOutCallback=onLoggedOutCallback;
return this;
}
private void confirmLogOut(String accountID){
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
new M3AlertDialogBuilder(activity)
@@ -113,7 +119,10 @@ public class AccountSwitcherSheet extends BottomSheet{
}
private void logOut(String accountID){
String activeAccount=AccountSessionManager.getInstance().getLastActiveAccountID();
AccountSessionManager.get(accountID).logOut(activity, ()->{
if(accountID.equals(activeAccount) && onLoggedOutCallback!=null)
onLoggedOutCallback.run();
dismiss();
((MainActivity)activity).restartHomeFragment();
});
@@ -133,6 +142,8 @@ public class AccountSwitcherSheet extends BottomSheet{
AccountSessionManager.getInstance().removeAccount(session.getID());
sessions.remove(session);
if(sessions.isEmpty()){
if(onLoggedOutCallback!=null)
onLoggedOutCallback.run();
progress.dismiss();
Nav.goClearingStack(activity, SplashFragment.class, null);
dismiss();
@@ -144,6 +155,8 @@ public class AccountSwitcherSheet extends BottomSheet{
AccountSessionManager.getInstance().removeAccount(session.getID());
sessions.remove(session);
if(sessions.isEmpty()){
if(onLoggedOutCallback!=null)
onLoggedOutCallback.run();
progress.dismiss();
Nav.goClearingStack(activity, SplashFragment.class, null);
dismiss();

View File

@@ -0,0 +1,122 @@
package org.joinmastodon.android.ui;
import android.annotation.SuppressLint;
import android.content.Context;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.UiUtils;
import androidx.annotation.NonNull;
import me.grishka.appkit.imageloader.ViewImageLoader;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.V;
public class NonMutualPreReplySheet extends PreReplySheet{
private boolean fullBioShown=false;
@SuppressLint("DefaultLocale")
public NonMutualPreReplySheet(@NonNull Context context, ResultListener resultListener, Account account){
super(context, resultListener);
icon.setImageResource(R.drawable.ic_waving_hand_24px);
title.setText(R.string.non_mutual_sheet_title);
text.setText(R.string.non_mutual_sheet_text);
LinearLayout userInfo=new LinearLayout(context);
userInfo.setOrientation(LinearLayout.HORIZONTAL);
userInfo.setBackgroundResource(R.drawable.bg_user_info);
UiUtils.setAllPaddings(userInfo, 12);
ImageView ava=new ImageView(context);
ava.setScaleType(ImageView.ScaleType.CENTER_CROP);
ava.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
ava.setOutlineProvider(OutlineProviders.roundedRect(12));
ava.setClipToOutline(true);
ava.setForeground(context.getResources().getDrawable(R.drawable.fg_user_info_ava, context.getTheme()));
userInfo.addView(ava, UiUtils.makeLayoutParams(56, 56, 0, 0, 12, 0));
ViewImageLoader.loadWithoutAnimation(ava, context.getResources().getDrawable(R.drawable.image_placeholder), new UrlImageLoaderRequest(account.avatarStatic, V.dp(56), V.dp(56)));
LinearLayout nameAndFields=new LinearLayout(context);
nameAndFields.setOrientation(LinearLayout.VERTICAL);
nameAndFields.setMinimumHeight(V.dp(56));
nameAndFields.setGravity(Gravity.CENTER_VERTICAL);
userInfo.addView(nameAndFields, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
TextView name=new TextView(context);
name.setSingleLine();
name.setEllipsize(TextUtils.TruncateAt.END);
name.setTextAppearance(R.style.m3_title_medium);
name.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3OnSurface));
name.setText(account.displayName);
name.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
nameAndFields.addView(name, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(24)));
if(!TextUtils.isEmpty(account.note)){
String strippedBio=HtmlParser.stripAndRemoveInvisibleSpans(account.note);
TextView bioShort=new TextView(context);
bioShort.setTextAppearance(R.style.m3_body_medium);
bioShort.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3Secondary));
bioShort.setMaxLines(2);
bioShort.setEllipsize(TextUtils.TruncateAt.END);
bioShort.setText(strippedBio);
nameAndFields.addView(bioShort, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
TextView bioFull=new TextView(context);
bioFull.setTextAppearance(R.style.m3_body_medium);
bioFull.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3Secondary));
bioFull.setText(strippedBio);
bioFull.setVisibility(View.GONE);
nameAndFields.addView(bioFull, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
nameAndFields.setOnClickListener(v->{
UiUtils.beginLayoutTransition((ViewGroup) getWindow().getDecorView());
fullBioShown=!fullBioShown;
if(fullBioShown){
bioFull.setVisibility(View.VISIBLE);
bioShort.setVisibility(View.GONE);
}else{
bioFull.setVisibility(View.GONE);
bioShort.setVisibility(View.VISIBLE);
}
});
}else{
TextView username=new TextView(context);
username.setTextAppearance(R.style.m3_body_medium);
username.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3Secondary));
username.setSingleLine();
username.setEllipsize(TextUtils.TruncateAt.END);
username.setText(account.getDisplayUsername());
username.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
nameAndFields.addView(username, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(20)));
}
contentWrap.addView(userInfo, UiUtils.makeLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0, 0, 8));
for(int i=0;i<3;i++){
View item=context.getSystemService(LayoutInflater.class).inflate(R.layout.item_other_numbered_rule, contentWrap, false);
TextView number=item.findViewById(R.id.number);
number.setText(String.format("%d", i+1));
TextView title=item.findViewById(R.id.title);
TextView text=item.findViewById(R.id.text);
title.setText(switch(i){
case 0 -> R.string.non_mutual_title1;
case 1 -> R.string.non_mutual_title2;
case 2 -> R.string.non_mutual_title3;
default -> throw new IllegalStateException("Unexpected value: "+i);
});
text.setText(switch(i){
case 0 -> R.string.non_mutual_text1;
case 1 -> R.string.non_mutual_text2;
case 2 -> R.string.non_mutual_text3;
default -> throw new IllegalStateException("Unexpected value: "+i);
});
contentWrap.addView(item);
}
}
}

View File

@@ -0,0 +1,23 @@
package org.joinmastodon.android.ui;
import android.content.Context;
import org.joinmastodon.android.R;
import org.joinmastodon.android.model.Status;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import androidx.annotation.NonNull;
public class OldPostPreReplySheet extends PreReplySheet{
public OldPostPreReplySheet(@NonNull Context context, ResultListener resultListener, Status status){
super(context, resultListener);
int months=(int)status.createdAt.atZone(ZoneId.systemDefault()).until(ZonedDateTime.now(), ChronoUnit.MONTHS);
String monthsStr=months>24 ? context.getString(R.string.more_than_two_years) : context.getResources().getQuantityString(R.plurals.x_months, months, months);
title.setText(context.getString(R.string.old_post_sheet_title, monthsStr));
text.setText(R.string.old_post_sheet_text);
icon.setImageResource(R.drawable.ic_history_24px);
}
}

View File

@@ -0,0 +1,54 @@
package org.joinmastodon.android.ui;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.ui.utils.UiUtils;
import androidx.annotation.NonNull;
import me.grishka.appkit.views.BottomSheet;
public abstract class PreReplySheet extends BottomSheet{
protected ImageView icon;
protected TextView title, text;
protected Button gotItButton, dontRemindButton;
protected LinearLayout contentWrap;
public PreReplySheet(@NonNull Context context, ResultListener resultListener){
super(context);
View content=context.getSystemService(LayoutInflater.class).inflate(R.layout.sheet_pre_reply, null);
setContentView(content);
setNavigationBarBackground(new ColorDrawable(UiUtils.alphaBlendColors(UiUtils.getThemeColor(context, R.attr.colorM3Surface),
UiUtils.getThemeColor(context, R.attr.colorM3Primary), 0.05f)), !UiUtils.isDarkTheme());
icon=findViewById(R.id.icon);
title=findViewById(R.id.title);
text=findViewById(R.id.text);
gotItButton=findViewById(R.id.btn_got_it);
dontRemindButton=findViewById(R.id.btn_dont_remind_again);
contentWrap=findViewById(R.id.content_wrap);
gotItButton.setOnClickListener(v->{
dismiss();
resultListener.onButtonClicked(false);
});
dontRemindButton.setOnClickListener(v->{
dismiss();
resultListener.onButtonClicked(true);
});
}
@FunctionalInterface
public interface ResultListener{
void onButtonClicked(boolean notAgain);
}
}

View File

@@ -0,0 +1,217 @@
package org.joinmastodon.android.ui;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Outline;
import android.graphics.PixelFormat;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.ui.utils.UiUtils;
import androidx.annotation.Keep;
import androidx.annotation.StringRes;
import me.grishka.appkit.utils.CubicBezierInterpolator;
import me.grishka.appkit.utils.V;
public class Snackbar{
private static Snackbar current;
private final Context context;
private int bottomOffset;
private FrameLayout windowView;
private LinearLayout contentView;
private boolean hasAction;
private AnimatableOutlineProvider outlineProvider;
private Animator currentAnim;
private Runnable dismissRunnable=this::dismiss;
private Snackbar(Context context, String text, String action, Runnable onActionClick, int bottomOffset){
this.context=context;
this.bottomOffset=bottomOffset;
hasAction=onActionClick!=null;
windowView=new FrameLayout(context);
windowView.setClipToPadding(false);
contentView=new LinearLayout(context);
contentView.setOrientation(LinearLayout.HORIZONTAL);
contentView.setBaselineAligned(false);
contentView.setBackgroundColor(UiUtils.getThemeColor(context, R.attr.colorM3SurfaceInverse));
contentView.setOutlineProvider(outlineProvider=new AnimatableOutlineProvider(contentView));
contentView.setClipToOutline(true);
contentView.setElevation(V.dp(6));
contentView.setPaddingRelative(V.dp(16), 0, V.dp(8), 0);
FrameLayout.LayoutParams lp=new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.leftMargin=lp.topMargin=lp.rightMargin=lp.bottomMargin=V.dp(16);
windowView.addView(contentView, lp);
TextView textView=new TextView(context);
textView.setTextAppearance(R.style.m3_body_medium);
textView.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3OnSurfaceInverse));
textView.setMaxLines(2);
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setText(text);
textView.setMinHeight(V.dp(48));
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
textView.setPadding(0, V.dp(14), 0, V.dp(14));
contentView.addView(textView, new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
if(action!=null){
Button button=new Button(context);
int primaryInverse=UiUtils.getThemeColor(context, R.attr.colorM3PrimaryInverse);
button.setTextColor(primaryInverse);
button.setBackgroundResource(R.drawable.bg_rect_4dp_ripple);
button.setBackgroundTintList(ColorStateList.valueOf(primaryInverse));
button.setText(action);
button.setPadding(V.dp(8), 0, V.dp(8), 0);
button.setOnClickListener(v->onActionClick.run());
LinearLayout.LayoutParams blp=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, V.dp(40));
blp.leftMargin=blp.topMargin=blp.rightMargin=blp.bottomMargin=V.dp(4);
contentView.addView(button, blp);
}
}
public void show(){
if(current!=null)
current.dismiss();
current=this;
WindowManager.LayoutParams lp=new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, PixelFormat.TRANSLUCENT);
lp.width=ViewGroup.LayoutParams.MATCH_PARENT;
lp.height=ViewGroup.LayoutParams.WRAP_CONTENT;
lp.gravity=Gravity.BOTTOM;
lp.y=bottomOffset;
WindowManager wm=context.getSystemService(WindowManager.class);
wm.addView(windowView, lp);
windowView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
@Override
public boolean onPreDraw(){
windowView.getViewTreeObserver().removeOnPreDrawListener(this);
AnimatorSet set=new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(outlineProvider, "fraction", 0, 1),
ObjectAnimator.ofFloat(contentView, View.ALPHA, 0, 1)
);
set.setInterpolator(AnimationUtils.loadInterpolator(context, R.interpolator.m3_sys_motion_easing_standard_decelerate));
set.setDuration(350);
set.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
currentAnim=null;
}
});
currentAnim=set;
set.start();
return true;
}
});
windowView.postDelayed(dismissRunnable, 4000);
}
public void dismiss(){
current=null;
if(currentAnim!=null){
currentAnim.cancel();
}
windowView.removeCallbacks(dismissRunnable);
ObjectAnimator anim=ObjectAnimator.ofFloat(contentView, View.ALPHA, 0);
anim.setInterpolator(CubicBezierInterpolator.DEFAULT);
anim.setDuration(200);
anim.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
WindowManager wm=context.getSystemService(WindowManager.class);
wm.removeView(windowView);
}
});
anim.start();
}
private static class AnimatableOutlineProvider extends ViewOutlineProvider{
private float fraction=1f;
private final View view;
private AnimatableOutlineProvider(View view){
this.view=view;
}
@Override
public void getOutline(View view, Outline outline){
outline.setRoundRect(0, Math.round(view.getHeight()*(1f-fraction)), view.getWidth(), view.getHeight(), V.dp(4));
}
@Keep
public float getFraction(){
return fraction;
}
@Keep
public void setFraction(float fraction){
this.fraction=fraction;
view.invalidateOutline();
}
}
public static class Builder{
private final Context context;
private String text;
private String action;
private Runnable onActionClick;
private int bottomOffset;
public Builder(Context context){
this.context=context;
}
public Builder setText(String text){
this.text=text;
return this;
}
public Builder setText(@StringRes int res){
text=context.getString(res);
return this;
}
public Builder setAction(String action, Runnable onActionClick){
this.action=action;
this.onActionClick=onActionClick;
return this;
}
public Builder setAction(@StringRes int action, Runnable onActionClick){
this.action=context.getString(action);
this.onActionClick=onActionClick;
return this;
}
public Builder setBottomOffset(int offset){
bottomOffset=offset;
return this;
}
public Snackbar create(){
return new Snackbar(context, text, action, onActionClick, bottomOffset);
}
public void show(){
create().show();
}
}
}

View File

@@ -39,8 +39,8 @@ public class GenericListItemsAdapter<T> extends UsableRecyclerView.Adapter<ListI
public ListItemViewHolder<?> onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
if(viewType==R.id.list_item_simple || viewType==R.id.list_item_simple_tinted)
return new SimpleListItemViewHolder(parent.getContext(), parent);
if(viewType==R.id.list_item_switch)
return new SwitchListItemViewHolder(parent.getContext(), parent);
if(viewType==R.id.list_item_switch || viewType==R.id.list_item_switch_separated)
return new SwitchListItemViewHolder(parent.getContext(), parent, viewType==R.id.list_item_switch_separated);
if(viewType==R.id.list_item_checkbox)
return new CheckboxOrRadioListItemViewHolder(parent.getContext(), parent, false);
if(viewType==R.id.list_item_radio)

View File

@@ -2,37 +2,49 @@ package org.joinmastodon.android.ui.displayitems;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.fragments.StatusEditHistoryFragment;
import org.joinmastodon.android.fragments.ThreadFragment;
import org.joinmastodon.android.fragments.account_list.StatusFavoritesListFragment;
import org.joinmastodon.android.fragments.account_list.StatusReblogsListFragment;
import org.joinmastodon.android.fragments.account_list.StatusRelatedAccountListFragment;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.Snackbar;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.parceler.Parcels;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;
import androidx.annotation.PluralsRes;
import androidx.annotation.StringRes;
import me.grishka.appkit.Nav;
import me.grishka.appkit.utils.V;
public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
public final Status status;
private static final DateTimeFormatter TIME_FORMATTER=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT);
private static final DateTimeFormatter TIME_FORMATTER=DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
private static final DateTimeFormatter TIME_FORMATTER_LONG=DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);
private static final DateTimeFormatter DATE_FORMATTER=DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
public ExtendedFooterStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status){
super(parentID, parentFragment);
@@ -45,7 +57,7 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
}
public static class Holder extends StatusDisplayItem.Holder<ExtendedFooterStatusDisplayItem>{
private final TextView time;
private final TextView time, date, app, dateAppSeparator;
private final TextView favorites, reblogs, editHistory;
public Holder(Context context, ViewGroup parent){
@@ -53,30 +65,46 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
reblogs=findViewById(R.id.reblogs);
favorites=findViewById(R.id.favorites);
editHistory=findViewById(R.id.edit_history);
time=findViewById(R.id.timestamp);
time=findViewById(R.id.time);
date=findViewById(R.id.date);
app=findViewById(R.id.app_name);
dateAppSeparator=findViewById(R.id.date_app_separator);
reblogs.setOnClickListener(v->startAccountListFragment(StatusReblogsListFragment.class));
favorites.setOnClickListener(v->startAccountListFragment(StatusFavoritesListFragment.class));
editHistory.setOnClickListener(v->startEditHistoryFragment());
time.setOnClickListener(v->showTimeSnackbar());
app.setOnClickListener(v->UiUtils.launchWebBrowser(context, item.status.application.website));
}
@SuppressLint("DefaultLocale")
@Override
public void onBind(ExtendedFooterStatusDisplayItem item){
Status s=item.status;
favorites.setText(itemView.getResources().getQuantityString(R.plurals.x_favorites, (int)item.status.favouritesCount, item.status.favouritesCount));
reblogs.setText(itemView.getResources().getQuantityString(R.plurals.x_reblogs, (int)item.status.reblogsCount, item.status.reblogsCount));
favorites.setText(getFormattedPlural(R.plurals.x_favorites, item.status.favouritesCount));
reblogs.setText(getFormattedPlural(R.plurals.x_reblogs, item.status.reblogsCount));
if(s.editedAt!=null){
editHistory.setVisibility(View.VISIBLE);
editHistory.setText(item.parentFragment.getString(R.string.last_edit_at_x, UiUtils.formatRelativeTimestampAsMinutesAgo(itemView.getContext(), s.editedAt, false)));
ZonedDateTime dt=s.editedAt.atZone(ZoneId.systemDefault());
String time=TIME_FORMATTER.format(dt);
if(!dt.toLocalDate().equals(LocalDate.now())){
time+=" · "+DATE_FORMATTER.format(dt);
}
editHistory.setText(getFormattedSubstitutedString(R.string.last_edit_at_x, time));
}else{
editHistory.setVisibility(View.GONE);
}
String timeStr=TIME_FORMATTER.format(item.status.createdAt.atZone(ZoneId.systemDefault()));
ZonedDateTime dt=item.status.createdAt.atZone(ZoneId.systemDefault());
time.setText(TIME_FORMATTER.format(dt));
date.setText(DATE_FORMATTER.format(dt));
if(item.status.application!=null && !TextUtils.isEmpty(item.status.application.name)){
time.setText(item.parentFragment.getString(R.string.timestamp_via_app, timeStr, item.status.application.name));
app.setVisibility(View.VISIBLE);
dateAppSeparator.setVisibility(View.VISIBLE);
app.setText(item.status.application.name);
app.setEnabled(!TextUtils.isEmpty(item.status.application.website));
}else{
time.setText(timeStr);
app.setVisibility(View.GONE);
dateAppSeparator.setVisibility(View.GONE);
}
}
@@ -85,14 +113,39 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
return false;
}
private SpannableStringBuilder getFormattedPlural(@PluralsRes int res, int quantity){
String str=item.parentFragment.getResources().getQuantityString(res, quantity, quantity);
private SpannableStringBuilder getFormattedPlural(@PluralsRes int res, long quantity){
String str=item.parentFragment.getResources().getQuantityString(res, (int)quantity, quantity);
String formattedNumber=String.format(Locale.getDefault(), "%,d", quantity);
int index=str.indexOf(formattedNumber);
SpannableStringBuilder ssb=new SpannableStringBuilder(str);
if(index>=0){
ssb.setSpan(new TypefaceSpan("sans-serif-medium"), index, index+formattedNumber.length(), 0);
ssb.setSpan(new ForegroundColorSpan(UiUtils.getThemeColor(item.parentFragment.getActivity(), android.R.attr.textColorPrimary)), index, index+formattedNumber.length(), 0);
ForegroundColorSpan colorSpan=new ForegroundColorSpan(UiUtils.getThemeColor(itemView.getContext(), R.attr.colorM3OnSurfaceVariant));
ssb.setSpan(colorSpan, index, index+formattedNumber.length(), 0);
Object typefaceSpan;
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.S){
typefaceSpan=new TypefaceSpan(Typeface.create(Typeface.DEFAULT, 600, false));
}else{
typefaceSpan=new StyleSpan(Typeface.BOLD);
}
ssb.setSpan(typefaceSpan, index, index+formattedNumber.length(), 0);
}
return ssb;
}
private SpannableStringBuilder getFormattedSubstitutedString(@StringRes int res, String substitution){
String str=item.parentFragment.getString(res, substitution);
int index=item.parentFragment.getString(res).indexOf("%s");
SpannableStringBuilder ssb=new SpannableStringBuilder(str);
if(index>=0){
ForegroundColorSpan colorSpan=new ForegroundColorSpan(UiUtils.getThemeColor(itemView.getContext(), R.attr.colorM3OnSurfaceVariant));
ssb.setSpan(colorSpan, index, index+substitution.length(), 0);
Object typefaceSpan;
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.S){
typefaceSpan=new TypefaceSpan(Typeface.create(Typeface.DEFAULT, 600, false));
}else{
typefaceSpan=new StyleSpan(Typeface.BOLD);
}
ssb.setSpan(typefaceSpan, index, index+substitution.length(), 0);
}
return ssb;
}
@@ -110,5 +163,16 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
args.putString("id", item.status.id);
Nav.go(item.parentFragment.getActivity(), StatusEditHistoryFragment.class, args);
}
private void showTimeSnackbar(){
int bottomOffset=0;
if(item.parentFragment instanceof ThreadFragment tf){
bottomOffset=tf.getSnackbarOffset();
}
new Snackbar.Builder(itemView.getContext())
.setText(itemView.getContext().getString(R.string.posted_at, TIME_FORMATTER_LONG.format(item.status.createdAt.atZone(ZoneId.systemDefault()))))
.setBottomOffset(bottomOffset)
.show();
}
}
}

View File

@@ -1,12 +1,11 @@
package org.joinmastodon.android.ui.displayitems;
import android.app.Activity;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -25,10 +24,7 @@ import org.joinmastodon.android.model.StatusPrivacy;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.parceler.Parcels;
import java.text.DecimalFormat;
import me.grishka.appkit.Nav;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.V;
public class FooterStatusDisplayItem extends StatusDisplayItem{
@@ -51,6 +47,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
private final TextView reply, boost, favorite;
private final ImageView share;
private final ColorStateList buttonColors;
private final View replyBtn, boostBtn, favoriteBtn, shareBtn;
private final View.AccessibilityDelegate buttonAccessibilityDelegate=new View.AccessibilityDelegate(){
@Override
@@ -93,18 +90,18 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
UiUtils.fixCompoundDrawableTintOnAndroid6(boost);
UiUtils.fixCompoundDrawableTintOnAndroid6(favorite);
}
View reply=findViewById(R.id.reply_btn);
View boost=findViewById(R.id.boost_btn);
View favorite=findViewById(R.id.favorite_btn);
View share=findViewById(R.id.share_btn);
reply.setOnClickListener(this::onReplyClick);
reply.setAccessibilityDelegate(buttonAccessibilityDelegate);
boost.setOnClickListener(this::onBoostClick);
boost.setAccessibilityDelegate(buttonAccessibilityDelegate);
favorite.setOnClickListener(this::onFavoriteClick);
favorite.setAccessibilityDelegate(buttonAccessibilityDelegate);
share.setOnClickListener(this::onShareClick);
share.setAccessibilityDelegate(buttonAccessibilityDelegate);
replyBtn=findViewById(R.id.reply_btn);
boostBtn=findViewById(R.id.boost_btn);
favoriteBtn=findViewById(R.id.favorite_btn);
shareBtn=findViewById(R.id.share_btn);
replyBtn.setOnClickListener(this::onReplyClick);
replyBtn.setAccessibilityDelegate(buttonAccessibilityDelegate);
boostBtn.setOnClickListener(this::onBoostClick);
boostBtn.setAccessibilityDelegate(buttonAccessibilityDelegate);
favoriteBtn.setOnClickListener(this::onFavoriteClick);
favoriteBtn.setAccessibilityDelegate(buttonAccessibilityDelegate);
shareBtn.setOnClickListener(this::onShareClick);
shareBtn.setAccessibilityDelegate(buttonAccessibilityDelegate);
}
@Override
@@ -112,10 +109,18 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
bindButton(reply, item.status.repliesCount);
bindButton(boost, item.status.reblogsCount);
bindButton(favorite, item.status.favouritesCount);
boost.setSelected(item.status.reblogged);
favorite.setSelected(item.status.favourited);
boost.setEnabled(item.status.visibility==StatusPrivacy.PUBLIC || item.status.visibility==StatusPrivacy.UNLISTED
|| (item.status.visibility==StatusPrivacy.PRIVATE && item.status.account.id.equals(AccountSessionManager.getInstance().getAccount(item.accountID).self.id)));
boostBtn.setSelected(item.status.reblogged);
favoriteBtn.setSelected(item.status.favourited);
boolean isOwn=item.status.account.id.equals(AccountSessionManager.getInstance().getAccount(item.accountID).self.id);
boostBtn.setEnabled(item.status.visibility==StatusPrivacy.PUBLIC || item.status.visibility==StatusPrivacy.UNLISTED
|| (item.status.visibility==StatusPrivacy.PRIVATE && isOwn));
Drawable d=itemView.getResources().getDrawable(switch(item.status.visibility){
case PUBLIC, UNLISTED -> R.drawable.ic_boost;
case PRIVATE -> isOwn ? R.drawable.ic_boost_private : R.drawable.ic_boost_disabled_24px;
case DIRECT -> R.drawable.ic_boost_disabled_24px;
}, itemView.getContext().getTheme());
d.setBounds(0, 0, V.dp(20), V.dp(20));
boost.setCompoundDrawablesRelative(d, null, null, null);
}
private void bindButton(TextView btn, long count){
@@ -129,10 +134,12 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
}
private void onReplyClick(View v){
Bundle args=new Bundle();
args.putString("account", item.accountID);
args.putParcelable("replyTo", Parcels.wrap(item.status));
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
item.parentFragment.maybeShowPreReplySheet(item.status, ()->{
Bundle args=new Bundle();
args.putString("account", item.accountID);
args.putParcelable("replyTo", Parcels.wrap(item.status));
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
});
}
private void onBoostClick(View v){

View File

@@ -115,8 +115,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
private final TextView name, timeAndUsername, extraText;
private final ImageView avatar, more;
private final PopupMenu optionsMenu;
private Relationship relationship;
private APIRequest<?> currentRelationshipRequest;
public Holder(Activity activity, ViewGroup parent){
this(activity, R.layout.display_item_header, parent);
@@ -136,10 +134,11 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
optionsMenu=new PopupMenu(activity, more);
optionsMenu.inflate(R.menu.post);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.P)
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.P && !UiUtils.isEMUI())
optionsMenu.getMenu().setGroupDividerEnabled(true);
optionsMenu.setOnMenuItemClickListener(menuItem->{
Account account=item.user;
Relationship relationship=item.parentFragment.getRelationship(account.id);
int id=menuItem.getItemId();
if(id==R.id.edit){
final Bundle args=new Bundle();
@@ -192,7 +191,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
else
progress.dismiss();
}, rel->{
relationship=rel;
item.parentFragment.putRelationship(account.id, rel);
Toast.makeText(activity, activity.getString(rel.following ? R.string.followed_user : rel.requested ? R.string.following_user_requested : R.string.unfollowed_user, account.getDisplayUsername()), Toast.LENGTH_SHORT).show();
});
}else if(id==R.id.bookmark){
@@ -235,10 +234,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
more.setVisibility(item.inset ? View.GONE : View.VISIBLE);
avatar.setClickable(!item.inset);
avatar.setContentDescription(item.parentFragment.getString(R.string.avatar_description, item.user.acct));
if(currentRelationshipRequest!=null){
currentRelationshipRequest.cancel();
}
relationship=null;
}
@Override
@@ -272,31 +267,13 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
private void onMoreClick(View v){
updateOptionsMenu();
optionsMenu.show();
if(relationship==null && currentRelationshipRequest==null){
currentRelationshipRequest=new GetAccountRelationships(Collections.singletonList(item.user.id))
.setCallback(new Callback<>(){
@Override
public void onSuccess(List<Relationship> result){
if(!result.isEmpty()){
relationship=result.get(0);
updateOptionsMenu();
}
currentRelationshipRequest=null;
}
@Override
public void onError(ErrorResponse error){
currentRelationshipRequest=null;
}
})
.exec(item.parentFragment.getAccountID());
}
}
private void updateOptionsMenu(){
if(item.parentFragment.getActivity()==null)
return;
Account account=item.user;
Relationship relationship=item.parentFragment.getRelationship(account.id);
Menu menu=optionsMenu.getMenu();
boolean isOwnPost=AccountSessionManager.getInstance().isSelf(item.parentFragment.getAccountID(), account);
boolean canTranslate=item.status!=null && item.status.getContentStatus().isEligibleForTranslation();

View File

@@ -102,7 +102,7 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
}
private void onClick(View v){
UiUtils.openURL(itemView.getContext(), item.parentFragment.getAccountID(), item.status.card.url);
UiUtils.openURL(itemView.getContext(), item.parentFragment.getAccountID(), item.status.card.url, item.status);
}
}
}

View File

@@ -9,6 +9,7 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.text.TextUtils;
import android.util.Pair;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -21,6 +22,8 @@ import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.Translation;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.drawables.SpoilerStripesDrawable;
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
@@ -31,7 +34,12 @@ import org.joinmastodon.android.ui.views.MediaGridLayout;
import org.joinmastodon.android.utils.TypedObjectPool;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
@@ -45,6 +53,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
private final PhotoLayoutHelper.TiledLayoutResult tiledLayout;
private final TypedObjectPool<GridItemType, MediaAttachmentViewController> viewPool;
private final List<Attachment> attachments;
private final Map<String, Pair<String, String>> translatedAttachments = new HashMap<>();
private final ArrayList<ImageLoaderRequest> requests=new ArrayList<>();
public final Status status;
public boolean sensitiveRevealed;
@@ -181,6 +190,25 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
c.altButton.setAlpha(1f);
}
controllers.add(c);
if (item.status.translation != null){
if(item.status.translationState==Status.TranslationState.SHOWN){
if(!item.translatedAttachments.containsKey(att.id)){
Optional<Translation.MediaAttachment> translatedAttachment=Arrays.stream(item.status.translation.mediaAttachments).filter(mediaAttachment->mediaAttachment.id.equals(att.id)).findFirst();
translatedAttachment.ifPresent(mediaAttachment->{
item.translatedAttachments.put(mediaAttachment.id, new Pair<>(att.description, mediaAttachment.description));
att.description=mediaAttachment.description;
});
}else{
//SAFETY: must be non-null, as we check if the map contains the attachment before
att.description=Objects.requireNonNull(item.translatedAttachments.get(att.id)).second;
}
}else{
if (item.translatedAttachments.containsKey(att.id)) {
att.description=Objects.requireNonNull(item.translatedAttachments.get(att.id)).first;
}
}
}
c.bind(att, item.status);
i++;
}

View File

@@ -10,6 +10,7 @@ import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Poll;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
@@ -22,6 +23,7 @@ import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
public class PollOptionStatusDisplayItem extends StatusDisplayItem{
private CharSequence text;
private CharSequence translatedText;
public final Poll.Option option;
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
private boolean showResults;
@@ -29,12 +31,15 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
private boolean isMostVoted;
private final int optionIndex;
public final Poll poll;
public final Status status;
public PollOptionStatusDisplayItem(String parentID, Poll poll, int optionIndex, BaseStatusListFragment parentFragment){
public PollOptionStatusDisplayItem(String parentID, Poll poll, int optionIndex, BaseStatusListFragment parentFragment, Status status){
super(parentID, parentFragment);
this.optionIndex=optionIndex;
option=poll.options.get(optionIndex);
this.poll=poll;
this.status=status;
text=HtmlParser.parseCustomEmoji(option.title, poll.emojis);
emojiHelper.setText(text);
showResults=poll.isExpired() || poll.voted;
@@ -83,7 +88,14 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
@Override
public void onBind(PollOptionStatusDisplayItem item){
text.setText(item.text);
if (item.status.translation != null && item.status.translationState == Status.TranslationState.SHOWN) {
if(item.translatedText==null){
item.translatedText=item.status.translation.poll.options[item.optionIndex].title;
}
text.setText(item.translatedText);
} else {
text.setText(item.text);
}
percent.setVisibility(item.showResults ? View.VISIBLE : View.GONE);
itemView.setClickable(!item.showResults);
if(item.showResults){

View File

@@ -26,6 +26,7 @@ public class SpoilerStatusDisplayItem extends StatusDisplayItem{
public final Status status;
public final ArrayList<StatusDisplayItem> contentItems=new ArrayList<>();
private final CharSequence parsedTitle;
private CharSequence translatedTitle;
private final CustomEmojiHelper emojiHelper;
private final Type type;
@@ -85,7 +86,14 @@ public class SpoilerStatusDisplayItem extends StatusDisplayItem{
@Override
public void onBind(SpoilerStatusDisplayItem item){
title.setText(item.parsedTitle);
if(item.status.translationState==Status.TranslationState.SHOWN){
if(item.translatedTitle==null){
item.translatedTitle=item.status.translation.spoilerText;
}
title.setText(item.translatedTitle);
}else{
title.setText(item.parsedTitle);
}
action.setText(item.status.spoilerRevealed ? R.string.spoiler_hide : R.string.spoiler_show);
}

View File

@@ -135,7 +135,7 @@ public abstract class StatusDisplayItem{
}
if(!TextUtils.isEmpty(statusForContent.content)){
SpannableStringBuilder parsedText=HtmlParser.parse(statusForContent.content, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, accountID);
SpannableStringBuilder parsedText=HtmlParser.parse(statusForContent.content, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, accountID, statusForContent);
if(filtered){
HtmlParser.applyFilterHighlights(fragment.getActivity(), parsedText, status.filtered);
}
@@ -162,7 +162,7 @@ public abstract class StatusDisplayItem{
}
}
if(statusForContent.poll!=null){
buildPollItems(parentID, fragment, statusForContent.poll, contentItems);
buildPollItems(parentID, fragment, statusForContent.poll, status, contentItems);
}
if(statusForContent.card!=null && statusForContent.mediaAttachments.isEmpty() && TextUtils.isEmpty(statusForContent.spoilerText)){
contentItems.add(new LinkCardStatusDisplayItem(parentID, fragment, statusForContent));
@@ -192,10 +192,10 @@ public abstract class StatusDisplayItem{
return items;
}
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, List<StatusDisplayItem> items){
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, Status status, List<StatusDisplayItem> items){
int i=0;
for(Poll.Option opt:poll.options){
items.add(new PollOptionStatusDisplayItem(parentID, poll, i, fragment));
items.add(new PollOptionStatusDisplayItem(parentID, poll, i, fragment, status));
i++;
}
items.add(new PollFooterStatusDisplayItem(parentID, fragment, poll));

View File

@@ -59,7 +59,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
public void setTranslatedText(String text){
Status statusForContent=status.getContentStatus();
translatedText=HtmlParser.parse(text, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, parentFragment.getAccountID());
translatedText=HtmlParser.parse(text, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, parentFragment.getAccountID(), statusForContent);
translationEmojiHelper.setText(translatedText);
}

View File

@@ -13,6 +13,7 @@ import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
@@ -533,23 +534,31 @@ public class PhotoViewer implements ZoomPanView.Listener{
}
}
private MediaPlayer findCurrentVideoPlayer(){
private GifVViewHolder findCurrentVideoPlayerHolder(){
RecyclerView rv=(RecyclerView) pager.getChildAt(0);
if(rv.findViewHolderForAdapterPosition(pager.getCurrentItem()) instanceof GifVViewHolder vvh && vvh.playerReady){
return vvh.player;
return vvh;
}
return null;
}
private MediaPlayer findCurrentVideoPlayer(){
GifVViewHolder holder=findCurrentVideoPlayerHolder();
return holder!=null ? holder.player : null;
}
private void pauseVideo(){
MediaPlayer player=findCurrentVideoPlayer();
if(player==null || !player.isPlaying())
GifVViewHolder holder=findCurrentVideoPlayerHolder();
if(holder==null || !holder.player.isPlaying())
return;
player.pause();
holder.player.pause();
videoPlayPauseButton.setImageResource(R.drawable.ic_play_24);
videoPlayPauseButton.setContentDescription(activity.getString(R.string.play));
stopUpdatingVideoPosition();
windowView.removeCallbacks(uiAutoHider);
// Some MediaPlayer implementations clear the texture when the app goes into background.
// This makes sure the frame on which the video was paused is retained on the screen.
holder.wrap.setBackground(new BitmapDrawable(holder.textureView.getBitmap()));
}
private void resumeVideo(){
@@ -817,7 +826,10 @@ public class PhotoViewer implements ZoomPanView.Listener{
@Override
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface){
// A new frame of video was rendered. Clear the thumbnail or paused frame, if any, to avoid overdraw and free up some memory.
if(player.isPlaying() && wrap.getBackground()!=null){
wrap.setBackground(null);
}
}
private void startPlayer(){

View File

@@ -68,7 +68,7 @@ public class HtmlParser{
* @param emojis Custom emojis that are present in source as <code>:code:</code>
* @return a spanned string
*/
public static SpannableStringBuilder parse(String source, List<Emoji> emojis, List<Mention> mentions, List<Hashtag> tags, String accountID){
public static SpannableStringBuilder parse(String source, List<Emoji> emojis, List<Mention> mentions, List<Hashtag> tags, String accountID, Object parentObject){
class SpanInfo{
public Object span;
public int start;
@@ -120,7 +120,7 @@ public class HtmlParser{
}else{
linkType=LinkSpan.Type.URL;
}
openSpans.add(new SpanInfo(new LinkSpan(href, null, linkType, accountID, linkObject), ssb.length(), el));
openSpans.add(new SpanInfo(new LinkSpan(href, null, linkType, accountID, linkObject, parentObject), ssb.length(), el));
}
case "br" -> ssb.append('\n');
case "span" -> {
@@ -203,8 +203,28 @@ public class HtmlParser{
public static String stripAndRemoveInvisibleSpans(String html){
Document doc=Jsoup.parseBodyFragment(html);
doc.body().select("span.invisible").remove();
Cleaner cleaner=new Cleaner(Safelist.none());
return cleaner.clean(doc).body().html();
Cleaner cleaner=new Cleaner(Safelist.none().addTags("br", "p"));
StringBuilder sb=new StringBuilder();
cleaner.clean(doc).body().traverse(new NodeVisitor(){
@Override
public void head(Node node, int depth){
if(node instanceof TextNode tn){
sb.append(tn.text());
}else if(node instanceof Element el){
if("br".equals(el.tagName())){
sb.append('\n');
}
}
}
@Override
public void tail(Node node, int depth){
if(node instanceof Element el && "p".equals(el.tagName()) && el.nextSibling()!=null){
sb.append("\n\n");
}
}
});
return sb.toString();
}
public static CharSequence parseLinks(String text){
@@ -216,7 +236,7 @@ public class HtmlParser{
String url=matcher.group(3);
if(TextUtils.isEmpty(matcher.group(4)))
url="http://"+url;
ssb.setSpan(new LinkSpan(url, null, LinkSpan.Type.URL, null, null), matcher.start(3), matcher.end(3), 0);
ssb.setSpan(new LinkSpan(url, null, LinkSpan.Type.URL, null, null, null), matcher.start(3), matcher.end(3), 0);
}while(matcher.find()); // Find more URLs
return ssb;
}

View File

@@ -15,13 +15,15 @@ public class LinkSpan extends CharacterStyle {
private Type type;
private String accountID;
private Object linkObject;
private Object parentObject;
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, Object linkObject){
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, Object linkObject, Object parentObject){
this.listener=listener;
this.link=link;
this.type=type;
this.accountID=accountID;
this.linkObject=linkObject;
this.parentObject=parentObject;
}
public int getColor(){
@@ -36,7 +38,7 @@ public class LinkSpan extends CharacterStyle {
public void onClick(Context context){
switch(getType()){
case URL -> UiUtils.openURL(context, accountID, link);
case URL -> UiUtils.openURL(context, accountID, link, parentObject);
case MENTION -> UiUtils.openProfileByID(context, accountID, link);
case HASHTAG -> {
if(linkObject instanceof Hashtag ht)

View File

@@ -93,7 +93,7 @@ public class InsetStatusItemDecoration extends RecyclerView.ItemDecoration{
outRect.left=outRect.right=V.dp(8);
if(!bottomSiblingInset)
outRect.bottom=V.dp(16);
if(!topSiblingInset && displayItems.get(pos-1) instanceof NotificationHeaderStatusDisplayItem)
if(!topSiblingInset && pos > 1 && displayItems.get(pos-1) instanceof NotificationHeaderStatusDisplayItem)
outRect.top=V.dp(-8);
}
}

View File

@@ -83,6 +83,7 @@ import java.time.format.FormatStyle;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -616,9 +617,15 @@ public class UiUtils{
return GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.DARK;
}
public static void openURL(Context context, String accountID, String url){
public static void openURL(Context context, String accountID, String url, Object parentObject){
String objectURL=null;
if(parentObject instanceof Status s){
objectURL=s.url;
}else if(parentObject instanceof Account a){
objectURL=a.url;
}
Uri uri=Uri.parse(url);
if(accountID!=null && "https".equals(uri.getScheme())){
if(accountID!=null && "https".equals(uri.getScheme()) && !Objects.equals(url, objectURL)){
List<String> path=uri.getPathSegments();
if(AccountSessionManager.getInstance().getAccount(accountID).domain.equalsIgnoreCase(uri.getAuthority()) && path.size()==2 && path.get(0).matches("^@[a-zA-Z0-9_]+$") && path.get(1).matches("^[0-9]+$")){
// Match URLs like https://mastodon.social/@Gargron/108132679274083591
@@ -649,10 +656,20 @@ public class UiUtils{
Bundle args=new Bundle();
args.putString("account", accountID);
if(result.statuses!=null && !result.statuses.isEmpty()){
args.putParcelable("status", Parcels.wrap(result.statuses.get(0)));
Status s=result.statuses.get(0);
if(parentObject instanceof Status status && s.id.equals(status.id)){
launchWebBrowser(context, url);
return;
}
args.putParcelable("status", Parcels.wrap(s));
Nav.go((Activity)context, ThreadFragment.class, args);
}else if(result.accounts!=null && !result.accounts.isEmpty()){
args.putParcelable("profileAccount", Parcels.wrap(result.accounts.get(0)));
Account a=result.accounts.get(0);
if(parentObject instanceof Account account && a.id.equals(account.id)){
launchWebBrowser(context, url);
return;
}
args.putParcelable("profileAccount", Parcels.wrap(a));
Nav.go((Activity)context, ProfileFragment.class, args);
}else{
launchWebBrowser(context, url);
@@ -685,6 +702,10 @@ public class UiUtils{
return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.code"));
}
public static boolean isEMUI() {
return !TextUtils.isEmpty(getSystemProperty("ro.build.version.emui"));
}
public static int alphaBlendColors(int color1, int color2, float alpha){
float alpha0=1f-alpha;
int r=Math.round(((color1 >> 16) & 0xFF)*alpha0+((color2 >> 16) & 0xFF)*alpha);
@@ -831,4 +852,18 @@ public class UiUtils{
Toast.makeText(context, R.string.text_copied, Toast.LENGTH_SHORT).show();
}
}
public static void setAllPaddings(View view, int paddingDp){
int pad=V.dp(paddingDp);
view.setPadding(pad, pad, pad, pad);
}
public static ViewGroup.MarginLayoutParams makeLayoutParams(int width, int height, int marginStart, int marginTop, int marginEnd, int marginBottom){
ViewGroup.MarginLayoutParams lp=new ViewGroup.MarginLayoutParams(width>0 ? V.dp(width) : width, height>0 ? V.dp(height) : height);
lp.topMargin=V.dp(marginTop);
lp.bottomMargin=V.dp(marginBottom);
lp.setMarginStart(V.dp(marginStart));
lp.setMarginEnd(V.dp(marginEnd));
return lp;
}
}

View File

@@ -181,6 +181,8 @@ public class ToolbarDropdownMenuController{
public void resizeOnNextFrame(){
if(currentTransition!=null)
currentTransition.cancel();
if(windowView==null)
return;
int origBottom=menuContainer.getBottom();
menuContainer.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
@Override

View File

@@ -2,10 +2,13 @@ package org.joinmastodon.android.ui.viewholders;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import org.joinmastodon.android.R;
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.M3Switch;
import me.grishka.appkit.utils.V;
@@ -14,8 +17,17 @@ public class SwitchListItemViewHolder extends CheckableListItemViewHolder{
private final M3Switch sw;
private boolean ignoreListener;
public SwitchListItemViewHolder(Context context, ViewGroup parent){
public SwitchListItemViewHolder(Context context, ViewGroup parent, boolean separated){
super(context, parent);
if(separated){
View separator=new View(context);
separator.setBackgroundColor(UiUtils.getThemeColor(context, R.attr.colorM3OutlineVariant));
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(V.dp(1), V.dp(32));
lp.gravity=Gravity.TOP;
lp.setMarginStart(V.dp(16));
lp.setMarginEnd(V.dp(-1));
checkableLayout.addView(separator, lp);
}
sw=new M3Switch(context);
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(V.dp(52), V.dp(32));
lp.gravity=Gravity.TOP;

View File

@@ -173,6 +173,7 @@ public class ReorderableLinearLayout extends LinearLayout implements CustomViewH
else
bottomSibling=null;
dragListener.onSwapItems(prevIndex, index);
final View draggedView=this.draggedView;
draggedView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
@Override
public boolean onPreDraw(){

View File

@@ -0,0 +1,128 @@
package org.joinmastodon.android.ui.views;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import org.joinmastodon.android.R;
import java.util.ArrayList;
/**
* Something like a horizontal LinearLayout, but wraps child views onto a new line if they don't fit
*/
public class WrappingLinearLayout extends ViewGroup{
private int verticalGap, horizontalGap;
private ArrayList<Integer> rowHeights=new ArrayList<>();
public WrappingLinearLayout(Context context){
this(context, null);
}
public WrappingLinearLayout(Context context, AttributeSet attrs){
this(context, attrs, 0);
}
public WrappingLinearLayout(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.WrappingLinearLayout);
verticalGap=ta.getDimensionPixelOffset(R.styleable.WrappingLinearLayout_android_verticalGap, 0);
horizontalGap=ta.getDimensionPixelOffset(R.styleable.WrappingLinearLayout_android_horizontalGap, 0);
ta.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int w=MeasureSpec.getSize(widthMeasureSpec)-getPaddingLeft()-getPaddingRight();
int heightUsed=0, widthRemain=w, currentRowHeight=0;
rowHeights.clear();
for(int i=0;i<getChildCount();i++){
View child=getChildAt(i);
if(child.getVisibility()==GONE)
continue;
LayoutParams lp=child.getLayoutParams();
int horizontalPadding=getPaddingLeft()+getPaddingRight();
int verticalPadding=getPaddingTop()+getPaddingBottom();
int horizontalMargins=0, verticalMargins=0;
if(lp instanceof MarginLayoutParams mlp){
horizontalPadding+=mlp.leftMargin+mlp.rightMargin;
verticalPadding+=mlp.topMargin+mlp.bottomMargin;
horizontalMargins=mlp.leftMargin+mlp.rightMargin;
verticalMargins=mlp.topMargin+mlp.bottomMargin;
}
child.measure(getChildMeasureSpec(widthMeasureSpec, horizontalPadding, lp.width), getChildMeasureSpec(heightMeasureSpec, verticalPadding, lp.height));
currentRowHeight=Math.max(child.getMeasuredHeight()+verticalMargins, currentRowHeight);
if(child.getMeasuredWidth()+(widthRemain<w ? horizontalGap : 0)+horizontalMargins>widthRemain){
// Doesn't fit into the current row. Start a new one.
heightUsed+=currentRowHeight+verticalGap;
rowHeights.add(currentRowHeight);
currentRowHeight=child.getMeasuredHeight()+verticalMargins;
widthRemain=w;
}else{
// Does fit. Advance horizontally.
if(widthRemain<w)
widthRemain-=horizontalGap;
widthRemain-=child.getMeasuredWidth()+horizontalMargins;
}
}
// Take last row into account
heightUsed+=currentRowHeight;
rowHeights.add(currentRowHeight);
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), heightUsed+getPaddingTop()+getPaddingBottom());
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b){
if(rowHeights.isEmpty())
return;
boolean rtl=getLayoutDirection()==LAYOUT_DIRECTION_RTL;
int xOffset=rtl ? getPaddingRight() : getPaddingLeft();
int endPadding=rtl ? getPaddingLeft() : getPaddingRight();
int yOffset=getPaddingTop();
int w=getWidth()-getPaddingLeft()-getPaddingRight();
int currentRowIndex=0;
boolean firstInRow=true;
for(int i=0;i<getChildCount();i++){
View child=getChildAt(i);
if(child.getVisibility()==GONE)
continue;
int childW=child.getMeasuredWidth();
int childH=child.getMeasuredHeight();
int rowHeight=rowHeights.get(currentRowIndex);
int childY, childX=xOffset;
if(getWidth()-(xOffset+childW+(firstInRow ? 0 : horizontalGap))>=endPadding){
xOffset+=childW+horizontalGap;
if(child.getLayoutParams() instanceof MarginLayoutParams mlp){
xOffset+=mlp.leftMargin+mlp.rightMargin;
}
firstInRow=false;
}else if(currentRowIndex<rowHeights.size()-1){
xOffset=rtl ? getPaddingRight() : getPaddingLeft();
yOffset+=rowHeight+verticalGap;
currentRowIndex++;
childX=xOffset;
rowHeight=rowHeights.get(currentRowIndex);
}
if(childH<rowHeight){
childY=yOffset+rowHeight/2-childH/2;
}else{
childY=yOffset;
}
if(rtl){
childX=getWidth()-childX-childW;
}
if(child.getLayoutParams() instanceof MarginLayoutParams mlp){
childX+=rtl ? mlp.rightMargin : mlp.leftMargin;
childY+=mlp.topMargin;
}
child.layout(childX, childY, childX+childW, childY+childH);
}
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs){
return new MarginLayoutParams(getContext(), attrs);
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/m3_on_surface_overlay">
<item android:id="@android:id/mask">
<shape>
<solid android:color="#000"/>
</shape>
</item>
</ripple>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="12dp"/>
<solid android:color="?colorM3SurfaceVariant"/>
<stroke android:color="?colorM3OutlineVariant" android:width="1dp"/>
</shape>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:left="16dp" android:right="16dp">
<shape>
<solid android:color="?colorM3OutlineVariant"/>
<size android:height="0.5dp"/>
</shape>
</item>
</layer-list>

View File

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

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/ic_boost_fill_alt_24px"/>
<item android:drawable="@drawable/ic_boost_24px"/>
</selector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M7,22L3,18L7,14L8.4,15.45L6.85,17H17V13H19V19H6.85L8.4,20.55L7,22ZM5,11V5H17.15L15.6,3.45L17,2L21,6L17,10L15.6,8.55L17.15,7H7V11H5Z"
android:fillColor="#000000"/>
</vector>

View File

@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M19,13V17.879L17,15.879V13H19Z"
android:fillColor="#000000"/>
<path
android:pathData="M2.414,2.707L1,4.121L5,8.121V11H7V10.121L13.879,17H6.85L8.4,15.45L7,14L3,18L7,22L8.4,20.55L6.85,19H15.879L19.385,22.506L20.799,21.092L2.414,2.707Z"
android:fillColor="#000000"/>
<path
android:pathData="M17.15,7H8.121L6.121,5H17.15L15.6,3.45L17,2L21,6L17,10L15.6,8.55L17.15,7Z"
android:fillColor="#000000"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M6.775,22.875L2.15,18.25L6.775,13.625L8.8,15.7L7.675,16.8H16.95V12.8H19.85V19.7H7.675L8.8,20.8L6.775,22.875ZM4.15,11.45V4.55H16.35L15.225,3.45L17.25,1.375L21.875,6L17.25,10.625L15.225,8.55L16.35,7.45H7.05V11.45H4.15Z"
android:fillColor="#000000"/>
</vector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/ic_private_boost_fill_alt_24px"/>
<item android:drawable="@drawable/ic_private_boost_24px"/>
</selector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M18,13V11H22V13ZM19.2,20 L16,17.6 17.2,16 20.4,18.4ZM17.2,8 L16,6.4 19.2,4 20.4,5.6ZM5,19V15H4Q3.175,15 2.588,14.412Q2,13.825 2,13V11Q2,10.175 2.588,9.587Q3.175,9 4,9H8L13,6V18L8,15H7V19ZM14,15.35V8.65Q14.675,9.25 15.088,10.113Q15.5,10.975 15.5,12Q15.5,13.025 15.088,13.887Q14.675,14.75 14,15.35ZM4,11Q4,11 4,11Q4,11 4,11V13Q4,13 4,13Q4,13 4,13H8.55L11,14.45V9.55L8.55,11ZM7.5,12Q7.5,12 7.5,12Q7.5,12 7.5,12Q7.5,12 7.5,12Q7.5,12 7.5,12Z"/>
</vector>

View File

@@ -1,42 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M15,31c0,2.209 -0.791,4 -3,4H5c-4,0 -4,-14 0,-14h7c2.209,0 3,1.791 3,4v6z"
android:fillColor="#553788"/>
<path
android:pathData="M34,33h-1V23h1c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1H10c-4,0 -4,14 0,14h24c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1z"
android:fillColor="#9266CC"/>
<path
android:pathData="M34.172,33H11c-2,0 -2,-10 0,-10h23.172c1.104,0 1.104,10 0,10z"
android:fillColor="#CCD6DD"/>
<path
android:pathData="M11.5,25h23.35c-0.135,-1.175 -0.36,-2 -0.678,-2H11c-1.651,0 -1.938,6.808 -0.863,9.188C9.745,29.229 10.199,25 11.5,25z"
android:fillColor="#99AAB5"/>
<path
android:pathData="M12,8c0,2.209 -1.791,4 -4,4H4C0,12 0,1 4,1h4c2.209,0 4,1.791 4,4v3z"
android:fillColor="#269"/>
<path
android:pathData="M31,10h-1V3h1c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1H7C3,1 3,12 7,12h24c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1z"
android:fillColor="#55ACEE"/>
<path
android:pathData="M31.172,10H8c-2,0 -2,-7 0,-7h23.172c1.104,0 1.104,7 0,7z"
android:fillColor="#CCD6DD"/>
<path
android:pathData="M8,5h23.925c-0.114,-1.125 -0.364,-2 -0.753,-2H8C6.807,3 6.331,5.489 6.562,7.5 6.718,6.142 7.193,5 8,5z"
android:fillColor="#99AAB5"/>
<path
android:pathData="M20,17c0,2.209 -1.791,4 -4,4H6c-4,0 -4,-9 0,-9h10c2.209,0 4,1.791 4,4v1z"
android:fillColor="#F4900C"/>
<path
android:pathData="M35,19h-1v-5h1c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1H15c-4,0 -4,9 0,9h20c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1z"
android:fillColor="#FFAC33"/>
<path
android:pathData="M35.172,19H16c-2,0 -2,-5 0,-5h19.172c1.104,0 1.104,5 0,5z"
android:fillColor="#CCD6DD"/>
<path
android:pathData="M16,16h19.984c-0.065,-1.062 -0.334,-2 -0.812,-2H16c-1.274,0 -1.733,2.027 -1.383,3.5 0.198,-0.839 0.657,-1.5 1.383,-1.5z"
android:fillColor="#99AAB5"/>
</vector>

View File

@@ -1,15 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M32.218,10.913c-0.81,-1.187 -2.172,-1.967 -3.718,-1.967H28s-5.353,-5.672 -5.15,-6.091C21.754,3.446 21,4.591 21,5.924c0,0 -5.509,-3.431 -5.247,-3.947C14.71,2.669 14,3.946 14,5.424v0.522S8.553,4.321 8.857,3.851C7.757,4.441 7,5.588 7,6.924V8.81l-6,6.272v2.645l17.16,14.439c0,0.001 13.128,-22.164 14.058,-21.253z"
android:fillColor="#EF9645"/>
<path
android:pathData="M4.124,18.946c1.474,0 2.738,-0.831 3.392,-2.043 0.678,1.212 1.958,2.043 3.446,2.043h0.076c1.153,0 2.169,-0.51 2.889,-1.298 0.023,-0.024 0.073,-0.082 0.073,-0.082 0.185,-0.212 0.343,-0.448 0.481,-0.695 0.04,-0.072 0.281,-0.621 0.342,-0.833 0.052,-0.173 0.106,-0.344 0.134,-0.526 0.141,0.167 0.296,0.319 0.46,0.46 0.069,0.059 0.45,0.339 0.576,0.413 0.589,0.351 1.271,0.56 2.008,0.56h3.166c-0.535,0.27 -0.999,0.614 -1.424,1 -1.729,1.568 -2.579,4.085 -2.579,7.663 0,0.276 0.224,0.5 0.5,0.5s0.5,-0.224 0.5,-0.5c0,-3.962 1.01,-6.427 3.24,-7.663 1.175,-0.651 2.682,-0.967 4.571,-0.967 0.059,0 0.526,-0.033 0.526,-0.033 0.276,0 0.5,-0.224 0.5,-0.5s-0.224,-0.5 -0.5,-0.5H18c-1.657,0 -3,-1.343 -3,-3s1.343,-3 3,-3h11c0.973,0 2.288,0.056 3.218,0.967 0.325,0.318 0.604,0.736 0.803,1.297l1.659,5.472c0.156,0.512 0.73,2.857 0.626,3.346 0,7.34 -8.7,14.972 -19.004,14.972C6.326,36 1,27.883 1,17.957v-0.229c0.01,0.01 0.021,0.016 0.031,0.026 0.881,0.882 1.799,1.192 2.845,1.192h0.248z"
android:fillColor="#FFDC5D"/>
<path
android:pathData="M3.864,5.946h0.271C5.718,5.946 7,7.229 7,8.81v6.272c0,1.582 -1.282,2.864 -2.864,2.864h-0.272C2.282,17.946 1,16.664 1,15.082L1,8.81c0,-1.581 1.282,-2.864 2.864,-2.864zM14,14.946c0,0.891 -0.396,1.683 -1.014,2.233 -0.53,0.472 -1.221,0.767 -1.986,0.767 -1.657,0 -3,-1.343 -3,-3v-9c0,-0.816 0.328,-1.554 0.857,-2.095 0.544,-0.557 1.302,-0.905 2.143,-0.905 1.657,0 3,1.343 3,3v9zM18,8.946c-1.201,0 -2.267,0.541 -3,1.38v-6.38c0,-0.758 0.29,-1.442 0.753,-1.97 0.55,-0.627 1.347,-1.03 2.247,-1.03 1.657,0 3,1.343 3,3v5h-3zM22,4.939c0,-0.812 0.326,-1.545 0.85,-2.085 0.544,-0.559 1.301,-0.909 2.143,-0.909h0.014C26.66,1.946 28,3.286 28,4.939v4.007h-6L22,4.939z"
android:fillColor="#FFDC5D"/>
</vector>

View File

@@ -1,18 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M18,1C8.059,1 0,7.268 0,15c0,4.368 2.574,8.268 6.604,10.835C6.08,28.144 4.859,31.569 2,35c5.758,-0.96 9.439,-3.761 11.716,-6.416 1.376,0.262 2.805,0.416 4.284,0.416 9.941,0 18,-6.268 18,-14S27.941,1 18,1z"
android:fillColor="#BDDDF4"/>
<path
android:pathData="M18,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"
android:fillColor="#2A6797"/>
<path
android:pathData="M26,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"
android:fillColor="#2A6797"/>
<path
android:pathData="M10,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"
android:fillColor="#2A6797"/>
</vector>

View File

@@ -1,21 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M18,3.143c-9.941,0 -18,6.908 -18,15.428 0,1.066 0.126,2.107 0.367,3.112C2.146,24.744 3.377,22.812 9,20c5.727,-2.864 0,4 -2,8 -0.615,1.23 -0.282,2.271 0.56,3.124C10.506,32.928 14.104,34 18,34c9.941,0 18,-6.907 18,-15.429 0,-8.52 -8.059,-15.428 -18,-15.428zM20.849,27.59c-0.395,1.346 -2.46,1.924 -4.613,1.291 -2.153,-0.632 -3.578,-2.234 -3.183,-3.581 0.395,-1.346 2.46,-1.924 4.613,-1.29 2.153,0.631 3.578,2.233 3.183,3.58z"
android:fillColor="#D99E82"/>
<path
android:pathData="M10,11m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:fillColor="#5C913B"/>
<path
android:pathData="M20,9m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:fillColor="#269"/>
<path
android:pathData="M29,15m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:fillColor="#DD2E44"/>
<path
android:pathData="M28,24m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:fillColor="#FFCC4D"/>
</vector>

View File

@@ -1,21 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M18,4c7.257,0 13,4 14.699,2 0.197,-0.323 0.301,-0.657 0.301,-1 0,-2 -6.716,-5 -15,-5C9.716,0 3,3 3,5c0,0.343 0.104,0.677 0.301,1C5,8 10.743,4 18,4z"
android:fillColor="#F4900C"/>
<path
android:pathData="M18,3C11.787,3 7.384,4.81 5.727,5.618c-0.477,0.233 -0.539,0.84 -0.415,1.278S16,34 16,34s0.896,2 2,2 2,-2 2,-2L30.704,6.779s0.213,-0.842 -0.569,-1.229C28.392,4.689 24.047,3 18,3z"
android:fillColor="#FFCC4D"/>
<path
android:pathData="M18,31c0,-2.208 -1.791,-4 -4,-4 -0.254,0 -0.5,0.029 -0.741,0.075L16,34s0.071,0.14 0.19,0.342C17.279,33.627 18,32.399 18,31zM17,20c0,-2.209 -1.792,-4 -4,-4 -1.426,0 -2.67,0.752 -3.378,1.876l2.362,5.978c0.327,0.086 0.663,0.146 1.016,0.146 2.208,0 4,-1.792 4,-4z"
android:fillColor="#BE1931"/>
<path
android:pathData="M16,8m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"
android:fillColor="#BE1931"/>
<path
android:pathData="M25,9c-2.208,0 -4,1.791 -4,4s1.792,4 4,4c0.682,0 1.315,-0.187 1.877,-0.488l1.89,-4.806C28.227,10.135 26.752,9 25,9zM19,25c0,1.868 1.288,3.425 3.019,3.864l2.893,-7.357C24.342,21.194 23.697,21 23,21c-2.208,0 -4,1.792 -4,4zM10,12c0,-2.209 -1.791,-4 -4,-4 -0.087,0 -0.169,0.02 -0.255,0.026 0.55,1.412 1.575,4.016 2.775,7.057C9.416,14.349 10,13.248 10,12z"
android:fillColor="#BE1931"/>
</vector>

View File

@@ -1,54 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M32.325,10.958s2.315,0.024 3.511,1.177c-0.336,-4.971 -2.104,-8.249 -5.944,-10.13 -3.141,-1.119 -6.066,1.453 -6.066,1.453s0.862,-1.99 2.19,-2.746C23.789,0.236 21.146,0 18,0c-3.136,0 -5.785,0.227 -8.006,0.701 1.341,0.745 2.215,2.758 2.215,2.758S9.194,0.803 6,2.053C2.221,3.949 0.481,7.223 0.158,12.174c1.183,-1.19 3.55,-1.215 3.55,-1.215S-0.105,13.267 0.282,16.614c0.387,2.947 1.394,5.967 2.879,8.722C3.039,22.15 5.917,20 5.917,20s-2.492,5.96 -0.581,8.738c1.935,2.542 4.313,4.641 6.976,5.916 -0.955,-1.645 -0.136,-3.044 -0.103,-2.945 0.042,0.125 0.459,3.112 2.137,3.743 1.178,0.356 2.4,0.548 3.654,0.548 1.292,0 2.55,-0.207 3.761,-0.583 1.614,-0.691 2.024,-3.585 2.064,-3.708 0.032,-0.098 0.843,1.287 -0.09,2.921 2.706,-1.309 5.118,-3.463 7.064,-6.073 1.699,-2.846 -0.683,-8.557 -0.683,-8.557s2.85,2.13 2.757,5.288c1.556,-2.906 2.585,-6.104 2.911,-9.2 -0.035,-3.061 -3.459,-5.13 -3.459,-5.13z"
android:fillColor="#662113"/>
<path
android:pathData="M13.859,9.495c0.596,2.392 0.16,4.422 -2.231,5.017 -2.392,0.596 -6.363,0.087 -6.958,-2.304 -0.596,-2.392 0.469,-5.39 1.81,-5.724 1.341,-0.334 6.784,0.62 7.379,3.011zM22.963,27.927c0,2.74 -2.222,4.963 -4.963,4.963s-4.963,-2.223 -4.963,-4.963c0,-2.741 2.223,-4.964 4.963,-4.964 2.741,0 4.963,2.222 4.963,4.964z"
android:fillColor="#FFCC4D"/>
<path
android:pathData="M21.309,27.927c0,1.827 -1.481,3.309 -3.309,3.309s-3.309,-1.481 -3.309,-3.309c0,-1.827 1.481,-3.31 3.309,-3.31s3.309,1.483 3.309,3.31z"
android:fillColor="#DD2E44"/>
<path
android:pathData="M11.052,8.997c0.871,1.393 0.447,3.229 -0.946,4.1 -1.394,0.871 -2.608,0.797 -3.479,-0.596 -0.871,-1.394 -0.186,-4.131 0.324,-4.45 0.51,-0.319 3.23,-0.448 4.101,0.946z"
android:fillColor="#E6AAAA"/>
<path
android:pathData="M22.141,9.495c-0.596,2.392 -0.159,4.422 2.232,5.017 2.392,0.596 6.363,0.087 6.959,-2.304 0.596,-2.392 -0.47,-5.39 -1.811,-5.724 -1.342,-0.334 -6.786,0.62 -7.38,3.011z"
android:fillColor="#FFCC4D"/>
<path
android:pathData="M24.948,8.997c-0.871,1.393 -0.447,3.229 0.945,4.1 1.394,0.871 2.608,0.797 3.479,-0.596 0.871,-1.394 0.185,-4.131 -0.324,-4.45 -0.51,-0.319 -3.229,-0.448 -4.1,0.946z"
android:fillColor="#E6AAAA"/>
<path
android:pathData="M18,7.125h-0.002C5.167,7.126 7.125,12.083 8.5,18.667 9.875,25.25 10.384,27 10.384,27h15.228s0.51,-1.75 1.885,-8.333C28.872,12.083 30.829,7.126 18,7.125z"
android:fillColor="#FFCC4D"/>
<path
android:pathData="M12,16s0,-1.5 1.5,-1.5S15,16 15,16v1.5s0,1.5 -1.5,1.5 -1.5,-1.5 -1.5,-1.5L12,16zM21,16s0,-1.5 1.5,-1.5S24,16 24,16v1.5s0,1.5 -1.5,1.5 -1.5,-1.5 -1.5,-1.5L21,16z"
android:fillColor="#272B2B"/>
<path
android:pathData="M20.168,21.521c-1.598,0 -1.385,0.848 -2.168,2.113 -0.783,-1.266 -0.571,-2.113 -2.168,-2.113 -6.865,0 -6.837,0.375 -6.865,2.828 -0.058,4.986 2.802,6.132 5.257,6.06 1.597,-0.048 2.994,-0.88 3.777,-2.131 0.783,1.251 2.179,2.083 3.776,2.131 2.455,0.072 5.315,-1.073 5.257,-6.06 -0.029,-2.453 -0.001,-2.828 -6.866,-2.828z"
android:fillColor="#FFE8B6"/>
<path
android:pathData="M14.582,21.411c-1.14,0.233 2.279,4.431 3.418,4.431s4.559,-4.198 3.419,-4.431c-1.14,-0.232 -5.698,-0.232 -6.837,0z"
android:fillColor="#272B2B"/>
<path
android:pathData="M11.5,24.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
android:fillColor="#D99E82"/>
<path
android:pathData="M10.5,26.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
android:fillColor="#D99E82"/>
<path
android:pathData="M12.5,27.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
android:fillColor="#D99E82"/>
<path
android:pathData="M24.5,24.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
android:fillColor="#D99E82"/>
<path
android:pathData="M25.5,26.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
android:fillColor="#D99E82"/>
<path
android:pathData="M23.5,27.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
android:fillColor="#D99E82"/>
</vector>

View File

@@ -1,27 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M16,9h4v17h-4z"
android:fillColor="#99AAB5"/>
<path
android:pathData="M10,24.5c0,0.828 -0.672,1.5 -1.5,1.5h-3c-0.828,0 -1.5,-0.672 -1.5,-1.5S4.672,23 5.5,23h3c0.828,0 1.5,0.672 1.5,1.5z"
android:fillColor="#DA2F47"/>
<path
android:pathData="M34,33c0,1.104 -0.896,2 -2,2H4c-1.104,0 -2,-0.896 -2,-2v-6c0,-1.104 0.896,-2 2,-2h28c1.104,0 2,0.896 2,2v6z"
android:fillColor="#31373D"/>
<path
android:pathData="M10,34.5c0,0.828 -0.671,1.5 -1.5,1.5h-3c-0.829,0 -1.5,-0.672 -1.5,-1.5S4.671,33 5.5,33h3c0.829,0 1.5,0.672 1.5,1.5zM32,34.5c0,0.828 -0.672,1.5 -1.5,1.5h-3c-0.828,0 -1.5,-0.672 -1.5,-1.5s0.672,-1.5 1.5,-1.5h3c0.828,0 1.5,0.672 1.5,1.5z"
android:fillColor="#31373D"/>
<path
android:pathData="M18,7m-5,0a5,5 0,1 1,10 0a5,5 0,1 1,-10 0"
android:fillColor="#DA2F47"/>
<path
android:pathData="M25,26c0,1.104 -0.896,2 -2,2H13c-1.104,0 -2,-0.896 -2,-2v-1c0,-1.104 3.896,-6 5,-6h4c1.104,0 5,4.896 5,6v1z"
android:fillColor="#31373D"/>
<path
android:pathData="M33,28c0,0.553 -0.447,1 -1,1H4c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h28c0.553,0 1,0.447 1,1z"
android:fillColor="#66757F"/>
</vector>

View File

@@ -1,15 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M34.453,15.573c-0.864,-7.3 -5.729,-10.447 -13.93,-10.447 -0.391,0 -0.763,0.017 -1.139,0.031 -0.013,-0.01 -0.022,-0.021 -0.035,-0.031C14.655,1.605 4.091,2.779 1.745,6.3c-3.255,4.883 -1.174,22.3 0,24.646 1.173,2.35 4.694,3.521 5.868,2.35 1.174,-1.176 0,-1.176 -1.173,-3.521 -0.85,-1.701 -0.466,-5.859 0.255,-8.471 0.028,0.168 0.068,0.322 0.1,0.486 0.39,2.871 1.993,7.412 1.993,9.744 0,3.564 2.102,4.107 4.694,4.107 2.593,0 4.695,-0.543 4.695,-4.107 0,-0.24 -0.008,-0.463 -0.012,-0.695 0.757,0.064 1.535,0.107 2.359,0.107 0.497,0 0.977,-0.016 1.448,-0.039 -0.004,0.209 -0.013,0.41 -0.013,0.627 0,3.564 2.103,4.107 4.694,4.107 2.593,0 4.695,-0.543 4.695,-4.107 0,-1.801 1.192,-4.625 2.039,-6.982 0.159,-0.354 0.291,-0.732 0.42,-1.117 0.118,1.307 0.193,2.706 0.193,4.206 0,0.553 0.447,1 1,1s1,-0.447 1,-1c0,-5.153 -0.771,-9.248 -1.547,-12.068z"
android:fillColor="#99AAB5"/>
<path
android:pathData="M19.35,5.126S23,10.641 20,15.641c-3,5 -7.838,5 -11,5 -2,0 -1,2 0,2 1.414,0 8.395,1.211 12,-6 3,-6 -1.65,-11.515 -1.65,-11.515z"
android:fillColor="#66757F"/>
<path
android:pathData="M6.5,14.141m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"
android:fillColor="#292F33"/>
</vector>

View File

@@ -1,18 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M33,36H4c4,0 3,-9 3,-9 0,-2.209 1.791,-15 4,-15h21s4,0 4,4v17s0,3 -3,3z"
android:fillColor="#99AAB5"/>
<path
android:pathData="M30,33c0,3 3,3 3,3H3s-3,0 -3,-4V4c0,-2.209 1.791,-4 4,-4h22c2.209,0 4,1.791 4,4v29z"
android:fillColor="#CCD6DD"/>
<path
android:pathData="M27,20c0,0.553 -0.447,1 -1,1h-8c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h8c0.553,0 1,0.447 1,1zM27,16c0,0.553 -0.447,1 -1,1h-8c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h8c0.553,0 1,0.447 1,1zM27,12c0,0.553 -0.447,1 -1,1h-8c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h8c0.553,0 1,0.447 1,1zM27,24c0,0.553 -0.447,1 -1,1L4,25c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h22c0.553,0 1,0.447 1,1zM27,28c0,0.553 -0.447,1 -1,1L4,29c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h22c0.553,0 1,0.447 1,1zM27,32c0,0.553 -0.447,1 -1,1L4,33c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h22c0.553,0 1,0.447 1,1zM25,9s2,0 2,-2L27,5s0,-2 -2,-2L5,3S3,3 3,5v2s0,2 2,2h20z"
android:fillColor="#99AAB5"/>
<path
android:pathData="M13,21s2,0 2,-2v-6s0,-2 -2,-2H5s-2,0 -2,2v6s0,2 2,2h8z"
android:fillColor="#55ACEE"/>
</vector>

View File

@@ -1,24 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M0,27c0,2.209 1.791,4 4,4h28c2.209,0 4,-1.791 4,-4v-0.5H0v0.5z"
android:fillColor="#880082"/>
<path
android:pathData="M0,22.07h36v4.6H0z"
android:fillColor="#3558A0"/>
<path
android:pathData="M0,17.83h36v4.5H0z"
android:fillColor="#138F3E"/>
<path
android:pathData="M0,13.5h36V18H0z"
android:fillColor="#FAD220"/>
<path
android:pathData="M0,9.17h36v4.5H0z"
android:fillColor="#FF5000"/>
<path
android:pathData="M32,5H4C1.791,5 0,6.791 0,9v0.33h36V9c0,-2.209 -1.791,-4 -4,-4z"
android:fillColor="#FF000E"/>
</vector>

View File

@@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M36,5V3H0v30h36v-2H6v-5h30v-2H6v-5h30v-2H6v-5h30v-2H6V5z"
android:fillColor="#8899A6"/>
<path
android:pathData="M27.827,20.562c-0.223,-0.646 -0.543,-1.227 -0.947,-1.723 -0.411,-0.513 -0.926,-0.928 -1.529,-1.232 -0.61,-0.31 -1.259,-0.46 -1.981,-0.46 -0.086,0 -0.208,0.009 -0.366,0.026l-0.533,-2.593c0.613,-0.603 1.156,-1.299 1.616,-2.077 0.499,-0.847 0.885,-1.77 1.145,-2.741 0.269,-0.978 0.399,-1.942 0.399,-2.945 0,-2.106 -0.542,-3.94 -1.627,-5.475 -0.158,-0.196 -0.288,-0.343 -0.387,-0.431 -0.394,-0.355 -0.788,-0.412 -1.704,0.266 -0.47,0.352 -0.883,0.86 -1.224,1.506 -0.352,0.644 -0.608,1.366 -0.786,2.2 -0.185,0.826 -0.283,1.723 -0.292,2.684 0.041,1.352 0.234,2.701 0.576,4.013 -0.77,0.779 -1.392,1.43 -1.881,1.951 -0.521,0.569 -1.038,1.222 -1.539,1.943 -0.495,0.711 -0.91,1.493 -1.233,2.324 -0.317,0.807 -0.497,1.693 -0.533,2.655 0.008,0.982 0.195,1.944 0.561,2.864 0.365,0.902 0.884,1.726 1.546,2.45 0.665,0.718 1.448,1.287 2.325,1.694 1.23,0.569 2.644,0.749 4.02,0.51 0.063,0.288 0.146,0.629 0.244,1.022 0.157,0.647 0.274,1.172 0.35,1.56 0.073,0.391 0.109,0.766 0.109,1.122 0,0.541 -0.059,0.955 -0.197,1.301 -0.05,0.202 -0.185,0.412 -0.401,0.62 -0.233,0.227 -0.508,0.401 -0.839,0.533 -0.468,0.184 -0.922,0.231 -1.289,0.181 0.195,-0.105 0.375,-0.241 0.537,-0.405 0.433,-0.443 0.652,-0.988 0.652,-1.622 0,-0.447 -0.109,-0.875 -0.328,-1.282 -0.215,-0.375 -0.508,-0.684 -0.886,-0.929 -0.378,-0.225 -0.778,-0.341 -1.226,-0.341h-0.006c-0.512,0.034 -0.954,0.195 -1.301,0.471 -0.36,0.266 -0.646,0.619 -0.852,1.051 -0.193,0.406 -0.307,0.847 -0.338,1.362 0.04,1.04 0.477,1.885 1.306,2.508 0.784,0.581 1.707,0.877 2.739,0.877 0.743,0 1.434,-0.164 2.053,-0.487 0.634,-0.326 1.148,-0.796 1.529,-1.402 0.37,-0.602 0.559,-1.291 0.559,-2.046 0,-0.495 -0.043,-0.96 -0.129,-1.419 -0.085,-0.458 -0.211,-1.08 -0.384,-1.869 -0.124,-0.535 -0.219,-0.987 -0.288,-1.35 0.965,-0.428 1.712,-1.049 2.226,-1.85 0.576,-0.898 0.867,-1.908 0.867,-3 -0.001,-0.665 -0.112,-1.342 -0.333,-2.015zM24.705,25.74l-1.047,-5.149c0.261,0.056 0.502,0.147 0.727,0.276 0.396,0.224 0.703,0.529 0.945,0.938 0.241,0.39 0.392,0.838 0.456,1.303 0,1.246 -0.354,2.115 -1.081,2.632zM23.547,7.101c-0.181,0.526 -0.43,1.057 -0.743,1.577 -0.307,0.517 -0.629,0.973 -0.959,1.359 -0.105,0.125 -0.202,0.231 -0.288,0.322 -0.078,-0.354 -0.128,-0.746 -0.149,-1.165 0.016,-0.685 0.116,-1.364 0.305,-2.081 0.17,-0.661 0.408,-1.259 0.695,-1.756 0.305,-0.468 0.621,-0.705 0.944,-0.705 0.115,0 0.196,0.028 0.259,0.087 0.07,0.071 0.119,0.208 0.15,0.454 0.03,0.133 0.047,0.303 0.047,0.494 0,0.443 -0.088,0.918 -0.261,1.414zM18.602,18.58c0.653,-0.943 1.452,-1.837 2.431,-2.718l0.339,1.739c-0.717,0.362 -1.321,0.9 -1.801,1.61 -0.552,0.82 -0.846,1.727 -0.872,2.717 0.017,0.913 0.309,1.736 0.871,2.451 0.566,0.708 1.294,1.181 2.169,1.4l0.12,0.03 0.122,-0.029c0.537,-0.127 0.594,-0.471 0.594,-0.613 0,-0.345 -0.224,-0.621 -0.579,-0.72 -0.367,-0.17 -0.637,-0.417 -0.82,-0.758 -0.202,-0.368 -0.309,-0.713 -0.309,-0.994 0,-0.476 0.17,-0.903 0.516,-1.303 0.214,-0.242 0.432,-0.432 0.654,-0.572l1.093,5.508c-0.382,0.081 -0.733,0.132 -1.046,0.152 -1.384,-0.045 -2.518,-0.5 -3.369,-1.35 -0.434,-0.442 -0.747,-0.907 -0.958,-1.423 -0.213,-0.516 -0.327,-1.059 -0.342,-1.584 0.029,-1.27 0.429,-2.463 1.187,-3.543z"
android:fillColor="#31373D"/>
</vector>

View File

@@ -1,15 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M14,34.5a4,1.5 0,1 0,8 0a4,1.5 0,1 0,-8 0z"
android:fillColor="#292F33"/>
<path
android:pathData="M14.339,10.725S16.894,34.998 18.001,35c1.106,0.001 3.66,-24.275 3.66,-24.275h-7.322z"
android:fillColor="#99AAB5"/>
<path
android:pathData="M18,8m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
android:fillColor="#DD2E44"/>
</vector>

View File

@@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M11,36s-4,0 -4,-4V4s0,-4 4,-4h14s4,0 4,4v28s0,4 -4,4H11z"
android:fillColor="#31373D"/>
<path
android:pathData="M9,5h18v26H9z"
android:fillColor="#55ACEE"/>
</vector>

View File

@@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
<path
android:pathData="M17,27c-1.657,0 -3,-1.343 -3,-3v-4c0,-1.657 1.343,-3 3,-3 0.603,-0.006 6,-1 6,-5 0,-2 -2,-4 -5,-4 -2.441,0 -4,2 -4,3 0,1.657 -1.343,3 -3,3s-3,-1.343 -3,-3c0,-4.878 4.58,-9 10,-9 8,0 11,5.982 11,11 0,4.145 -2.277,7.313 -6.413,8.92 -0.9,0.351 -1.79,0.587 -2.587,0.747V24c0,1.657 -1.343,3 -3,3z"
android:fillColor="#BE1931"/>
<path
android:pathData="M17,32m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
android:fillColor="#BE1931"/>
</vector>

View File

@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M8.4,15.45L7,14L3,18L7,22L8.4,20.55L6.85,19H13.5V18C13.5,17.657 13.564,17.317 13.699,17H6.85L8.4,15.45Z"
android:fillColor="#000000"/>
<path
android:pathData="M5,5V11H7V7H17.15L15.6,8.55L17,10L21,6L17,2L15.6,3.45L17.15,5H5Z"
android:fillColor="#000000"/>
<path
android:pathData="M16,22C15.717,22 15.475,21.908 15.275,21.725C15.092,21.525 15,21.283 15,21V18C15,17.717 15.092,17.483 15.275,17.3C15.475,17.1 15.717,17 16,17V16C16,15.45 16.192,14.983 16.575,14.6C16.975,14.2 17.45,14 18,14C18.55,14 19.017,14.2 19.4,14.6C19.8,14.983 20,15.45 20,16V17C20.283,17 20.517,17.1 20.7,17.3C20.9,17.483 21,17.717 21,18V21C21,21.283 20.9,21.525 20.7,21.725C20.517,21.908 20.283,22 20,22H16ZM17,17H19V16C19,15.717 18.9,15.483 18.7,15.3C18.517,15.1 18.283,15 18,15C17.717,15 17.475,15.1 17.275,15.3C17.092,15.483 17,15.717 17,16V17Z"
android:fillColor="#000000"/>
</vector>

View File

@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M2.15,18.25L6.775,22.875L8.8,20.8L7.675,19.7H13.5V18C13.5,17.583 13.594,17.172 13.795,16.8H7.675L8.8,15.7L6.775,13.625L2.15,18.25Z"
android:fillColor="#000000"/>
<path
android:pathData="M4.15,4.55V11.45H7.05V7.45H16.35L15.225,8.55L17.25,10.625L21.875,6L17.25,1.375L15.225,3.45L16.35,4.55H4.15Z"
android:fillColor="#000000"/>
<path
android:pathData="M16,22C15.717,22 15.475,21.908 15.275,21.725C15.092,21.525 15,21.283 15,21V18C15,17.717 15.092,17.483 15.275,17.3C15.475,17.1 15.717,17 16,17V16C16,15.45 16.192,14.983 16.575,14.6C16.975,14.2 17.45,14 18,14C18.55,14 19.017,14.2 19.4,14.6C19.8,14.983 20,15.45 20,16V17C20.283,17 20.517,17.1 20.7,17.3C20.9,17.483 21,17.717 21,18V21C21,21.283 20.9,21.525 20.7,21.725C20.517,21.908 20.283,22 20,22H16ZM17,17H19V16C19,15.717 18.9,15.483 18.7,15.3C18.517,15.1 18.283,15 18,15C17.717,15 17.475,15.1 17.275,15.3C17.092,15.483 17,15.717 17,16V17Z"
android:fillColor="#000000"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M17,23Q19.5,23 21.25,21.25Q23,19.5 23,17H21.5Q21.5,18.875 20.188,20.188Q18.875,21.5 17,21.5ZM1,7H2.5Q2.5,5.125 3.812,3.812Q5.125,2.5 7,2.5V1Q4.5,1 2.75,2.75Q1,4.5 1,7ZM3.525,20.475Q1.025,17.975 1.025,14.475Q1.025,10.975 3.525,8.475L7.05,4.925Q7.775,4.2 8.812,4.2Q9.85,4.2 10.575,4.925Q10.675,5.025 10.763,5.125Q10.85,5.225 10.9,5.325L13.425,2.8Q14.15,2.075 15.188,2.075Q16.225,2.075 16.95,2.8Q17.075,2.925 17.15,3.025Q17.225,3.125 17.3,3.225Q18.025,2.725 18.925,2.8Q19.825,2.875 20.475,3.525Q21.05,4.1 21.175,4.837Q21.3,5.575 21,6.3Q21.15,6.375 21.288,6.475Q21.425,6.575 21.55,6.7Q22.275,7.425 22.275,8.463Q22.275,9.5 21.55,10.225L21.15,10.625Q21.25,10.675 21.35,10.762Q21.45,10.85 21.55,10.95Q22.275,11.675 22.275,12.712Q22.275,13.75 21.55,14.475L15.525,20.475Q13.025,22.975 9.525,22.975Q6.025,22.975 3.525,20.475ZM4.925,19.075Q5.875,20.025 7.075,20.5Q8.275,20.975 9.525,20.975Q10.775,20.975 11.975,20.5Q13.175,20.025 14.125,19.075L20.125,13.05Q20.275,12.9 20.275,12.7Q20.275,12.5 20.125,12.35Q19.975,12.2 19.775,12.2Q19.575,12.2 19.425,12.35L15.9,15.9L14.475,14.475L20.125,8.825Q20.275,8.675 20.275,8.462Q20.275,8.25 20.125,8.1Q19.975,7.975 19.775,7.962Q19.575,7.95 19.425,8.1L14.475,13.05L13.05,11.65L19.075,5.625Q19.225,5.475 19.225,5.275Q19.225,5.075 19.075,4.925Q18.925,4.775 18.725,4.775Q18.525,4.775 18.375,4.925L12.35,10.95L10.95,9.525L15.525,4.925Q15.675,4.775 15.675,4.575Q15.675,4.375 15.525,4.225Q15.4,4.075 15.188,4.075Q14.975,4.075 14.825,4.225L8.525,10.525Q9.05,11.875 8.775,13.337Q8.5,14.8 7.4,15.9L6,14.475Q6.875,13.6 6.875,12.35Q6.875,11.1 6,10.225L9.175,7.05Q9.325,6.9 9.325,6.7Q9.325,6.5 9.175,6.35Q9.025,6.2 8.825,6.212Q8.625,6.225 8.475,6.35L4.925,9.875Q3.975,10.825 3.5,12.025Q3.025,13.225 3.025,14.475Q3.025,15.725 3.5,16.925Q3.975,18.125 4.925,19.075Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="110dp"
android:height="18dp"
android:viewportWidth="110"
android:viewportHeight="18">
<path
android:pathData="M18.406,9.999V17.878H15.287V10.231C15.287,8.618 14.609,7.8 13.254,7.8C11.755,7.8 11.004,8.771 11.004,10.69V14.876H7.903V10.69C7.903,8.771 7.151,7.8 5.653,7.8C4.297,7.8 3.619,8.618 3.619,10.231V17.878H0.5V9.999C0.5,8.389 0.91,7.109 1.733,6.162C2.581,5.215 3.693,4.73 5.072,4.73C6.668,4.73 7.877,5.344 8.676,6.572L9.453,7.876L10.23,6.572C11.029,5.344 12.238,4.73 13.834,4.73C15.214,4.73 16.325,5.215 17.174,6.162C17.997,7.109 18.406,8.389 18.406,9.999ZM29.152,13.916C29.795,13.235 30.105,12.378 30.105,11.345C30.105,10.311 29.795,9.454 29.152,8.798C28.532,8.118 27.745,7.79 26.791,7.79C25.838,7.79 25.051,8.118 24.431,8.798C23.811,9.454 23.501,10.311 23.501,11.345C23.501,12.378 23.811,13.235 24.431,13.916C25.051,14.571 25.838,14.899 26.791,14.899C27.745,14.899 28.532,14.571 29.152,13.916ZM30.105,5.042H33.181V17.647H30.105V16.16C29.176,17.395 27.888,18 26.219,18C24.622,18 23.263,17.37 22.118,16.084C20.998,14.798 20.426,13.21 20.426,11.345C20.426,9.504 20.998,7.916 22.118,6.63C23.263,5.345 24.622,4.689 26.219,4.689C27.888,4.689 29.176,5.294 30.105,6.529V5.042ZM43.528,11.118C44.434,11.798 44.888,12.756 44.864,13.966C44.864,15.252 44.41,16.26 43.481,16.966C42.551,17.647 41.431,18 40.072,18C37.616,18 35.947,16.992 35.065,15L37.735,13.412C38.093,14.496 38.879,15.05 40.072,15.05C41.168,15.05 41.717,14.697 41.717,13.966C41.717,13.437 41.001,12.958 39.547,12.58C38.999,12.429 38.546,12.277 38.188,12.151C37.688,11.95 37.258,11.723 36.901,11.445C36.019,10.765 35.566,9.857 35.566,8.698C35.566,7.462 35.995,6.479 36.853,5.773C37.735,5.042 38.808,4.689 40.095,4.689C42.146,4.689 43.648,5.571 44.625,7.361L42.003,8.874C41.621,8.017 40.978,7.588 40.095,7.588C39.166,7.588 38.713,7.941 38.713,8.622C38.713,9.151 39.428,9.63 40.882,10.008C42.003,10.26 42.885,10.639 43.528,11.118ZM53.304,8.168H50.61V13.412C50.61,14.042 50.848,14.42 51.301,14.597C51.635,14.723 52.303,14.748 53.304,14.697V17.647C51.23,17.899 49.728,17.698 48.846,17.017C47.964,16.361 47.534,15.151 47.534,13.412V8.168H45.46V5.042H47.534V2.496L50.61,1.513V5.042H53.304V8.168ZM63.103,13.84C63.723,13.185 64.033,12.353 64.033,11.344C64.033,10.336 63.723,9.504 63.103,8.849C62.483,8.193 61.721,7.866 60.791,7.866C59.861,7.866 59.098,8.193 58.478,8.849C57.882,9.529 57.572,10.361 57.572,11.344C57.572,12.328 57.882,13.16 58.478,13.84C59.098,14.496 59.861,14.823 60.791,14.823C61.721,14.823 62.483,14.496 63.103,13.84ZM56.308,16.084C55.093,14.798 54.497,13.235 54.497,11.344C54.497,9.479 55.093,7.916 56.308,6.63C57.524,5.345 59.026,4.689 60.791,4.689C62.555,4.689 64.057,5.345 65.273,6.63C66.489,7.916 67.109,9.504 67.109,11.344C67.109,13.21 66.489,14.798 65.273,16.084C64.057,17.37 62.579,18 60.791,18C59.002,18 57.524,17.37 56.308,16.084ZM77.385,13.916C78.005,13.235 78.314,12.378 78.314,11.345C78.314,10.311 78.005,9.454 77.385,8.798C76.765,8.118 75.978,7.79 75.024,7.79C74.071,7.79 73.284,8.118 72.64,8.798C72.021,9.454 71.71,10.311 71.71,11.345C71.71,12.378 72.021,13.235 72.64,13.916C73.284,14.571 74.094,14.899 75.024,14.899C75.978,14.899 76.765,14.571 77.385,13.916ZM78.314,0H81.39V17.647H78.314V16.16C77.409,17.395 76.121,18 74.452,18C72.855,18 71.472,17.37 70.328,16.084C69.207,14.798 68.635,13.21 68.635,11.345C68.635,9.504 69.207,7.916 70.328,6.63C71.472,5.345 72.855,4.689 74.452,4.689C76.121,4.689 77.409,5.294 78.314,6.529V0ZM92.191,13.84C92.811,13.185 93.12,12.353 93.12,11.344C93.12,10.336 92.811,9.504 92.191,8.849C91.571,8.193 90.808,7.866 89.878,7.866C88.948,7.866 88.185,8.193 87.565,8.849C86.969,9.529 86.659,10.361 86.659,11.344C86.659,12.328 86.969,13.16 87.565,13.84C88.185,14.496 88.948,14.823 89.878,14.823C90.808,14.823 91.571,14.496 92.191,13.84ZM85.396,16.084C84.18,14.798 83.584,13.235 83.584,11.344C83.584,9.479 84.18,7.916 85.396,6.63C86.612,5.345 88.114,4.689 89.878,4.689C91.642,4.689 93.144,5.345 94.36,6.63C95.576,7.916 96.196,9.504 96.196,11.344C96.196,13.21 95.576,14.798 94.36,16.084C93.144,17.37 91.666,18 89.878,18C88.09,18 86.612,17.37 85.396,16.084ZM109.5,9.908V17.647H106.424V10.311C106.424,9.479 106.21,8.849 105.781,8.37C105.375,7.941 104.803,7.714 104.064,7.714C102.324,7.714 101.442,8.748 101.442,10.84V17.647H98.366V5.042H101.442V6.454C102.181,5.269 103.349,4.689 104.994,4.689C106.305,4.689 107.378,5.143 108.213,6.076C109.071,7.009 109.5,8.269 109.5,9.908Z"
android:fillColor="#282C37"/>
</vector>

View File

@@ -4,73 +4,133 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@drawable/divider_inset_16dp_start"
android:paddingBottom="8dp"
android:divider="@drawable/divider_inset_16dp"
android:showDividers="middle">
<TextView
android:id="@+id/timestamp"
<org.joinmastodon.android.ui.views.WrappingLinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="20dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:minHeight="20dp"
android:gravity="center_vertical"
android:textAppearance="@style/m3_body_large"
android:textSize="16sp"
android:textColor="?colorM3OnSurfaceVariant"
tools:text="Dec 12, 2021, 12:42 PM via Mastodon for Android"/>
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:horizontalGap="8dp"
android:verticalGap="8dp"
android:clipToPadding="false">
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorM3Secondary"
android:background="@drawable/bg_button_borderless_rounded"
android:backgroundTint="?colorM3Secondary"
android:singleLine="true"
android:ellipsize="end"
android:paddingVertical="4dp"
android:paddingHorizontal="8dp"
android:layout_marginVertical="-4dp"
android:layout_marginHorizontal="-8dp"
tools:text="8:24 AM"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorM3Secondary"
android:importantForAccessibility="no"
android:text="·"/>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorM3Secondary"
android:singleLine="true"
android:ellipsize="end"
tools:text="2023-11-08"/>
<TextView
android:id="@+id/date_app_separator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorM3Secondary"
android:importantForAccessibility="no"
android:text="·"/>
<TextView
android:id="@+id/app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorM3Secondary"
android:singleLine="true"
android:ellipsize="end"
android:paddingVertical="4dp"
android:paddingHorizontal="8dp"
android:layout_marginVertical="-4dp"
android:layout_marginHorizontal="-8dp"
android:background="@drawable/bg_button_borderless_rounded"
android:backgroundTint="?colorM3Secondary"
tools:text="Mastodon for Android dfjklafjdsalkfjdslakfjdsaklfjdslak"/>
</org.joinmastodon.android.ui.views.WrappingLinearLayout>
<TextView
android:id="@+id/edit_history"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_height="36dp"
android:paddingStart="16dp"
android:paddingEnd="24dp"
android:background="?android:selectableItemBackground"
android:textAppearance="@style/m3_body_large"
android:textColor="?colorM3OnSurface"
android:singleLine="true"
android:ellipsize="end"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorM3Secondary"
android:gravity="center_vertical"
android:drawableStart="@drawable/ic_edit_24px"
android:drawableTint="?colorM3OnSurfaceVariant"
android:drawablePadding="16dp"
tools:text="Last edit bla bla"/>
<TextView
android:id="@+id/reblogs"
<org.joinmastodon.android.ui.views.WrappingLinearLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:paddingStart="16dp"
android:paddingEnd="24dp"
android:background="?android:selectableItemBackground"
android:textAppearance="@style/m3_body_large"
android:textColor="?colorM3OnSurface"
android:singleLine="true"
android:ellipsize="end"
android:gravity="center_vertical"
android:drawableStart="@drawable/ic_repeat_24px"
android:drawableTint="?colorM3OnSurfaceVariant"
android:drawablePadding="16dp"
tools:text="123 boosts"/>
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:horizontalGap="8dp"
android:verticalGap="8dp"
android:clipToPadding="false">
<TextView
android:id="@+id/favorites"
android:layout_width="match_parent"
android:layout_height="48dp"
android:paddingStart="16dp"
android:paddingEnd="24dp"
android:background="?android:selectableItemBackground"
android:textAppearance="@style/m3_body_large"
android:textColor="?colorM3OnSurface"
android:singleLine="true"
android:ellipsize="end"
android:gravity="center_vertical"
android:drawableStart="@drawable/ic_star_24px"
android:drawableTint="?colorM3OnSurfaceVariant"
android:drawablePadding="16dp"
tools:text="123 favorites"/>
<TextView
android:id="@+id/reblogs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorM3Secondary"
android:background="@drawable/bg_button_borderless_rounded"
android:backgroundTint="?colorM3Secondary"
android:singleLine="true"
android:ellipsize="end"
android:paddingVertical="4dp"
android:paddingHorizontal="8dp"
android:layout_marginVertical="-4dp"
android:layout_marginHorizontal="-8dp"
tools:text="123 boosts"/>
<TextView
android:id="@+id/favorites"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorM3Secondary"
android:background="@drawable/bg_button_borderless_rounded"
android:backgroundTint="?colorM3Secondary"
android:singleLine="true"
android:ellipsize="end"
android:paddingVertical="4dp"
android:paddingHorizontal="8dp"
android:layout_marginVertical="-4dp"
android:layout_marginHorizontal="-8dp"
tools:text="123 favorites"/>
</org.joinmastodon.android.ui.views.WrappingLinearLayout>
</LinearLayout>

View File

@@ -27,6 +27,7 @@
android:textColor="?colorM3OnSurfaceVariant"
android:gravity="center_vertical"
android:textAppearance="@style/m3_label_medium"
android:duplicateParentState="true"
tools:text="123"/>
</FrameLayout>
@@ -54,6 +55,7 @@
android:textColor="?colorM3OnSurfaceVariant"
android:gravity="center_vertical"
android:textAppearance="@style/m3_label_medium"
android:duplicateParentState="true"
tools:text="123"/>
</FrameLayout>
@@ -81,6 +83,7 @@
android:textColor="?colorM3OnSurfaceVariant"
android:gravity="center_vertical"
android:textAppearance="@style/m3_label_medium"
android:duplicateParentState="true"
tools:text="123"/>
</FrameLayout>

View File

@@ -11,6 +11,7 @@
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:id="@+id/scrollable_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
@@ -34,6 +35,7 @@
android:foregroundGravity="center"
android:foregroundTint="?colorM3OnSecondaryContainer"
android:scaleType="centerCrop"
android:contentDescription="@string/profile_header"
android:background="?colorM3SecondaryContainer"/>
<FrameLayout
@@ -51,6 +53,7 @@
android:foregroundGravity="center"
android:foregroundTint="?colorM3OnSecondaryContainer"
android:scaleType="centerCrop"
android:contentDescription="@string/profile_picture"
android:background="?colorM3SecondaryContainer"/>
</FrameLayout>
@@ -104,39 +107,6 @@
android:hint="@string/profile_bio"/>
</org.joinmastodon.android.ui.views.FloatingHintEditTextLayout>
<org.joinmastodon.android.ui.views.ReorderableLinearLayout
android:id="@+id/profile_fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
<Button
android:id="@+id/add_row"
android:layout_width="match_parent"
android:layout_height="56dp"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingEnd="24dp"
android:textAppearance="@style/m3_body_large"
android:textColor="?colorM3OnSurface"
android:drawableEnd="@drawable/ic_add_24px"
android:drawableTint="?colorM3OnSurface"
android:drawablePadding="16dp"
android:singleLine="true"
android:ellipsize="end"
android:background="?android:attr/selectableItemBackground"
android:stateListAnimator="@null"
android:text="@string/profile_add_row"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:textAppearance="@style/m3_body_small"
android:textColor="?colorM3OnSurfaceVariant"
android:text="@string/profile_setup_explanation"/>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<me.grishka.appkit.views.FragmentRootLinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:id="@+id/appkit_loader_root"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?colorM3Surface">
<include layout="@layout/appkit_toolbar"/>
<FrameLayout
android:id="@+id/appkit_loader_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<include layout="@layout/loading"
android:id="@+id/loading"/>
<ViewStub android:layout="?errorViewLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/error"
android:visibility="gone"/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/content_stub"/>
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="?colorM3OutlineVariant"/>
<FrameLayout
android:id="@+id/reply_button_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_m3_surface2">
<LinearLayout
android:id="@+id/reply_button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="8dp"
android:orientation="horizontal"
android:background="?colorM3SurfaceVariant"
android:foreground="@drawable/bg_rect_4dp_ripple"
android:foregroundTint="?colorM3OnSurfaceVariant"
android:padding="8dp">
<ImageView
android:id="@+id/avatar"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="8dp"
android:importantForAccessibility="no"
android:scaleType="centerCrop"/>
<TextView
android:id="@+id/reply_btn_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAppearance="@style/m3_body_medium"
android:textColor="?colorM3OnSurfaceVariant"
android:singleLine="true"
android:ellipsize="end"
tools:text="Reply to ..."/>
</LinearLayout>
</FrameLayout>
</me.grishka.appkit.views.FragmentRootLinearLayout>

View File

@@ -2,7 +2,7 @@
<org.joinmastodon.android.ui.views.CheckableRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="72dp"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageView
@@ -11,6 +11,7 @@
android:layout_height="40dp"
android:layout_margin="16dp"
android:layout_alignParentStart="true"
android:layout_centerInParent="true"
android:importantForAccessibility="no"/>
<View
@@ -26,11 +27,13 @@
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="24dp"
android:layout_height="wrap_content"
android:minHeight="24dp"
android:layout_marginTop="14dp"
android:layout_toEndOf="@id/avatar"
android:layout_toStartOf="@id/radiobtn"
android:textAppearance="@style/m3_body_large"
android:textSize="16sp"
android:textColor="?colorM3OnSurface"
android:gravity="center_vertical|start"
android:textAlignment="viewStart"
@@ -40,12 +43,15 @@
<TextView
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_height="wrap_content"
android:minHeight="20dp"
android:layout_marginBottom="14dp"
android:layout_below="@id/name"
android:layout_toEndOf="@id/avatar"
android:layout_toStartOf="@id/radiobtn"
android:textColor="?colorM3OnSurfaceVariant"
android:textAppearance="@style/m3_body_medium"
android:textSize="14sp"
android:singleLine="true"
android:gravity="center_vertical|start"
android:textAlignment="viewStart"

View File

@@ -24,6 +24,7 @@
android:minHeight="24dp"
android:gravity="center_vertical|start"
android:textAppearance="@style/m3_body_large"
android:textSize="16sp"
android:textColor="?colorM3OnSurface"
android:textAlignment="viewStart"
tools:text="Title"/>
@@ -35,6 +36,7 @@
android:minHeight="20dp"
android:gravity="center_vertical|start"
android:textAppearance="@style/m3_body_medium"
android:textSize="14sp"
android:textColor="?colorM3OnSurfaceVariant"
android:textAlignment="viewStart"
tools:text="Subtitle"/>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="8dp"
android:baselineAligned="false">
<TextView
android:id="@+id/number"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_marginEnd="16dp"
android:textColor="?colorM3Primary"
android:fontFamily="sans-serif-condensed"
android:textStyle="bold"
android:textSize="22dp"
android:gravity="center"
android:includeFontPadding="false"
tools:text="1"/>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/number"
android:textAppearance="@style/m3_body_large"
android:textSize="16sp"
android:textColor="?colorM3OnSurface"
android:minHeight="20sp"
android:gravity="center_vertical|start"
tools:text="No discrimination, including (but not limited to) racism, sexism, homophobia or transphobia."/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/number"
android:layout_below="@id/title"
android:textAppearance="@style/m3_body_medium"
android:textSize="14sp"
android:textColor="?colorM3OnSurfaceVariant"
android:paddingVertical="2sp"
android:lineSpacingExtra="4sp"
android:gravity="start"
tools:text="No discrimination, including (but not limited to) racism, sexism, homophobia or transphobia."/>
</RelativeLayout>

View File

@@ -29,6 +29,7 @@
android:layout_height="wrap_content"
android:layout_gravity="top"
android:textAppearance="@style/m3_body_large"
android:textSize="16sp"
android:textColor="?colorM3OnSurface"
tools:text="No discrimination, including (but not limited to) racism, sexism, homophobia or transphobia."/>

View File

@@ -2,11 +2,14 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_height="wrap_content"
android:minHeight="56dp"
android:gravity="center_vertical|start"
android:textAlignment="viewStart"
android:textColor="?colorM3OnSurface"
android:textAppearance="@style/m3_body_large"
android:textSize="16sp"
android:paddingVertical="14dp"
android:singleLine="true"
android:ellipsize="end"
android:paddingLeft="24dp"

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<org.joinmastodon.android.ui.views.CustomScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_bottom_sheet">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp">
<View
android:id="@+id/handle"
android:layout_width="match_parent"
android:layout_height="36dp"
android:background="@drawable/bg_bottom_sheet_handle"/>
<ImageView
android:id="@+id/icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_below="@id/handle"
android:layout_alignParentStart="true"
android:layout_marginEnd="16dp"
android:background="@drawable/white_circle"
android:backgroundTint="?colorM3PrimaryContainer"
android:scaleType="center"
android:tint="?colorM3OnPrimaryContainer"
tools:src="@drawable/ic_waving_hand_24px"
android:importantForAccessibility="no"/>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/icon"
android:layout_below="@id/handle"
android:layout_marginBottom="4dp"
android:textAppearance="@style/m3_title_large"
android:fontFamily="sans-serif"
android:textColor="?colorM3OnSurface"
tools:text="@string/non_mutual_sheet_title"/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:layout_toEndOf="@id/icon"
android:textAppearance="@style/m3_body_medium"
tools:text="@string/non_mutual_sheet_text"/>
<LinearLayout
android:id="@+id/content_wrap"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/text"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:minHeight="8dp"
android:orientation="vertical"/>
<Button
android:id="@+id/btn_got_it"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_below="@id/content_wrap"
android:layout_marginBottom="8dp"
style="@style/Widget.Mastodon.M3.Button.Tonal"
android:text="@string/got_it"/>
<Button
android:id="@+id/btn_dont_remind_again"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_below="@id/btn_got_it"
android:layout_marginBottom="8dp"
style="@style/Widget.Mastodon.M3.Button.Text"
android:text="@string/dont_remind_again"/>
</RelativeLayout>
</org.joinmastodon.android.ui.views.CustomScrollView>

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/delete" android:showAsAction="always" android:icon="@drawable/ic_delete_24px" android:title="@string/delete"/>
</menu>

View File

@@ -18,9 +18,9 @@
<string name="poll_ended">الاطلاع على نتائج استطلاع الرأي الذي صوّت فيه</string>
<string name="share_toot_title">شارك</string>
<string name="settings">الإعدادات</string>
<string name="publish">انشر</string>
<string name="discard_draft">أتريد التخلص من المسودة؟</string>
<string name="discard">تخلص</string>
<string name="publish">نَشر</string>
<string name="discard_draft">أتريد إلغاء المسودة؟</string>
<string name="discard">إلغاء</string>
<string name="cancel">إلغاء</string>
<plurals name="followers">
<item quantity="zero">لا متابِعين</item>
@@ -211,19 +211,7 @@
<string name="password">كلمة المرور</string>
<string name="confirm_password">تأكيد كلمة المرور</string>
<string name="password_note">ضمّن الأحرف الكبيرة والأحرف الخاصة والأرقام لزيادة قوة كلمة المرور.</string>
<string name="category_academia">أكاديمي</string>
<string name="category_activism">النشطاء</string>
<string name="category_all">الكل</string>
<string name="category_art">فنون</string>
<string name="category_food">طعام</string>
<string name="category_furry">حيوان ذو فرو</string>
<string name="category_games">ألعاب</string>
<string name="category_general">عام</string>
<string name="category_journalism">صحافة</string>
<string name="category_lgbt">مجتمع الميم</string>
<string name="category_music">موسيقى</string>
<string name="category_regional">إقليمي</string>
<string name="category_tech">تقني</string>
<string name="confirm_email_title">تحقق من صندوق الوارد الخاص بك</string>
<!-- %s is the email address -->
<string name="confirm_email_subtitle">اضغط على الرابط الذي أرسلناه إليك للتحقق من %s. سننتظر هنا.</string>
@@ -314,6 +302,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">هذه هي جميع المشاركات من جميع المستخدمين في الخادم الخاص بك (%s).</string>
<string name="recommended_accounts_info_banner">قد تعجبك هذه الحسابات استنادا إلى حسابات أخرى تتابعها.</string>
<string name="see_new_posts">المنشورات الجديدة</string>
<string name="load_missing_posts">حمّل المَنشورات المَفقودَة</string>
<string name="follow_back">رُدّ المتابعة</string>
<string name="button_follow_pending">معلق</string>
@@ -352,7 +341,6 @@
<item quantity="many">أعيد نشره %,d مرات</item>
<item quantity="other">أعيد نشره %,d مرات</item>
</plurals>
<string name="timestamp_via_app">%1$s عبر %2$s</string>
<string name="time_now">الآن</string>
<string name="edit_history">تاريخ التعديل</string>
<string name="last_edit_at_x">آخر تعديل %s</string>
@@ -432,7 +420,6 @@
<string name="profile_add_row">إضافة صف</string>
<string name="profile_setup">إعداد الملف الشخصي</string>
<string name="profile_setup_subtitle">يمكنك دائماً إكمال هذا في وقت لاحق في علامة التبويب الملف الشخصي.</string>
<string name="profile_setup_explanation">يمكنك إضافة ما يصل إلى أربعة حقول شخصية لأي شيء تريده. الموقع، الروابط، الضمائر - السماء هي الحد الأقصى.</string>
<string name="popular_on_mastodon">مشهور على ماستدون</string>
<string name="follow_all">اتبع الكل</string>
<string name="server_rules_disagree">لا أوافق</string>
@@ -703,6 +690,9 @@
<string name="post_translated">مُترجَم مِن %1$s باستخدام %2$s</string>
<string name="translation_show_original">إظهار الأصل</string>
<string name="translation_failed">فشِلَت الترجَمة. قد لم يتمكّن مدير الخادم من تفعيل الترجمات على هذا الخادم أو أنّ هذا الخادم يُشغِّل نسخة قديمة من ماستدون حيث الترجمات غير مدعومة بعد.</string>
<string name="settings_privacy">الخصوصية و الوصول</string>
<string name="settings_discoverable">ميزة الملف الشخصي والمشاركات في خوارزميات الاكتشاف</string>
<string name="settings_indexable">تضمين المشاركات العامة في نتائج البحث</string>
<plurals name="x_participants">
<item quantity="zero">لا مُشارِك</item>
<item quantity="one">مشارِك واحد</item>
@@ -711,7 +701,44 @@
<item quantity="many">مُشارِكًا</item>
<item quantity="other">مُشارك</item>
</plurals>
<string name="error_playing_video">خطأ في تشغيل الفيديو</string>
<string name="timeline_following">الصفحة الرئيسية</string>
<string name="lists">القوائم</string>
<string name="followed_hashtags">الوسوم المتابَعة</string>
<string name="manage_lists">إدارة القوائم</string>
<string name="manage_hashtags">إدارة الوسوم</string>
<!-- Screen reader description for the menu on the home timeline screen -->
<string name="dropdown_menu">القائمة المنسدلة</string>
<string name="edit_list">تعديل القائمة</string>
<string name="list_members">قائمة الاعضاء</string>
<string name="delete_list">حذف القائمة</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">حذف \"%s\"؟</string>
<string name="list_exclusive">إخفاء الأعضاء في المتابعة</string>
<string name="list_exclusive_subtitle">إذا كان هناك شخص ما في هذه القائمة، فقم بإخفائه في مخططك الزمني لتجنب رؤية مشاركاته مرتين.</string>
<string name="list_name">اسم القائمة</string>
<string name="list_show_replies_to">إظهار الردود على</string>
<string name="list_replies_no_one">لا أحد</string>
<string name="list_replies_members">أعضاء القائمة</string>
<string name="list_replies_anyone">أي شخص أتابعه</string>
<string name="confirm_remove_list_members">إزالة أعضاء؟</string>
<string name="remove">إزالة</string>
<string name="add_list_member">إضافة عضو</string>
<string name="search_among_people_you_follow">البحث بين الأشخاص الذين تتابعهم</string>
<string name="add_user_to_list">إضافة القائمة…</string>
<string name="add_user_to_list_title">إضافة إلى القائمة</string>
<!-- %s is a username -->
<string name="remove_from_list">إزالة من القائمة</string>
<string name="confirm_remove_list_member">إزالة عضو؟</string>
<string name="no_followed_hashtags_title">مواكبة الاهتمامات من خلال متابعة الوسوم</string>
<string name="no_followed_hashtags_subtitle">سوف تظهر المتابعات هنا</string>
<string name="no_lists_title">تنظيم موجزك باستخدام القوائم</string>
<string name="manage_accounts">إضافة أو تبديل الحسابات</string>
<string name="create_list">إنشاء قائمة</string>
<string name="step_x_of_y">الخطوة %1$d من %2$d</string>
<string name="create">إنشاء</string>
<string name="manage_list_members">إدارة قائمة الأعضاء</string>
<string name="list_no_members">لا أعضاء حتى الآن</string>
<string name="list_find_users">البحث عن مستخدمين للإضافة</string>
<!-- %s is a time interval ("5 months") -->
</resources>

View File

@@ -15,6 +15,7 @@
<string name="user_sent_follow_request">%s адправіў вам запыт на падпіску</string>
<string name="user_favorited">%s упадабаў ваш допіс</string>
<string name="notification_boosted">%s пашырыў ваш допіс</string>
<string name="poll_ended">Прагляд вынікаў апытання, у якім вы прынялі ўдзел</string>
<string name="share_toot_title">Абагуліць</string>
<string name="settings">Налады</string>
<string name="publish">Апублікаваць</string>
@@ -186,19 +187,7 @@
<string name="password">Пароль</string>
<string name="confirm_password">Пацвердзіць пароль</string>
<string name="password_note">Выкарыстоўвайце вялікія літары, спецыяльныя сімвалы і лічбы, каб павялічыць надзейнасць пароля.</string>
<string name="category_academia">Акадэмія</string>
<string name="category_activism">Актывізм</string>
<string name="category_all">Усе</string>
<string name="category_art">Мастацтва</string>
<string name="category_food">Ежа</string>
<string name="category_furry">Furry</string>
<string name="category_games">Гульні</string>
<string name="category_general">Асноўныя</string>
<string name="category_journalism">Журналістыка</string>
<string name="category_lgbt">ЛГБТ</string>
<string name="category_music">Музыка</string>
<string name="category_regional">Рэгіянальныя</string>
<string name="category_tech">Тэхналогіі</string>
<string name="confirm_email_title">Праверце паштовую скрыню</string>
<!-- %s is the email address -->
<string name="confirm_email_subtitle">Націсніце на спасылку, якую мы адправілі, каб спраўдзіць %s. Мы вас пачакаем тут.</string>
@@ -222,9 +211,16 @@
<string name="notification_type_poll">Апытанні</string>
<string name="choose_account">Выберыце ўліковы запіс</string>
<string name="err_not_logged_in">Спачатку ўвайдзіце ў Mastodon</string>
<plurals name="cant_add_more_than_x_attachments">
<item quantity="one">Вы не можаце дадаць больш за %d далучэнне</item>
<item quantity="few">Вы не можаце дадаць больш за %d далучэнняў</item>
<item quantity="many">Вы не можаце дадаць больш за %d далучэнняў</item>
<item quantity="other">Вы не можаце дадаць больш за %d далучэнняў</item>
</plurals>
<string name="media_attachment_unsupported_type">Тып файла %s не падтрымліваецца</string>
<string name="media_attachment_too_big">Памер файла %1$s перавышае абмежаванне ў %2$s МБ</string>
<string name="settings_theme">Знешні выгляд</string>
<string name="theme_auto">Выкарыстоўваць сістэмную тэму</string>
<string name="theme_light">Светлая</string>
<string name="theme_dark">Цёмная</string>
<string name="settings_behavior">Паводзіны</string>
@@ -237,6 +233,8 @@
<string name="settings_clear_cache">Ачысціць кэш медыя</string>
<string name="settings_app_version">Mastodon для Android v%1$s (%2$d)</string>
<string name="media_cache_cleared">Кэш медыя ачышчаны</string>
<string name="confirm_log_out">Выйсці з %s?</string>
<string name="sensitive_content_explain">Аўтар пазначыў гэтае медыя як адчувальнае.</string>
<string name="avatar_description">Перайсці да профілю %s</string>
<string name="more_options">Больш опцый</string>
<string name="new_post">Новы допіс</string>
@@ -271,8 +269,14 @@
<string name="error_saving_file">Памылка пры захаванні файла</string>
<string name="file_saved">Файл захаваны</string>
<string name="downloading">Спампоўванне…</string>
<string name="no_app_to_handle_action">Няма патрэбнай праграмы для гэтага дзеяння</string>
<string name="local_timeline">Лакальнае</string>
<string name="trending_posts_info_banner">Гэтыя допісы набіраюць папулярнасць у Mastodon.</string>
<string name="trending_links_info_banner">Гэта навіны, аб якіх кажуць на Mastodon.</string>
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Гэта ўсе допісы ад усіх карыстальнікаў на вашым серверы (%s).</string>
<string name="recommended_accounts_info_banner">Вам могуць спадабацца гэтыя ўліковыя запісы на аснове вашых падпісак.</string>
<string name="see_new_posts">Новыя допісы</string>
<string name="load_missing_posts">Загрузіць адсутныя допісы</string>
<string name="follow_back">Падпісацца ў адказ</string>
<string name="button_follow_pending">Чакаюць</string>
@@ -303,7 +307,6 @@
<item quantity="many">%,d пашырэнняў</item>
<item quantity="other">%,d пашырэння</item>
</plurals>
<string name="timestamp_via_app">%1$s праз %2$s</string>
<string name="time_now">толькі што</string>
<string name="edit_history">Гісторыя рэдагавання</string>
<string name="last_edit_at_x">Апошняе рэдагаванне %s</string>
@@ -361,6 +364,7 @@
<string name="login_title">З вяртаннем</string>
<string name="login_subtitle">Увайдзіце з дапамогай сервера, на якім вы стварылі свой уліковы запіс.</string>
<string name="server_url">URL-адрас сервера</string>
<string name="signup_random_server_explain">Мы абярэм сервер на аснове вашай мовы, калі вы працягнеце без выбару.</string>
<string name="server_filter_any_language">Любая мова</string>
<string name="server_filter_instant_signup">Імгненная рэгістрацыя</string>
<string name="server_filter_manual_review">Ручная праверка</string>
@@ -378,7 +382,6 @@
<string name="profile_add_row">Дадаць радок</string>
<string name="profile_setup">Налады профілю</string>
<string name="profile_setup_subtitle">Вы можаце завяршыць гэта пазней на ўкладцы Профіль.</string>
<string name="profile_setup_explanation">Вы можаце дадаць да чатырох палёў профіля для ўсяго, што хочаце. Месцазнаходжанне, спасылкі, займеннікі - няма мяжы магчымасцям.</string>
<string name="popular_on_mastodon">Папулярна на Mastodon</string>
<string name="follow_all">Падпісацца на ўсіх</string>
<string name="server_rules_disagree">Не згодны</string>
@@ -389,11 +392,16 @@
<!-- Shown in a progress dialog when you tap "follow all" -->
<string name="sending_follows">Падпісваемся…</string>
<!-- %1$s is server domain, %2$s is email domain. You can reorder these placeholders to fit your language better. -->
<string name="signup_email_domain_blocked">%1$s не дазваляе зарэгістравацца ад %2$s. Паспрабуйце іншы ці &lt;a&gt;выберыце іншы сервер&lt;/a&gt;.</string>
<string name="spoiler_show">Усё адно паказаць</string>
<string name="spoiler_hide">Схаваць зноў</string>
<string name="poll_multiple_choice">Абярыце адзін або некалькі</string>
<string name="save_changes">Захаваць змены</string>
<string name="profile_featured">Рэкамендаванае</string>
<string name="profile_timeline">Стужка</string>
<string name="view_all">Праглядзець усё</string>
<string name="profile_endorsed_accounts">Уліковыя запісы</string>
<string name="verified_link">Правераная спасылка</string>
<string name="show">Паказаць</string>
<string name="hide">Схаваць</string>
<string name="join_default_server">Далучыцца да %s</string>
@@ -403,30 +411,75 @@
<string name="welcome_to_mastodon">Вітаем у Mastodon</string>
<string name="welcome_paragraph1">Mastodon - гэта дэцэнтралізаваная сацыяльная сетка, што азначае, што ні адна кампанія не кантралюе яе. Яна складаецца з мноства незалежна працуючых сервераў, злучаных разам.</string>
<string name="what_are_servers">Што такое серверы?</string>
<string name="welcome_paragraph2">Кожны ўліковы запіс Mastodon размяшчаецца на серверы - кожны са сваімі каштоўнасцямі, правіламі, &amp; адміністратарамі. Незалежна ад таго, які сервер вы вылучыце, вы можаце сачыць і ўзаемадзейнічаць з людзьмі на любым серверы.</string>
<string name="opening_link">Адкрыццё спасылкі…</string>
<string name="link_not_supported">Гэтая спасылка не падтрымліваецца ў праграме</string>
<string name="log_out_all_accounts">Выйсці з усіх уліковых запісаў</string>
<string name="confirm_log_out_all_accounts">Выйсці з усіх уліковых запісаў?</string>
<string name="retry">Паўтарыць</string>
<string name="post_failed">Не ўдалося адправіць допіс</string>
<!-- %s is formatted file size ("467 KB image") -->
<string name="attachment_description_image">%s выява</string>
<string name="attachment_description_video">%s відэа</string>
<string name="attachment_description_audio">%s аўдыё</string>
<string name="attachment_description_unknown">%s файл</string>
<string name="attachment_type_image">Выява</string>
<string name="attachment_type_video">Відэа</string>
<string name="attachment_type_audio">Аўдыё</string>
<string name="attachment_type_gif">GIF</string>
<string name="attachment_type_unknown">Файл</string>
<string name="attachment_x_percent_uploaded">%d%% загружана</string>
<string name="add_poll_option">Дадаць варыянт адказу</string>
<string name="poll_length">Тэрмін апытання</string>
<string name="poll_style">Стыль</string>
<string name="compose_poll_single_choice">Адзін варыянт</string>
<string name="compose_poll_multiple_choice">Некалькі варыянтаў</string>
<string name="delete_poll_option">Выдаліць варыянт адказу</string>
<string name="poll_style_title">Стыль апытання</string>
<string name="alt_text">Альтэрнатыўны тэкст</string>
<string name="help">Даведка</string>
<string name="what_is_alt_text">Што такое альтэрнатыўны тэкст?</string>
<string name="alt_text_help">Альтэрнатыўны тэкст змяшчае апісанні выяў для людзей з парушэннямі зроку, нізкахуткаснымі злучэннямі або тых, хто шукае дадатковы кантэкст.\n\nВы можаце палепшыць даступнасць і разуменне для ўсіх, напісаўшы ясны і кароткі альтэрнатыўны тэкст.\n\n<ul><li>Адзначце важныя элементы</li>\n<li>Ахоплівайце тэкст выявам</li>\n<li>Выкарыстоўвайце звычайную структуру прапаноў</li>\n<li>Пазбягайце лішняй інфармацыі</li>\n<li>Засяродзьцеся на тэндэнцыях і ключавых высновах у складаных візуальных формах (напрыклад, дыяграмах або картах)</li></ul></string>
<string name="edit_post">Рэдагаваць допіс</string>
<string name="no_verified_link">Няма спраўджанай спасылкі</string>
<string name="compose_autocomplete_emoji_empty">Агляд emoji</string>
<string name="compose_autocomplete_users_empty">Знайдзіце тых, каго шукаеце</string>
<string name="no_search_results">Нічога не знойдзена па гэтым запыце</string>
<string name="language">Мова</string>
<string name="language_default">Перадвызначана</string>
<string name="language_system">Сістэма</string>
<string name="language_detecting">Вызначэнне мовы</string>
<string name="language_cant_detect">Не ўдалося вызначыць мову</string>
<string name="language_detected">Выяўлена</string>
<string name="media_hidden">Медыя схавана</string>
<string name="post_hidden">Допіс схаваны</string>
<string name="report_title_post">Паскардзіцца на допіс</string>
<string name="forward_report_explanation">Уліковы запіс належыць іншаму серверу. Адправіць туды ананімную копію гэтай справаздачы?</string>
<!-- %s is the server domain -->
<string name="forward_report_to_server">Пераслаць на %s</string>
<!-- Shown on the "stamp" on the screen that appears after you report a post/user. Please keep the translation short, preferably a single word -->
<string name="reported">Паведамлена</string>
<string name="report_unfollow_explanation">Каб больш не бачыць іх допісы ў вашай стужцы, адмяніце падпіску на іх.</string>
<string name="muted_user">Ігнараваць %s</string>
<string name="report_sent_already_blocked">Вы ўжо заблакіравалі гэтага карыстальніка, таму вам больш нічога не трэба рабіць, пакуль мы разглядаем ваша данясенне.</string>
<string name="report_personal_already_blocked">Вы ўжо заблакіравалі гэтага карыстальніка, таму больш нічога рабіць не трэба.\n\nДзякуй, што дапамагаеце захаваць Mastodon бяспечным месцам для ўсіх!</string>
<string name="blocked_user">Заблакіраваць %s</string>
<string name="mark_all_notifications_read">Адзначыць усё як прачытанае</string>
<string name="settings_display">Адлюстраванне</string>
<string name="settings_filters">Фільтры</string>
<string name="settings_server_explanation">Агульныя звесткі, правілы, мадэратары</string>
<!-- %s is the app name (Mastodon, key app_name). I made it a placeholder so everything Just Works™ with forks -->
<string name="about_app">Аб %s</string>
<string name="default_post_language">Мова допісаў па змаўчанні</string>
<string name="settings_alt_text_reminders">Даданне напамінаў пра тэкст alt</string>
<string name="settings_confirm_unfollow">Спытайце, перш чым адпісацца ад каго-небудзь</string>
<string name="settings_confirm_boost">Пытаць перад пашырэннем</string>
<string name="settings_confirm_delete_post">Спытаць перад выдаленнем допісаў</string>
<string name="pause_all_notifications">Прыпыніць усе</string>
<string name="pause_notifications_off">Выкл.</string>
<string name="notifications_policy_anyone">Кожны</string>
<string name="notifications_policy_followed">Людзі, якія падпісаны на вас</string>
<string name="notifications_policy_follower">Людзі, на якіх вы падпісаны</string>
<string name="notifications_policy_no_one">Ніхто</string>
<string name="settings_notifications_policy">Атрымліваць апавяшчэнні ад</string>
<string name="notification_type_mentions_and_replies">Згадванні і адказы</string>
@@ -445,9 +498,19 @@
<!-- %s is the timestamp ("tomorrow at 12:34") -->
<string name="pause_notifications_ends">Скончыцца %s</string>
<!-- %s is the timestamp ("tomorrow at 12:34") -->
<string name="pause_notifications_banner">Апавяшчэнні адновяцца %s.</string>
<string name="resume_notifications_now">Аднавіць зараз</string>
<string name="open_system_notification_settings">Перайсці ў налады апавяшчэнняў</string>
<string name="about_server">Пра сервер</string>
<string name="server_rules">Правілы</string>
<string name="server_administrator">Адміністратар</string>
<string name="send_email_to_server_admin">Напісаць адміністратару</string>
<string name="notifications_disabled_in_system">Уключыце апавяшчэння ў наладах прылады, каб бачыць абнаўлення адкуль згодна.</string>
<string name="settings_even_more">Яшчэ больш налад</string>
<string name="settings_show_cws">Паказваць папярэджанні аб змесце</string>
<string name="settings_hide_sensitive_media">Хаваць медыя пазначаныя як далікатныя</string>
<string name="settings_show_interaction_counts">Паказваць колькасць узаемадзеянняў пад допісамі</string>
<string name="settings_show_emoji_in_names">Карыстальніцкія emoji у імёнах</string>
<plurals name="in_x_seconds">
<item quantity="one">праз %d секунду</item>
<item quantity="few">праз %d секунды</item>
@@ -472,41 +535,78 @@
<item quantity="many">%d гадзін таму</item>
<item quantity="other">%d гадзіны таму</item>
</plurals>
<string name="alt_text_reminder_title">У медыя адсутнічае альтэрнатыўны тэкст</string>
<plurals name="alt_text_reminder_x_images">
<item quantity="one">%s выявы не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
<item quantity="few">%s выявы не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
<item quantity="many">%s выявы не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
<item quantity="other">%s выявы не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
</plurals>
<plurals name="alt_text_reminder_x_attachments">
<item quantity="one">%s медыя далучэнні не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
<item quantity="few">%s медыя далучэнні не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
<item quantity="many">%s медыя далучэнні не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
<item quantity="other">%s медыя далучэнні не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
</plurals>
<string name="count_one">Адзін</string>
<string name="count_two">Два</string>
<string name="count_three">Тры</string>
<string name="count_four">Чатыры</string>
<string name="alt_text_reminder_post_anyway">Допіс</string>
<!-- %s is the username -->
<string name="unfollow_confirmation">Адпісацца ад %s?</string>
<string name="filter_active">Актыўны</string>
<string name="filter_inactive">Неактыўны</string>
<string name="settings_add_filter">Дадаць фільтр</string>
<string name="settings_edit_filter">Рэдагаваць фільтр</string>
<string name="settings_filter_duration">Працягласць</string>
<string name="settings_filter_muted_words">Ігнараваныя словы</string>
<string name="settings_filter_context">Ігнараваць</string>
<string name="settings_filter_show_cw">Паказаць з папярэджаннем аб змесце</string>
<string name="settings_filter_show_cw_explanation">Па-ранейшаму паказваць допісы, якія адпавядаюць гэтаму фільтру, але з папярэджаннем аб змесце</string>
<string name="settings_delete_filter">Выдаліць фільтр</string>
<string name="filter_duration_forever">Назаўсёды</string>
<!-- %s is the timestamp ("tomorrow at 12:34") -->
<string name="settings_filter_ends">Скончыцца %s</string>
<plurals name="settings_x_muted_words">
<item quantity="one">%d заглушанае слова ці фраза</item>
<item quantity="few">%d заглушаных слоў ці фраз</item>
<item quantity="many">%d заглушаных слоў ці фраз</item>
<item quantity="other">%d заглушаных слоў ці фраз</item>
</plurals>
<string name="selection_2_options">%1$s і %2$s</string>
<string name="selection_3_options">%1$s, %2$s і %3$s</string>
<string name="selection_4_or_more">%1$s, %2$s і %3$d больш</string>
<string name="filter_context_home_lists">Галоўная &amp; спісы</string>
<string name="filter_context_notifications">Апавяшчэнні</string>
<string name="filter_context_public_timelines">Публічныя стужкі</string>
<string name="filter_context_threads_replies">Ланцугі &amp; адказы</string>
<string name="filter_context_profiles">Профілі</string>
<string name="settings_filter_title">Загаловак</string>
<string name="settings_delete_filter_title">Выдаліць фільтр \"%s\"?</string>
<string name="settings_delete_filter_confirmation">Гэты фільтр будзе выдалены з уліковага запісу на ўсіх вашых прыладах.</string>
<string name="add_muted_word">Дадаць слова да ігнаруемых</string>
<string name="edit_muted_word">Рэдагаваць ігнараванае слова</string>
<string name="add">Дадаць</string>
<string name="filter_word_or_phrase">Слова або фраза</string>
<string name="filter_add_word_help">Словы адчувальныя да рэгістра і павінны супадаць з поўным словам.\n\nКалі адфільтраваць слова «яблык», будуць схаваны паведамленні са словам «яблык» або «ЯбЛыК», але не, напрыклад, «яблычны».</string>
<string name="settings_delete_filter_word">Выдаліць слова \"%s\"?</string>
<string name="enter_selection_mode">Выбраць</string>
<string name="select_all">Выбраць усё</string>
<string name="settings_filter_duration_title">Працягласць фільтра</string>
<string name="filter_duration_custom">Уласнае</string>
<plurals name="settings_delete_x_filter_words">
<item quantity="one">Выдаліць %d слова?</item>
<item quantity="few">Выдаліць %d словы?</item>
<item quantity="many">Выдаліць %d словаў?</item>
<item quantity="other">Выдаліць %d слова?</item>
</plurals>
<plurals name="x_items_selected">
<item quantity="one">%d выбрана</item>
<item quantity="few">%d выбрана</item>
<item quantity="many">%d выбрана</item>
<item quantity="other">%d выбрана</item>
</plurals>
<string name="required_form_field_blank">Не можа быць пустым</string>
<string name="filter_word_already_in_list">Ужо ў спісе</string>
<string name="app_update_ready">Абнаўленне праграмы гатова</string>
@@ -527,8 +627,73 @@
<string name="time_hours_ago_short">%d г таму</string>
<string name="time_days_ago_short">%d дз таму</string>
<!-- %s is the name of the post language -->
<string name="translate_post">Перакласці з %s</string>
<!-- %1$s is the language, %2$s is the name of the translation service -->
<string name="post_translated">Перакладзена з %1$s з дапамогай %2$s</string>
<string name="translation_show_original">Паказаць арыгінал</string>
<string name="translation_failed">Збой перакладу. Магчыма, адміністратар не ўключыў пераклады на гэтым серверы або гэты сервер працуе са старой версіяй Mastodon, дзе пераклады яшчэ не падтрымліваюцца.</string>
<string name="settings_privacy">Прыватнасць і дасяжнасць</string>
<string name="settings_discoverable">Уключыць профіль і допісы ў алгарытмы рэкамендацый</string>
<string name="settings_indexable">Індэксаваць публічныя допісы ў пошукавых сістэмах</string>
<plurals name="x_participants">
<item quantity="one">%,d удзельнік</item>
<item quantity="few">%,d удзельнікаў</item>
<item quantity="many">%,d удзельнікаў</item>
<item quantity="other">%,d удзельнікі</item>
</plurals>
<plurals name="x_posts_today">
<item quantity="one">%,d допіс сёння</item>
<item quantity="few">%,d допісаў сёння</item>
<item quantity="many">%,d допісаў сёння</item>
<item quantity="other">%,d допісы сёння</item>
</plurals>
<string name="error_playing_video">Памылка прайгравання відэа</string>
<string name="timeline_following">Галоўная</string>
<string name="lists">Спісы</string>
<string name="followed_hashtags">Адсочваныя хэштэгі</string>
<string name="manage_lists">Кіраванне спісамі</string>
<string name="manage_hashtags">Кіраванне хэштэгамі</string>
<!-- Screen reader description for the menu on the home timeline screen -->
<string name="dropdown_menu">Раскрываючаеся меню</string>
<string name="edit_list">Рэдагаваць спіс</string>
<string name="list_members">Спіс удзельнікаў</string>
<string name="delete_list">Выдаліць спіс</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">Выдаліць “%s”?</string>
<string name="list_exclusive">Схаваць удзельнікаў у падпісках</string>
<string name="list_exclusive_subtitle">Калі нехта ёсць у гэтым спісе, схавайце яго ў стужцы падпісак, каб яго допісы не з\'яўляліся двойчы.</string>
<string name="list_name">Назва спіса</string>
<string name="list_show_replies_to">Паказаць адказы да</string>
<string name="list_replies_no_one">Ніводны</string>
<string name="list_replies_members">Удзельнікі гэтага спісу</string>
<string name="list_replies_anyone">Нехта, на каго я падпісаны</string>
<string name="confirm_remove_list_members">Выдаліць удзельнікаў?</string>
<string name="remove">Выдаліць</string>
<string name="add_list_member">Дадаць удзельніка</string>
<string name="search_among_people_you_follow">Шукайце сярод людзей, на якіх Вы падпісаны</string>
<string name="add_user_to_list">Дадаць да спісу…</string>
<string name="add_user_to_list_title">Дадаць да спісу</string>
<!-- %s is a username -->
<string name="manage_user_lists">Кіраваць спісамі з %s</string>
<string name="remove_from_list">Выдаліць са спісу</string>
<string name="confirm_remove_list_member">Выдаліць удзельніка?</string>
<string name="no_followed_hashtags_title">Сачыце за інтарэсамі па хэштэгах</string>
<string name="no_followed_hashtags_subtitle">Тут з\'явяцца хэштэгі</string>
<string name="no_lists_title">Арганізуйце сваю стужку з дапамогай спісаў</string>
<string name="no_lists_subtitle">Ваш з\'явіцца тут</string>
<string name="manage_accounts">Дадаць або пераключыць уліковыя запісы</string>
<plurals name="x_posts_recently">
<item quantity="one">%,d нядаўні допіс</item>
<item quantity="few">%,d нядаўніх допісаў</item>
<item quantity="many">%,d нядаўніх допісаў</item>
<item quantity="other">%,d нядаўнія допісы</item>
</plurals>
<string name="create_list">Ствараць спiс</string>
<string name="step_x_of_y">Крок %1$d з %2$d</string>
<string name="create">Стварыць</string>
<string name="manage_list_members">Кіраванне ўдзельнікамі спісу</string>
<string name="list_no_members">Пакуль няма ўдзельнікаў</string>
<string name="list_find_users">Знайдзіце карыстальнікаў для дадання</string>
<string name="reply_to_user">Адказаць %s</string>
<!-- %s is a time interval ("5 months") -->
</resources>

View File

@@ -122,10 +122,6 @@
<string name="email">ই-মেইল</string>
<string name="password">পাসওয়ার্ড</string>
<string name="confirm_password">পাসওয়ার্ড নিশ্চিত করুন</string>
<string name="category_lgbt">LGBT</string>
<string name="category_music">সঙ্গীত</string>
<string name="category_regional">আঞ্চলিক</string>
<string name="category_tech">তথ্য-প্রযুক্তি</string>
<string name="confirm_email_title">আপনার ইনবক্স দেখুন</string>
<!-- %s is the email address -->
<string name="open_email_app">ই-মেইল অ্যাপ খুলুন</string>
@@ -204,4 +200,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<!-- %s is a time interval ("5 months") -->
</resources>

View File

@@ -93,19 +93,7 @@
<string name="unfollow">Prestani pratiti</string>
<string name="back">Nazad</string>
<string name="password_note">Koristite velika slova, brojeve i oznake da bi osigurali lozinku.</string>
<string name="category_academia">Akademija</string>
<string name="category_activism">Aktivizam</string>
<string name="category_all">Sve</string>
<string name="category_art">Umjetnost</string>
<string name="category_food">Hrana</string>
<string name="category_furry">Ljubimci</string>
<string name="category_games">Igre</string>
<string name="category_general">Generalno</string>
<string name="category_journalism">Novinarstvo</string>
<string name="category_lgbt">LGBT</string>
<string name="category_music">Muzika</string>
<string name="category_regional">Regionalno</string>
<string name="category_tech">Tehnika</string>
<!-- %s is the email address -->
<string name="resend">Ponovo poslato</string>
<string name="open_email_app">Otvori email</string>
@@ -187,4 +175,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<!-- %s is a time interval ("5 months") -->
</resources>

View File

@@ -136,19 +136,7 @@
<string name="password">Contrasenya</string>
<string name="confirm_password">Confirmar contrasenya</string>
<string name="password_note">Inclou lletres majúscules, caràcters especials i números per augmentar la seguretat de la teva contrasenya.</string>
<string name="category_academia">Acadèmic</string>
<string name="category_activism">Activisme</string>
<string name="category_all">Totes</string>
<string name="category_art">Art</string>
<string name="category_food">Menjar</string>
<string name="category_furry">Furry</string>
<string name="category_games">Jocs</string>
<string name="category_general">General</string>
<string name="category_journalism">Periodisme</string>
<string name="category_lgbt">LGBT</string>
<string name="category_music">Música</string>
<string name="category_regional">Regional</string>
<string name="category_tech">Tecnologia</string>
<string name="confirm_email_title">Comprova la teva safata d\'entrada</string>
<!-- %s is the email address -->
<string name="resend">Reenvia</string>
@@ -226,7 +214,6 @@
<item quantity="one">%,d favorit</item>
<item quantity="other">%,d favorits</item>
</plurals>
<string name="timestamp_via_app">%1$s través de %2$s</string>
<string name="time_now">ara</string>
<string name="edit_history">Editar lhistorial</string>
<string name="last_edit_at_x">Darrera edició: %s</string>
@@ -297,4 +284,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<!-- %s is a time interval ("5 months") -->
</resources>

View File

@@ -187,19 +187,7 @@
<string name="password">Heslo</string>
<string name="confirm_password">Potvrdit heslo</string>
<string name="password_note">Použijte velká písmena, speciální znaky a čísla, abyste zvýšili sílu hesla.</string>
<string name="category_academia">Akademická sféra</string>
<string name="category_activism">Aktivismus</string>
<string name="category_all">Vše</string>
<string name="category_art">Umění</string>
<string name="category_food">Jídlo</string>
<string name="category_furry">Furry</string>
<string name="category_games">Hry</string>
<string name="category_general">Obecné</string>
<string name="category_journalism">Žurnalistika</string>
<string name="category_lgbt">LGBT</string>
<string name="category_music">Hudba</string>
<string name="category_regional">Regionální</string>
<string name="category_tech">Technologie</string>
<string name="confirm_email_title">Zkontrolujte si příchozí poštu</string>
<!-- %s is the email address -->
<string name="confirm_email_subtitle">Klepněte na odkaz, který jsme vám poslali, abyste ověřili %s. Budeme tu na vás čekat.</string>
@@ -318,7 +306,6 @@
<item quantity="many">%,d boostů</item>
<item quantity="other">%,d boostů</item>
</plurals>
<string name="timestamp_via_app">%1$s přes %2$s</string>
<string name="time_now">teď</string>
<string name="edit_history">Historie úprav</string>
<string name="last_edit_at_x">Poslední úprava %s</string>
@@ -394,7 +381,6 @@
<string name="profile_add_row">Přidat řádek</string>
<string name="profile_setup">Nastavení profilu</string>
<string name="profile_setup_subtitle">Toto můžete vždy dokončit později v záložce Profil.</string>
<string name="profile_setup_explanation">Můžete přidat až čtyři pole profilu pro cokoliv, co chcete. Umístění, odkazy, oslovení — limitem je obloha.</string>
<string name="popular_on_mastodon">Populární na Mastodonu</string>
<string name="follow_all">Sledovat všechny</string>
<string name="server_rules_disagree">Nesouhlasit</string>
@@ -643,4 +629,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<!-- %s is a time interval ("5 months") -->
</resources>

View File

@@ -163,19 +163,7 @@
<string name="password">Adgangskode</string>
<string name="confirm_password">Bekræft adgangskode</string>
<string name="password_note">Benyt majuskler, specialtegn og tal for at øge adgangskodens styrke.</string>
<string name="category_academia">Forskning og højere uddannelser</string>
<string name="category_activism">Aktivisme</string>
<string name="category_all">Alt</string>
<string name="category_art">Kunst</string>
<string name="category_food">Mad</string>
<string name="category_furry">Pelsdyr</string>
<string name="category_games">Spil</string>
<string name="category_general">Generelt</string>
<string name="category_journalism">Journalistik</string>
<string name="category_lgbt">LGBT</string>
<string name="category_music">Musik</string>
<string name="category_regional">Regionalt</string>
<string name="category_tech">Teknologi</string>
<string name="confirm_email_title">Tjek din indbakke</string>
<!-- %s is the email address -->
<string name="confirm_email_subtitle">Tryk på det modtage link for at bekræfte %s. Vi venter her så længe.</string>
@@ -284,7 +272,6 @@
<item quantity="one">%,d fremhævning</item>
<item quantity="other">%,d fremhævninger</item>
</plurals>
<string name="timestamp_via_app">%1$s via %2$s</string>
<string name="time_now">nu</string>
<string name="edit_history">Rediger historik</string>
<string name="last_edit_at_x">Senest ændret: %s</string>
@@ -356,7 +343,6 @@
<string name="profile_add_row">Tilføj række</string>
<string name="profile_setup">Profilopsætning</string>
<string name="profile_setup_subtitle">Du kan altid afslutte dette senere i fanen Profil.</string>
<string name="profile_setup_explanation">Du kan tilføje op til fire profilfelter til lige, hvad du ønsker. Placering, links, pronomener — du bestemmer.</string>
<string name="popular_on_mastodon">Populært på Mastodon</string>
<string name="follow_all">Følg alle</string>
<string name="server_rules_disagree">Ikke enig</string>
@@ -507,4 +493,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<!-- %s is a time interval ("5 months") -->
</resources>

View File

@@ -163,19 +163,7 @@
<string name="password">Passwort</string>
<string name="confirm_password">Passwort bestätigen</string>
<string name="password_note">Verwende Großbuchstaben, Sonderzeichen und Zahlen, um deine Passwortstärke zu erhöhen.</string>
<string name="category_academia">Bildung</string>
<string name="category_activism">Bürgerbeteiligung</string>
<string name="category_all">Alle</string>
<string name="category_art">Kunst</string>
<string name="category_food">Essen</string>
<string name="category_furry">Furry</string>
<string name="category_games">Spiele</string>
<string name="category_general">Allgemein</string>
<string name="category_journalism">Journalismus</string>
<string name="category_lgbt">LGBT</string>
<string name="category_music">Musik</string>
<string name="category_regional">Regional</string>
<string name="category_tech">Technik</string>
<string name="confirm_email_title">Überprüfe deinen Posteingang</string>
<!-- %s is the email address -->
<string name="confirm_email_subtitle">Bitte klicke auf den Link, den wir an %s geschickt haben, um dich zu verifizieren. Wir warten bis dahin einfach hier.</string>
@@ -285,7 +273,6 @@
<item quantity="one">%,d geteilter Beitrag</item>
<item quantity="other">%,d geteilte Beiträge</item>
</plurals>
<string name="timestamp_via_app">%1$s via %2$s</string>
<string name="time_now">jetzt</string>
<string name="edit_history">Verlauf bearbeiten</string>
<string name="last_edit_at_x">Zuletzt bearbeitet: %s</string>
@@ -357,7 +344,6 @@
<string name="profile_add_row">Zeile hinzufügen</string>
<string name="profile_setup">Profil einrichten</string>
<string name="profile_setup_subtitle">Du kannst dies jederzeit später auf dem Profil-Reiter vervollständigen.</string>
<string name="profile_setup_explanation">Du kannst bis zu vier Profilfelder für alles, was du möchtest, hinzufügen. Standort, Links, Pronomen - deiner Fantasie sind hier keine Grenzen gesetzt.</string>
<string name="popular_on_mastodon">Beliebt auf Mastodon</string>
<string name="follow_all">Allen folgen</string>
<string name="server_rules_disagree">Ablehnen</string>
@@ -594,8 +580,6 @@
<string name="error_playing_video">Fehler bei Videowiedergabe</string>
<string name="lists">Listen</string>
<string name="followed_hashtags">Gefolgte Hashtags</string>
<string name="no_lists">Du hast noch keine Listen.</string>
<string name="no_followed_hashtags">Du folgst keinen Hashtags.</string>
<string name="manage_lists">Listen verwalten</string>
<string name="manage_hashtags">Hashtags verwalten</string>
<!-- Screen reader description for the menu on the home timeline screen -->
@@ -627,4 +611,11 @@
<string name="no_lists_title">Startseite mit Listen organisieren</string>
<string name="no_lists_subtitle">Deine werden hier erscheinen</string>
<string name="manage_accounts">Konten hinzufügen oder wechseln</string>
<string name="create_list">Liste erstellen</string>
<string name="step_x_of_y">Schritt %1$d von %2$d</string>
<string name="manage_list_members">Listenmitglieder verwalten</string>
<string name="list_no_members">Noch keine Mitglieder</string>
<string name="dont_remind_again">Nicht erneut erinnern</string>
<!-- %s is a time interval ("5 months") -->
<string name="old_post_sheet_title">Dieser Beitrag ist %s alt</string>
</resources>

View File

@@ -163,19 +163,7 @@
<string name="password">Κωδικός πρόσβασης</string>
<string name="confirm_password">Επιβεβαίωση κωδικού πρόσβασης</string>
<string name="password_note">Να συμπεριλάβεις κεφαλαία γράμματα, ειδικούς χαρακτήρες και αριθμούς για να αυξήσεις την ισχύ του κωδικού πρόσβασης.</string>
<string name="category_academia">Ακαδημία</string>
<string name="category_activism">Ακτιβισμός</string>
<string name="category_all">Όλα</string>
<string name="category_art">Τέχνη</string>
<string name="category_food">Φαγητό</string>
<string name="category_furry">Γούνινη</string>
<string name="category_games">Παιχνίδια</string>
<string name="category_general">Γενικά</string>
<string name="category_journalism">Δημοσιογραφία</string>
<string name="category_lgbt">LGBT</string>
<string name="category_music">Μουσική</string>
<string name="category_regional">Τοπικό</string>
<string name="category_tech">Τεχνολογία</string>
<string name="confirm_email_title">Έλεγξε τα Εισερχόμενα σου</string>
<!-- %s is the email address -->
<string name="confirm_email_subtitle">Πάτησε το σύνδεσμο που σού στείλαμε για να επαληθεύσεις το %s. Θα σε περιμένουμε εδώ.</string>
@@ -285,7 +273,6 @@
<item quantity="one">%,d ενίσχυση</item>
<item quantity="other">%,d ενισχύσεις</item>
</plurals>
<string name="timestamp_via_app">%1$s μέσω %2$s</string>
<string name="time_now">τώρα</string>
<string name="edit_history">Επεξεργασία ιστορικού</string>
<string name="last_edit_at_x">Τελευταία επεξεργασία %s</string>
@@ -357,7 +344,6 @@
<string name="profile_add_row">Προσθήκη γραμμής</string>
<string name="profile_setup">Ρύθμιση προφίλ</string>
<string name="profile_setup_subtitle">Μπορείς πάντα να το ολοκληρώσεις αργότερα στην καρτέλα Προφίλ.</string>
<string name="profile_setup_explanation">Μπορείς να προσθέσεις έως και τέσσερα πεδία προφίλ για οτιδήποτε θες. Τοποθεσία, συνδέσμους, αντωνυμίες - δεν υπάρχουν όρια.</string>
<string name="popular_on_mastodon">Δημοφιλή στο Mastodon</string>
<string name="follow_all">Ακολούθησε όλους</string>
<string name="server_rules_disagree">Διαφωνώ</string>
@@ -603,8 +589,6 @@
<string name="timeline_following">Αρχική</string>
<string name="lists">Λίστες</string>
<string name="followed_hashtags">Ετικέτες που ακολουθούνται</string>
<string name="no_lists">Δεν έχεις καμία λίστα ακόμα.</string>
<string name="no_followed_hashtags">Δεν ακολουθείς καμία ετικέτα.</string>
<string name="manage_lists">Διαχείριση λιστών</string>
<string name="manage_hashtags">Διαχείριση ετικετών</string>
<!-- Screen reader description for the menu on the home timeline screen -->
@@ -628,4 +612,5 @@
<string name="add_user_to_list">Προσθήκη στη λίστα…</string>
<string name="add_user_to_list_title">Προσθήκη στη λίστα</string>
<!-- %s is a username -->
<!-- %s is a time interval ("5 months") -->
</resources>

View File

@@ -163,19 +163,7 @@
<string name="password">Contraseña</string>
<string name="confirm_password">Confirmar contraseña</string>
<string name="password_note">Incluye letras mayúsculas, caracteres especiales y números para aumentar la fuerza de tu contraseña.</string>
<string name="category_academia">Académico</string>
<string name="category_activism">Activismo</string>
<string name="category_all">Todas</string>
<string name="category_art">Arte</string>
<string name="category_food">Comida</string>
<string name="category_furry">Furry</string>
<string name="category_games">Juegos</string>
<string name="category_general">General</string>
<string name="category_journalism">Periodismo</string>
<string name="category_lgbt">LGBT</string>
<string name="category_music">Música</string>
<string name="category_regional">Regional</string>
<string name="category_tech">Tecnología</string>
<string name="confirm_email_title">Revisa tu bandeja de entrada</string>
<!-- %s is the email address -->
<string name="confirm_email_subtitle">Pulsa el enlace que te hemos enviado para verificar %s. Esperaremos aquí mismo.</string>
@@ -285,7 +273,6 @@
<item quantity="one">%,d retooteo</item>
<item quantity="other">%,d retooteos</item>
</plurals>
<string name="timestamp_via_app">%1$s a través de %2$s</string>
<string name="time_now">ahora</string>
<string name="edit_history">Editar historial</string>
<string name="last_edit_at_x">Última edición: %s</string>
@@ -357,7 +344,6 @@
<string name="profile_add_row">Añadir fila</string>
<string name="profile_setup">Configuración del perfil</string>
<string name="profile_setup_subtitle">Siempre puedes completar esto más tarde en la pestaña Perfil.</string>
<string name="profile_setup_explanation">Puedes añadir hasta cuatro campos de perfil para todo lo que quieras. Ubicación, enlaces, pronombres — el cielo es el límite.</string>
<string name="popular_on_mastodon">Popular en Mastodon</string>
<string name="follow_all">Seguir a todos</string>
<string name="server_rules_disagree">En desacuerdo</string>
@@ -594,8 +580,6 @@
<string name="error_playing_video">Error al reproducir el video</string>
<string name="lists">Listas</string>
<string name="followed_hashtags">Etiquetas seguidas</string>
<string name="no_lists">Aún no tienes ninguna lista.</string>
<string name="no_followed_hashtags">Aún no sigues ninguna etiqueta.</string>
<string name="manage_lists">Administrar listas</string>
<string name="manage_hashtags">Administrar etiquetas</string>
<!-- Screen reader description for the menu on the home timeline screen -->
@@ -624,4 +608,5 @@
<string name="confirm_remove_list_member">¿Eliminar miembro?</string>
<string name="no_followed_hashtags_title">Manténgase al día con los intereses siguiendo las etiquetas</string>
<string name="no_followed_hashtags_subtitle">Los seguidores aparecerán aquí</string>
<!-- %s is a time interval ("5 months") -->
</resources>

View File

@@ -162,19 +162,7 @@
<string name="password">Pasahitza</string>
<string name="confirm_password">Berretsi pasahitza</string>
<string name="password_note">Sartu letra larriak, karaktere bereziak eta zenbakiak zure pasahitzaren segurtasuna areagotzeko.</string>
<string name="category_academia">Akademia</string>
<string name="category_activism">Aktibismoa</string>
<string name="category_all">Denak</string>
<string name="category_art">Artea</string>
<string name="category_food">Janaria</string>
<string name="category_furry">Furry</string>
<string name="category_games">Jokoak</string>
<string name="category_general">Orokorra</string>
<string name="category_journalism">Kazetaritza</string>
<string name="category_lgbt">LGBT</string>
<string name="category_music">Musika</string>
<string name="category_regional">Herrialdekoa</string>
<string name="category_tech">Teknologia</string>
<string name="confirm_email_title">Egiaztatu zure sarrerako ontzia</string>
<!-- %s is the email address -->
<string name="confirm_email_didnt_get">Ez duzu estekarik jaso?</string>
@@ -275,7 +263,6 @@
<item quantity="one">Gogoko bat</item>
<item quantity="other">%,d gogoko</item>
</plurals>
<string name="timestamp_via_app">%1$s %2$s -en bidez</string>
<string name="time_now">orain</string>
<string name="edit_history">Editatu historia</string>
<string name="last_edit_at_x">Azken edizioa %s</string>
@@ -352,6 +339,7 @@
<!-- Shown in a progress dialog when you tap "follow all" -->
<!-- %1$s is server domain, %2$s is email domain. You can reorder these placeholders to fit your language better. -->
<string name="spoiler_show">Erakutsi hala ere</string>
<string name="spoiler_hide">Berrezkutatu</string>
<string name="poll_multiple_choice">Aukeratu bat edo gehiago</string>
<string name="save_changes">Gorde aldaketak</string>
<string name="profile_featured">Nabarmenak</string>
@@ -418,6 +406,10 @@
<string name="notifications_policy_follower">Zuk jarraitzen dituzun pertsonak</string>
<string name="notifications_policy_no_one">Bat ere ez</string>
<string name="pause_all_notifications_title">Pausatu jakinarazpen guztiak</string>
<plurals name="x_weeks">
<item quantity="one">aste %d</item>
<item quantity="other">%d aste</item>
</plurals>
<!-- %1$s is the date (may be relative, e.g. "today" or "yesterday"), %2$s is the time. You can reorder these placeholders if that works better for your language -->
<string name="date_at_time">%1$s %2$s-etan</string>
<string name="today">gaur</string>
@@ -428,11 +420,24 @@
<string name="about_server">Honi buruz</string>
<string name="server_rules">Arauak</string>
<string name="server_administrator">Administratzailea</string>
<string name="send_email_to_server_admin">Administratzaileari mezua</string>
<string name="settings_show_cws">Erakutsi eduki abisuak</string>
<plurals name="in_x_seconds">
<item quantity="one">segundo %d barru</item>
<item quantity="other">%d segundo barru</item>
</plurals>
<plurals name="in_x_minutes">
<item quantity="one">minutu %d barru</item>
<item quantity="other">%d minutu barru</item>
</plurals>
<plurals name="in_x_hours">
<item quantity="one">Ordu %d barru</item>
<item quantity="other">%d ordu barru</item>
</plurals>
<plurals name="x_hours_ago">
<item quantity="one">Duela ordu %d</item>
<item quantity="other">Duela %d ordu</item>
</plurals>
<string name="count_one">Bat</string>
<string name="count_two">Bi</string>
<string name="count_three">Hiru</string>
@@ -469,6 +474,7 @@
<string name="search_mastodon">Bilatu Mastodonen</string>
<string name="clear_all">Garbitu dena</string>
<string name="search_open_url">Ireki URLa Mastodonen</string>
<string name="search_go_to_account">Joan hona %s</string>
<!-- Shown in the post header. Please keep it short -->
<string name="time_seconds_ago_short">Duela %d segundo</string>
<string name="time_minutes_ago_short">Duela %d minutu</string>
@@ -480,10 +486,13 @@
<string name="settings_privacy">Pribatutasuna eta irismena</string>
<string name="settings_discoverable">Ezagutarazi profila eta bidalketak bilaketa algoritmoetan</string>
<string name="settings_indexable">Gehitu argitalpen publikoak bilaketa-emaitzetan</string>
<plurals name="x_participants">
<item quantity="one">partaide %,d</item>
<item quantity="other">%d partaide</item>
</plurals>
<string name="timeline_following">Hasiera</string>
<string name="lists">Zerrendak</string>
<string name="followed_hashtags">Jarraitutako traolak</string>
<string name="no_lists">Ez duzu zerrendarik oraindik.</string>
<string name="manage_lists">Kudeatu zerrendak</string>
<string name="manage_hashtags">Kudeatu traolak</string>
<!-- Screen reader description for the menu on the home timeline screen -->
@@ -507,8 +516,11 @@
<!-- %s is a username -->
<string name="remove_from_list">Kendu zerrendatik</string>
<string name="confirm_remove_list_member">Kendu kideak?</string>
<string name="no_lists_subtitle">Zurea hemen agertuko da</string>
<string name="create_list">Sortu zerrenda</string>
<string name="step_x_of_y">%1$d pausua %2$d -(e)tik</string>
<string name="create">Sortu</string>
<string name="manage_list_members">Kudeatu partaide zerrrenda</string>
<string name="list_no_members">Oraindik ez dago kiderik</string>
<!-- %s is a time interval ("5 months") -->
</resources>

View File

@@ -163,19 +163,7 @@
<string name="password">گذرواژه</string>
<string name="confirm_password">تأیید گذرواژه</string>
<string name="password_note">برای افزایش قدرت گذرواژه خود، حروف بزرگ، کاراکترهای خاص و اعداد را اضافه کنید.</string>
<string name="category_academia">دانشگاه</string>
<string name="category_activism">فعالیت</string>
<string name="category_all">همه</string>
<string name="category_art">هنر</string>
<string name="category_food">غذا</string>
<string name="category_furry">خزدار</string>
<string name="category_games">بازی‌ها</string>
<string name="category_general">عمومی</string>
<string name="category_journalism">روزنامه نگاری</string>
<string name="category_lgbt">LGBT</string>
<string name="category_music">موسیقی</string>
<string name="category_regional">منطقه‌ای</string>
<string name="category_tech">فناوری</string>
<string name="confirm_email_title">صندوق ورودیتان را بررسی کنید</string>
<!-- %s is the email address -->
<string name="confirm_email_subtitle">برای تأیید %s، روی پیوندی که برای شما ارسال کردیم ضربه بزنید. همین جا منتظر می‌مانیم.</string>
@@ -285,7 +273,6 @@
<item quantity="one">%,d تقویت</item>
<item quantity="other">%,d تقویت‌ها</item>
</plurals>
<string name="timestamp_via_app">%1$s از طریق %2$s</string>
<string name="time_now">اکنون</string>
<string name="edit_history">ویرایش تاریخچه</string>
<string name="last_edit_at_x">آخرین ویرایش %s</string>
@@ -357,7 +344,6 @@
<string name="profile_add_row">افزودن سطر</string>
<string name="profile_setup">تنظیم نمایه</string>
<string name="profile_setup_subtitle">همیشه می‌توانید این را بعداً در برگه نمایه تکمیل کنید.</string>
<string name="profile_setup_explanation">شما می توانید تا چهار قسمت نمایه برای هر چیزی که می خواهید اضافه کنید. مکان، پیوندها، ضمایر - آسمان حد است.</string>
<string name="popular_on_mastodon">محبوب در ماستودون</string>
<string name="follow_all">پی‌گیری همه</string>
<string name="server_rules_disagree">مخالفم</string>
@@ -603,8 +589,6 @@
<string name="timeline_following">خانه</string>
<string name="lists">سیاهه‌ها</string>
<string name="followed_hashtags">برچسب‌های پی‌گرفته</string>
<string name="no_lists">شما هنوز هیچ سیاهه‌ای ندارید.</string>
<string name="no_followed_hashtags">شما هیچ برچسبی را پی نمی‌گیرید.</string>
<string name="manage_lists">مدیریت سیاهه‌ها</string>
<string name="manage_hashtags">مدیریت برچسب‌ها</string>
<!-- Screen reader description for the menu on the home timeline screen -->
@@ -623,11 +607,16 @@
<string name="confirm_remove_list_members">حذف اعضا؟</string>
<string name="remove">برداشتن</string>
<string name="add_list_member">افزودن عضو</string>
<string name="search_among_people_you_follow">جست‌وجو بین کسانی که پی‌گرفته‌اید</string>
<string name="add_user_to_list">افزودن به سیاهه…</string>
<string name="add_user_to_list_title">افزودن به سیاهه</string>
<!-- %s is a username -->
<string name="remove_from_list">برداشتن از سیاهه</string>
<string name="confirm_remove_list_member">حذف عضو؟</string>
<string name="no_followed_hashtags_title">با پیگیری برچسب‌ها با علاقه‌مندی‌ها همراه باشید</string>
<string name="no_followed_hashtags_subtitle">پیگیرهای شما اینجا ظاهر می‌شود</string>
<string name="no_lists_title">سازماندهی کردن خوراک خانه خود با سیاهه‌ها</string>
<string name="no_lists_subtitle">مال شما اینجا ظاهر می‌شود</string>
<string name="manage_accounts">افزودن یا جابجا شدن بین حساب‌ها</string>
<plurals name="x_posts_recently">
<item quantity="one">%,d فرسته اخیرا ارسال کرده</item>
@@ -639,4 +628,5 @@
<string name="manage_list_members">مدیریت اعضای سیاهه</string>
<string name="list_no_members">هنوز هیچ عضوی نیست</string>
<string name="list_find_users">پیدا کردن کاربرانی برای افزودن</string>
<!-- %s is a time interval ("5 months") -->
</resources>

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