Compare commits

..

164 Commits

Author SHA1 Message Date
sk
c8122aa65b fuck it, production release 2023-10-28 15:09:00 +02:00
sk
ef1584de55 merge upstream strings 2023-10-28 14:50:56 +02:00
sk
3075030b1c add todo 2023-10-27 17:38:54 +02:00
sk
42c56401db fix wrong check for gap item
re sk22#898
2023-10-27 17:34:47 +02:00
sk
a18a4383e5 update gap in database when deleting status
closes sk22#898
2023-10-27 17:19:59 +02:00
sk
375b5b3133 fix gaps not showing time
closes sk22#889
2023-10-27 16:14:16 +02:00
sk
4cab916957 move status list fragment check out of predicate 2023-10-27 16:02:14 +02:00
sk
7902691093 avoid index out of bounds
closes sk22#904
2023-10-27 01:28:27 +02:00
sk
d5d9e20a06 update strings 2023-10-26 18:53:40 +02:00
Codeberg Translate
1eb55428db Update translation files
Updated by "Remove blank strings" hook in Weblate.

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/
2023-10-26 16:39:24 +00:00
reindex
9b82d704f6 Translated using Weblate (Japanese)
Currently translated at 11.1% (2 of 18 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ja/
2023-10-26 16:39:24 +00:00
reindex
dbf3d2776e Translated using Weblate (Japanese)
Currently translated at 86.4% (345 of 399 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ja/
2023-10-26 16:39:24 +00:00
Espasant3
c077b9d47c Translated using Weblate (Galician)
Currently translated at 98.4% (393 of 399 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-10-26 16:39:24 +00:00
kallekn
34157805a1 Translated using Weblate (Finnish)
Currently translated at 100.0% (399 of 399 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fi/
2023-10-26 16:39:24 +00:00
AiOO
576da2a3eb Translated using Weblate (Korean)
Currently translated at 99.2% (396 of 399 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-10-26 16:39:24 +00:00
SomeTr
e99e5b2836 Translated using Weblate (Ukrainian)
Currently translated at 99.7% (398 of 399 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-26 16:39:24 +00:00
Oliebol
fe25974958 Translated using Weblate (Dutch)
Currently translated at 91.7% (366 of 399 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/nl/
2023-10-26 16:39:24 +00:00
Linerly
1a95b4e361 Translated using Weblate (Indonesian)
Currently translated at 100.0% (399 of 399 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-10-26 16:39:24 +00:00
Choukajohn
35e3d5afc4 Translated using Weblate (French)
Currently translated at 100.0% (399 of 399 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-10-26 16:39:24 +00:00
gallegonovato
cc1e13d1bd Translated using Weblate (Spanish)
Currently translated at 100.0% (399 of 399 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-10-26 16:39:24 +00:00
poesty
0b622f8f2a Translated using Weblate (Chinese (Simplified))
Currently translated at 99.7% (398 of 399 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-10-26 16:39:24 +00:00
gallegonovato
9cf7da6419 Translated using Weblate (Spanish)
Currently translated at 100.0% (398 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-10-26 16:39:24 +00:00
sk
812ab7198c revert, i said!
actually, the cached posts limit can stay
2023-10-26 18:38:06 +02:00
sk
e8c9253a76 don't remove gap when removing status
re: sk22#898
2023-10-26 18:32:46 +02:00
sk
c8f633ae3b don't hide gap behind warning
closes sk22#899
2023-10-26 18:23:56 +02:00
sk
af339a833f fix gap time being wrong when next status is own
closes sk22#902
2023-10-26 18:11:54 +02:00
sk
708142e1b8 Revert "refresh data from cache"
This reverts commit 60a998be89.
2023-10-26 17:53:36 +02:00
sk
55f32671c5 Revert "fix timeline breaking when max_id is null"
This reverts commit 289db09770.
2023-10-26 17:52:43 +02:00
sk
289db09770 fix timeline breaking when max_id is null 2023-10-25 14:42:35 +02:00
sk
89d7dfd694 don't globally remove status on refresh
closes sk22#896
2023-10-23 23:55:04 +02:00
sk
60a998be89 refresh data from cache 2023-10-23 01:00:26 +02:00
sk
128e75bc24 fix animatable avatars not playing in notification headers
closes sk22#882
2023-10-22 23:35:09 +02:00
sk
69c60d484c load custom emoji in reply header
closes sk22#886
2023-10-22 23:30:33 +02:00
sk
c70750a508 fix strings 2023-10-22 23:21:47 +02:00
sk
5553ca25a1 Merge remote-tracking branch 'upstream/l10n_master' 2023-10-22 23:10:56 +02:00
sk
ff87829e72 Merge remote-tracking branch 'weblate/main' 2023-10-22 23:09:45 +02:00
sk
02983c76b9 add mutuals follow button state
closes sk22#890
2023-10-22 23:09:35 +02:00
sk
3e28eb2ccf fix polls not updating when behind spoiler
closes sk22#892
2023-10-22 22:39:10 +02:00
sk
3cf23474e3 fix issue with too-wide context menu icons
closes sk22#893
2023-10-22 22:10:25 +02:00
sk
9f0ff2dcd4 fix editing scheduled/drafted polls
closes sk22#894
2023-10-22 21:44:02 +02:00
Eugen Rochko
8ed9fb6276 New translations strings.xml (Chinese Traditional) 2023-10-22 08:53:38 +02:00
SomeTr
df7a0ee490 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (18 of 18 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/uk/
2023-10-21 20:53:12 +00:00
Espasant3
2e360dc275 Translated using Weblate (Galician)
Currently translated at 98.7% (393 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-10-21 20:53:12 +00:00
poesty
8dc88d2fd7 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.7% (397 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-10-21 20:53:12 +00:00
Eugen Rochko
901c70efc3 New translations strings.xml (Icelandic) 2023-10-21 19:24:31 +02:00
Eugen Rochko
3d44e5d2cc New translations strings.xml (Icelandic) 2023-10-21 18:27:37 +02:00
Eugen Rochko
33ea3da84d New translations strings.xml (Basque) 2023-10-21 11:37:37 +02:00
Eugen Rochko
e97203a6e3 New translations strings.xml (Thai) 2023-10-21 09:36:50 +02:00
Eugen Rochko
b3f2987b14 New translations strings.xml (Vietnamese) 2023-10-21 03:54:29 +02:00
Eugen Rochko
c7426453a5 New translations strings.xml (German) 2023-10-21 02:52:53 +02:00
sk
b60c1a5db3 add back old see_new_posts strings 2023-10-21 01:43:03 +02:00
Eugen Rochko
664d5cc4c3 New translations strings.xml (German) 2023-10-21 01:04:51 +02:00
sk
47d1b182ac fix see new posts button design 2023-10-21 01:00:51 +02:00
sk
c33c3d9112 fix compatibility issue 2023-10-21 00:54:38 +02:00
sk
ff99e1023a Revert "use tonal background for see new posts button"
This reverts commit 8009dc0a75.
2023-10-20 16:23:02 +02:00
sk
8009dc0a75 use tonal background for see new posts button 2023-10-20 15:31:06 +02:00
sk
20039ec97e bump version 2023-10-20 13:33:02 +02:00
SomeTr
172d25eeb0 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (398 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-20 11:32:21 +00:00
alextecplayz
fa04e00032 Translated using Weblate (Romanian)
Currently translated at 100.0% (398 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ro/
2023-10-20 11:32:21 +00:00
Linerly
3ff442894d Translated using Weblate (Indonesian)
Currently translated at 100.0% (398 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-10-20 11:32:21 +00:00
Choukajohn
edb0823bf9 Translated using Weblate (French)
Currently translated at 100.0% (398 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-10-20 11:32:21 +00:00
sk
9de83355e1 revert api timeout and increase for search
closes sk22#881
2023-10-20 13:31:27 +02:00
sk
183fb0e8c0 use fluent back button 2023-10-20 12:54:51 +02:00
sk
d624a04e18 fix see new posts button font size 2023-10-20 12:50:34 +02:00
sk
303461d803 take switcher width into account for button 2023-10-20 12:17:12 +02:00
sk
11c7816bb1 make show new posts button less disruptive 2023-10-20 11:43:35 +02:00
sk
b5eae13a16 introduce separate tonal selector backgrounds 2023-10-20 11:43:15 +02:00
sk
59026286a1 don't cache as many posts 2023-10-20 10:46:56 +02:00
sk
ef0fbb26a4 don't return before refreshDone 2023-10-20 10:33:45 +02:00
sk
387b31193f hopefully unfuck removing statuses and reblogs 2023-10-19 21:42:17 +02:00
sk22
95fa547f15 Translated using Weblate (German)
Currently translated at 100.0% (398 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-10-19 15:13:41 +00:00
sk22
3198c9adb1 Translated using Weblate (German)
Currently translated at 99.2% (395 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-10-19 15:07:29 +00:00
SomeTr
e1af6f4643 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (18 of 18 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/uk/
2023-10-19 15:07:29 +00:00
SomeTr
cc52e491b0 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (396 of 396 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-19 15:07:29 +00:00
Choukajohn
b0db0d9f2e Translated using Weblate (French)
Currently translated at 100.0% (396 of 396 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-10-19 15:07:29 +00:00
sk
d699788a12 fix string 2023-10-19 17:07:18 +02:00
sk
bdbf441e1a Merge remote-tracking branch 'upstream/l10n_master' 2023-10-19 17:01:46 +02:00
sk
0deba2885b Merge remote-tracking branch 'weblate/main' 2023-10-19 17:01:13 +02:00
sk
48b39fd3bc boop version 2023-10-19 16:59:45 +02:00
sk
875b235e6d restart when show replies/boosts changes
closes sk22#879
2023-10-19 16:58:26 +02:00
sk
1711682322 don't display extra text if visibility == local 2023-10-19 16:54:23 +02:00
sk
70f5ec7500 update header layout 2023-10-19 16:54:07 +02:00
sk
d34c73c210 add options for locking account and default vis 2023-10-19 16:49:23 +02:00
sk
50a0586e8a fix content type index and title 2023-10-19 16:02:51 +02:00
Jacoco
1d2ca1e500 fix: hiding discovery on Akkoma + hiding privacy settings (#867)
* Hide privacy settings on Akkoma

* Fix Akkoma skipping discovery

* Make settings order more clear in the code
2023-10-19 15:42:29 +02:00
EndermanCo
34b7123a8d Translated using Weblate (Persian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fa/
2023-10-19 10:17:38 +00:00
butterflyoffire
ec718ff58e Translated using Weblate (Arabic)
Currently translated at 80.4% (317 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ar/
2023-10-19 10:17:38 +00:00
ihor_ck
20a442e27f Translated using Weblate (Ukrainian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-19 10:17:38 +00:00
SomeTr
47cb74abc9 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-19 10:17:37 +00:00
SomeTr
a11e53c89a Translated using Weblate (Ukrainian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-19 10:17:37 +00:00
David Lapshin
d721e8ca46 Translated using Weblate (Russian)
Currently translated at 99.7% (393 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2023-10-19 10:17:37 +00:00
alextecplayz
23e5dcd030 Translated using Weblate (Romanian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ro/
2023-10-19 10:17:37 +00:00
Linerly
25dd2cfab8 Translated using Weblate (Indonesian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-10-19 10:17:37 +00:00
Choukajohn
8537c7a7ae Translated using Weblate (French)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-10-19 10:17:37 +00:00
gallegonovato
ebd7f9c36c Translated using Weblate (Spanish)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-10-19 10:17:37 +00:00
poesty
49cda3aeb2 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.7% (393 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-10-19 10:17:37 +00:00
sk
67cbc8aff2 don't load new posts every time we hit the top 2023-10-19 01:06:03 +02:00
sk
5db44cbf9d don't save bidi-safe string in account
also support custom emoji in account switcher
closes sk22#859
2023-10-19 01:01:53 +02:00
sk
95858e3280 remove debug println 2023-10-19 00:44:10 +02:00
sk
36846acbe5 fix null pointer when content language is null 2023-10-19 00:38:06 +02:00
sk
b95d944003 save own posts from timeline before removing them 2023-10-19 00:22:52 +02:00
sk
f52886af74 don't add own boosts to home
closes sk22#875
2023-10-19 00:09:09 +02:00
sk
6cbe406cef load new posts on reload 2023-10-19 00:04:54 +02:00
sk
3097bc7168 oops: put home timeline if result NOT empty 2023-10-18 23:28:44 +02:00
sk
5f7faa69e8 remove existing statuses to move them up 2023-10-18 22:07:10 +02:00
sk
ed24e89a96 don't compare newly fetched posts to created post
closes sk22#866
2023-10-18 21:48:11 +02:00
sk
8ea05c6ebd fix menu grouping 2023-10-18 21:24:59 +02:00
sk
a30fcbbe34 reorder profile menu
closes sk22#873
2023-10-18 21:23:58 +02:00
sk
39f76f9988 always show "boosted" text in reply/boost line
closes sk22#874
2023-10-18 21:21:03 +02:00
sk
5135653cd3 wow!! configurable first fraction 2023-10-18 21:11:48 +02:00
sk
2e4f04cd88 fix divide by zero error 2023-10-18 20:40:23 +02:00
Eugen Rochko
a44e0e036a New translations strings.xml (Persian) 2023-10-18 20:27:30 +02:00
Eugen Rochko
5d54c1bae4 New translations strings.xml (Spanish) 2023-10-18 20:27:29 +02:00
sk
09577074a9 merge settings changes 2023-10-18 20:26:20 +02:00
sk
53f0e2a933 change extra text size 2023-10-18 19:39:12 +02:00
sk
b8dccbbef1 now hopefully fixing header/subtitle extra sizing 2023-10-18 19:23:13 +02:00
Eugen Rochko
2ef17ba051 New translations strings.xml (Spanish) 2023-10-18 19:15:17 +02:00
Eugen Rochko
f63daf3a4e New translations strings.xml (Thai) 2023-10-18 19:15:16 +02:00
Eugen Rochko
52b079be2a New translations strings.xml (Thai) 2023-10-18 18:11:40 +02:00
Eugen Rochko
efeca17106 New translations strings.xml (Chinese Traditional) 2023-10-18 11:34:03 +02:00
Eugen Rochko
6827166c1d New translations strings.xml (Galician) 2023-10-18 08:51:11 +02:00
Eugen Rochko
04483e61e8 New translations strings.xml (Galician) 2023-10-18 07:49:15 +02:00
Eugen Rochko
22fe174922 New translations strings.xml (Icelandic) 2023-10-17 20:07:09 +02:00
Eugen Rochko
f143da3913 New translations strings.xml (Kabyle) 2023-10-17 04:25:08 +02:00
Eugen Rochko
7e9f41c74b New translations strings.xml (Scottish Gaelic) 2023-10-17 04:25:05 +02:00
Eugen Rochko
a1474d0d29 New translations strings.xml (Filipino) 2023-10-17 04:25:03 +02:00
Eugen Rochko
0dce936ad3 New translations strings.xml (Persian) 2023-10-17 04:24:58 +02:00
Eugen Rochko
6ebbbb4c6c New translations strings.xml (Indonesian) 2023-10-17 04:24:57 +02:00
Eugen Rochko
dc6ddbd0ee New translations strings.xml (Portuguese, Brazilian) 2023-10-17 04:24:56 +02:00
Eugen Rochko
86c81d6b53 New translations strings.xml (Galician) 2023-10-17 04:24:55 +02:00
Eugen Rochko
451a92aa36 New translations strings.xml (Vietnamese) 2023-10-17 04:24:53 +02:00
Eugen Rochko
5c42e67e73 New translations strings.xml (Chinese Simplified) 2023-10-17 04:24:52 +02:00
Eugen Rochko
d20d36d964 New translations strings.xml (Turkish) 2023-10-17 04:24:51 +02:00
Eugen Rochko
1a8d46c71e New translations strings.xml (Slovenian) 2023-10-17 04:24:50 +02:00
Eugen Rochko
91da10eca3 New translations strings.xml (Portuguese) 2023-10-17 04:24:49 +02:00
Eugen Rochko
3bb0dcee53 New translations strings.xml (Polish) 2023-10-17 04:24:48 +02:00
Eugen Rochko
d3fd4b200f New translations strings.xml (Norwegian) 2023-10-17 04:24:47 +02:00
Eugen Rochko
fed96864e1 New translations strings.xml (Dutch) 2023-10-17 04:24:46 +02:00
Eugen Rochko
3b351bea27 New translations strings.xml (Korean) 2023-10-17 04:24:45 +02:00
Eugen Rochko
254e01dca1 New translations strings.xml (Armenian) 2023-10-17 04:24:44 +02:00
Eugen Rochko
19158e1d48 New translations strings.xml (Hungarian) 2023-10-17 04:24:43 +02:00
Eugen Rochko
bffb78fccf New translations strings.xml (Basque) 2023-10-17 04:24:41 +02:00
Eugen Rochko
a3800592a2 New translations strings.xml (Greek) 2023-10-17 04:24:39 +02:00
Eugen Rochko
22a498dfc9 New translations strings.xml (German) 2023-10-17 04:24:38 +02:00
Eugen Rochko
9ea96e32bd New translations strings.xml (Danish) 2023-10-17 04:24:37 +02:00
Eugen Rochko
68f51a123e New translations strings.xml (Czech) 2023-10-17 04:24:36 +02:00
Eugen Rochko
43b1b63581 New translations strings.xml (Catalan) 2023-10-17 04:24:35 +02:00
Eugen Rochko
43b4a2c515 New translations strings.xml (Belarusian) 2023-10-17 04:24:34 +02:00
Eugen Rochko
5b9cfdb689 New translations strings.xml (Arabic) 2023-10-17 04:24:33 +02:00
Eugen Rochko
b43cd7103a New translations strings.xml (Spanish) 2023-10-17 04:24:32 +02:00
Eugen Rochko
30e4f6e0f5 New translations strings.xml (French) 2023-10-17 04:24:30 +02:00
Eugen Rochko
1d0ebf889b New translations strings.xml (Chinese Traditional) 2023-10-17 04:24:28 +02:00
Eugen Rochko
7c4f1da485 New translations strings.xml (Finnish) 2023-10-17 04:24:27 +02:00
Eugen Rochko
8163921014 New translations strings.xml (Russian) 2023-10-17 04:24:26 +02:00
Eugen Rochko
993393dd96 New translations strings.xml (Swedish) 2023-10-17 04:24:25 +02:00
Eugen Rochko
82aed43934 New translations strings.xml (Italian) 2023-10-17 04:24:24 +02:00
Eugen Rochko
fa65134c26 New translations strings.xml (Ukrainian) 2023-10-17 04:24:23 +02:00
Eugen Rochko
af4266c739 New translations strings.xml (Japanese) 2023-10-17 04:24:22 +02:00
Eugen Rochko
f72ea2e763 New translations strings.xml (Icelandic) 2023-10-17 04:24:21 +02:00
Eugen Rochko
c5540270a3 New translations strings.xml (Thai) 2023-10-17 04:24:20 +02:00
sk
5840c94395 isolate bi-directional text in display name 2023-10-17 01:03:06 +02:00
sk
92d7ae67ef don't break custom emoji in pronouns 2023-10-17 00:38:27 +02:00
sk
fc09514a4d the pronouns are stored in the balls (extra text)
also, improve max-width behavior
2023-10-17 00:28:00 +02:00
sk
300fa97781 remove comment 2023-10-16 19:36:30 +02:00
142 changed files with 2142 additions and 1250 deletions

View File

@@ -15,8 +15,8 @@ android {
applicationId "org.joinmastodon.android.sk"
minSdk 23
targetSdk 33
versionCode 105
versionName "2.1.6+fork.105"
versionCode 108
versionName "2.1.6+fork.108"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resourceConfigurations += ['ar-rSA', 'ar-rDZ', '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

@@ -266,7 +266,7 @@ public class AudioPlayerService extends Service{
private void updateNotification(boolean dismissable, boolean removeNotification){
Notification.Builder bldr=new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_ntf_logo)
.setContentTitle(status.account.displayName)
.setContentTitle(status.account.getDisplayName())
.setContentText(HtmlParser.strip(status.content))
.setOngoing(!dismissable)
.setShowWhen(false)

View File

@@ -120,6 +120,8 @@ public class CacheController{
values.put("time", s.createdAt.getEpochSecond());
db.insertWithOnConflict("home_timeline", null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
if(!clear)
db.delete("home_timeline", "`id` NOT IN (SELECT `id` FROM `home_timeline` ORDER BY `time` DESC LIMIT ?)", new String[]{"1000"});
});
}
@@ -271,6 +273,28 @@ public class CacheController{
public void deleteStatus(String id){
runOnDbThread((db)->{
String gapId=null;
int gapFlags=0;
// select to-be-removed and newer row
try(Cursor cursor=db.query("home_timeline", new String[]{"id", "flags"}, "`time`>=(SELECT `time` FROM `home_timeline` WHERE `id`=?)", new String[]{id}, null, null, "`time` ASC", "2")){
boolean hadGapAfter=false;
// always either one or two iterations (only one if there's no newer post)
while(cursor.moveToNext()){
String currentId=cursor.getString(0);
int currentFlags=cursor.getInt(1);
if(currentId.equals(id)){
hadGapAfter=((currentFlags & POST_FLAG_GAP_AFTER)!=0);
}else if(hadGapAfter){
gapFlags=currentFlags|POST_FLAG_GAP_AFTER;
gapId=currentId;
}
}
}
if(gapId!=null){
ContentValues values=new ContentValues();
values.put("flags", gapFlags);
db.update("home_timeline", values, "`id`=?", new String[]{gapId});
}
db.delete("home_timeline", "`id`=?", new String[]{id});
});
}

View File

@@ -53,9 +53,7 @@ public class MastodonAPIController{
.registerTypeAdapter(Status.class, new Status.StatusDeserializer())
.create();
private static WorkerThread thread=new WorkerThread("MastodonAPIController");
private static OkHttpClient httpClient=new OkHttpClient.Builder()
.readTimeout(5, TimeUnit.MINUTES)
.build();
private static OkHttpClient httpClient=new OkHttpClient.Builder().build();
private AccountSession session;
private static List<String> badDomains = new ArrayList<>();
@@ -113,13 +111,13 @@ public class MastodonAPIController{
}
Request hreq=builder.build();
Call call=httpClient.newCall(hreq);
OkHttpClient client=req.timeout>0
? httpClient.newBuilder().readTimeout(req.timeout, TimeUnit.MILLISECONDS).build()
: httpClient;
Call call=client.newCall(hreq);
synchronized(req){
req.okhttpCall=call;
}
if(req.timeout>0){
call.timeout().timeout(req.timeout, TimeUnit.MILLISECONDS);
}
if(BuildConfig.DEBUG)
Log.d(TAG, "["+(session==null ? "no-auth" : session.getID())+"] Sending request: "+hreq);

View File

@@ -153,8 +153,9 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
headers.put(key, value);
}
protected void setTimeout(long timeout){
public MastodonAPIRequest<T> setTimeout(long timeout){
this.timeout=timeout;
return this;
}
protected String getPathPrefix(){

View File

@@ -218,7 +218,7 @@ public class AccountSession{
public void savePreferencesIfPending(){
if(preferencesNeedSaving){
new UpdateAccountCredentialsPreferences(preferences, null, self.discoverable, self.source.indexable)
new UpdateAccountCredentialsPreferences(preferences, self.locked, self.discoverable, self.source.indexable)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Account result){

View File

@@ -9,5 +9,6 @@ public class StatusCreatedEvent{
public StatusCreatedEvent(Status status, String accountID){
this.status=status;
this.accountID=accountID;
status.fromStatusCreated=true;
}
}

View File

@@ -468,10 +468,14 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
protected void updatePoll(String itemID, Status status, Poll poll){
status.poll=poll;
int firstOptionIndex=-1, footerIndex=-1;
int spoilerFirstOptionIndex=-1, spoilerFooterIndex=-1;
SpoilerStatusDisplayItem spoilerItem=null;
int i=0;
for(StatusDisplayItem item:displayItems){
if(item.parentID.equals(itemID)){
if(item instanceof PollOptionStatusDisplayItem && firstOptionIndex==-1){
if(item instanceof SpoilerStatusDisplayItem){
spoilerItem=(SpoilerStatusDisplayItem) item;
}else if(item instanceof PollOptionStatusDisplayItem && firstOptionIndex==-1){
firstOptionIndex=i;
}else if(item instanceof PollFooterStatusDisplayItem){
footerIndex=i;
@@ -484,8 +488,16 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
throw new IllegalStateException("Can't find all poll items in displayItems");
List<StatusDisplayItem> pollItems=displayItems.subList(firstOptionIndex, footerIndex+1);
int prevSize=pollItems.size();
if(spoilerItem!=null){
spoilerFirstOptionIndex=spoilerItem.contentItems.indexOf(pollItems.get(0));
spoilerFooterIndex=spoilerItem.contentItems.indexOf(pollItems.get(pollItems.size()-1));
}
pollItems.clear();
StatusDisplayItem.buildPollItems(itemID, this, poll, pollItems);
if(spoilerItem!=null){
spoilerItem.contentItems.subList(spoilerFirstOptionIndex, spoilerFooterIndex+1).clear();
spoilerItem.contentItems.addAll(spoilerFirstOptionIndex, pollItems);
}
if(prevSize!=pollItems.size()){
adapter.notifyItemRangeRemoved(firstOptionIndex, prevSize);
adapter.notifyItemRangeInserted(firstOptionIndex, pollItems.size());

View File

@@ -150,7 +150,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
public LinearLayout mainLayout;
private SizeListenerLinearLayout contentView;
private TextView selfName, selfUsername, selfExtraText, extraText, pronouns;
private TextView selfName, selfUsername, selfExtraText, extraText;
private ImageView selfAvatar;
private Account self;
private String instanceDomain;
@@ -200,7 +200,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
public Instance instance;
public Status editingStatus;
private ScheduledStatus scheduledStatus;
public ScheduledStatus scheduledStatus;
private boolean redraftStatus;
private ContentType contentType;
@@ -326,7 +326,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
selfUsername=view.findViewById(R.id.self_username);
selfAvatar=view.findViewById(R.id.self_avatar);
selfExtraText=view.findViewById(R.id.self_extra_text);
HtmlParser.setTextWithCustomEmoji(selfName, self.displayName, self.emojis);
HtmlParser.setTextWithCustomEmoji(selfName, self.getDisplayName(), self.emojis);
selfUsername.setText('@'+self.username+'@'+instanceDomain);
if(self.avatar!=null)
ViewImageLoader.load(selfAvatar, null, new UrlImageLoaderRequest(self.avatar));
@@ -626,7 +626,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
});
View originalPost=view.findViewById(R.id.original_post);
extraText=view.findViewById(R.id.extra_text);
pronouns=view.findViewById(R.id.pronouns);
originalPost.setVisibility(View.VISIBLE);
originalPost.setOnClickListener(v->{
Bundle args=new Bundle();
@@ -666,7 +665,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
moreBtn.setBackground(null);
TextView name = view.findViewById(R.id.name);
name.setText(HtmlParser.parseCustomEmoji(status.account.displayName, status.account.emojis));
name.setText(HtmlParser.parseCustomEmoji(status.account.getDisplayName(), status.account.emojis));
UiUtils.loadCustomEmojiInTextView(name);
String time = status==null || status.editedAt==null
@@ -700,7 +699,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(16)));
}
replyText.setText(getString(quote!=null? R.string.sk_quoting_user : R.string.in_reply_to, status.account.displayName));
replyText.setText(HtmlParser.parseCustomEmoji(getString(quote!=null? R.string.sk_quoting_user : R.string.in_reply_to, status.account.getDisplayName()), status.account.emojis));
UiUtils.loadCustomEmojiInTextView(replyText);
int visibilityNameRes = switch (status.visibility) {
case PUBLIC -> R.string.visibility_public;
case UNLISTED -> R.string.sk_visibility_unlisted;
@@ -708,7 +708,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
case DIRECT -> R.string.visibility_private;
case LOCAL -> R.string.sk_local_only;
};
replyText.setContentDescription(getString(R.string.in_reply_to, status.account.displayName) + ", " + getString(visibilityNameRes));
replyText.setContentDescription(getString(R.string.in_reply_to, status.account.getDisplayName()) + ", " + getString(visibilityNameRes));
replyText.setOnClickListener(v->{
scrollView.smoothScrollTo(0, 0);
});
@@ -1455,8 +1455,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
private void updateHeaders() {
UiUtils.setExtraTextInfo(getContext(), selfExtraText, null, false, false, localOnly || statusVisibility==StatusPrivacy.LOCAL, null);
if (replyTo != null) UiUtils.setExtraTextInfo(getContext(), extraText, pronouns, true, false, replyTo.localOnly || replyTo.visibility==StatusPrivacy.LOCAL, replyTo.account);
UiUtils.setExtraTextInfo(getContext(), selfExtraText, false, false, localOnly, null);
if (replyTo != null) UiUtils.setExtraTextInfo(getContext(), extraText, true, false, replyTo.localOnly || replyTo.visibility==StatusPrivacy.LOCAL, replyTo.account);
}
private void buildVisibilityPopup(View v){

View File

@@ -20,7 +20,6 @@ import org.joinmastodon.android.api.requests.accounts.GetFollowRequests;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.HeaderPaginationList;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Relationship;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.text.HtmlParser;
@@ -271,7 +270,7 @@ public class FollowRequestsListFragment extends MastodonRecyclerFragment<FollowR
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
relationship=relationships.get(item.account.id);
UiUtils.setExtraTextInfo(getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
UiUtils.setExtraTextInfo(getContext(), null, true, false, false, item.account);
if(relationship==null || !relationship.followedBy){
actionWrap.setVisibility(View.GONE);
@@ -366,9 +365,9 @@ public class FollowRequestsListFragment extends MastodonRecyclerFragment<FollowR
coverRequest=new UrlImageLoaderRequest(account.header, 1000, 1000);
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
if(account.emojis.isEmpty()){
parsedName=account.displayName;
parsedName= account.getDisplayName();
}else{
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
emojiHelper.setText(new SpannableStringBuilder(parsedName).append(parsedBio));
}
}

View File

@@ -32,7 +32,6 @@ import org.joinmastodon.android.events.NotificationsMarkerUpdatedEvent;
import org.joinmastodon.android.events.StatusDisplaySettingsChangedEvent;
import org.joinmastodon.android.fragments.discover.DiscoverFragment;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.model.PaginatedResponse;
import org.joinmastodon.android.ui.AccountSwitcherSheet;
@@ -71,14 +70,12 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
private TextView notificationsBadge;
private String accountID;
private boolean isAkkoma;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
accountID=getArguments().getString("account");
setTitle(R.string.sk_app_name);
isAkkoma = getInstance().map(Instance::isAkkoma).orElse(false);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
setRetainInstance(true);
@@ -89,7 +86,6 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
homeTabFragment=new HomeTabFragment();
homeTabFragment.setArguments(args);
args=new Bundle(args);
args.putBoolean("disableDiscover", isAkkoma);
args.putBoolean("noAutoLoad", true);
discoverFragment=new DiscoverFragment();
discoverFragment.setArguments(args);
@@ -296,7 +292,7 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
if(tab==R.id.tab_profile){
ArrayList<String> options=new ArrayList<>();
for(AccountSession session:AccountSessionManager.getInstance().getLoggedInAccounts()){
options.add(session.self.displayName+"\n("+session.self.username+"@"+session.domain+")");
options.add(session.self.getDisplayName()+"\n("+session.self.username+"@"+session.domain+")");
}
new AccountSwitcherSheet(getActivity(), this).show();
return true;

View File

@@ -233,21 +233,25 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
ViewTreeObserver vto = getToolbar().getViewTreeObserver();
if (vto.isAlive()) {
vto.addOnGlobalLayoutListener(() -> {
Toolbar t = getToolbar();
if (t == null) return;
int toolbarWidth = t.getWidth();
if (toolbarWidth == 0) return;
vto.addOnGlobalLayoutListener(()->{
Toolbar t=getToolbar();
if(t==null) return;
int toolbarWidth=t.getWidth();
if(toolbarWidth==0) return;
int toolbarFrameWidth = toolbarFrame.getWidth();
int padding = toolbarWidth - toolbarFrameWidth;
FrameLayout parent = ((FrameLayout) toolbarShowNewPostsBtn.getParent());
if (padding == parent.getPaddingStart()) return;
int toolbarFrameWidth=toolbarFrame.getWidth();
int actionsWidth=toolbarWidth-toolbarFrameWidth;
// margin (4) + padding (12) + icon (24) + margin (8) + chevron (16) + padding (12)
int switcherWidth=V.dp(76);
FrameLayout parent=((FrameLayout) toolbarShowNewPostsBtn.getParent());
if(actionsWidth==parent.getPaddingStart()) return;
int paddingMax=Math.max(actionsWidth, switcherWidth);
int paddingEnd=(Math.max(0, switcherWidth-actionsWidth));
// toolbar frame goes from screen edge to beginning of right-aligned option buttons.
// centering button by applying the same space on the left
parent.setPaddingRelative(padding, 0, 0, 0);
toolbarShowNewPostsBtn.setMaxWidth(toolbarWidth - padding * 2);
parent.setPaddingRelative(paddingMax, 0, paddingEnd, 0);
toolbarShowNewPostsBtn.setMaxWidth(toolbarWidth-paddingMax*2);
switcher.setPivotX(V.dp(28)); // padding + half of icon
switcher.setPivotY(switcher.getHeight() / 2f);

View File

@@ -61,7 +61,7 @@ public class HomeTimelineFragment extends StatusListFragment {
maxID=result.maxID;
AccountSessionManager.get(accountID).filterStatuses(result.items, getFilterContext());
onDataLoaded(result.items, !empty);
if(result.isFromCache())
if(result.isFromCache() && GlobalUserPreferences.loadNewPosts)
loadNewPosts();
}
});
@@ -74,7 +74,7 @@ public class HomeTimelineFragment extends StatusListFragment {
list.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){
if(parent != null && parent.isNewPostsBtnShown() && list.getChildAdapterPosition(list.getChildAt(0))<=getMainAdapterOffset()){
if(parent!=null && parent.isNewPostsBtnShown() && list.getChildAdapterPosition(list.getChildAt(0))<=getMainAdapterOffset()){
parent.hideNewPostsButton();
}
}
@@ -87,7 +87,7 @@ public class HomeTimelineFragment extends StatusListFragment {
if(!getArguments().getBoolean("noAutoLoad")){
if(!loaded && !dataLoading){
loadData();
}else if(!dataLoading){
}else if(!dataLoading && GlobalUserPreferences.loadNewPosts){
loadNewPosts();
}
}
@@ -117,48 +117,54 @@ public class HomeTimelineFragment extends StatusListFragment {
}
public void onStatusCreated(Status status){
if(status.reblog!=null) return;
prependItems(Collections.singletonList(status), true);
}
private void loadNewPosts(){
if (!GlobalUserPreferences.loadNewPosts) return;
dataLoading=true;
// we only care about the data that was actually retrieved from the timeline api since
// user-created statuses are probably in the wrong position
List<Status> dataFromTimeline=data.stream().filter(s->!s.fromStatusCreated).collect(Collectors.toList());
// The idea here is that we request the timeline such that if there are fewer than `limit` posts,
// we'll get the currently topmost post as last in the response. This way we know there's no gap
// between the existing and newly loaded parts of the timeline.
String sinceID=data.size()>1 ? data.get(1).id : "1";
String sinceID=dataFromTimeline.size()>1 ? dataFromTimeline.get(1).id : "1";
currentRequest=new GetHomeTimeline(null, null, 20, sinceID, getLocalPrefs().timelineReplyVisibility)
.setCallback(new Callback<>(){
@Override
public void onSuccess(List<Status> result){
currentRequest=null;
dataLoading=false;
refreshDone();
if(result.isEmpty() || getActivity()==null)
return;
Status last=result.get(result.size()-1);
List<Status> toAdd;
if(!data.isEmpty() && last.id.equals(data.get(0).id)){ // This part intersects with the existing one
if(!dataFromTimeline.isEmpty() && last.id.equals(dataFromTimeline.get(0).id)){ // This part intersects with the existing one
toAdd=new ArrayList<>(result.subList(0, result.size()-1)); // Remove the already known last post
}else{
last.hasGapAfter=last.id;
toAdd=result;
}
if(!toAdd.isEmpty())
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(new ArrayList<>(toAdd), false);
// removing statuses that come up as duplicates (hopefully only posts and boosts that were locally created
// and thus were already prepended to the timeline earlier)
List<String> existingIds=data.stream().map(Status::getID).collect(Collectors.toList());
toAdd.removeIf(s->existingIds.contains(s.getID()));
List<Status> toAddUnfiltered=new ArrayList<>(toAdd);
AccountSessionManager.get(accountID).filterStatuses(toAdd, getFilterContext());
if(!toAdd.isEmpty()){
prependItems(toAdd, true);
if(parent != null && GlobalUserPreferences.showNewPostsButton) parent.showNewPostsButton();
}
if(toAddUnfiltered.isEmpty())
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(toAddUnfiltered, false);
}
@Override
public void onError(ErrorResponse error){
currentRequest=null;
dataLoading=false;
refreshDone();
}
})
.exec(accountID);
@@ -206,6 +212,7 @@ public class HomeTimelineFragment extends StatusListFragment {
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(gapStatus), false);
}
}else{
// TODO: refactor this code. it's too long. incomprehensible, even
if(downwards) {
Set<String> idsBelowGap=new HashSet<>();
boolean belowGap=false;
@@ -325,7 +332,7 @@ public class HomeTimelineFragment extends StatusListFragment {
currentRequest=null;
dataLoading=false;
}
if (parent != null) parent.hideNewPostsButton();
if(parent!=null) parent.hideNewPostsButton();
super.onRefresh();
}

View File

@@ -621,14 +621,14 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
@SuppressLint("SetTextI18n")
private void bindHeaderView(){
setTitle(account.displayName);
setTitle(account.getDisplayName());
setSubtitle(getResources().getQuantityString(R.plurals.x_posts, (int)(account.statusesCount%1000), account.statusesCount));
ViewImageLoader.load(avatar, null, new UrlImageLoaderRequest(
TextUtils.isEmpty(account.avatar) ? getSession().getDefaultAvatarUrl() :
GlobalUserPreferences.playGifs ? account.avatar : account.avatarStatic,
V.dp(100), V.dp(100)));
ViewImageLoader.load(cover, null, new UrlImageLoaderRequest(GlobalUserPreferences.playGifs ? account.header : account.headerStatic, 1000, 1000));
SpannableStringBuilder ssb=new SpannableStringBuilder(account.displayName);
SpannableStringBuilder ssb=new SpannableStringBuilder(account.getDisplayName());
if(AccountSessionManager.get(accountID).getLocalPreferences().customEmojiInNames)
HtmlParser.parseCustomEmoji(ssb, account.emojis);
name.setText(ssb);

View File

@@ -9,6 +9,7 @@ import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.api.CacheController;
import org.joinmastodon.android.api.session.AccountLocalPreferences;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.EmojiReactionsUpdatedEvent;
@@ -24,6 +25,7 @@ import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.displayitems.EmojiReactionsStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
import org.parceler.Parcels;
@@ -31,6 +33,10 @@ import org.parceler.Parcels;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -176,56 +182,73 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>
}
}
private void iterateRemoveStatus(List<Status> l, String id){
Iterator<Status> it=l.iterator();
while(it.hasNext()){
if(it.next().getContentStatus().id.equals(id)){
it.remove();
}
}
}
private void removeStatusDisplayItems(Status status, int index, int ancestorFirstIndex, int ancestorLastIndex, boolean deleteContent){
private boolean removeStatusDisplayItems(String parentID, int firstIndex, int ancestorFirstIndex, int ancestorLastIndex){
// did we find an ancestor that is also the status' neighbor?
if(ancestorFirstIndex>=0 && ancestorLastIndex==index-1){
for(int i=ancestorFirstIndex; i<=ancestorLastIndex; i++){
StatusDisplayItem item=displayItems.get(i);
String id=deleteContent ? item.getContentID() : item.parentID;
// update ancestor to have no descendant anymore
if(id.equals(status.inReplyToId)) item.hasDescendantNeighbor=false;
}
if(ancestorFirstIndex>=0 && ancestorLastIndex==firstIndex-1){
// update ancestor to have no descendant anymore
displayItems.subList(ancestorFirstIndex, ancestorLastIndex+1).forEach(i->i.hasDescendantNeighbor=false);
adapter.notifyItemRangeChanged(ancestorFirstIndex, ancestorLastIndex-ancestorFirstIndex+1);
}
if(index==-1) return;
int lastIndex;
for(lastIndex=index;lastIndex<displayItems.size();lastIndex++){
if(firstIndex==-1) return false;
int lastIndex=firstIndex;
while(lastIndex<displayItems.size()){
StatusDisplayItem item=displayItems.get(lastIndex);
String id=deleteContent ? item.getContentID() : item.parentID;
if(!id.equals(status.id)) break;
if(!item.parentID.equals(parentID) || item instanceof GapStatusDisplayItem) break;
lastIndex++;
}
displayItems.subList(index, lastIndex).clear();
adapter.notifyItemRangeRemoved(index, lastIndex-index);
int count=lastIndex-firstIndex;
if(count<1) return false;
displayItems.subList(firstIndex, lastIndex).clear();
adapter.notifyItemRangeRemoved(firstIndex, count);
return true;
}
protected void removeStatus(Status status){
boolean deleteContent=status==status.getContentStatus();
final AccountSessionManager asm=AccountSessionManager.getInstance();
final CacheController cache=AccountSessionManager.get(accountID).getCacheController();
final boolean unReblogging=status.reblog!=null && asm.isSelf(accountID, status.account);
final Predicate<Status> isToBeRemovedReblog=item->item!=null && item.reblog!=null
&& item.reblog.id.equals(status.reblog.id)
&& asm.isSelf(accountID, item.account);
final BiPredicate<String, Supplier<String>> isToBeRemovedContent=(parentId, contentIdSupplier)->
parentId.equals(status.id) || contentIdSupplier.get().equals(status.id);
int ancestorFirstIndex=-1, ancestorLastIndex=-1;
for(int i=0;i<displayItems.size();i++){
StatusDisplayItem item=displayItems.get(i);
String id=deleteContent ? item.getContentID() : item.parentID;
if(id.equals(status.id)){
removeStatusDisplayItems(status, i, ancestorFirstIndex, ancestorLastIndex, deleteContent);
ancestorFirstIndex=ancestorLastIndex=-1;
continue;
}
if(id.equals(status.inReplyToId)){
// we found a status that the to-be-removed status replies to!
// storing indices to maybe update its display items
if(item.parentID.equals(status.inReplyToId)){
if(ancestorFirstIndex==-1) ancestorFirstIndex=i;
ancestorLastIndex=i;
}
// if we're un-reblogging, we compare the reblogged status's id with the current status's
if(unReblogging
? isToBeRemovedReblog.test(getStatusByID(item.parentID))
: isToBeRemovedContent.test(item.parentID, item::getContentStatusID)){
// if statuses are removed from index i, the next iteration should be on the same index again
if(removeStatusDisplayItems(item.parentID, i, ancestorFirstIndex, ancestorLastIndex)) i--;
// resetting in case we find another occurrence of the same status that also has ancestors
// (we won't - unless the timeline is being especially weird)
ancestorFirstIndex=-1; ancestorLastIndex=-1;
}
}
iterateRemoveStatus(data, status.id);
iterateRemoveStatus(preloadedData, status.id);
Consumer<List<Status>> removeStatusFromData=(list)->{
Iterator<Status> it=list.iterator();
while(it.hasNext()){
Status s=it.next();
if(unReblogging
? isToBeRemovedReblog.test(s)
: isToBeRemovedContent.test(s.id, s::getContentStatusID)){
it.remove();
cache.deleteStatus(s.id);
}
}
};
removeStatusFromData.accept(data);
removeStatusFromData.accept(preloadedData);
}
@Override
@@ -296,10 +319,14 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>
@Subscribe
public void onReblogDeleted(ReblogDeletedEvent ev){
AccountSessionManager asm=AccountSessionManager.getInstance();
if(!ev.accountID.equals(accountID))
return;
for(Status item : data){
if(item.getContentStatus().id.equals(ev.statusID) && item.reblog!=null){
boolean itemIsOwnReblog=item.reblog!=null
&& item.getContentStatusID().equals(ev.statusID)
&& asm.isSelf(accountID, item.account);
if(itemIsOwnReblog){
removeStatus(item);
break;
}

View File

@@ -64,7 +64,7 @@ public class ThreadFragment extends StatusListFragment implements ProvidesAssist
knownAccounts.put(inReplyToAccount.id, inReplyToAccount);
data.add(mainStatus);
onAppendItems(Collections.singletonList(mainStatus));
setTitle(HtmlParser.parseCustomEmoji(getString(R.string.post_from_user, mainStatus.account.displayName), mainStatus.account.emojis));
setTitle(HtmlParser.parseCustomEmoji(getString(R.string.post_from_user, mainStatus.account.getDisplayName()), mainStatus.account.emojis));
transitionFinished = getArguments().getBoolean("noTransition", false);
}

View File

@@ -261,7 +261,7 @@ public class DiscoverAccountsFragment extends MastodonRecyclerFragment<DiscoverA
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
relationship=relationships.get(item.account.id);
UiUtils.setExtraTextInfo(getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
UiUtils.setExtraTextInfo(getContext(), null, true, false, false, item.account);
if(relationship==null){
actionWrap.setVisibility(View.GONE);
@@ -330,9 +330,9 @@ public class DiscoverAccountsFragment extends MastodonRecyclerFragment<DiscoverA
coverRequest=new UrlImageLoaderRequest(account.header, 1000, 1000);
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
if(account.emojis.isEmpty()){
parsedName=account.displayName;
parsedName= account.getDisplayName();
}else{
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
emojiHelper.setText(new SpannableStringBuilder(parsedName).append(parsedBio));
}
}

View File

@@ -13,8 +13,10 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.IsOnTop;
import org.joinmastodon.android.fragments.ScrollableToTop;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.SearchResult;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.SimpleViewHolder;
@@ -155,7 +157,7 @@ public class DiscoverFragment extends AppKitFragment implements ScrollableToTop,
}
});
disableDiscover=getArguments().getBoolean("disableDiscover");
disableDiscover=AccountSessionManager.get(accountID).getInstance().map(Instance::isAkkoma).orElse(false);
searchView=view.findViewById(R.id.search_fragment);
if(searchFragment==null){
searchFragment=new SearchFragment();

View File

@@ -36,6 +36,7 @@ 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.api.SimpleCallback;
import me.grishka.appkit.utils.V;
public class SearchFragment extends BaseStatusListFragment<SearchResult>{
@@ -142,7 +143,7 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
}*/
int offset=_offset;
currentRequest=new GetSearchResults(currentQuery, type, type==null, maxID, offset, type==null ? 0 : count)
.setCallback(new Callback<>(){
.setCallback(new SimpleCallback<>(this){
@Override
public void onSuccess(SearchResults result){
ArrayList<SearchResult> results=new ArrayList<>();
@@ -165,16 +166,8 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
unfilteredResults=results;
onDataLoaded(filterSearchResults(results), type!=null && !results.isEmpty());
}
@Override
public void onError(ErrorResponse error){
currentRequest=null;
Activity a=getActivity();
if(a==null)
return;
error.showToast(a);
}
})
.setTimeout(180000) // 3 minutes (searches can take a long time)
.exec(accountID);
}

View File

@@ -115,7 +115,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
onDataLoaded(results.stream().map(sr->{
SearchResultViewModel vm=new SearchResultViewModel(sr, accountID, true);
if(sr.type==SearchResult.Type.HASHTAG){
vm.hashtagItem.onClick=()->openHashtag(sr);
vm.hashtagItem.setOnClick(i->openHashtag(sr));
}
return vm;
}).collect(Collectors.toList()), false);
@@ -132,7 +132,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
.map(sr->{
SearchResultViewModel vm=new SearchResultViewModel(sr, accountID, false);
if(sr.type==SearchResult.Type.HASHTAG){
vm.hashtagItem.onClick=()->openHashtag(sr);
vm.hashtagItem.setOnClick(i->openHashtag(sr));
}
return vm;
})
@@ -429,11 +429,11 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
wrapSuicideDialog(()->deliverResult(currentQuery, null));
}
private void onOpenURLClick(){
private void onOpenURLClick(ListItem<?> item_){
UiUtils.openURL(getContext(), accountID, searchViewHelper.getQuery(), false);
}
private void onGoToHashtagClick(){
private void onGoToHashtagClick(ListItem<?> item_){
wrapSuicideDialog(()->{
String q=searchViewHelper.getQuery();
if(q.startsWith("#"))
@@ -442,7 +442,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
});
}
private void onGoToAccountClick(){
private void onGoToAccountClick(ListItem<?> item_){
String q=searchViewHelper.getQuery();
if(!q.startsWith("@")){
q="@"+q;
@@ -459,11 +459,11 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
}).ifPresent(progress -> progress.wrapProgress((Activity) getContext(), R.string.loading, true));
}
private void onGoToStatusSearchClick(){
private void onGoToStatusSearchClick(ListItem<?> item_){
wrapSuicideDialog(()->deliverResult(searchViewHelper.getQuery(), SearchResult.Type.STATUS));
}
private void onGoToAccountSearchClick(){
private void onGoToAccountSearchClick(ListItem<?> item_){
wrapSuicideDialog(()->deliverResult(searchViewHelper.getQuery(), SearchResult.Type.ACCOUNT));
}

View File

@@ -3,7 +3,6 @@ package org.joinmastodon.android.fragments.onboarding;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;

View File

@@ -34,7 +34,6 @@ import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
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 ReportDoneFragment extends MastodonToolbarFragment{

View File

@@ -73,7 +73,7 @@ public class EditFilterFragment extends BaseSettingsFragment<Void> implements On
durationItem=new ListItem<>(R.string.settings_filter_duration, 0, this::onDurationClick),
wordsItem=new ListItem<>(R.string.settings_filter_muted_words, 0, this::onWordsClick),
contextItem=new ListItem<>(R.string.settings_filter_context, 0, this::onContextClick),
cwItem=new CheckableListItem<>(R.string.settings_filter_show_cw, R.string.settings_filter_show_cw_explanation, CheckableListItem.Style.SWITCH, filter==null || filter.filterAction==FilterAction.WARN, ()->toggleCheckableItem(cwItem))
cwItem=new CheckableListItem<>(R.string.settings_filter_show_cw, R.string.settings_filter_show_cw_explanation, CheckableListItem.Style.SWITCH, filter==null || filter.filterAction==FilterAction.WARN, this::toggleCheckableItem)
));
if(filter!=null){
@@ -113,7 +113,7 @@ public class EditFilterFragment extends BaseSettingsFragment<Void> implements On
return 1;
}
private void onDurationClick(){
private void onDurationClick(ListItem<Void> item_){
int[] durationOptions={
1800,
3600,
@@ -182,21 +182,21 @@ public class EditFilterFragment extends BaseSettingsFragment<Void> implements On
alert.setOnDismissListener(dialog->callback.accept(null));
}
private void onWordsClick(){
private void onWordsClick(ListItem<Void> item){
Bundle args=new Bundle();
args.putString("account", accountID);
args.putParcelableArrayList("words", (ArrayList<? extends Parcelable>) keywords.stream().map(Parcels::wrap).collect(Collectors.toCollection(ArrayList::new)));
Nav.goForResult(getActivity(), FilterWordsFragment.class, args, WORDS_RESULT, this);
}
private void onContextClick(){
private void onContextClick(ListItem<Void> item){
Bundle args=new Bundle();
args.putString("account", accountID);
args.putSerializable("context", context);
Nav.goForResult(getActivity(), FilterContextFragment.class, args, CONTEXT_RESULT, this);
}
private void onDeleteClick(){
private void onDeleteClick(ListItem<Void> item_){
AlertDialog alert=new M3AlertDialogBuilder(getActivity())
.setTitle(getString(R.string.settings_delete_filter_title, filter.title))
.setMessage(R.string.settings_delete_filter_confirmation)

View File

@@ -22,10 +22,9 @@ public class FilterContextFragment extends BaseSettingsFragment<FilterContext> i
setTitle(R.string.settings_filter_context);
context=(EnumSet<FilterContext>) getArguments().getSerializable("context");
onDataLoaded(Arrays.stream(FilterContext.values()).map(c->{
CheckableListItem<FilterContext> item=new CheckableListItem<>(c.getDisplayNameRes(), 0, CheckableListItem.Style.CHECKBOX, context.contains(c), null);
CheckableListItem<FilterContext> item=new CheckableListItem<>(c.getDisplayNameRes(), 0, CheckableListItem.Style.CHECKBOX, context.contains(c), this::toggleCheckableItem);
item.parentObject=c;
item.isEnabled=true;
item.onClick=()->toggleCheckableItem(item);
return item;
}).collect(Collectors.toList()));
}

View File

@@ -1,11 +1,6 @@
package org.joinmastodon.android.fragments.settings;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.IntEvaluator;
import android.animation.ObjectAnimator;
import android.app.AlertDialog;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
@@ -27,6 +22,7 @@ import org.joinmastodon.android.model.FilterKeyword;
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.ActionModeHelper;
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.FloatingHintEditTextLayout;
@@ -37,7 +33,6 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import me.grishka.appkit.FragmentStackActivity;
import me.grishka.appkit.fragments.OnBackPressedListener;
import me.grishka.appkit.utils.V;
@@ -60,7 +55,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
FilterKeyword word=Parcels.unwrap(p);
ListItem<FilterKeyword> item=new ListItem<>(word.keyword, null, null, word);
item.isEnabled=true;
item.onClick=()->onWordClick(item);
item.setOnClick(this::onWordClick);
return item;
}).collect(Collectors.toList()));
setHasOptionsMenu(true);
@@ -114,7 +109,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
inflater.inflate(R.menu.settings_filter_words, menu);
inflater.inflate(R.menu.selectable_list, menu);
}
@Override
@@ -174,7 +169,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
w.keyword=input;
ListItem<FilterKeyword> item=new ListItem<>(w.keyword, null, null, w);
item.isEnabled=true;
item.onClick=()->onWordClick(item);
item.setOnClick(this::onWordClick);
data.add(item);
itemsAdapter.notifyItemInserted(data.size()-1);
}else{
@@ -228,29 +223,15 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
return;
V.setVisibilityAnimated(fab, View.GONE);
actionMode=getActivity().startActionMode(new ActionMode.Callback(){
actionMode=ActionModeHelper.startActionMode(this, ()->elevationOnScrollListener.getCurrentStatusBarColor(), new ActionMode.Callback(){
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu){
ObjectAnimator anim=ObjectAnimator.ofInt(getActivity().getWindow(), "statusBarColor", elevationOnScrollListener.getCurrentStatusBarColor(), UiUtils.getThemeColor(getActivity(), R.attr.colorM3Primary));
anim.setEvaluator(new IntEvaluator(){
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
}
});
anim.start();
((FragmentStackActivity) getActivity()).invalidateSystemBarColors(FilterWordsFragment.this);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu){
mode.getMenuInflater().inflate(R.menu.settings_filter_words_action_mode, menu);
for(int i=0;i<menu.size();i++){
Drawable icon=menu.getItem(i).getIcon().mutate();
icon.setTint(UiUtils.getThemeColor(getActivity(), R.attr.colorM3OnPrimary));
menu.getItem(i).setIcon(icon);
}
deleteItem=menu.findItem(R.id.delete);
return true;
}
@@ -266,21 +247,6 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
@Override
public void onDestroyActionMode(ActionMode mode){
leaveSelectionMode(true);
ObjectAnimator anim=ObjectAnimator.ofInt(getActivity().getWindow(), "statusBarColor", UiUtils.getThemeColor(getActivity(), R.attr.colorM3Primary), elevationOnScrollListener.getCurrentStatusBarColor());
anim.setEvaluator(new IntEvaluator(){
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
}
});
anim.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
getActivity().getWindow().setStatusBarColor(0);
}
});
anim.start();
((FragmentStackActivity) getActivity()).invalidateSystemBarColors(FilterWordsFragment.this);
}
});
@@ -289,7 +255,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
ListItem<FilterKeyword> item=data.get(i);
CheckableListItem<FilterKeyword> newItem=new CheckableListItem<>(item.title, null, CheckableListItem.Style.CHECKBOX, selectAll, null);
newItem.isEnabled=true;
newItem.onClick=()->onSelectionModeWordClick(newItem);
newItem.setOnClick(this::onSelectionModeWordClick);
newItem.parentObject=item.parentObject;
if(selectAll)
selectedItems.add(newItem);
@@ -313,7 +279,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
ListItem<FilterKeyword> item=data.get(i);
ListItem<FilterKeyword> newItem=new ListItem<>(item.title, null, null);
newItem.isEnabled=true;
newItem.onClick=()->onWordClick(newItem);
newItem.setOnClick(this::onWordClick);
newItem.parentObject=item.parentObject;
data.set(i, newItem);
}

View File

@@ -16,7 +16,6 @@ import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.utils.UiUtils;
import java.util.List;
import java.util.Objects;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.imageloader.ImageCache;
@@ -26,23 +25,32 @@ import me.grishka.appkit.utils.V;
public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
private ListItem<Void> mediaCacheItem;
private AccountSession session;
private boolean timelineCacheCleared=false;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setTitle(getString(R.string.about_app, getString(R.string.sk_app_name)));
AccountSession s=AccountSessionManager.get(accountID);
session=AccountSessionManager.get(accountID);
onDataLoaded(List.of(
new ListItem<>(R.string.sk_settings_donate, 0, R.drawable.ic_fluent_heart_24_regular, ()->UiUtils.openHashtagTimeline(getActivity(), accountID, getString(R.string.donate_hashtag))),
new ListItem<>(R.string.sk_settings_contribute, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), getString(R.string.repo_url))),
new ListItem<>(R.string.settings_tos, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/terms")),
new ListItem<>(R.string.settings_privacy_policy, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), getString(R.string.privacy_policy_url)), 0, true),
mediaCacheItem=new ListItem<>(R.string.settings_clear_cache, 0, this::onClearMediaCacheClick)
new ListItem<>(R.string.sk_settings_donate, 0, R.drawable.ic_fluent_heart_24_regular, i->UiUtils.openHashtagTimeline(getActivity(), accountID, getString(R.string.donate_hashtag))),
new ListItem<>(R.string.sk_settings_contribute, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), getString(R.string.repo_url))),
new ListItem<>(R.string.settings_tos, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/terms")),
new ListItem<>(R.string.settings_privacy_policy, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), getString(R.string.privacy_policy_url)), 0, true),
mediaCacheItem=new ListItem<>(R.string.settings_clear_cache, 0, this::onClearMediaCacheClick),
new ListItem<>(getString(R.string.sk_settings_clear_timeline_cache), session.domain, this::onClearTimelineCacheClick)
));
updateMediaCacheItem();
}
@Override
protected void onHidden(){
super.onHidden();
if(timelineCacheCleared) getActivity().recreate();
}
@Override
protected void doLoadData(int offset, int count){}
@@ -63,7 +71,7 @@ public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
return adapter;
}
private void onClearMediaCacheClick(){
private void onClearMediaCacheClick(ListItem<?> item){
MastodonAPIController.runInBackground(()->{
Activity activity=getActivity();
ImageCache.getInstance(getActivity()).clear();
@@ -74,6 +82,12 @@ public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
});
}
private void onClearTimelineCacheClick(ListItem<?> item){
session.getCacheController().putHomeTimeline(List.of(), true);
Toast.makeText(getContext(), R.string.sk_timeline_cache_cleared, Toast.LENGTH_SHORT).show();
timelineCacheCleared=true;
}
private void updateMediaCacheItem(){
long size=ImageCache.getInstance(getActivity()).getDiskCache().size();
mediaCacheItem.subtitle=UiUtils.formatFileSize(getActivity(), size, false);

View File

@@ -46,20 +46,20 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
List<ListItem<Void>> items = new ArrayList<>(List.of(
languageItem=new ListItem<>(getString(R.string.default_post_language), postLanguage!=null ? postLanguage.getDisplayName(getContext()) : null, R.drawable.ic_fluent_local_language_24_regular, this::onDefaultLanguageClick),
altTextItem=new CheckableListItem<>(R.string.settings_alt_text_reminders, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.altTextReminders, R.drawable.ic_fluent_image_alt_text_24_regular, ()->toggleCheckableItem(altTextItem)),
playGifsItem=new CheckableListItem<>(R.string.settings_gif, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.playGifs, R.drawable.ic_fluent_gif_24_regular, ()->toggleCheckableItem(playGifsItem)),
overlayMediaItem=new CheckableListItem<>(R.string.sk_settings_continues_playback, R.string.sk_settings_continues_playback_summary, CheckableListItem.Style.SWITCH, GlobalUserPreferences.overlayMedia, R.drawable.ic_fluent_play_circle_hint_24_regular, ()->toggleCheckableItem(overlayMediaItem)),
customTabsItem=new CheckableListItem<>(R.string.settings_custom_tabs, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.useCustomTabs, R.drawable.ic_fluent_link_24_regular, ()->toggleCheckableItem(customTabsItem)),
confirmUnfollowItem=new CheckableListItem<>(R.string.settings_confirm_unfollow, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmUnfollow, R.drawable.ic_fluent_person_delete_24_regular, ()->toggleCheckableItem(confirmUnfollowItem)),
confirmBoostItem=new CheckableListItem<>(R.string.settings_confirm_boost, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmBoost, R.drawable.ic_fluent_arrow_repeat_all_24_regular, ()->toggleCheckableItem(confirmBoostItem)),
confirmDeleteItem=new CheckableListItem<>(R.string.settings_confirm_delete_post, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmDeletePost, R.drawable.ic_fluent_delete_24_regular, ()->toggleCheckableItem(confirmDeleteItem)),
altTextItem=new CheckableListItem<>(R.string.settings_alt_text_reminders, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.altTextReminders, R.drawable.ic_fluent_image_alt_text_24_regular, i->toggleCheckableItem(altTextItem)),
playGifsItem=new CheckableListItem<>(R.string.settings_gif, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.playGifs, R.drawable.ic_fluent_gif_24_regular, i->toggleCheckableItem(playGifsItem)),
overlayMediaItem=new CheckableListItem<>(R.string.sk_settings_continues_playback, R.string.sk_settings_continues_playback_summary, CheckableListItem.Style.SWITCH, GlobalUserPreferences.overlayMedia, R.drawable.ic_fluent_play_circle_hint_24_regular, i->toggleCheckableItem(overlayMediaItem)),
customTabsItem=new CheckableListItem<>(R.string.settings_custom_tabs, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.useCustomTabs, R.drawable.ic_fluent_link_24_regular, i->toggleCheckableItem(customTabsItem)),
confirmUnfollowItem=new CheckableListItem<>(R.string.settings_confirm_unfollow, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmUnfollow, R.drawable.ic_fluent_person_delete_24_regular, i->toggleCheckableItem(confirmUnfollowItem)),
confirmBoostItem=new CheckableListItem<>(R.string.settings_confirm_boost, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmBoost, R.drawable.ic_fluent_arrow_repeat_all_24_regular, i->toggleCheckableItem(confirmBoostItem)),
confirmDeleteItem=new CheckableListItem<>(R.string.settings_confirm_delete_post, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmDeletePost, R.drawable.ic_fluent_delete_24_regular, i->toggleCheckableItem(confirmDeleteItem)),
prefixRepliesItem=new ListItem<>(R.string.sk_settings_prefix_reply_cw_with_re, getPrefixWithRepliesString(), R.drawable.ic_fluent_arrow_reply_24_regular, this::onPrefixRepliesClick),
forwardReportsItem=new CheckableListItem<>(R.string.sk_settings_forward_report_default, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.forwardReportDefault, R.drawable.ic_fluent_arrow_forward_24_regular, ()->toggleCheckableItem(forwardReportsItem)),
loadNewPostsItem=new CheckableListItem<>(R.string.sk_settings_load_new_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.loadNewPosts, R.drawable.ic_fluent_arrow_sync_24_regular, this::onLoadNewPostsClick),
seeNewPostsBtnItem=new CheckableListItem<>(R.string.sk_settings_see_new_posts_button, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNewPostsButton, R.drawable.ic_fluent_arrow_up_24_regular, ()->toggleCheckableItem(seeNewPostsBtnItem)),
remoteLoadingItem=new CheckableListItem<>(R.string.sk_settings_allow_remote_loading, R.string.sk_settings_allow_remote_loading_explanation, CheckableListItem.Style.SWITCH, GlobalUserPreferences.allowRemoteLoading, R.drawable.ic_fluent_communication_24_regular, ()->toggleCheckableItem(remoteLoadingItem), true),
showBoostsItem=new CheckableListItem<>(R.string.sk_settings_show_boosts, 0, CheckableListItem.Style.SWITCH, lp.showBoosts, R.drawable.ic_fluent_arrow_repeat_all_24_regular, ()->toggleCheckableItem(showBoostsItem)),
showRepliesItem=new CheckableListItem<>(R.string.sk_settings_show_replies, 0, CheckableListItem.Style.SWITCH, lp.showReplies, R.drawable.ic_fluent_arrow_reply_24_regular, ()->toggleCheckableItem(showRepliesItem))
forwardReportsItem=new CheckableListItem<>(R.string.sk_settings_forward_report_default, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.forwardReportDefault, R.drawable.ic_fluent_arrow_forward_24_regular, i->toggleCheckableItem(forwardReportsItem)),
loadNewPostsItem=new CheckableListItem<>(R.string.sk_settings_load_new_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.loadNewPosts, R.drawable.ic_fluent_arrow_sync_24_regular, i->onLoadNewPostsClick()),
seeNewPostsBtnItem=new CheckableListItem<>(R.string.sk_settings_see_new_posts_button, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNewPostsButton, R.drawable.ic_fluent_arrow_up_24_regular, i->toggleCheckableItem(seeNewPostsBtnItem)),
remoteLoadingItem=new CheckableListItem<>(R.string.sk_settings_allow_remote_loading, R.string.sk_settings_allow_remote_loading_explanation, CheckableListItem.Style.SWITCH, GlobalUserPreferences.allowRemoteLoading, R.drawable.ic_fluent_communication_24_regular, i->toggleCheckableItem(remoteLoadingItem), true),
showBoostsItem=new CheckableListItem<>(R.string.sk_settings_show_boosts, 0, CheckableListItem.Style.SWITCH, lp.showBoosts, R.drawable.ic_fluent_arrow_repeat_all_24_regular, i->toggleCheckableItem(showBoostsItem)),
showRepliesItem=new CheckableListItem<>(R.string.sk_settings_show_replies, 0, CheckableListItem.Style.SWITCH, lp.showReplies, R.drawable.ic_fluent_arrow_reply_24_regular, i->toggleCheckableItem(showRepliesItem))
));
if(isInstanceAkkoma()) items.add(
@@ -93,7 +93,7 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
@Override
protected void doLoadData(int offset, int count){}
private void onDefaultLanguageClick(){
private void onDefaultLanguageClick(ListItem<?> item){
if (languageResolver == null) return;
ComposeLanguageAlertViewController vc=new ComposeLanguageAlertViewController(getActivity(), null, new ComposeLanguageAlertViewController.SelectedOption(postLanguage), null, languageResolver);
new M3AlertDialogBuilder(getActivity())
@@ -112,14 +112,14 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
.show();
}
private void onPrefixRepliesClick(){
private void onPrefixRepliesClick(ListItem<?> item){
int selected=GlobalUserPreferences.prefixReplies.ordinal();
int[] newSelected={selected};
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_settings_prefix_reply_cw_with_re)
.setSingleChoiceItems((String[]) IntStream.of(R.string.sk_settings_prefix_replies_never, R.string.sk_settings_prefix_replies_always, R.string.sk_settings_prefix_replies_to_others).mapToObj(this::getString).toArray(String[]::new),
selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->{
selected, (dlg, which)->newSelected[0]=which)
.setPositiveButton(R.string.ok, (dlg, which)->{
GlobalUserPreferences.prefixReplies=GlobalUserPreferences.PrefixRepliesMode.values()[newSelected[0]];
prefixRepliesItem.subtitleRes=getPrefixWithRepliesString();
rebindItem(prefixRepliesItem);
@@ -128,7 +128,7 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
.show();
}
private void onReplyVisibilityClick(){
private void onReplyVisibilityClick(ListItem<?> item){
AccountLocalPreferences lp=getLocalPrefs();
int selected=lp.timelineReplyVisibility==null ? 2 : switch(lp.timelineReplyVisibility){
case "following" -> 0;
@@ -139,8 +139,8 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_settings_prefix_reply_cw_with_re)
.setSingleChoiceItems((String[]) IntStream.of(R.string.sk_settings_reply_visibility_following, R.string.sk_settings_reply_visibility_self, R.string.sk_settings_reply_visibility_all).mapToObj(this::getString).toArray(String[]::new),
selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->{
selected, (dlg, which)->newSelected[0]=which)
.setPositiveButton(R.string.ok, (dlg, which)->{
lp.timelineReplyVisibility=switch(newSelected[0]){
case 0 -> "following";
case 1 -> "self";
@@ -176,6 +176,8 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
GlobalUserPreferences.allowRemoteLoading=remoteLoadingItem.checked;
GlobalUserPreferences.save();
AccountLocalPreferences lp=getLocalPrefs();
boolean restartPlease=lp.showBoosts!=showBoostsItem.checked
|| lp.showReplies!=showRepliesItem.checked;
lp.showBoosts=showBoostsItem.checked;
lp.showReplies=showRepliesItem.checked;
lp.save();
@@ -186,6 +188,7 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
s.preferences.postingDefaultLanguage=newPostLanguage.language.getLanguage();
s.savePreferencesLater();
}
if(restartPlease) getActivity().recreate();
}
@Override

View File

@@ -39,7 +39,7 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
@Override
protected void doLoadData(int offset, int count){}
private void onTestEmailConfirmClick(){
private void onTestEmailConfirmClick(ListItem<?> item){
AccountSession sess=AccountSessionManager.getInstance().getAccount(accountID);
sess.activated=false;
sess.activationInfo=new AccountActivationInfo("test@email", System.currentTimeMillis());
@@ -49,18 +49,18 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
Nav.goClearingStack(getActivity(), AccountActivationFragment.class, args);
}
private void onForceSelfUpdateClick(){
private void onForceSelfUpdateClick(ListItem<?> item){
GithubSelfUpdater.forceUpdate=true;
GithubSelfUpdater.getInstance().maybeCheckForUpdates();
restartUI();
}
private void onResetUpdaterClick(){
private void onResetUpdaterClick(ListItem<?> item){
GithubSelfUpdater.getInstance().reset();
restartUI();
}
private void onResetDiscoverBannersClick(){
private void onResetDiscoverBannersClick(ListItem<?> item){
DiscoverInfoBannerHelper.reset();
restartUI();
}

View File

@@ -56,29 +56,29 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
onDataLoaded(List.of(
themeItem=new ListItem<>(R.string.settings_theme, getAppearanceValue(), R.drawable.ic_fluent_weather_moon_24_regular, this::onAppearanceClick),
colorItem=new ListItem<>(getString(R.string.sk_settings_color_palette), getColorPaletteValue(), R.drawable.ic_fluent_color_24_regular, this::onColorClick),
trueBlackModeItem=new CheckableListItem<>(R.string.sk_settings_true_black, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.trueBlackTheme, R.drawable.ic_fluent_dark_theme_24_regular, this::onTrueBlackModeClick, true),
trueBlackModeItem=new CheckableListItem<>(R.string.sk_settings_true_black, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.trueBlackTheme, R.drawable.ic_fluent_dark_theme_24_regular, i->onTrueBlackModeClick(), true),
publishTextItem=new ListItem<>(getString(R.string.sk_settings_publish_button_text), getPublishButtonText(), R.drawable.ic_fluent_send_24_regular, this::onPublishTextClick),
autoRevealCWsItem=new ListItem<>(R.string.sk_settings_auto_reveal_equal_spoilers, getAutoRevealSpoilersText(), R.drawable.ic_fluent_eye_24_regular, this::onAutoRevealSpoilersClick),
revealCWsItem=new CheckableListItem<>(R.string.sk_settings_always_reveal_content_warnings, 0, CheckableListItem.Style.SWITCH, lp.revealCWs, R.drawable.ic_fluent_chat_warning_24_regular, ()->toggleCheckableItem(revealCWsItem)),
hideSensitiveMediaItem=new CheckableListItem<>(R.string.settings_hide_sensitive_media, 0, CheckableListItem.Style.SWITCH, lp.hideSensitiveMedia, R.drawable.ic_fluent_flag_24_regular, ()->toggleCheckableItem(hideSensitiveMediaItem)),
interactionCountsItem=new CheckableListItem<>(R.string.settings_show_interaction_counts, 0, CheckableListItem.Style.SWITCH, lp.showInteractionCounts, R.drawable.ic_fluent_number_row_24_regular, ()->toggleCheckableItem(interactionCountsItem)),
emojiInNamesItem=new CheckableListItem<>(R.string.settings_show_emoji_in_names, 0, CheckableListItem.Style.SWITCH, lp.customEmojiInNames, R.drawable.ic_fluent_emoji_24_regular, ()->toggleCheckableItem(emojiInNamesItem)),
marqueeItem=new CheckableListItem<>(R.string.sk_settings_enable_marquee, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.toolbarMarquee, R.drawable.ic_fluent_text_more_24_regular, ()->toggleCheckableItem(marqueeItem)),
reduceMotionItem=new CheckableListItem<>(R.string.sk_settings_reduce_motion, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.reduceMotion, R.drawable.ic_fluent_star_emphasis_24_regular, ()->toggleCheckableItem(reduceMotionItem)),
disableSwipeItem=new CheckableListItem<>(R.string.sk_settings_tabs_disable_swipe, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableSwipe, R.drawable.ic_fluent_swipe_right_24_regular, ()->toggleCheckableItem(disableSwipeItem)),
altIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showAltIndicator, R.drawable.ic_fluent_scan_text_24_regular, ()->toggleCheckableItem(altIndicatorItem)),
noAltIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_no_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNoAltIndicator, R.drawable.ic_fluent_important_24_regular, ()->toggleCheckableItem(noAltIndicatorItem)),
collapsePostsItem=new CheckableListItem<>(R.string.sk_settings_collapse_long_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.collapseLongPosts, R.drawable.ic_fluent_chevron_down_24_regular, ()->toggleCheckableItem(collapsePostsItem)),
spectatorModeItem=new CheckableListItem<>(R.string.sk_settings_hide_interaction, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.spectatorMode, R.drawable.ic_fluent_star_off_24_regular, ()->toggleCheckableItem(spectatorModeItem)),
hideFabItem=new CheckableListItem<>(R.string.sk_settings_hide_fab, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.autoHideFab, R.drawable.ic_fluent_edit_24_regular, ()->toggleCheckableItem(hideFabItem)),
translateOpenedItem=new CheckableListItem<>(R.string.sk_settings_translate_only_opened, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.translateButtonOpenedOnly, R.drawable.ic_fluent_translate_24_regular, ()->toggleCheckableItem(translateOpenedItem)),
likeIconItem=new CheckableListItem<>(R.string.sk_settings_like_icon, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.likeIcon, R.drawable.ic_fluent_heart_24_regular, ()->toggleCheckableItem(likeIconItem)),
underlinedLinksItem=new CheckableListItem<>(R.string.sk_settings_underlined_links, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.underlinedLinks, R.drawable.ic_fluent_text_underline_24_regular, ()->toggleCheckableItem(underlinedLinksItem)),
disablePillItem=new CheckableListItem<>(R.string.sk_disable_pill_shaped_active_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableM3PillActiveIndicator, R.drawable.ic_fluent_pill_24_regular, ()->toggleCheckableItem(disablePillItem)),
showNavigationLabelsItem=new CheckableListItem<>(R.string.sk_settings_show_labels_in_navigation_bar, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNavigationLabels, R.drawable.ic_fluent_tag_24_regular, ()->toggleCheckableItem(showNavigationLabelsItem), true),
pronounsInTimelinesItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_timelines, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInTimelines, 0, ()->toggleCheckableItem(pronounsInTimelinesItem)),
pronounsInThreadsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_threads, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInThreads, 0, ()->toggleCheckableItem(pronounsInThreadsItem)),
pronounsInUserListingsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_user_listings, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInUserListings, 0, ()->toggleCheckableItem(pronounsInUserListingsItem))
revealCWsItem=new CheckableListItem<>(R.string.sk_settings_always_reveal_content_warnings, 0, CheckableListItem.Style.SWITCH, lp.revealCWs, R.drawable.ic_fluent_chat_warning_24_regular, i->toggleCheckableItem(revealCWsItem)),
hideSensitiveMediaItem=new CheckableListItem<>(R.string.settings_hide_sensitive_media, 0, CheckableListItem.Style.SWITCH, lp.hideSensitiveMedia, R.drawable.ic_fluent_flag_24_regular, i->toggleCheckableItem(hideSensitiveMediaItem)),
interactionCountsItem=new CheckableListItem<>(R.string.settings_show_interaction_counts, 0, CheckableListItem.Style.SWITCH, lp.showInteractionCounts, R.drawable.ic_fluent_number_row_24_regular, i->toggleCheckableItem(interactionCountsItem)),
emojiInNamesItem=new CheckableListItem<>(R.string.settings_show_emoji_in_names, 0, CheckableListItem.Style.SWITCH, lp.customEmojiInNames, R.drawable.ic_fluent_emoji_24_regular, i->toggleCheckableItem(emojiInNamesItem)),
marqueeItem=new CheckableListItem<>(R.string.sk_settings_enable_marquee, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.toolbarMarquee, R.drawable.ic_fluent_text_more_24_regular, i->toggleCheckableItem(marqueeItem)),
reduceMotionItem=new CheckableListItem<>(R.string.sk_settings_reduce_motion, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.reduceMotion, R.drawable.ic_fluent_star_emphasis_24_regular, i->toggleCheckableItem(reduceMotionItem)),
disableSwipeItem=new CheckableListItem<>(R.string.sk_settings_tabs_disable_swipe, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableSwipe, R.drawable.ic_fluent_swipe_right_24_regular, i->toggleCheckableItem(disableSwipeItem)),
altIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showAltIndicator, R.drawable.ic_fluent_scan_text_24_regular, i->toggleCheckableItem(altIndicatorItem)),
noAltIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_no_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNoAltIndicator, R.drawable.ic_fluent_important_24_regular, i->toggleCheckableItem(noAltIndicatorItem)),
collapsePostsItem=new CheckableListItem<>(R.string.sk_settings_collapse_long_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.collapseLongPosts, R.drawable.ic_fluent_chevron_down_24_regular, i->toggleCheckableItem(collapsePostsItem)),
spectatorModeItem=new CheckableListItem<>(R.string.sk_settings_hide_interaction, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.spectatorMode, R.drawable.ic_fluent_star_off_24_regular, i->toggleCheckableItem(spectatorModeItem)),
hideFabItem=new CheckableListItem<>(R.string.sk_settings_hide_fab, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.autoHideFab, R.drawable.ic_fluent_edit_24_regular, i->toggleCheckableItem(hideFabItem)),
translateOpenedItem=new CheckableListItem<>(R.string.sk_settings_translate_only_opened, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.translateButtonOpenedOnly, R.drawable.ic_fluent_translate_24_regular, i->toggleCheckableItem(translateOpenedItem)),
likeIconItem=new CheckableListItem<>(R.string.sk_settings_like_icon, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.likeIcon, R.drawable.ic_fluent_heart_24_regular, i->toggleCheckableItem(likeIconItem)),
underlinedLinksItem=new CheckableListItem<>(R.string.sk_settings_underlined_links, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.underlinedLinks, R.drawable.ic_fluent_text_underline_24_regular, i->toggleCheckableItem(underlinedLinksItem)),
disablePillItem=new CheckableListItem<>(R.string.sk_disable_pill_shaped_active_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableM3PillActiveIndicator, R.drawable.ic_fluent_pill_24_regular, i->toggleCheckableItem(disablePillItem)),
showNavigationLabelsItem=new CheckableListItem<>(R.string.sk_settings_show_labels_in_navigation_bar, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNavigationLabels, R.drawable.ic_fluent_tag_24_regular, i->toggleCheckableItem(showNavigationLabelsItem), true),
pronounsInTimelinesItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_timelines, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInTimelines, 0, i->toggleCheckableItem(pronounsInTimelinesItem)),
pronounsInThreadsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_threads, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInThreads, 0, i->toggleCheckableItem(pronounsInThreadsItem)),
pronounsInUserListingsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_user_listings, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInUserListings, 0, i->toggleCheckableItem(pronounsInUserListingsItem))
));
trueBlackModeItem.checkedChangeListener=checked->onTrueBlackModeClick();
}
@@ -166,7 +166,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
maybeApplyNewThemeRightNow(null, null, prev);
}
private void onAppearanceClick(){
private void onAppearanceClick(ListItem<?> item_){
int selected=switch(GlobalUserPreferences.theme){
case LIGHT -> 0;
case DARK -> 1;
@@ -197,7 +197,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
.show();
}
private void onColorClick(){
private void onColorClick(ListItem<?> item_){
boolean multiple=AccountSessionManager.getInstance().getLoggedInAccounts().size() > 1;
int indexOffset=multiple ? 1 : 0;
int selected=lp.color==null ? 0 : lp.color.ordinal() + indexOffset;
@@ -226,7 +226,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
AlertDialog.Builder alert=new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_settings_color_palette)
.setSingleChoiceItems(items.toArray(String[]::new),
.setSingleChoiceItems(items.stream().toArray(String[]::new),
selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->save.accept(false))
.setNegativeButton(R.string.cancel, null);
@@ -234,7 +234,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
alert.show();
}
private void onPublishTextClick(){
private void onPublishTextClick(ListItem<?> item_){
TextInputFrameLayout input = new TextInputFrameLayout(
getContext(),
getString(R.string.publish),
@@ -257,7 +257,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
.show();
}
private void onAutoRevealSpoilersClick(){
private void onAutoRevealSpoilersClick(ListItem<?> item_){
int selected=GlobalUserPreferences.autoRevealEqualSpoilers.ordinal();
int[] newSelected={selected};
new M3AlertDialogBuilder(getActivity())

View File

@@ -67,16 +67,14 @@ public class SettingsFiltersFragment extends BaseSettingsFragment<Filter>{
Nav.go(getActivity(), EditFilterFragment.class, args);
}
private void onAddFilterClick(){
private void onAddFilterClick(ListItem<?> item){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), EditFilterFragment.class, args);
}
private ListItem<Filter> makeListItem(Filter f){
ListItem<Filter> item=new ListItem<>(f.title, getString(f.isActive() ? R.string.filter_active : R.string.filter_inactive), null, f);
item.onClick=()->onFilterClick(item);
item.isEnabled=true;
ListItem<Filter> item=new ListItem<>(f.title, getString(f.isActive() ? R.string.filter_active : R.string.filter_inactive), this::onFilterClick, f);
return item;
}

View File

@@ -19,6 +19,7 @@ import org.joinmastodon.android.ui.utils.UiUtils;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import me.grishka.appkit.Nav;
@@ -36,15 +37,15 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
lp=s.getLocalPreferences();
onDataLoaded(List.of(
new ListItem<>(AccountSessionManager.get(accountID).domain, getString(R.string.settings_server_explanation), R.drawable.ic_fluent_server_24_regular, this::onServerClick),
new ListItem<>(R.string.sk_settings_profile, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/profile")),
new ListItem<>(R.string.sk_settings_posting, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/preferences/other")),
new ListItem<>(R.string.sk_settings_auth, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/auth/edit"), 0, true),
contentTypesItem=new CheckableListItem<>(R.string.sk_settings_content_types, R.string.sk_settings_content_types_explanation, CheckableListItem.Style.SWITCH, lp.contentTypesEnabled, R.drawable.ic_fluent_text_edit_style_24_regular, this::onContentTypeClick),
new ListItem<>(R.string.sk_settings_profile, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/profile")),
new ListItem<>(R.string.sk_settings_posting, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/preferences/other")),
new ListItem<>(R.string.sk_settings_auth, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/auth/edit"), 0, true),
contentTypesItem=new CheckableListItem<>(R.string.sk_settings_content_types, R.string.sk_settings_content_types_explanation, CheckableListItem.Style.SWITCH, lp.contentTypesEnabled, R.drawable.ic_fluent_text_edit_style_24_regular, i->onContentTypeClick()),
defaultContentTypeItem=new ListItem<>(R.string.sk_settings_default_content_type, lp.defaultContentType.getName(), R.drawable.ic_fluent_text_bold_24_regular, this::onDefaultContentTypeClick, 0, true),
emojiReactionsItem=new CheckableListItem<>(R.string.sk_settings_emoji_reactions, R.string.sk_settings_emoji_reactions_explanation, CheckableListItem.Style.SWITCH, lp.emojiReactionsEnabled, R.drawable.ic_fluent_emoji_laugh_24_regular, this::onEmojiReactionsClick),
emojiReactionsItem=new CheckableListItem<>(R.string.sk_settings_emoji_reactions, R.string.sk_settings_emoji_reactions_explanation, CheckableListItem.Style.SWITCH, lp.emojiReactionsEnabled, R.drawable.ic_fluent_emoji_laugh_24_regular, i->onEmojiReactionsClick()),
showEmojiReactionsItem=new ListItem<>(R.string.sk_settings_show_emoji_reactions, getShowEmojiReactionsString(), R.drawable.ic_fluent_emoji_24_regular, this::onShowEmojiReactionsClick, 0, true),
localOnlyItem=new CheckableListItem<>(R.string.sk_settings_support_local_only, R.string.sk_settings_local_only_explanation, CheckableListItem.Style.SWITCH, lp.localOnlySupported, R.drawable.ic_fluent_eye_24_regular, this::onLocalOnlyClick),
glitchModeItem=new CheckableListItem<>(R.string.sk_settings_glitch_instance, R.string.sk_settings_glitch_mode_explanation, CheckableListItem.Style.SWITCH, lp.glitchInstance, R.drawable.ic_fluent_eye_24_filled, ()->toggleCheckableItem(glitchModeItem))
localOnlyItem=new CheckableListItem<>(R.string.sk_settings_support_local_only, R.string.sk_settings_local_only_explanation, CheckableListItem.Style.SWITCH, lp.localOnlySupported, R.drawable.ic_fluent_eye_24_regular, i->onLocalOnlyClick()),
glitchModeItem=new CheckableListItem<>(R.string.sk_settings_glitch_instance, R.string.sk_settings_glitch_mode_explanation, CheckableListItem.Style.SWITCH, lp.glitchInstance, R.drawable.ic_fluent_eye_24_filled, i->toggleCheckableItem(glitchModeItem))
));
contentTypesItem.checkedChangeListener=checked->onContentTypeClick();
defaultContentTypeItem.isEnabled=contentTypesItem.checked;
@@ -68,7 +69,7 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
E.post(new StatusDisplaySettingsChangedEvent(accountID));
}
private void onServerClick(){
private void onServerClick(ListItem<?> item){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), SettingsServerFragment.class, args);
@@ -87,23 +88,23 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
defaultContentTypeItem.subtitleRes=lp.defaultContentType.getName();
}
private void onDefaultContentTypeClick(){
int selected=lp.defaultContentType.ordinal();
int[] newSelected={selected};
ContentType[] supportedContentTypes=Arrays.stream(ContentType.values())
private void onDefaultContentTypeClick(ListItem<?> item_){
List<ContentType> supportedContentTypes=Arrays.stream(ContentType.values())
.filter(t->t.supportedByInstance(getInstance().orElse(null)))
.toArray(ContentType[]::new);
String[] names=Arrays.stream(supportedContentTypes)
.collect(Collectors.toList());
int selected=supportedContentTypes.indexOf(lp.defaultContentType);
int[] newSelected={selected};
String[] names=supportedContentTypes.stream()
.map(ContentType::getName)
.map(this::getString)
.toArray(String[]::new);
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.settings_theme)
.setTitle(R.string.sk_settings_default_content_type)
.setSingleChoiceItems(names,
selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->{
ContentType type=supportedContentTypes[newSelected[0]];
ContentType type=supportedContentTypes.get(newSelected[0]);
lp.defaultContentType=type;
defaultContentTypeItem.subtitleRes=type.getName();
rebindItem(defaultContentTypeItem);
@@ -112,7 +113,7 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
.show();
}
private void onShowEmojiReactionsClick(){
private void onShowEmojiReactionsClick(ListItem<?> item_){
int selected=lp.showEmojiReactions.ordinal();
int[] newSelected={selected};
new M3AlertDialogBuilder(getActivity())

View File

@@ -18,6 +18,7 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.AccountSwitcherSheet;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.HideableSingleViewRecyclerAdapter;
import org.joinmastodon.android.ui.utils.UiUtils;
@@ -49,7 +50,7 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
account = AccountSessionManager.get(accountID);
account=AccountSessionManager.get(accountID);
setTitle(R.string.settings);
setSubtitle(account.getFullUsername());
onDataLoaded(List.of(
@@ -59,15 +60,17 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
new ListItem<>(R.string.settings_notifications, 0, R.drawable.ic_fluent_alert_24_regular, this::onNotificationsClick),
new ListItem<>(R.string.sk_settings_instance, 0, R.drawable.ic_fluent_server_24_regular, this::onInstanceClick),
new ListItem<>(getString(R.string.about_app, getString(R.string.sk_app_name)), null, R.drawable.ic_fluent_info_24_regular, this::onAboutClick, null, 0, true),
new ListItem<>(R.string.manage_accounts, 0, R.drawable.ic_fluent_person_swap_24_regular, this::onManageAccountsClick),
new ListItem<>(R.string.log_out, 0, R.drawable.ic_fluent_sign_out_24_regular, this::onLogOutClick, R.attr.colorM3Error, false)
));
Instance instance = AccountSessionManager.getInstance().getInstanceInfo(account.domain);
if (!instance.isAkkoma())
Instance instance=AccountSessionManager.getInstance().getInstanceInfo(account.domain);
if(!instance.isAkkoma()){
data.add(3, new ListItem<>(R.string.settings_filters, 0, R.drawable.ic_fluent_filter_24_regular, this::onFiltersClick));
}
if(BuildConfig.DEBUG || BuildConfig.BUILD_TYPE.equals("appcenterPrivateBeta")){
data.add(0, new ListItem<>("Debug settings", null, R.drawable.ic_fluent_wrench_screwdriver_24_regular, ()->Nav.go(getActivity(), SettingsDebugFragment.class, makeFragmentArgs()), null, 0, true));
data.add(0, new ListItem<>("Debug settings", null, R.drawable.ic_fluent_wrench_screwdriver_24_regular, i->Nav.go(getActivity(), SettingsDebugFragment.class, makeFragmentArgs()), null, 0, true));
}
AccountSession session=AccountSessionManager.get(accountID);
@@ -128,35 +131,39 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
return args;
}
private void onBehaviorClick(){
private void onBehaviorClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsBehaviorFragment.class, makeFragmentArgs());
}
private void onDisplayClick(){
private void onDisplayClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsDisplayFragment.class, makeFragmentArgs());
}
private void onPrivacyClick(){
private void onPrivacyClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsPrivacyFragment.class, makeFragmentArgs());
}
private void onFiltersClick(){
private void onFiltersClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsFiltersFragment.class, makeFragmentArgs());
}
private void onNotificationsClick(){
private void onNotificationsClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsNotificationsFragment.class, makeFragmentArgs());
}
private void onInstanceClick(){
private void onInstanceClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsInstanceFragment.class, makeFragmentArgs());
}
private void onAboutClick(){
private void onAboutClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsAboutAppFragment.class, makeFragmentArgs());
}
private void onLogOutClick(){
private void onManageAccountsClick(ListItem<?> item){
new AccountSwitcherSheet(getActivity(), null).show();
}
private void onLogOutClick(ListItem<?> item_){
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
new M3AlertDialogBuilder(getActivity())
.setMessage(getString(R.string.confirm_log_out, session.getFullUsername()))

View File

@@ -27,7 +27,6 @@ import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.HideableSingleViewRecyclerAdapter;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.unifiedpush.android.connector.RegistrationDialogContent;
import org.unifiedpush.android.connector.UnifiedPush;
import java.time.Instant;
@@ -73,21 +72,21 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
useUnifiedPush=!getDistributor(getContext()).isEmpty();
onDataLoaded(List.of(
pauseItem=new CheckableListItem<>(getString(R.string.pause_all_notifications), getPauseItemSubtitle(), CheckableListItem.Style.SWITCH, false, R.drawable.ic_fluent_alert_snooze_24_regular, ()->onPauseNotificationsClick(false)),
pauseItem=new CheckableListItem<>(getString(R.string.pause_all_notifications), getPauseItemSubtitle(), CheckableListItem.Style.SWITCH, false, R.drawable.ic_fluent_alert_snooze_24_regular, i->onPauseNotificationsClick(false)),
policyItem=new ListItem<>(R.string.settings_notifications_policy, 0, R.drawable.ic_fluent_people_24_regular, this::onNotificationsPolicyClick, 0, true),
mentionsItem=new CheckableListItem<>(R.string.notification_type_mentions_and_replies, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.mention, R.drawable.ic_fluent_mention_24_regular, ()->toggleCheckableItem(mentionsItem)),
boostsItem=new CheckableListItem<>(R.string.notification_type_reblog, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.reblog, R.drawable.ic_fluent_arrow_repeat_all_24_regular, ()->toggleCheckableItem(boostsItem)),
favoritesItem=new CheckableListItem<>(R.string.notification_type_favorite, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.favourite, R.drawable.ic_fluent_star_24_regular, ()->toggleCheckableItem(favoritesItem)),
followersItem=new CheckableListItem<>(R.string.notification_type_follow, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.follow, R.drawable.ic_fluent_person_add_24_regular, ()->toggleCheckableItem(followersItem)),
pollsItem=new CheckableListItem<>(R.string.notification_type_poll, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.poll, R.drawable.ic_fluent_poll_24_regular, ()->toggleCheckableItem(pollsItem)),
updateItem=new CheckableListItem<>(R.string.sk_notification_type_update, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.update, R.drawable.ic_fluent_history_24_regular, ()->toggleCheckableItem(updateItem)),
postsItem=new CheckableListItem<>(R.string.sk_notification_type_posts, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.status, R.drawable.ic_fluent_chat_24_regular, ()->toggleCheckableItem(postsItem), true),
mentionsItem=new CheckableListItem<>(R.string.notification_type_mentions_and_replies, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.mention, R.drawable.ic_fluent_mention_24_regular, i->toggleCheckableItem(mentionsItem)),
boostsItem=new CheckableListItem<>(R.string.notification_type_reblog, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.reblog, R.drawable.ic_fluent_arrow_repeat_all_24_regular, i->toggleCheckableItem(boostsItem)),
favoritesItem=new CheckableListItem<>(R.string.notification_type_favorite, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.favourite, R.drawable.ic_fluent_star_24_regular, i->toggleCheckableItem(favoritesItem)),
followersItem=new CheckableListItem<>(R.string.notification_type_follow, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.follow, R.drawable.ic_fluent_person_add_24_regular, i->toggleCheckableItem(followersItem)),
pollsItem=new CheckableListItem<>(R.string.notification_type_poll, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.poll, R.drawable.ic_fluent_poll_24_regular, i->toggleCheckableItem(pollsItem)),
updateItem=new CheckableListItem<>(R.string.sk_notification_type_update, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.update, R.drawable.ic_fluent_history_24_regular, i->toggleCheckableItem(updateItem)),
postsItem=new CheckableListItem<>(R.string.sk_notification_type_posts, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.status, R.drawable.ic_fluent_chat_24_regular, i->toggleCheckableItem(postsItem), true),
uniformIconItem=new CheckableListItem<>(R.string.sk_settings_uniform_icon_for_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.uniformNotificationIcon, R.drawable.ic_ntf_logo, ()->toggleCheckableItem(uniformIconItem)),
deleteItem=new CheckableListItem<>(R.string.sk_settings_enable_delete_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.enableDeleteNotifications, R.drawable.ic_fluent_mail_inbox_dismiss_24_regular, ()->toggleCheckableItem(deleteItem)),
onlyLatestItem=new CheckableListItem<>(R.string.sk_settings_single_notification, 0, CheckableListItem.Style.SWITCH, lp.keepOnlyLatestNotification, R.drawable.ic_fluent_convert_range_24_regular, ()->toggleCheckableItem(onlyLatestItem), true),
unifiedPushItem=new CheckableListItem<>(R.string.sk_settings_unifiedpush, 0, CheckableListItem.Style.SWITCH, useUnifiedPush, R.drawable.ic_fluent_alert_arrow_up_24_regular, this::onUnifiedPush, true)
uniformIconItem=new CheckableListItem<>(R.string.sk_settings_uniform_icon_for_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.uniformNotificationIcon, R.drawable.ic_ntf_logo, i->toggleCheckableItem(uniformIconItem)),
deleteItem=new CheckableListItem<>(R.string.sk_settings_enable_delete_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.enableDeleteNotifications, R.drawable.ic_fluent_mail_inbox_dismiss_24_regular, i->toggleCheckableItem(deleteItem)),
onlyLatestItem=new CheckableListItem<>(R.string.sk_settings_single_notification, 0, CheckableListItem.Style.SWITCH, lp.keepOnlyLatestNotification, R.drawable.ic_fluent_convert_range_24_regular, i->toggleCheckableItem(onlyLatestItem), true),
unifiedPushItem=new CheckableListItem<>(R.string.sk_settings_unifiedpush, 0, CheckableListItem.Style.SWITCH, useUnifiedPush, R.drawable.ic_fluent_alert_arrow_up_24_regular, i->onUnifiedPushClick(), true)
));
//only enable when distributors, who can receive notifications, are available
@@ -98,7 +97,7 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
typeItems=List.of(mentionsItem, boostsItem, favoritesItem, followersItem, pollsItem, updateItem, postsItem);
pauseItem.checkedChangeListener=checked->onPauseNotificationsClick(true);
unifiedPushItem.checkedChangeListener=checked->onUnifiedPush();
unifiedPushItem.checkedChangeListener=checked->onUnifiedPushClick();
updatePolicyItem(null);
updatePauseItem();
}
@@ -254,7 +253,7 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
alert.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
}
private void onNotificationsPolicyClick(){
private void onNotificationsPolicyClick(ListItem<?> item_){
String[] items=Stream.of(
R.string.notifications_policy_anyone,
R.string.notifications_policy_followed,
@@ -328,7 +327,7 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
}
}
private void onUnifiedPush(){
private void onUnifiedPushClick(){
if(getDistributor(getContext()).isEmpty()){
List<String> distributors = UnifiedPush.getDistributors(getContext(), new ArrayList<>());
showUnifiedPushRegisterDialog(distributors);

View File

@@ -2,40 +2,98 @@ package org.joinmastodon.android.fragments.settings;
import android.os.Bundle;
import androidx.annotation.StringRes;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.StatusPrivacy;
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import java.util.ArrayList;
import java.util.List;
public class SettingsPrivacyFragment extends BaseSettingsFragment<Void>{
private CheckableListItem<Void> discoverableItem, indexableItem;
private CheckableListItem<Void> discoverableItem, indexableItem, lockedItem;
private ListItem<Void> privacyItem;
private StatusPrivacy privacy=null;
private Instance instance;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setTitle(R.string.settings_privacy);
Account self=AccountSessionManager.get(accountID).self;
AccountSession session=AccountSessionManager.get(accountID);
Account self=session.self;
instance=AccountSessionManager.getInstance().getInstanceInfo(session.domain);
privacy=self.source.privacy;
onDataLoaded(List.of(
discoverableItem=new CheckableListItem<>(R.string.settings_discoverable, 0, CheckableListItem.Style.SWITCH, self.discoverable, R.drawable.ic_fluent_thumb_like_dislike_24_regular, ()->toggleCheckableItem(discoverableItem)),
indexableItem=new CheckableListItem<>(R.string.settings_indexable, 0, CheckableListItem.Style.SWITCH, self.source.indexable!=null ? self.source.indexable : true, R.drawable.ic_fluent_search_24_regular, ()->toggleCheckableItem(indexableItem))
privacyItem=new ListItem<>(R.string.sk_settings_default_visibility, getPrivacyString(privacy), R.drawable.ic_fluent_eye_24_regular, this::onPrivacyClick, 0, true),
lockedItem=new CheckableListItem<>(R.string.sk_settings_lock_account, 0, CheckableListItem.Style.SWITCH, self.locked, R.drawable.ic_fluent_person_available_24_regular, i->toggleCheckableItem(lockedItem))
));
if(self.source.indexable==null)
indexableItem.isEnabled=false;
if(!instance.isAkkoma()){
data.addAll(List.of(
discoverableItem=new CheckableListItem<>(R.string.settings_discoverable, 0, CheckableListItem.Style.SWITCH, self.discoverable, R.drawable.ic_fluent_thumb_like_dislike_24_regular, i->toggleCheckableItem(discoverableItem)),
indexableItem=new CheckableListItem<>(R.string.settings_indexable, 0, CheckableListItem.Style.SWITCH, self.source.indexable!=null ? self.source.indexable : true, R.drawable.ic_fluent_search_24_regular, i->toggleCheckableItem(indexableItem))
));
if(self.source.indexable==null)
indexableItem.isEnabled=false;
}
}
@Override
protected void doLoadData(int offset, int count){}
private @StringRes int getPrivacyString(StatusPrivacy p){
if(p==null) return R.string.visibility_public;
return switch(p){
case PUBLIC -> R.string.visibility_public;
case UNLISTED -> R.string.sk_visibility_unlisted;
case PRIVATE -> R.string.visibility_followers_only;
case DIRECT -> R.string.visibility_private;
case LOCAL -> R.string.sk_local_only;
};
}
private void onPrivacyClick(ListItem<?> item_){
Account self=AccountSessionManager.get(accountID).self;
List<StatusPrivacy> options=new ArrayList<>(List.of(StatusPrivacy.PUBLIC, StatusPrivacy.UNLISTED, StatusPrivacy.PRIVATE, StatusPrivacy.DIRECT));
if(instance.isAkkoma()) options.add(StatusPrivacy.LOCAL);
int selected=options.indexOf(self.source.privacy);
int[] newSelected={selected};
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_settings_default_visibility)
.setSingleChoiceItems(options.stream().map(this::getPrivacyString).map(this::getString).toArray(String[]::new),
selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->{
privacy=options.get(newSelected[0]);
privacyItem.subtitleRes=getPrivacyString(privacy);
rebindItem(privacyItem);
})
.setNegativeButton(R.string.cancel, null)
.show();
}
@Override
public void onPause(){
super.onPause();
Account self=AccountSessionManager.get(accountID).self;
if(self.discoverable!=discoverableItem.checked || (self.source.indexable!=null && self.source.indexable!=indexableItem.checked)){
self.discoverable=discoverableItem.checked;
self.source.indexable=indexableItem.checked;
AccountSessionManager.get(accountID).savePreferencesLater();
AccountSession s=AccountSessionManager.get(accountID);
Account self=s.self;
boolean savePlease=self.locked!=lockedItem.checked
|| self.source.privacy!=privacy
|| (discoverableItem!=null && self.discoverable!=discoverableItem.checked)
|| (indexableItem!=null && self.source.indexable!=null && self.source.indexable!=indexableItem.checked);
if(savePlease){
if(discoverableItem!=null) self.discoverable=discoverableItem.checked;
if(indexableItem!=null) self.source.indexable=indexableItem.checked;
self.locked=lockedItem.checked;
s.preferences.postingDefaultVisibility=privacy;
s.savePreferencesLater();
}
}
}

View File

@@ -145,7 +145,7 @@ public class SettingsServerAboutFragment extends LoaderFragment{
if(!TextUtils.isEmpty(instance.email)){
needDivider=true;
SimpleListItemViewHolder holder=new SimpleListItemViewHolder(getActivity(), scrollingLayout);
ListItem<Void> item=new ListItem<>(R.string.send_email_to_server_admin, 0, R.drawable.ic_fluent_mail_24_regular, ()->{});
ListItem<Void> item=new ListItem<>(R.string.send_email_to_server_admin, 0, R.drawable.ic_fluent_mail_24_regular, i->{});
holder.bind(item);
holder.itemView.setBackground(UiUtils.getThemeDrawable(getActivity(), android.R.attr.selectableItemBackground));
holder.itemView.setOnClickListener(v->openAdminEmail());

View File

@@ -6,8 +6,6 @@ import android.text.TextUtils;
import androidx.annotation.Nullable;
import org.joinmastodon.android.api.ObjectValidationException;
import org.joinmastodon.android.api.RequiredField;
import org.joinmastodon.android.api.requests.instance.GetInstance;
import org.parceler.Parcel;
import java.time.Instant;
@@ -15,9 +13,6 @@ import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
/**
* Represents a user of Mastodon and their associated profile.
*/
@@ -163,26 +158,26 @@ public class Account extends BaseModel implements Searchable{
if(fields!=null){
for(AccountField f:fields)
f.postprocess();
} else {
fields = Collections.emptyList();
}else{
fields=Collections.emptyList();
}
if(emojis!=null){
for(Emoji e:emojis)
e.postprocess();
} else {
emojis = Collections.emptyList();
}else{
emojis=Collections.emptyList();
}
if(moved!=null)
moved.postprocess();
if(fqn == null) fqn = getFullyQualifiedName();
if(id == null) id = "";
if(username == null) username = "";
if(fqn==null) fqn=getFullyQualifiedName();
if(id==null) id="";
if(username==null) username="";
if(TextUtils.isEmpty(displayName))
displayName = !TextUtils.isEmpty(username) ? username : "";
if(acct == null) acct = "";
if(url == null) url = "";
if(note == null) note = "";
if(avatar == null) avatar = "";
displayName=!TextUtils.isEmpty(username) ? username : "";
if(acct==null) acct="";
if(url==null) url="";
if(note==null) note="";
if(avatar==null) avatar="";
}
public boolean isLocal(){
@@ -212,6 +207,10 @@ public class Account extends BaseModel implements Searchable{
return fqn != null ? fqn : acct.split("@")[0] + "@" + getDomainFromURL();
}
public String getDisplayName(){
return '\u2068'+displayName+'\u2069';
}
@Override
public String toString(){
return "Account{"+

View File

@@ -6,6 +6,7 @@ import org.joinmastodon.android.model.Poll.Option;
import org.parceler.Parcel;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
@@ -27,10 +28,10 @@ public class ScheduledStatus extends BaseModel implements DisplayItemsParent{
@Override
public void postprocess() throws ObjectValidationException {
super.postprocess();
if (mediaAttachments == null) mediaAttachments = List.of();
if(mediaAttachments==null) mediaAttachments=List.of();
for(Attachment a:mediaAttachments)
a.postprocess();
if (params != null) params.postprocess();
if(params!=null) params.postprocess();
}
@Parcel
@@ -53,7 +54,7 @@ public class ScheduledStatus extends BaseModel implements DisplayItemsParent{
@Override
public void postprocess() throws ObjectValidationException {
super.postprocess();
if (poll != null) poll.postprocess();
if(poll!=null) poll.postprocess();
}
}
@@ -67,25 +68,26 @@ public class ScheduledStatus extends BaseModel implements DisplayItemsParent{
public boolean hideTotals;
public Poll toPoll() {
Poll p = new Poll();
p.voted = true;
p.emojis = List.of();
p.ownVotes = List.of();
p.multiple = multiple;
p.options = options.stream().map(Option::new).collect(Collectors.toList());
Poll p=new Poll();
p.voted=true;
p.emojis=List.of();
p.ownVotes=List.of();
p.multiple=multiple;
p.options=options.stream().map(Option::new).collect(Collectors.toList());
p.expiresAt=Instant.now().plus(Integer.parseInt(expiresIn)+1, ChronoUnit.SECONDS);
return p;
}
}
public Status toStatus() {
Status s = Status.ofFake(id, params.text, scheduledAt);
s.mediaAttachments = mediaAttachments;
s.inReplyToId = params.inReplyToId > 0 ? "" + params.inReplyToId : null;
s.spoilerText = params.spoilerText;
s.visibility = params.visibility;
s.language = params.language;
s.sensitive = params.sensitive;
if (params.poll != null) s.poll = params.poll.toPoll();
Status s=Status.ofFake(id, params.text, scheduledAt);
s.mediaAttachments=mediaAttachments;
s.inReplyToId=params.inReplyToId>0 ? ""+params.inReplyToId : null;
s.spoilerText=params.spoilerText;
s.visibility=params.visibility;
s.language=params.language;
s.sensitive=params.sensitive;
if(params.poll!=null) s.poll=params.poll.toPoll();
return s;
}
}

View File

@@ -26,22 +26,13 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import org.joinmastodon.android.api.ObjectValidationException;
import org.joinmastodon.android.api.RequiredField;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.EmojiReactionsUpdatedEvent;
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.utils.StatusTextEncoder;
import org.parceler.Parcel;
import java.lang.reflect.Type;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Pattern;
@Parcel
@@ -104,6 +95,7 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
private transient String strippedText;
public transient TranslationState translationState=TranslationState.HIDDEN;
public transient Translation translation;
public transient boolean fromStatusCreated;
public Status(){}
@@ -203,6 +195,10 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
return reblog!=null ? reblog : this;
}
public String getContentStatusID(){
return getContentStatus().id;
}
public String getStrippedText(){
if(strippedText==null)
strippedText=HtmlParser.strip(content);

View File

@@ -33,9 +33,9 @@ public class AccountViewModel{
V.dp(50), V.dp(50));
emojiHelper=new CustomEmojiHelper();
if(session.getLocalPreferences().customEmojiInNames)
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
else
parsedName=account.displayName;
parsedName=account.getDisplayName();
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName);
ssb.append(parsedBio);

View File

@@ -9,42 +9,42 @@ public class CheckableListItem<T> extends ListItem<T>{
public boolean checked;
public Consumer<Boolean> checkedChangeListener;
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick, T parentObject, boolean dividerAfter){
super(title, subtitle, iconRes, onClick, parentObject, 0, dividerAfter);
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick, T parentObject, boolean dividerAfter){
super(title, subtitle, iconRes, (Consumer<ListItem<T>>)(Object)onClick, parentObject, 0, dividerAfter);
this.style=style;
this.checked=checked;
}
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Runnable onClick){
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick){
this(title, subtitle, style, checked, 0, onClick, null, false);
}
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Runnable onClick, T parentObject){
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick, T parentObject){
this(title, subtitle, style, checked, 0, onClick, parentObject, false);
}
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick){
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick){
this(title, subtitle, style, checked, iconRes, onClick, null, false);
}
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick, T parentObject){
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick, T parentObject){
this(title, subtitle, style, checked, iconRes, onClick, parentObject, false);
}
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Runnable onClick){
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick){
this(titleRes, subtitleRes, style, checked, 0, onClick, false);
}
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Runnable onClick, boolean dividerAfter){
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick, boolean dividerAfter){
this(titleRes, subtitleRes, style, checked, 0, onClick, dividerAfter);
}
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Runnable onClick){
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick){
this(titleRes, subtitleRes, style, checked, iconRes, onClick, false);
}
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Runnable onClick, boolean dividerAfter){
super(titleRes, subtitleRes, iconRes, onClick, 0, dividerAfter);
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick, boolean dividerAfter){
super(titleRes, subtitleRes, iconRes, (Consumer<ListItem<T>>)(Object)onClick, 0, dividerAfter);
this.style=style;
this.checked=checked;
}

View File

@@ -2,6 +2,8 @@ package org.joinmastodon.android.model.viewmodel;
import org.joinmastodon.android.R;
import java.util.function.Consumer;
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
@@ -16,11 +18,11 @@ public class ListItem<T>{
public int iconRes;
public int colorOverrideAttr;
public boolean dividerAfter;
public Runnable onClick;
private Consumer<ListItem<T>> onClick;
public boolean isEnabled=true;
public T parentObject;
public ListItem(String title, String subtitle, int iconRes, Runnable onClick, T parentObject, int colorOverrideAttr, boolean dividerAfter){
public ListItem(String title, String subtitle, int iconRes, Consumer<ListItem<T>> onClick, T parentObject, int colorOverrideAttr, boolean dividerAfter){
this.title=title;
this.subtitle=subtitle;
this.iconRes=iconRes;
@@ -32,45 +34,41 @@ public class ListItem<T>{
isEnabled=false;
}
public ListItem(String title, String subtitle, Runnable onClick){
public ListItem(String title, String subtitle, Consumer<ListItem<T>> onClick){
this(title, subtitle, 0, onClick, null, 0, false);
}
public ListItem(String title, String subtitle, Runnable onClick, T parentObject){
public ListItem(String title, String subtitle, Consumer<ListItem<T>> onClick, T parentObject){
this(title, subtitle, 0, onClick, parentObject, 0, false);
}
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick){
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick){
this(title, subtitle, iconRes, onClick, null, 0, false);
}
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick, boolean dividerAfter){
this(title, subtitle, iconRes, onClick, null, 0, dividerAfter);
}
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick, T parentObject){
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick, T parentObject){
this(title, subtitle, iconRes, onClick, parentObject, 0, false);
}
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Runnable onClick){
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Consumer<ListItem<T>> onClick){
this(null, null, 0, onClick, null, 0, false);
this.titleRes=titleRes;
this.subtitleRes=subtitleRes;
}
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Runnable onClick, int colorOverrideAttr, boolean dividerAfter){
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Consumer<ListItem<T>> onClick, int colorOverrideAttr, boolean dividerAfter){
this(null, null, 0, onClick, null, colorOverrideAttr, dividerAfter);
this.titleRes=titleRes;
this.subtitleRes=subtitleRes;
}
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Runnable onClick){
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick){
this(null, null, iconRes, onClick, null, 0, false);
this.titleRes=titleRes;
this.subtitleRes=subtitleRes;
}
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Runnable onClick, int colorOverrideAttr, boolean dividerAfter){
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick, int colorOverrideAttr, boolean dividerAfter){
this(null, null, iconRes, onClick, null, colorOverrideAttr, dividerAfter);
this.titleRes=titleRes;
this.subtitleRes=subtitleRes;
@@ -79,4 +77,13 @@ public class ListItem<T>{
public int getItemViewType(){
return colorOverrideAttr==0 ? R.id.list_item_simple : R.id.list_item_simple_tinted;
}
public void performClick(){
if(onClick!=null)
onClick.accept(this);
}
public <I extends ListItem<T>> void setOnClick(Consumer<I> onClick){
this.onClick=(Consumer<ListItem<T>>) onClick;
}
}

View File

@@ -8,7 +8,7 @@ import android.graphics.drawable.Animatable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
@@ -27,6 +27,8 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.HomeFragment;
import org.joinmastodon.android.fragments.SplashFragment;
import org.joinmastodon.android.fragments.onboarding.CustomWelcomeFragment;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.CheckableRelativeLayout;
@@ -40,7 +42,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.recyclerview.widget.LinearLayoutManager;
import me.grishka.appkit.FragmentStackActivity;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
@@ -282,7 +283,7 @@ public class AccountSwitcherSheet extends BottomSheet{
@SuppressLint("SetTextI18n")
@Override
public void onBind(AccountSession item){
name.setText(item.self.displayName);
HtmlParser.setTextWithCustomEmoji(name, item.self.getDisplayName(), item.self.emojis);
username.setText(item.getFullUsername());
radioButton.setVisibility(externalShare ? View.GONE : View.VISIBLE);
extraBtnWrap.setVisibility(externalShare && openInApp ? View.VISIBLE : View.GONE);

View File

@@ -26,9 +26,7 @@ import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ProgressBarButton;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
@@ -53,9 +51,9 @@ public class AccountCardStatusDisplayItem extends StatusDisplayItem{
coverRequest=new UrlImageLoaderRequest(account.header, 1000, 1000);
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), parentFragment.getAccountID());
if(account.emojis.isEmpty()){
parsedName=account.displayName;
parsedName=account.getDisplayName();
}else{
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
emojiHelper.setText(new SpannableStringBuilder(parsedName).append(parsedBio));
}
}
@@ -149,7 +147,7 @@ public class AccountCardStatusDisplayItem extends StatusDisplayItem{
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
relationship=item.parentFragment.getRelationship(item.account.id);
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), null,true, false, false, item.account);
if(item.notification.type==Notification.Type.FOLLOW_REQUEST && (relationship==null || !relationship.followedBy)){
actionWrap.setVisibility(View.GONE);

View File

@@ -8,6 +8,7 @@ import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.fragments.StatusListFragment;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.drawables.SawtoothTearDrawable;
import org.joinmastodon.android.ui.utils.UiUtils;
@@ -63,10 +64,14 @@ public class GapStatusDisplayItem extends StatusDisplayItem{
}
top.setClickable(!item.loading);
bottom.setClickable(!item.loading);
StatusDisplayItem next=getNextVisibleDisplayItem().orElse(null);
Instant dateBelow=next instanceof HeaderStatusDisplayItem h ? h.status.createdAt
: next instanceof ReblogOrReplyLineStatusDisplayItem l ? l.status.createdAt
: null;
Status next=!(item.parentFragment instanceof StatusListFragment) ? null : getNextVisibleDisplayItem(i->{
Status s=((StatusListFragment) item.parentFragment).getStatusByID(i.parentID);
return s!=null && !s.fromStatusCreated;
})
.map(i->((StatusListFragment) item.parentFragment).getStatusByID(i.parentID))
.orElse(null);
bottom.setVisibility(next==null ? View.GONE : View.VISIBLE);
Instant dateBelow=next!=null ? next.createdAt : null;
String text=dateBelow!=null && item.status.createdAt!=null && dateBelow.isBefore(item.status.createdAt)
? UiUtils.formatPeriodBetween(item.parentFragment.getContext(), dateBelow, item.status.createdAt)
: null;

View File

@@ -96,7 +96,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
GlobalUserPreferences.playGifs ? user.avatar : user.avatarStatic,
V.dp(50), V.dp(50));
this.accountID=accountID;
parsedName=new SpannableStringBuilder(user.displayName);
parsedName=new SpannableStringBuilder(user.getDisplayName());
this.status=status;
this.notification=notification;
this.scheduledStatus=scheduledStatus;
@@ -137,7 +137,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
}
public static class Holder extends StatusDisplayItem.Holder<HeaderStatusDisplayItem> implements ImageLoaderViewHolder{
private final TextView name, time, username, extraText, pronouns;
private final TextView name, time, username, extraText;
private final View collapseBtn, timeUsernameSeparator;
private final ImageView avatar, more, visibility, deleteNotification, unreadIndicator, markAsRead, collapseBtnIcon, botIcon;
private final PopupMenu optionsMenu;
@@ -164,7 +164,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
collapseBtn=findViewById(R.id.collapse_btn);
collapseBtnIcon=findViewById(R.id.collapse_btn_icon);
extraText=findViewById(R.id.extra_text);
pronouns=findViewById(R.id.pronouns);
avatar.setOnClickListener(this::onAvaClick);
avatar.setOutlineProvider(OutlineProviders.roundedRect(12));
avatar.setClipToOutline(true);
@@ -332,7 +331,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
if(TextUtils.isEmpty(item.extraText)){
if (item.status != null) {
boolean displayPronouns=item.parentFragment instanceof ThreadFragment ? GlobalUserPreferences.displayPronounsInThreads : GlobalUserPreferences.displayPronounsInTimelines;
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), extraText, pronouns, displayPronouns, item.status.visibility==StatusPrivacy.DIRECT, item.status.localOnly || item.status.visibility==StatusPrivacy.LOCAL, item.status.account);
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), extraText, displayPronouns, item.status.visibility==StatusPrivacy.DIRECT, item.status.localOnly || item.status.visibility==StatusPrivacy.LOCAL, item.status.account);
}
}else{
extraText.setVisibility(View.VISIBLE);
@@ -547,7 +546,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
follow.setIcon(following ? R.drawable.ic_fluent_person_delete_24_regular : R.drawable.ic_fluent_person_add_24_regular);
manageUserLists.setVisible(relationship != null && relationship.following);
manageUserLists.setTitle(item.parentFragment.getString(R.string.sk_lists_with_user, username));
UiUtils.insetPopupMenuIcon(item.parentFragment.getContext(), follow);
// ic_fluent_person_add_24_regular actually has a width of 25dp -.-
UiUtils.insetPopupMenuIcon(item.parentFragment.getContext(), follow, following ? 0 : V.dp(-1));
}
workaroundChangingMenuItemWidths(menu, username);

View File

@@ -382,7 +382,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
}
public MediaAttachmentViewController getViewController(int index){
return controllers.get(index);
return index<controllers.size() ? controllers.get(index) : null;
}
public void setClipChildren(boolean clip){

View File

@@ -6,6 +6,7 @@ import static org.joinmastodon.android.ui.utils.UiUtils.generateFormattedString;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.ColorStateList;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
@@ -18,7 +19,6 @@ import android.widget.TextView;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountLocalPreferences;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
@@ -62,7 +62,7 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{
TextUtils.isEmpty(notification.account.avatar) ? session.getDefaultAvatarUrl() :
GlobalUserPreferences.playGifs ? notification.account.avatar : notification.account.avatarStatic,
V.dp(50), V.dp(50));
SpannableStringBuilder parsedName=new SpannableStringBuilder(notification.account.displayName);
SpannableStringBuilder parsedName=new SpannableStringBuilder(notification.account.getDisplayName());
HtmlParser.parseCustomEmoji(parsedName, notification.account.emojis);
String str = parentFragment.getString(switch(notification.type){
case FOLLOW -> R.string.user_followed_you;
@@ -147,6 +147,8 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{
item.emojiHelper.setImageDrawable(index-1, image);
text.invalidate();
}
if(image instanceof Animatable)
((Animatable) image).start();
}
@Override

View File

@@ -87,8 +87,9 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
@Override
public ImageLoaderRequest getImageRequest(int index){
CustomEmojiHelper helper=index<emojiHelper.getImageCount() ? emojiHelper : extra.emojiHelper;
return helper.getImageRequest(index%emojiHelper.getImageCount());
int firstHelperCount=emojiHelper.getImageCount();
CustomEmojiHelper helper=index<firstHelperCount ? emojiHelper : extra.emojiHelper;
return helper.getImageRequest(firstHelperCount>0 ? index%firstHelperCount : index);
}
public static class Holder extends StatusDisplayItem.Holder<ReblogOrReplyLineStatusDisplayItem> implements ImageLoaderViewHolder{
@@ -136,8 +137,9 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
@Override
public void setImage(int index, Drawable image){
CustomEmojiHelper helper=index<item.emojiHelper.getImageCount() ? item.emojiHelper : item.extra.emojiHelper;
helper.setImageDrawable(index%item.emojiHelper.getImageCount(), image);
int firstHelperCount=item.emojiHelper.getImageCount();
CustomEmojiHelper helper=index<firstHelperCount ? item.emojiHelper : item.extra.emojiHelper;
helper.setImageDrawable(firstHelperCount>0 ? index%firstHelperCount : index, image);
text.invalidate();
extraText.invalidate();
}

View File

@@ -15,7 +15,6 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountLocalPreferences;
import org.joinmastodon.android.api.session.AccountSessionManager;
@@ -29,8 +28,8 @@ import org.joinmastodon.android.fragments.ThreadFragment;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.DisplayItemsParent;
import org.joinmastodon.android.model.LegacyFilter;
import org.joinmastodon.android.model.FilterAction;
import org.joinmastodon.android.model.LegacyFilter;
import org.joinmastodon.android.model.FilterContext;
import org.joinmastodon.android.model.FilterResult;
import org.joinmastodon.android.model.Notification;
@@ -41,13 +40,14 @@ import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.viewholders.AccountViewHolder;
import org.joinmastodon.android.utils.StatusFilterPredicate;
import org.parceler.Parcels;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import me.grishka.appkit.Nav;
@@ -92,7 +92,7 @@ public abstract class StatusDisplayItem{
}
@NonNull
public String getContentID(){
public String getContentStatusID(){
if(parentFragment instanceof StatusListFragment slf){
Status s=slf.getContentStatusByID(parentID);
return s!=null ? s.id : parentID;
@@ -142,11 +142,11 @@ public abstract class StatusDisplayItem{
String parentID = parent.getID();
String text = threadReply ? fragment.getString(R.string.sk_show_thread)
: account == null ? fragment.getString(R.string.sk_in_reply)
: status.reblog != null ? account.displayName
: fragment.getString(R.string.in_reply_to, account.displayName);
: status.reblog != null ? account.getDisplayName()
: fragment.getString(R.string.in_reply_to, account.getDisplayName());
String fullText = threadReply ? fragment.getString(R.string.sk_show_thread)
: account == null ? fragment.getString(R.string.sk_in_reply)
: fragment.getString(R.string.in_reply_to, account.displayName);
: fragment.getString(R.string.in_reply_to, account.getDisplayName());
return new ReblogOrReplyLineStatusDisplayItem(
parentID, fragment, text, account == null ? List.of() : account.emojis,
R.drawable.ic_fluent_arrow_reply_20sp_filled, null, null, fullText, status
@@ -176,12 +176,11 @@ public abstract class StatusDisplayItem{
if(status.reblog!=null){
boolean isOwnPost = AccountSessionManager.getInstance().isSelf(fragment.getAccountID(), status.account);
String fullText = fragment.getString(R.string.user_boosted, status.account.displayName);
String text = replyLine != null ? status.account.displayName : fullText;
String text=fragment.getString(R.string.user_boosted, status.account.getDisplayName());
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, text, status.account.emojis, R.drawable.ic_fluent_arrow_repeat_all_20sp_filled, isOwnPost ? status.visibility : null, i->{
args.putParcelable("profileAccount", Parcels.wrap(status.account));
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
}, fullText, status));
}, null, status));
} else if (!(status.tags.isEmpty() ||
fragment instanceof HashtagTimelineFragment ||
fragment instanceof ListTimelineFragment
@@ -306,10 +305,7 @@ public abstract class StatusDisplayItem{
footer=new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID);
footer.hideCounts=hideCounts;
items.add(footer);
if(status.hasGapAfter!=null && !(fragment instanceof ThreadFragment))
items.add(new GapStatusDisplayItem(parentID, fragment, status));
}
int i=1;
boolean inset=(flags & FLAG_INSET)!=0;
// add inset dummy so last content item doesn't clip out of inset bounds
if((inset || footer==null) && (flags & FLAG_CHECKABLE)==0){
@@ -319,6 +315,10 @@ public abstract class StatusDisplayItem{
// !contentItems.isEmpty() && contentItems
// .get(contentItems.size() - 1) instanceof MediaGridStatusDisplayItem));
}
GapStatusDisplayItem gap=null;
if((flags & FLAG_NO_FOOTER)==0 && status.hasGapAfter!=null && !(fragment instanceof ThreadFragment))
items.add(gap=new GapStatusDisplayItem(parentID, fragment, status));
int i=1;
for(StatusDisplayItem item:items){
item.inset=inset;
item.index=i++;
@@ -330,8 +330,13 @@ public abstract class StatusDisplayItem{
}
}
return applyingFilter==null ? items :
new ArrayList<>(List.of(new WarningFilteredStatusDisplayItem(parentID, fragment, statusForContent, items, applyingFilter)));
List<StatusDisplayItem> nonGapItems=gap!=null ? items.subList(0, items.size()-1) : items;
WarningFilteredStatusDisplayItem warning=applyingFilter==null ? null :
new WarningFilteredStatusDisplayItem(parentID, fragment, statusForContent, nonGapItems, applyingFilter);
return applyingFilter==null ? items : new ArrayList<>(gap!=null
? List.of(warning, gap)
: Collections.singletonList(warning)
);
}
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, List<StatusDisplayItem> items){
@@ -388,12 +393,14 @@ public abstract class StatusDisplayItem{
}
public Optional<StatusDisplayItem> getNextVisibleDisplayItem(){
return getNextVisibleDisplayItem(null);
}
public Optional<StatusDisplayItem> getNextVisibleDisplayItem(Predicate<StatusDisplayItem> predicate){
Optional<StatusDisplayItem> next=getNextDisplayItem();
for(int offset=1; next.isPresent(); next=getDisplayItemOffset(++offset)){
if(!next.map(n->
(n instanceof EmojiReactionsStatusDisplayItem e && e.isHidden()) ||
(n instanceof DummyStatusDisplayItem)
).orElse(false)) return next;
boolean isHidden=next.map(n->(n instanceof EmojiReactionsStatusDisplayItem e && e.isHidden())
|| (n instanceof DummyStatusDisplayItem)).orElse(false);
if(!isHidden && (predicate==null || predicate.test(next.get()))) return next;
}
return Optional.empty();
}

View File

@@ -210,9 +210,10 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
Translation existingTrans=item.status.getContentStatus().translation;
String existingTransLang=existingTrans!=null ? existingTrans.detectedSourceLanguage : null;
String lang=existingTransLang!=null ? existingTransLang : item.status.getContentStatus().language;
String displayLang=Locale.forLanguageTag(lang != null ? lang
: AccountSessionManager.get(item.parentFragment.getAccountID()).preferences.postingDefaultLanguage).getDisplayLanguage();
translationButton.setText(item.parentFragment.getString(R.string.translate_post, !displayLang.isBlank() ? displayLang : lang));
Locale locale=lang!=null ? Locale.forLanguageTag(lang) : null;
translationButton.setText(locale!=null
? item.parentFragment.getString(R.string.translate_post, locale.getDisplayLanguage())
: item.parentFragment.getString(R.string.sk_translate_post));
translationButton.setClickable(true);
translationButton.animate().alpha(1).setDuration(100).start();
translationInfo.setVisibility(View.GONE);

View File

@@ -0,0 +1,88 @@
package org.joinmastodon.android.ui.utils;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.IntEvaluator;
import android.animation.ObjectAnimator;
import android.graphics.drawable.Drawable;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import org.joinmastodon.android.R;
import java.util.function.IntSupplier;
import me.grishka.appkit.FragmentStackActivity;
import me.grishka.appkit.fragments.AppKitFragment;
public class ActionModeHelper{
public static ActionMode startActionMode(AppKitFragment fragment, IntSupplier statusBarColorSupplier, ActionMode.Callback callback){
FragmentStackActivity activity=(FragmentStackActivity) fragment.getActivity();
return activity.startActionMode(new ActionMode.Callback(){
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu){
if(!callback.onCreateActionMode(mode, menu))
return false;
ObjectAnimator anim=ObjectAnimator.ofInt(activity.getWindow(), "statusBarColor", statusBarColorSupplier.getAsInt(), UiUtils.getThemeColor(activity, R.attr.colorM3Primary));
anim.setEvaluator(new IntEvaluator(){
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
}
});
anim.start();
activity.invalidateSystemBarColors(fragment);
View fakeView=new View(activity);
// mode.setCustomView(fakeView);
// int buttonID=activity.getResources().getIdentifier("action_mode_close_button", "id", "android");
// View btn=activity.getWindow().getDecorView().findViewById(buttonID);
// if(btn!=null){
// ((ViewGroup.MarginLayoutParams)btn.getLayoutParams()).setMarginEnd(0);
// }
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu){
if(!callback.onPrepareActionMode(mode, menu))
return false;
for(int i=0;i<menu.size();i++){
Drawable icon=menu.getItem(i).getIcon();
if(icon!=null){
icon=icon.mutate();
icon.setTint(UiUtils.getThemeColor(activity, R.attr.colorM3OnPrimary));
menu.getItem(i).setIcon(icon);
}
}
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item){
return callback.onActionItemClicked(mode, item);
}
@Override
public void onDestroyActionMode(ActionMode mode){
ObjectAnimator anim=ObjectAnimator.ofInt(activity.getWindow(), "statusBarColor", UiUtils.getThemeColor(activity, R.attr.colorM3Primary), statusBarColorSupplier.getAsInt());
anim.setEvaluator(new IntEvaluator(){
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
}
});
anim.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
activity.getWindow().setStatusBarColor(0);
}
});
anim.start();
activity.invalidateSystemBarColors(fragment);
callback.onDestroyActionMode(mode);
}
});
}
}

View File

@@ -480,7 +480,7 @@ public class UiUtils {
public static void confirmToggleBlockUser(Activity activity, String accountID, Account account, boolean currentlyBlocked, Consumer<Relationship> resultCallback) {
showConfirmationAlert(activity, activity.getString(currentlyBlocked ? R.string.confirm_unblock_title : R.string.confirm_block_title),
activity.getString(currentlyBlocked ? R.string.confirm_unblock : R.string.confirm_block, account.displayName),
activity.getString(currentlyBlocked ? R.string.confirm_unblock : R.string.confirm_block, account.getDisplayName()),
activity.getString(currentlyBlocked ? R.string.do_unblock : R.string.do_block),
R.drawable.ic_fluent_person_prohibited_28_regular,
() -> {
@@ -508,7 +508,7 @@ public class UiUtils {
public static void confirmSoftBlockUser(Activity activity, String accountID, Account account, Consumer<Relationship> resultCallback) {
showConfirmationAlert(activity,
activity.getString(R.string.sk_remove_follower),
activity.getString(R.string.sk_remove_follower_confirm, account.displayName),
activity.getString(R.string.sk_remove_follower_confirm, account.getDisplayName()),
activity.getString(R.string.sk_do_remove_follower),
R.drawable.ic_fluent_person_delete_24_regular,
() -> new SetAccountBlocked(account.id, true).setCallback(new Callback<>() {
@@ -566,7 +566,7 @@ public class UiUtils {
params.setMargins(0, V.dp(-12), 0, 0);
durationView.setLayoutParams(params);
Button button=durationView.findViewById(R.id.button);
((TextView) durationView.findViewById(R.id.message)).setText(context.getString(R.string.confirm_mute, account.displayName));
((TextView) durationView.findViewById(R.id.message)).setText(context.getString(R.string.confirm_mute, account.getDisplayName()));
AtomicReference<Duration> muteDuration=new AtomicReference<>(Duration.ZERO);
@@ -600,7 +600,7 @@ public class UiUtils {
new M3AlertDialogBuilder(context)
.setTitle(context.getString(currentlyMuted ? R.string.confirm_unmute_title : R.string.confirm_mute_title))
.setMessage(currentlyMuted ? context.getString(R.string.confirm_unmute, account.displayName) : null)
.setMessage(currentlyMuted ? context.getString(R.string.confirm_unmute, account.getDisplayName()) : null)
.setView(currentlyMuted ? null : durationView)
.setPositiveButton(context.getString(currentlyMuted ? R.string.do_unmute : R.string.do_mute), (dlg, i)->{
new SetAccountMuted(account.id, !currentlyMuted, muteDuration.get().getSeconds())
@@ -638,11 +638,8 @@ public class UiUtils {
@Override
public void onSuccess(Status result) {
resultCallback.accept(result);
CacheController cache=AccountSessionManager.get(accountID).getCacheController();
cache.deleteStatus(s.id);
E.post(new StatusDeletedEvent(s.id, accountID));
if(status!=s){
cache.deleteStatus(status.id);
E.post(new StatusDeletedEvent(status.id, accountID));
}
}
@@ -782,8 +779,8 @@ public class UiUtils {
button.setText(relationship.followedBy ? R.string.follow_back : R.string.button_follow);
styleRes=R.style.Widget_Mastodon_M3_Button_Filled;
}else{
button.setText(R.string.button_following);
styleRes=R.style.Widget_Mastodon_M3_Button_Tonal;
button.setText(relationship.followedBy ? R.string.sk_button_mutuals : R.string.button_following);
styleRes=relationship.followedBy ? R.style.Widget_Mastodon_M3_Button_Tonal_Outlined : R.style.Widget_Mastodon_M3_Button_Tonal;
}
TypedArray ta=button.getContext().obtainStyledAttributes(styleRes, new int[]{android.R.attr.background});
@@ -909,17 +906,26 @@ public class UiUtils {
}
public static void insetPopupMenuIcon(Context context, MenuItem item) {
ColorStateList iconTint = ColorStateList.valueOf(UiUtils.getThemeColor(context, android.R.attr.textColorSecondary));
insetPopupMenuIcon(item, iconTint);
insetPopupMenuIcon(context, item, 0);
}
public static void insetPopupMenuIcon(MenuItem item, ColorStateList iconTint) {
Drawable icon = item.getIcon().mutate();
if (Build.VERSION.SDK_INT >= 26) item.setIconTintList(iconTint);
public static void insetPopupMenuIcon(Context context, MenuItem item, int addWidth) {
ColorStateList iconTint = ColorStateList.valueOf(UiUtils.getThemeColor(context, android.R.attr.textColorSecondary));
insetPopupMenuIcon(item, iconTint, addWidth);
}
/**
* @param addWidth set if icon is too wide/narrow. if icon is 25dp in width, set to -1dp
*/
public static void insetPopupMenuIcon(MenuItem item, ColorStateList iconTint, int addWidth) {
Drawable icon=item.getIcon().mutate();
if(Build.VERSION.SDK_INT>=26) item.setIconTintList(iconTint);
else icon.setTintList(iconTint);
icon = new InsetDrawable(icon, V.dp(8), 0, V.dp(8), 0);
int pad=V.dp(8);
boolean rtl=icon.getLayoutDirection()==View.LAYOUT_DIRECTION_RTL;
icon=new InsetDrawable(icon, rtl ? pad+addWidth : pad, 0, rtl ? pad : addWidth+pad, 0);
item.setIcon(icon);
SpannableStringBuilder ssb = new SpannableStringBuilder(item.getTitle());
SpannableStringBuilder ssb = new SpannableStringBuilder(item.getTitle());
item.setTitle(ssb);
}
@@ -953,7 +959,7 @@ public class UiUtils {
if (subMenu != null) enableMenuIcons(context, subMenu, exclude);
if (item.getIcon() == null || Arrays.stream(exclude).anyMatch(id -> id == item.getItemId()))
continue;
insetPopupMenuIcon(item, iconTint);
insetPopupMenuIcon(item, iconTint, 0);
}
}
@@ -1110,23 +1116,21 @@ public class UiUtils {
return back;
}
public static boolean setExtraTextInfo(Context ctx, @Nullable TextView extraText, @Nullable TextView pronouns, boolean displayPronouns, boolean mentionedOnly, boolean localOnly, @Nullable Account account) {
List<String> extraParts = extraText!=null && (localOnly || mentionedOnly) ? new ArrayList<>() : null;
Optional<String> p=pronouns==null || !displayPronouns ? Optional.empty() : extractPronouns(ctx, account);
if(p.isPresent()) {
HtmlParser.setTextWithCustomEmoji(pronouns, p.get(), account.emojis);
pronouns.setVisibility(View.VISIBLE);
}else if(pronouns!=null){
pronouns.setVisibility(View.GONE);
}
public static boolean setExtraTextInfo(Context ctx, @Nullable TextView extraText, boolean displayPronouns, boolean mentionedOnly, boolean localOnly, @Nullable Account account) {
List<String> extraParts=new ArrayList<>();
Optional<String> p=!displayPronouns ? Optional.empty() : extractPronouns(ctx, account);
if(localOnly)
extraParts.add(ctx.getString(R.string.sk_inline_local_only));
if(mentionedOnly)
extraParts.add(ctx.getString(R.string.sk_inline_direct));
if(extraText!=null && extraParts!=null && !extraParts.isEmpty()) {
String sepp = ctx.getString(R.string.sk_separator);
String text = String.join(" " + sepp + " ", extraParts);
if(account == null) extraText.setText(text);
if(p.isPresent() && extraParts.isEmpty())
extraParts.add(p.get());
if(extraText!=null && !extraParts.isEmpty()) {
String sepp=ctx.getString(R.string.sk_separator);
String text=String.join(" " + sepp + " ", extraParts);
if(account==null) extraText.setText(text);
else HtmlParser.setTextWithCustomEmoji(extraText, text, account.emojis);
extraText.setVisibility(View.VISIBLE);
return true;
@@ -1702,14 +1706,17 @@ public class UiUtils {
Matcher matcher=trimPronouns.matcher(text);
if(!matcher.find()) return null;
String matched=matcher.group(1);
String pronouns=matcher.group(1);
// crude fix to allow for pronouns like "it(/she)"
int missingClosingParens=0;
for(char c : matched.toCharArray()){
for(char c : pronouns.toCharArray()){
if(c=='(') missingClosingParens++;
if(c==')') missingClosingParens--;
}
return matched+")".repeat(Math.max(0, missingClosingParens));
pronouns+=")".repeat(Math.max(0, missingClosingParens));
// if ends with an un-closed custom emoji
if(pronouns.matches("^.*\\s+:[a-zA-Z_]+$")) pronouns+=':';
return pronouns;
}
// https://stackoverflow.com/questions/9475589/how-to-get-string-from-different-locales-in-android

View File

@@ -134,7 +134,10 @@ public class ComposePollViewController{
DraftPollOption opt=createDraftPollOption(false);
opt.edit.setText(eopt.title);
}
pollDuration=(int)fragment.editingStatus.poll.expiresAt.minus(fragment.editingStatus.createdAt.toEpochMilli(), ChronoUnit.MILLIS).getEpochSecond();
if(fragment.scheduledStatus!=null && fragment.scheduledStatus.params.poll!=null)
pollDuration=Integer.parseInt(fragment.scheduledStatus.params.poll.expiresIn);
else if(fragment.editingStatus.poll.expiresAt!=null)
pollDuration=(int)fragment.editingStatus.poll.expiresAt.minus(fragment.editingStatus.createdAt.toEpochMilli(), ChronoUnit.MILLIS).getEpochSecond();
updatePollOptionHints();
pollDurationValue.setText(UiUtils.formatDuration(fragment.getContext(), pollDuration));
pollIsMultipleChoice=fragment.editingStatus.poll.multiple;

View File

@@ -73,6 +73,6 @@ public abstract class ListItemViewHolder<T extends ListItem<?>> extends Bindable
@Override
public void onClick(){
item.onClick.run();
item.performClick();
}
}

View File

@@ -1,33 +1,40 @@
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.widget.LinearLayout;
import android.widget.TextView;
import me.grishka.appkit.utils.V;
import org.joinmastodon.android.R;
/**
* A LinearLayout for TextViews. First child TextView will get truncated if it doesn't fit, remaining will always wrap content.
*/
public class HeaderSubtitleLinearLayout extends LinearLayout{
private float firstFraction;
public HeaderSubtitleLinearLayout(Context context){
super(context);
this(context, null);
}
public HeaderSubtitleLinearLayout(Context context, AttributeSet attrs){
super(context, attrs);
this(context, attrs, 0);
}
public HeaderSubtitleLinearLayout(Context context, AttributeSet attrs, int defStyleAttr){
super(context, attrs, defStyleAttr);
TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.HeaderSubtitleLinearLayout);
firstFraction=ta.getFraction(R.styleable.HeaderSubtitleLinearLayout_firstFraction, 1, 1, 0.5f);
ta.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
if(getLayoutChildCount()>1){
int remainingWidth=MeasureSpec.getSize(widthMeasureSpec);
int fullWidth=MeasureSpec.getSize(widthMeasureSpec);
int remainingWidth=fullWidth;
for(int i=1;i<getChildCount();i++){
View v=getChildAt(i);
if(v.getVisibility()==GONE)
@@ -38,8 +45,7 @@ public class HeaderSubtitleLinearLayout extends LinearLayout{
}
View first=getChildAt(0);
if(first instanceof TextView){
// guaranteeing at least 64dp of width for the display name
((TextView) first).setMaxWidth(Math.max(remainingWidth, V.dp(64)));
((TextView) first).setMaxWidth(Math.max(remainingWidth, (int)(firstFraction*fullWidth)));
}
}else{
View first=getChildAt(0);
@@ -58,4 +64,12 @@ public class HeaderSubtitleLinearLayout extends LinearLayout{
}
return count;
}
public void setFirstFraction(float firstFraction){
this.firstFraction=firstFraction;
}
public float getFirstFraction(){
return firstFraction;
}
}

View File

@@ -3,19 +3,13 @@
android:color="@color/m3_primary_overlay">
<item android:gravity="center_vertical" android:height="40dp">
<selector>
<item android:state_enabled="true" android:state_selected="true">
<item android:state_enabled="true">
<shape>
<solid android:color="?colorM3SecondaryContainer"/>
<corners android:radius="20dp"/>
</shape>
</item>
<item android:state_selected="false">
<shape>
<stroke android:color="@color/m3_on_surface_overlay" android:width="1dp"/>
<corners android:radius="20dp"/>
</shape>
</item>
<item android:state_enabled="false">
<item>
<shape>
<solid android:color="?colorM3DisabledBackground"/>
<corners android:radius="20dp"/>

View File

@@ -3,19 +3,13 @@
android:color="@color/m3_primary_overlay">
<item android:gravity="center" android:height="40dp" android:width="40dp">
<selector>
<item android:state_enabled="true" android:state_selected="true">
<item android:state_enabled="true">
<shape>
<solid android:color="?colorM3SecondaryContainer"/>
<corners android:radius="20dp"/>
</shape>
</item>
<item android:state_selected="false">
<shape>
<stroke android:color="@color/m3_on_surface_overlay" android:width="1dp"/>
<corners android:radius="20dp"/>
</shape>
</item>
<item android:state_enabled="false">
<item>
<shape>
<solid android:color="?colorM3DisabledBackground"/>
<corners android:radius="20dp"/>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/m3_primary_overlay">
<item android:gravity="center" android:height="40dp" android:width="40dp">
<selector>
<item android:state_enabled="true" android:state_selected="true">
<shape>
<solid android:color="?colorM3SecondaryContainer"/>
<corners android:radius="20dp"/>
</shape>
</item>
<item android:state_selected="false">
<shape>
<stroke android:color="@color/m3_on_surface_overlay" android:width="1dp"/>
<corners android:radius="20dp"/>
</shape>
</item>
<item android:state_enabled="false">
<shape>
<solid android:color="?colorM3DisabledBackground"/>
<corners android:radius="20dp"/>
</shape>
</item>
</selector>
</item>
<item android:id="@android:id/mask" android:gravity="center" android:height="40dp" android:width="40dp">
<shape>
<solid android:color="#000"/>
<corners android:radius="20dp"/>
</shape>
</item>
</ripple>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/m3_primary_overlay">
<item android:gravity="center_vertical" android:height="40dp">
<selector>
<item android:state_enabled="true">
<shape>
<solid android:color="?colorM3SecondaryContainer"/>
<stroke android:color="?colorM3OnSecondaryContainer" android:width="1dp"/>
<corners android:radius="20dp"/>
</shape>
</item>
<item>
<shape>
<solid android:color="?colorM3DisabledBackground"/>
<corners android:radius="20dp"/>
</shape>
</item>
</selector>
</item>
<item android:id="@android:id/mask" android:gravity="center_vertical" android:height="40dp">
<shape>
<solid android:color="#000"/>
<corners android:radius="20dp"/>
</shape>
</item>
</ripple>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/m3_primary_overlay">
<item android:gravity="center_vertical" android:height="40dp">
<selector>
<item android:state_enabled="true" android:state_selected="true">
<shape>
<solid android:color="?colorM3SecondaryContainer"/>
<corners android:radius="20dp"/>
</shape>
</item>
<item android:state_selected="false">
<shape>
<stroke android:color="@color/m3_on_surface_overlay" android:width="1dp"/>
<corners android:radius="20dp"/>
</shape>
</item>
<item android:state_enabled="false">
<shape>
<solid android:color="?colorM3DisabledBackground"/>
<corners android:radius="20dp"/>
</shape>
</item>
</selector>
</item>
<item android:id="@android:id/mask" android:gravity="center_vertical" android:height="40dp">
<shape>
<solid android:color="#000"/>
<corners android:radius="20dp"/>
</shape>
</item>
</ripple>

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/highlight_over_dark">
<item>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/m3_pressed_overlay">
<item android:gravity="center_vertical" android:height="36dp">
<shape>
<solid android:color="?colorPrimary800"/>
<corners android:radius="16sp"/>
<padding android:left="16sp" android:right="16sp"/>
<solid android:color="?colorM3Primary"/>
<corners android:radius="18dp"/>
</shape>
</item>
</ripple>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/m3_pressed_overlay">
<item android:gravity="center_vertical" android:height="36dp">
<shape>
<stroke android:color="@color/m3_on_surface_overlay" android:width="1dp"/>
<corners android:radius="18dp"/>
</shape>
</item>
</ripple>

View File

@@ -0,0 +1,3 @@
<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="M17.5 12c3.038 0 5.5 2.463 5.5 5.5 0 3.038-2.462 5.5-5.5 5.5-3.037 0-5.5-2.462-5.5-5.5 0-3.037 2.463-5.5 5.5-5.5zm-2.646 5.147c-0.195-0.196-0.512-0.196-0.707 0-0.196 0.195-0.196 0.512 0 0.707l2 2c0.195 0.195 0.512 0.195 0.707 0l4-4c0.195-0.195 0.195-0.512 0-0.707-0.195-0.196-0.512-0.196-0.707 0L16.5 18.793l-1.646-1.646zM12.023 14c-0.297 0.463-0.537 0.966-0.709 1.5H4.253c-0.414 0-0.75 0.335-0.75 0.75v0.577c0 0.535 0.192 1.053 0.54 1.46 1.253 1.469 3.22 2.214 5.957 2.214 0.597 0 1.157-0.035 1.68-0.106 0.246 0.495 0.553 0.954 0.912 1.367-0.795 0.16-1.66 0.24-2.592 0.24-3.146 0-5.532-0.906-7.098-2.74-0.58-0.679-0.898-1.543-0.898-2.435v-0.578C2.004 15.007 3.01 14 4.253 14h7.77zM10 2.005c2.762 0 5 2.239 5 5s-2.238 5-5 5c-2.761 0-5-2.239-5-5s2.239-5 5-5zm0 1.5c-1.933 0-3.5 1.567-3.5 3.5s1.567 3.5 3.5 3.5 3.5-1.567 3.5-3.5-1.567-3.5-3.5-3.5z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

View File

@@ -1,3 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="25dp" android:height="24dp" android:viewportWidth="25" android:viewportHeight="24">
<path android:pathData="M12.416 2c5.523 0 10 4.477 10 10s-4.477 10-10 10-10-4.477-10-10 4.477-10 10-10zm6.517 4.543L6.96 18.517c1.477 1.238 3.38 1.983 5.457 1.983 4.694 0 8.5-3.806 8.5-8.5 0-2.077-0.745-3.98-1.983-5.457zM12.416 3.5c-4.694 0-8.5 3.806-8.5 8.5 0 2.077 0.745 3.98 1.983 5.457L17.873 5.483C16.396 4.245 14.493 3.5 12.416 3.5z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

View File

@@ -30,7 +30,7 @@
android:layout_height="wrap_content"
android:minHeight="48dp"
android:minWidth="48dp"
android:background="@drawable/bg_button_m3_tonal_circle"
android:background="@drawable/bg_button_m3_tonal_circle_selector"
android:tooltipText="@string/sk_button_react"
android:contentDescription="@string/sk_button_react"
android:src="@drawable/ic_fluent_add_24_filled" />

View File

@@ -22,7 +22,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="15dp">
<!-- avatar width (46sp) / 2 - button width (24dp) / 2 -->
<FrameLayout
android:layout_weight="1"

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp">
@@ -10,7 +11,7 @@
android:id="@+id/buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginTop="5dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true">
@@ -107,6 +108,7 @@
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
android:id="@+id/name_wrap"
app:firstFraction="60%"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/avatar"
@@ -125,20 +127,6 @@
android:gravity="start|center_vertical"
tools:text="Eugen" />
<TextView
android:id="@+id/pronouns"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8sp"
android:maxWidth="161sp"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/m3_title_medium"
android:fontFamily="sans-serif"
android:textAlignment="viewStart"
android:textColor="?colorM3OnSurface"
tools:text="they/them" />
<TextView
android:id="@+id/extra_text"
android:layout_width="wrap_content"
@@ -146,8 +134,7 @@
android:layout_marginStart="8sp"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/m3_title_medium"
android:fontFamily="sans-serif"
android:textAppearance="@style/m3_body_medium"
android:textAlignment="viewStart"
android:textColor="?colorM3OnSurface"
tools:text="boosted your cat picture" />

View File

@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:firstFraction="30%"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -45,6 +47,6 @@
android:drawableTint="?colorM3OnSurface"
android:drawablePadding="6dp"
android:singleLine="true"
android:ellipsize="end"/>
android:ellipsize="middle"/>
</org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout>

View File

@@ -49,7 +49,7 @@
<Button
android:id="@+id/advanced"
style="@style/Widget.Mastodon.M3.Button.Outlined"
android:background="@drawable/bg_button_m3_tonal"
android:background="@drawable/bg_button_m3_tonal_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"

View File

@@ -110,7 +110,7 @@
android:layout_marginStart="8sp"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/m3_title_medium"
android:textAppearance="@style/m3_body_medium"
android:textAlignment="viewStart"
android:textColor="?colorM3OnSurface"
tools:text="@string/sk_inline_local_only" />
@@ -366,6 +366,7 @@
<Button
style="@style/Widget.Mastodon.M3.Button.Tonal.Icon"
android:background="@drawable/bg_button_m3_tonal_selector"
android:id="@+id/sensitive_item"
android:orientation="horizontal"
android:layout_width="wrap_content"

View File

@@ -93,7 +93,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
style="@style/Widget.Mastodon.M3.Button.Tonal"
android:background="@drawable/bg_button_m3_tonal_circle"
android:background="@drawable/bg_button_m3_tonal_circle_selector"
android:paddingStart="12dp"
android:drawableStart="@drawable/ic_fluent_alert_24_selector" />

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/switcher_btn"
style="@style/Widget.Mastodon.M3.Button.Text"
android:orientation="horizontal"
android:id="@+id/switcher_btn"
style="@style/Widget.Mastodon.M3.Button.Text"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|start"
@@ -14,55 +14,44 @@
android:tooltipText="@string/sk_switch_timeline"
android:paddingStart="12dp"
android:paddingEnd="12dp">
<ImageView
android:id="@+id/timeline_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_fluent_home_24_regular" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<ImageView
android:id="@+id/collapsed_chevron"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_fluent_chevron_down_16_filled"
android:visibility="gone" />
<TextView
android:id="@+id/timeline_title"
style="?android:attr/titleTextAppearance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:drawablePadding="8dp"
android:drawableEnd="@drawable/ic_fluent_chevron_down_16_filled" />
</FrameLayout>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/show_new_posts_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingVertical="2dp"
android:paddingStart="16dp"
android:paddingEnd="20dp"
android:minHeight="32sp"
android:maxLines="2"
android:ellipsize="end"
android:lineSpacingMultiplier="0.8"
android:textAppearance="@style/m3_title_medium"
android:textSize="16sp"
android:text="@string/see_new_posts"
android:textColor="@color/gray_25"
android:background="@drawable/bg_button_new_posts"
android:drawableStart="@drawable/ic_fluent_arrow_up_16_filled"
android:drawablePadding="8dp"
android:layout_gravity="center" />
</FrameLayout>
<ImageView
android:id="@+id/timeline_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_fluent_home_24_regular"/>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<ImageView
android:id="@+id/collapsed_chevron"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_fluent_chevron_down_16_filled"
android:visibility="gone"/>
<TextView
style="@style/action_bar_title"
android:id="@+id/timeline_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:drawablePadding="8dp"
android:drawableEnd="@drawable/ic_fluent_chevron_down_16_filled"/>
</FrameLayout>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
style="?toolbarActionButtonStyle"
android:id="@+id/show_new_posts_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/see_new_posts"
android:drawableStart="@drawable/ic_fluent_arrow_up_16_filled"
android:layout_gravity="center"/>
</FrameLayout>
</FrameLayout>

View File

@@ -23,5 +23,5 @@
android:layout_marginEnd="8dp"
android:drawableTint="@null"
android:drawableStart="@drawable/image_placeholder"
android:background="@drawable/bg_button_m3_tonal"/>
android:background="@drawable/bg_button_m3_tonal_selector"/>
</FrameLayout>

View File

@@ -1,13 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/menu_group1">
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:visible="false" android:icon="@drawable/ic_fluent_person_swap_24_regular">
<menu android:id="@+id/accounts" />
</item>
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
<item android:id="@+id/open_in_browser" android:title="@string/open_in_browser" android:icon="@drawable/ic_fluent_globe_24_regular"/>
</group>
<group android:id="@+id/menu_group2">
<item android:id="@+id/manage_user_lists" android:title="@string/sk_lists_with_user" android:icon="@drawable/ic_fluent_people_24_regular"/>
<item android:id="@+id/mute" android:title="@string/mute_user" android:icon="@drawable/ic_fluent_speaker_off_24_regular"/>
<item android:id="@+id/hide_boosts" android:title="@string/hide_boosts_from_user" android:icon="@drawable/ic_fluent_arrow_repeat_all_off_24_regular"/>
@@ -16,4 +9,11 @@
<item android:id="@+id/report" android:title="@string/report_user" android:icon="@drawable/ic_fluent_warning_24_regular"/>
<item android:id="@+id/block_domain" android:title="@string/block_domain" android:icon="@drawable/ic_fluent_shield_prohibited_24_regular"/>
</group>
<group android:id="@+id/menu_group2">
<item android:id="@+id/open_in_browser" android:title="@string/open_in_browser" android:icon="@drawable/ic_fluent_globe_24_regular"/>
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:visible="false" android:icon="@drawable/ic_fluent_person_swap_24_regular">
<menu android:id="@+id/accounts" />
</item>
</group>
</menu>

View File

@@ -1,14 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/followed_hashtags" android:title="@string/sk_hashtags_you_follow" android:icon="@drawable/ic_fluent_number_symbol_24_regular" android:showAsAction="always"/>
<item android:id="@+id/bookmarks" android:title="@string/bookmarks" android:icon="@drawable/ic_fluent_bookmark_multiple_24_regular" android:showAsAction="always"/>
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:icon="@drawable/ic_fluent_person_swap_24_regular">
<menu android:id="@+id/accounts" />
</item>
<item android:id="@+id/manage_user_lists" android:title="@string/sk_your_lists" android:icon="@drawable/ic_fluent_people_24_regular"/>
<item android:id="@+id/favorites" android:title="@string/your_favorites" android:icon="@drawable/ic_fluent_star_24_regular"/>
<item android:id="@+id/muted_accounts" android:title="@string/sk_muted_accounts" android:icon="@drawable/ic_fluent_speaker_off_24_regular"/>
<item android:id="@+id/blocked_accounts" android:title="@string/sk_blocked_accounts" android:icon="@drawable/ic_fluent_shield_24_regular"/>
<item android:id="@+id/scheduled" android:title="@string/sk_unsent_posts" android:icon="@drawable/ic_fluent_folder_open_24_regular"/>
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
<group android:id="@+id/menu_group1">
<item android:id="@+id/followed_hashtags" android:title="@string/sk_hashtags_you_follow" android:icon="@drawable/ic_fluent_number_symbol_24_regular" android:showAsAction="always"/>
<item android:id="@+id/bookmarks" android:title="@string/bookmarks" android:icon="@drawable/ic_fluent_bookmark_multiple_24_regular" android:showAsAction="always"/>
<item android:id="@+id/manage_user_lists" android:title="@string/sk_your_lists" android:icon="@drawable/ic_fluent_people_24_regular"/>
<item android:id="@+id/favorites" android:title="@string/your_favorites" android:icon="@drawable/ic_fluent_star_24_regular"/>
<item android:id="@+id/muted_accounts" android:title="@string/sk_muted_accounts" android:icon="@drawable/ic_fluent_speaker_off_24_regular"/>
<item android:id="@+id/blocked_accounts" android:title="@string/sk_blocked_accounts" android:icon="@drawable/ic_fluent_shield_24_regular"/>
<item android:id="@+id/scheduled" android:title="@string/sk_unsent_posts" android:icon="@drawable/ic_fluent_folder_open_24_regular"/>
</group>
<group android:id="@+id/menu_group2">
<item android:id="@+id/open_in_browser" android:title="@string/open_in_browser" android:icon="@drawable/ic_fluent_globe_24_regular"/>
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:visible="false" android:icon="@drawable/ic_fluent_person_swap_24_regular">
<menu android:id="@+id/accounts" />
</item>
</group>
</menu>

View File

@@ -1,474 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="get_started">الخطوات الأولى</string>
<string name="log_in">تسجيلُ الدخول</string>
<string name="next">التالي</string>
<string name="loading_instance">يَجري الحُصُول على معلومات المَثيل…</string>
<string name="error">خطأ</string>
<string name="not_a_mastodon_instance">%s لا يبدو كمثيل ماستدون.</string>
<string name="ok">حسنًا</string>
<string name="preparing_auth">جَارٍ الإعدَادُ لِلمُصادَقَة…</string>
<string name="finishing_auth">يُنهي المصادقة…</string>
<string name="user_boosted">أعادَ %s تَدوينَها</string>
<string name="in_reply_to">ردًا على %s</string>
<string name="notifications">الإشعارات</string>
<string name="user_followed_you">بَدَأ بِمُتابَعَتِك</string>
<string name="user_sent_follow_request">أرسَلَ طَلَبًا لِمُتابَعَتِك</string>
<string name="user_favorited">فَضَّلَ مَنشُورَك</string>
<string name="notification_boosted">أعادَ تَدوينَ مَنشُورَك</string>
<string name="poll_ended">انتهى استطلاعُ الرأي</string>
<string name="time_seconds">%d ثا</string>
<string name="time_minutes">%d د</string>
<string name="time_hours">%d سا</string>
<string name="time_days">%d يوم</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="cancel">إلغاء</string>
<plurals name="followers">
<item quantity="zero">لا متابِعين</item>
<item quantity="one">متابِع</item>
<item quantity="two">متابِعان</item>
<item quantity="few">متابِعين</item>
<item quantity="many">متابِعًا</item>
<item quantity="other">متابِع</item>
</plurals>
<plurals name="following">
<item quantity="zero">لا متابَعين</item>
<item quantity="one">متابَع</item>
<item quantity="two">متابَعان</item>
<item quantity="few">متابَعين</item>
<item quantity="many">متابَعًا</item>
<item quantity="other">متابَع</item>
</plurals>
<plurals name="posts">
<item quantity="zero">لا منشورات</item>
<item quantity="one">منشور</item>
<item quantity="two">منشوران</item>
<item quantity="few">منشورات</item>
<item quantity="many">منشورًا</item>
<item quantity="other">منشور</item>
</plurals>
<string name="posts">منشورات</string>
<string name="posts_and_replies">مَنشُوراتٌ وَرُدُود</string>
<string name="media">وسائط</string>
<string name="profile_about">حَول</string>
<string name="button_follow">تابِع</string>
<string name="button_following">يُتابِع</string>
<string name="edit_profile">حرّر الملف الشخصي</string>
<string name="mention_user">ذِكر @%s</string>
<string name="share_user">مُشارَكَةُ %s</string>
<string name="mute_user">كَتمُ %s</string>
<string name="unmute_user">إلغاء الكَتم عن @%s</string>
<string name="block_user">حَظرُ %s</string>
<string name="unblock_user">رفع الحَظر عن %s</string>
<string name="report_user">الإبلاغُ عَن %s</string>
<string name="block_domain">حَظرُ %s</string>
<string name="unblock_domain">رفع الحَظر عن %s</string>
<plurals name="x_posts">
<item quantity="zero">لا مَنشورات</item>
<item quantity="one">منشورٌ واحِد</item>
<item quantity="two">منشورانِ اثنان</item>
<item quantity="few">%,d منشورات</item>
<item quantity="many">%,d منشورًا</item>
<item quantity="other">%,d منشور</item>
</plurals>
<string name="profile_joined">انضم في</string>
<string name="done">تمّ</string>
<string name="loading">يحمل…</string>
<string name="field_label">التسمية</string>
<string name="field_content">المحتوى</string>
<string name="saving">يحفظ…</string>
<string name="post_from_user">نُشر من %s</string>
<string name="poll_option_hint">الخيار %d</string>
<plurals name="x_minutes">
<item quantity="zero">أقل من دقيقة</item>
<item quantity="one">دقيقة واحدة</item>
<item quantity="two">دقيقتان</item>
<item quantity="few">%d دقائق</item>
<item quantity="many">%d دقيقة</item>
<item quantity="other">%d دقيقة</item>
</plurals>
<plurals name="x_hours">
<item quantity="zero">أقل من ساعة</item>
<item quantity="one">ساعة واحدة</item>
<item quantity="two">ساعتان</item>
<item quantity="few">%d ساعات</item>
<item quantity="many">%d ساعة</item>
<item quantity="other">%d ساعة</item>
</plurals>
<plurals name="x_days">
<item quantity="zero">أقل من يوم</item>
<item quantity="one">يومٌ واحِد</item>
<item quantity="two">يَومان</item>
<item quantity="few">%d أيام</item>
<item quantity="many">%d يومًا</item>
<item quantity="other">%d يوم</item>
</plurals>
<string name="compose_poll_duration">المُدَّة: %s</string>
<plurals name="x_seconds_left">
<item quantity="zero">تتبقى لَحظة</item>
<item quantity="one">تتبقى ثانية واحِدة</item>
<item quantity="two">تتبقى ثانيتان</item>
<item quantity="few">تتبقى %d ثوان</item>
<item quantity="many">تتبقى %d ثانية</item>
<item quantity="other">تتبقى %d ثانية</item>
</plurals>
<plurals name="x_minutes_left">
<item quantity="zero">تبقت أقل من دقيقة</item>
<item quantity="one">تبقت دقيقة</item>
<item quantity="two">تبقت دقيقتان</item>
<item quantity="few">تبقت %d دقائق</item>
<item quantity="many">تبقت %d دقيقة</item>
<item quantity="other">تبقت %d دقيقة</item>
</plurals>
<plurals name="x_hours_left">
<item quantity="zero">تبقت أقل من ساعة</item>
<item quantity="one">تبقت ساعة واحدة</item>
<item quantity="two">تبقت ساعتان</item>
<item quantity="few">تبقت %d ساعات</item>
<item quantity="many">تبقت %d ساعة</item>
<item quantity="other">تبقت %d ساعة</item>
</plurals>
<plurals name="x_days_left">
<item quantity="zero">تبقى أقل من يوم</item>
<item quantity="one">تبقى يوم واحد</item>
<item quantity="two">تبقى يومان</item>
<item quantity="few">تبقى %d أيام</item>
<item quantity="many">تبقى %d يومًا</item>
<item quantity="other">تبقى %d يوم</item>
</plurals>
<plurals name="x_voters">
<item quantity="zero">لا يوجد مصوتون</item>
<item quantity="one">مصوت واحد</item>
<item quantity="two">مصوتان</item>
<item quantity="few">%,d مصوتين</item>
<item quantity="many">%,d مصوتًا</item>
<item quantity="other">%,d مصوت</item>
</plurals>
<string name="poll_closed">انتهى</string>
<string name="confirm_mute_title">اكتم الحساب</string>
<string name="confirm_mute">أكّد كتم %s</string>
<string name="do_mute">اكتم</string>
<string name="confirm_unmute_title">ارفع الكتم عن الحساب</string>
<string name="confirm_unmute">أكِّد رفع الكتم عن %s</string>
<string name="do_unmute">ارفع الكتم</string>
<string name="confirm_block_title">احجب الحساب</string>
<string name="confirm_block_domain_title">احجب النطاق</string>
<string name="confirm_block">أكّد حجب %s</string>
<string name="do_block">احجب</string>
<string name="confirm_unblock_title">ارفع الحجب عن الحساب</string>
<string name="confirm_unblock_domain_title">ارفع الحجب عن النطاق</string>
<string name="confirm_unblock">أكّد رفع الحجب عن %s</string>
<string name="do_unblock">ارفع الحجب</string>
<string name="button_muted">مَكتوم</string>
<string name="button_blocked">محجوب</string>
<string name="action_vote">صَوّت</string>
<string name="tap_to_reveal">اُنقُر لِلكَشف</string>
<string name="delete">احذف</string>
<string name="confirm_delete_title">احذف المنشور</string>
<string name="confirm_delete">أمتأكد من حذف هذا المنشور؟</string>
<string name="deleting">يحذف…</string>
<string name="notification_channel_audio_player">تشغيل الصوت</string>
<string name="play">شغّل</string>
<string name="pause">ألبث</string>
<string name="log_out">خروج</string>
<string name="add_account">أضف حساباً</string>
<string name="search_hint">ابحث</string>
<string name="hashtags">وُسُوم</string>
<string name="news">الأخبار</string>
<string name="for_you">لأجلك</string>
<string name="all_notifications">الكل</string>
<string name="mentions">الذِكر</string>
<plurals name="x_people_talking">
<item quantity="zero">لا أحد يتحدث</item>
<item quantity="one">شخص واحد يتحدث</item>
<item quantity="two">شخصان يتحدثان</item>
<item quantity="few">%d أشخاص يتحدثون</item>
<item quantity="many">%d شخصًا يتحدثون</item>
<item quantity="other">%d شخص يتحدثون</item>
</plurals>
<plurals name="discussed_x_times">
<item quantity="zero">لم يُناقش</item>
<item quantity="one">نوقش مرة واحدة</item>
<item quantity="two">نوقش مرتين</item>
<item quantity="few">نوقش %d مرات</item>
<item quantity="many">نوقش %d مرة</item>
<item quantity="other">نوقش %d مرة</item>
</plurals>
<string name="report_title">بلّغ عن %s</string>
<string name="report_choose_reason">ما هي المشكلة في هذا المنشور؟</string>
<string name="report_choose_reason_account">ما هي المشكلة مع %s؟</string>
<string name="report_choose_reason_subtitle">اختر أفضل تطابق</string>
<string name="report_reason_personal">لا يعجبني</string>
<string name="report_reason_personal_subtitle">ألا ترغب برؤيته</string>
<string name="report_reason_spam">إزعاج</string>
<string name="report_reason_spam_subtitle">روابط خبيثة أو تفاعل كاذب أو ردود متكررة</string>
<string name="report_reason_violation">ينتهك قواعد الخادم</string>
<string name="report_reason_violation_subtitle">تعلم أنه ينتهك قواعد محددة</string>
<string name="report_reason_other">شيء آخر</string>
<string name="report_reason_other_subtitle">لا تندرج هذه المشكلة ضمن فئات أخرى</string>
<string name="report_choose_rule">ما هي القواعد المنتهكة؟</string>
<string name="report_choose_rule_subtitle">اختر كل ما ينطبق</string>
<string name="report_choose_posts">هل توجد منشورات تدعم صحة هذا البلاغ؟</string>
<string name="report_choose_posts_subtitle">اختر كل ما ينطبق</string>
<string name="report_comment_title">هل لديك شيء آخر لتخبرنا به؟</string>
<string name="report_comment_hint">تعليقات إضافية</string>
<string name="sending_report">يرسل البلاغ…</string>
<string name="report_sent_title">شُكرًا لَكَ على التبليغ، سَنَنظُرُ فِي هَذَا الأمر.</string>
<string name="report_sent_subtitle">في أثناء مراجعتنا للبلاغ، يمكنك اتخاذ إجراء ضد @%s.</string>
<string name="unfollow_user">ألغ متابعة %s</string>
<string name="unfollow">ألغ المتابعة</string>
<string name="mute_user_explain">لن ترى منشوراتهم أو إعادة تدوينهم في التغذية الرئيسية. ولن يعلموا أنهم كتموا.</string>
<string name="block_user_explain">لن يتمكنوا من متابعتك أو رؤية منشوراتك، وسيكون بديهيًا لهم أنهم حجبوا.</string>
<string name="report_personal_title">لاترغب في مشاهدة هذا؟</string>
<string name="report_personal_subtitle">عندما ترى ما لا يعجبك في ماستدون، يمكنك إزالة صاحبها من تجربتك كمستخدم.</string>
<string name="back">العودة</string>
<string name="instance_catalog_title">يتكوّن ماستدون من مستخدمين موزّعين عبر خوادم مختلفة.</string>
<string name="instance_catalog_subtitle">اختر خادمًا بناءً على اهتماماتك، منطقتك أو يمكنك حتى اختيارُ مجتمعٍ ذي غرضٍ عام. وسيضل بامكانك التواصل مع المستخدمين من الخوادم الأخرى.</string>
<string name="search_communities">ابحث عن خادم أو أدخل رابطه</string>
<string name="instance_rules_title">بعض القواعد الأساسية</string>
<string name="instance_rules_subtitle">خذ دقيقة لمراجعة القواعد التي حددها وفرضها مديروا %s.</string>
<string name="signup_title">دعنا نجهزك في %s</string>
<string name="edit_photo">حرّر</string>
<string name="display_name">الاسم العلني</string>
<string name="username">اسم المستخدم</string>
<string name="email">البريد الإلكتروني</string>
<string name="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>
<string name="confirm_email_subtitle">أنقر على الرابط المرسل إليك لاستيثاق حسابك.</string>
<string name="resend">أعد الإرسال</string>
<string name="open_email_app">افتح تطبيق البريد الإلكتروني</string>
<string name="resent_email">أُرسلت رسالة التأكيد</string>
<string name="compose_hint">عَبِّر عَمَّ يَجُولُ فِي ذِهنِك</string>
<string name="content_warning">تحذير من المحتوى</string>
<string name="add_image_description">أضف وصفًا للصورة…</string>
<string name="retry_upload">حاول الرفع مجددًا</string>
<string name="edit_image">حرّر الصورة</string>
<string name="save">احفظ</string>
<string name="add_alt_text">أضف نصًا بديلًا</string>
<string name="alt_text_subtitle">يصف النص البديل محتوى الصور للمكفوفين وضعاف البصر. حاول تضمين أكبر قدر ممكن من التفاصيل ليفهموا السياق.</string>
<string name="alt_text_hint">مثال: كلب ينظر حوله بارتياب وعيناه مثبتتان على الكاميرا.</string>
<string name="visibility_public">علني</string>
<string name="visibility_followers_only">للمُتابِعينَ فقط</string>
<string name="visibility_private">لمن ذكرتُهم فقط</string>
<string name="search_all">الكل</string>
<string name="search_people">أشخاص</string>
<string name="recent_searches">عَمَليَّاُت البَحثِ الأخيرَة</string>
<string name="step_x_of_n">الخطوة %1$d من %2$d</string>
<string name="skip">تخطى</string>
<string name="notification_type_follow">متابعُون جُدُد</string>
<string name="notification_type_favorite">المفضلة</string>
<string name="notification_type_reblog">المعاد تدوينها</string>
<string name="notification_type_mention">الذِكر</string>
<string name="notification_type_poll">استطلاع رأي</string>
<string name="choose_account">اختر حسابًا</string>
<string name="err_not_logged_in">يرجى تسجيل الدخول إلى حساب ماستدون أولًا</string>
<plurals name="cant_add_more_than_x_attachments">
<item quantity="zero">يجب عليك إرفاق ملف</item>
<item quantity="one">لا يمكنك إرفاق ملف</item>
<item quantity="two">لا يمكنك إرفاق أكثر من ملفين</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="theme_true_black">الوضع الداكن الحقيقي</string>
<string name="settings_behavior">السلوك</string>
<string name="settings_gif">تشغيل الصور الرمزية المتحركة والرموز التعبيرية المتحركة</string>
<string name="settings_custom_tabs">استخدم المتصفح المضمن</string>
<string name="settings_notifications">الإشعارات</string>
<string name="notify_me_when">أشعِرني عند قيام</string>
<string name="notify_anyone">أيَّ شخصٍ</string>
<string name="notify_follower">مُتابِع</string>
<string name="notify_followed">شخص أُتابِعُه</string>
<string name="notify_none">لَا أحد</string>
<string name="notify_favorites">بِالإعْجاب بِمَنشوري</string>
<string name="notify_follow">بمتابعتي</string>
<string name="notify_reblog">بإعادة تدوين مَنشوري</string>
<string name="notify_mention">ذكرني</string>
<string name="settings_boring">المنطِقَةُ المُملَّة</string>
<string name="settings_account">إعدادات الحساب</string>
<string name="settings_contribute">ساهم في ماستدون</string>
<string name="settings_tos">شروط الخدمة</string>
<string name="settings_privacy_policy">سياسة الخصوصية</string>
<string name="settings_spicy">المنطِقَةُ اللَّاذِعَة</string>
<string name="settings_clear_cache">امسح التخزين المؤقت للوسائط</string>
<string name="settings_app_version">تطبيق ماستدون لأندرويد نسخة %1$s (%2$d)</string>
<string name="media_cache_cleared">مُسح التخزين المؤقت للوسائط</string>
<string name="confirm_log_out">أمتأكد من الخروج؟</string>
<string name="sensitive_content">محتوى حساس</string>
<string name="sensitive_content_explain">علّم المؤلف هته الوسائط كحساسة. اضغط لكشفها.</string>
<string name="media_hidden">اُنقُر لِلكَشف</string>
<string name="avatar_description">انتقل للصفحة الشخصية لـ %s</string>
<string name="more_options">مزيد من الخيارات</string>
<string name="reveal_content">اكشف المحتوى</string>
<string name="hide_content">اخف المحتوى</string>
<string name="new_post">منشور جديد</string>
<string name="button_reply">ردّ</string>
<string name="button_reblog">أعد تدوين</string>
<string name="button_favorite">فضّل</string>
<string name="button_share">شارك</string>
<string name="media_no_description">وسائط بدون وصف</string>
<string name="add_media">أضف وسائط</string>
<string name="add_poll">أضف استطلاع رأي</string>
<string name="emoji">إيموجي</string>
<string name="post_visibility">مرئية المنشور</string>
<string name="home_timeline">الخيط الزمني الرئيسي</string>
<string name="my_profile">ملفي الشخصي</string>
<string name="media_viewer">عارض الوسائط</string>
<string name="follow_user">تابع %s</string>
<string name="unfollowed_user">ألغ متابعة %s</string>
<string name="followed_user">أنت تتابع %s</string>
<string name="open_in_browser">افتح في المتصفح</string>
<string name="hide_boosts_from_user">اخف ما أعاد %s تدوينه</string>
<string name="show_boosts_from_user">أظهر ما أعاد %s تدوينه</string>
<string name="signup_reason">لماذا ترغب في الانضمام؟</string>
<string name="signup_reason_note">هذا سوف يساعدنا في مراجعة تطبيقك.</string>
<string name="clear">امسح</string>
<string name="profile_header">الصورة الفوقية</string>
<string name="profile_picture">صورة الملفّ الشخصي</string>
<string name="reorder">أعد الترتيب</string>
<string name="download">نزّل</string>
<string name="permission_required">يتطلب أذونات</string>
<string name="storage_permission_to_download">يحتاج هذا التطبيق أذن الوصول للتخزين لحفظ الملف.</string>
<string name="open_settings">افتح الإعدادات</string>
<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">هَذِهِ هِيَ المَنشُوراتُ الَّتي تَكْتَسِبُ شَعبِيَّةً فِي الرُّكنِ الخاصِّ بِكَ مِن مَاستودُون.</string>
<string name="trending_hashtags_info_banner">هَذِهِ هِيَ الوُسُومُ الَّتي تَكْتَسِبُ شَعبِيَّةً فِي الرُّكنِ الخاصِّ بِكَ مِن مَاستودُون.</string>
<string name="trending_links_info_banner">هَذِهِ هِيَ القِصَصُ الأخبارِيَّةُ المُتَنَاقَلَةُ بِكِثرَةٍ فِي الرُّكنِ الخاصِّ بِكَ مِن مَاستودُون.</string>
<string name="local_timeline_info_banner">هذه هي أحدث منشورات المستخدمين المتواجدين على نفس الخادم الذي تستخدمه.</string>
<string name="dismiss">رفض</string>
<string name="see_new_posts">استعرض المنشورات الجديدة</string>
<string name="load_missing_posts">حمّل المَنشورات المَفقودَة</string>
<string name="follow_back">رُدّ المتابعة</string>
<string name="button_follow_pending">معلق</string>
<string name="follows_you">يُتابِعُك</string>
<string name="manually_approves_followers">الموافقة اليدوية على طلبات المتابعة</string>
<string name="current_account">الحِسابُ الحاليّ</string>
<string name="log_out_account">تَسجيلُ الخُرُوجِ مِن %s</string>
<!-- translators: %,d is a valid placeholder, it formats the number with locale-dependent grouping separators -->
<plurals name="x_followers">
<item quantity="zero">ليس له متابِعون</item>
<item quantity="one">متابِع واحد</item>
<item quantity="two">متابِعان</item>
<item quantity="few">%,d متابِعين</item>
<item quantity="many">%,d متابِعًا</item>
<item quantity="other">%,d متابِع</item>
</plurals>
<plurals name="x_following">
<item quantity="zero">ليس له متابَعون</item>
<item quantity="one">متابَع واحد</item>
<item quantity="two">متابَعان</item>
<item quantity="few">%,d متابَعين</item>
<item quantity="many">%,d متابَعًا</item>
<item quantity="other">%,d متابَع</item>
</plurals>
<plurals name="x_favorites">
<item quantity="zero">دون تفضيلات</item>
<item quantity="one">تفضيل واحد</item>
<item quantity="two">تفضيلان</item>
<item quantity="few">%,d تفضيلات</item>
<item quantity="many">%,d تفضيلًا</item>
<item quantity="other">%,d تفضيل</item>
</plurals>
<plurals name="x_reblogs">
<item quantity="zero">لا إعادات تدوين</item>
<item quantity="one">إعاد تدوين واحدة</item>
<item quantity="two">إعادتا تدوين</item>
<item quantity="few">%,d إعادات تدوين</item>
<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="post_info_reblogs">إعادات التدوين</string>
<string name="post_info_favorites">المفضلة</string>
<string name="edit_history">تاريخ التعديل</string>
<string name="last_edit_at_x">آخر تعديل %s</string>
<string name="time_just_now">للتوّ</string>
<plurals name="x_seconds_ago">
<item quantity="zero">منذ %d ثانية</item>
<item quantity="one">منذ ثانية</item>
<item quantity="two">منذ ثانيتان</item>
<item quantity="few">%d ثواني</item>
<item quantity="many">منذ %d ثانية</item>
<item quantity="other">%d ثواني مضت</item>
</plurals>
<plurals name="x_minutes_ago">
<item quantity="zero">الان</item>
<item quantity="one">منذ دقيقة</item>
<item quantity="two">منذ دقيقتان</item>
<item quantity="few">%d دقائق مضت</item>
<item quantity="many">منذ %d دقائق</item>
<item quantity="other">منذ %d دقائق</item>
</plurals>
<string name="edited_timestamp">عُدّل في %s</string>
<string name="edit_original_post">المنشور الأصلي</string>
<string name="edit_text_edited">تم تعديل النص</string>
<string name="edit_spoiler_added">تم إضافة تحذير المحتوى</string>
<string name="edit_spoiler_edited">تم تعديل تحذير المحتوى</string>
<string name="edit_spoiler_removed">تم حذف تحذير المحتوى</string>
<string name="edit_poll_added">تمت إضافة استطلاع للرأي</string>
<string name="edit_poll_edited">تم تعديل الاستطلاع</string>
<string name="edit_poll_removed">تمت إزالة الاستطلاع</string>
<string name="edit_media_added">تمت إضافة الوسائط</string>
<string name="edit_media_removed">تمت إزالة الوسائط</string>
<string name="edit_media_reordered">تمت إعادة ترتيب الوسائط</string>
<string name="edit_marked_sensitive">مُعَين كحساس</string>
<string name="edit_marked_not_sensitive">مُعَين كمنشور غير حساس</string>
<string name="edit_multiple_changed">عُدّل المنشور</string>
<string name="edit">تعديل</string>
<string name="discard_changes">تجاهل التغييرات؟</string>
<string name="upload_failed">فشلت عملية التحميل</string>
<string name="file_size_bytes">%d بايت</string>
<string name="file_size_kb">%.2f كيلوبايت</string>
<string name="file_size_mb">%.2f ميغابايت</string>
<string name="file_size_gb">%.2f جيجابايت</string>
<string name="file_upload_progress">%1$s من %2$s</string>
<string name="file_upload_time_remaining">%s متبقية</string>
<string name="upload_error_connection_lost">فقد جهازك الاتصال بالإنترنت</string>
<string name="upload_processing">قيد المعالجة…</string>
<!-- %s is version like 1.2.3 -->
<string name="update_available">ماستدون %s للأندرويد جاهز للتنزيل.</string>
<!-- %s is version like 1.2.3 -->
<string name="update_ready">تم تنزيل ماستدون %s للأندرويد ومستعد لتثبيته.</string>
<!-- %s is file size -->
<string name="download_update">جارٍ التنزيل (%s)</string>
<string name="install_update">تثبيت</string>
<string name="privacy_policy_title">ماستدون وخصوصيتك</string>
<string name="privacy_policy_subtitle">على الرغم من أن تطبيق ماستدون لا يجمع أي بيانات، فإن الخادم الذي قمت بالتسجيل من خلاله قد تكون له سياسة مختلفة. خذ دقيقة للمراجعة والموافقة على سياسة خصوصية التطبيق ماستدون وسياسة الخصوصية للخادم الخاص بك.</string>
<string name="i_agree">أنا مُوافِق</string>
<string name="empty_list">هذه القائمة فارغة</string>
<string name="instance_signup_closed">هذا الخادم لا يقبل تسجيلات جديدة.</string>
<string name="text_copied">تم النسخ إلى الحافظة</string>
<string name="add_bookmark">إضافة إلى الفواصل المرجعية</string>
<string name="remove_bookmark">إزالة من الفواصل المرجعية</string>
<string name="bookmarks">الفواصل المرجعية</string>
<string name="your_favorites">مفضلاتك</string>
</resources>

View File

@@ -314,7 +314,6 @@
<!-- %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>
@@ -715,4 +714,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<string name="see_new_posts">استعرض المنشورات الجديدة</string>
</resources>

View File

@@ -324,4 +324,5 @@
<string name="sk_settings_continues_playback">تراكُب صوتي</string>
<string name="sk_settings_enable_marquee">تمكين تمرير النص في عناوين الأشرطة</string>
<string name="sk_settings_tabs_disable_swipe">تعطيل التمرير بين الألسِنة</string>
<string name="sk_settings_color_palette_default">افتراضي (%s)</string>
</resources>

View File

@@ -273,7 +273,6 @@
<string name="downloading">Спампоўванне…</string>
<string name="local_timeline">Лакальнае</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Паказаць новыя допісы</string>
<string name="load_missing_posts">Загрузіць адсутныя допісы</string>
<string name="follow_back">Падпісацца ў адказ</string>
<string name="button_follow_pending">Чакаюць</string>
@@ -532,4 +531,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<string name="see_new_posts">Паказаць новыя допісы</string>
</resources>

View File

@@ -208,7 +208,6 @@
<string name="file_saved">Fitxer desat</string>
<string name="downloading">S\'està baixant…</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Publicacions noves</string>
<string name="load_missing_posts">Carrega les publicacions faltants</string>
<string name="follow_back">Segueix</string>
<string name="button_follow_pending">Pendent</string>
@@ -298,4 +297,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<string name="see_new_posts">Publicacions noves</string>
</resources>

View File

@@ -288,7 +288,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Toto jsou všechny příspěvky od všech uživatelů na vašem serveru (%s).</string>
<string name="recommended_accounts_info_banner">Podle toho, koho sledujete, by se vám mohly líbit tyto účty.</string>
<string name="see_new_posts">Zobrazit nové příspěvky</string>
<string name="load_missing_posts">Načíst chybějící příspěvky</string>
<string name="follow_back">Sledovat nazpět</string>
<string name="button_follow_pending">Čekající</string>
@@ -644,4 +643,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<string name="see_new_posts">Zobrazit nové příspěvky</string>
</resources>

View File

@@ -262,7 +262,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Disse er alle indlæg fra alle brugere på din server (%s).</string>
<string name="recommended_accounts_info_banner">Baseret på andre, du følger, vil du måske synes om disse konti.</string>
<string name="see_new_posts">Se nye indlæg</string>
<string name="load_missing_posts">Indlæs manglende indlæg</string>
<string name="follow_back">Følg Tilbage</string>
<string name="button_follow_pending">Afventer</string>
@@ -508,4 +507,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<string name="see_new_posts">Se nye indlæg</string>
</resources>

View File

@@ -43,8 +43,8 @@
<string name="block_user">%s sperren</string>
<string name="unblock_user">%s entsperren</string>
<string name="report_user">%s melden</string>
<string name="block_domain">%s sperren</string>
<string name="unblock_domain">%s nicht mehr sperren</string>
<string name="block_domain">%s blockieren</string>
<string name="unblock_domain">%s nicht mehr blockieren</string>
<plurals name="x_posts">
<item quantity="one">%,d Beitrag</item>
<item quantity="other">%,d Beiträge</item>
@@ -98,12 +98,12 @@
<string name="do_unmute">Nicht mehr stummschalten</string>
<string name="confirm_block_title">Konto sperren</string>
<string name="confirm_block_domain_title">Domain sperren</string>
<string name="confirm_block">Bestätigen, um %s zu sperren</string>
<string name="confirm_block">Bestätigen, um %s zu blockieren</string>
<string name="do_block">Sperren</string>
<string name="confirm_unblock_title">Konto nicht mehr sperren</string>
<string name="confirm_unblock_domain_title">Domain nicht mehr blockieren</string>
<string name="confirm_unblock">Bestätigen, um Sperre von %s aufzuheben</string>
<string name="do_unblock">Sperre aufheben</string>
<string name="confirm_unblock">Bestätigen, um %s nicht mehr zu blockieren</string>
<string name="do_unblock">Nicht mehr blockieren</string>
<string name="button_blocked">Blockiert</string>
<string name="action_vote">Abstimmen</string>
<string name="delete">Löschen</string>
@@ -262,7 +262,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Dies sind alle Beiträge von allen Benutzern auf deinem Server (%s).</string>
<string name="recommended_accounts_info_banner">Dir könnten diese Konten gefallen, basierend auf Leuten, denen du folgst.</string>
<string name="see_new_posts">Neue Beiträge anzeigen</string>
<string name="see_new_posts">Neue Beiträge</string>
<string name="load_missing_posts">Weitere Beiträge laden</string>
<string name="follow_back">Zurückfolgen</string>
<string name="button_follow_pending">Ausstehend</string>
@@ -387,7 +387,7 @@
<string name="welcome_to_mastodon">Willkommen auf Mastodon</string>
<string name="welcome_paragraph1">Mastodon ist ein dezentrales, soziales Netzwerk. Das bedeutet, dass es nicht von einem einzigen Unternehmen kontrolliert wird. Das Netzwerk besteht aus unabhängig voneinander betriebenen Servern, die miteinander verbunden sind.</string>
<string name="what_are_servers">Was sind Server?</string>
<string name="welcome_paragraph2"><![CDATA[Jedes Mastodon-Konto wird auf einem Server gehostet. Jeder Server hat dabei seine eigenen Werte, Regeln und Administrator*innen. Aber egal, für welchen Server Du Dich entscheidest: Du kannst mit Leuten von anderen Servern interagieren und ihnen folgen.]]></string>
<string name="welcome_paragraph2">Jedes Mastodon-Konto wird auf einem Server erstellt jeder mit eigenen Werten, Regeln &amp; Administrator*innen. Du kannst trotzdem mit Personen interagieren, die ihr Konto auf einem anderen Server erstellt haben.</string>
<string name="opening_link">Link wird geöffnet…</string>
<string name="link_not_supported">Dieser Link wird in der App nicht unterstützt</string>
<string name="log_out_all_accounts">Von allen Konten abmelden</string>
@@ -583,8 +583,48 @@
<string name="time_hours_ago_short">vor %d Stunden</string>
<string name="time_days_ago_short">vor %d Tagen</string>
<!-- %s is the name of the post language -->
<string name="translate_post">Übersetzen aus %s</string>
<!-- %1$s is the language, %2$s is the name of the translation service -->
<string name="post_translated">Übersetzt aus %1$s mit %2$s</string>
<string name="translation_show_original">Original anzeigen</string>
<string name="translation_failed">Übersetzung fehlgeschlagen. Möglicherweise haben die Administrator*innen die Übersetzungen auf diesem Server nicht aktiviert oder dieser Server läuft mit einer älteren Version von Mastodon, in der Übersetzungen noch nicht unterstützt wurden.</string>
<string name="settings_privacy">Datenschutz und Reichweite</string>
<string name="settings_discoverable">Profil und Beiträge in Suchalgorithmen berücksichtigen</string>
<string name="settings_indexable">Öffentliche Beiträge in die Suchergebnisse einbeziehen</string>
<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 -->
<string name="dropdown_menu">Dropdown-Menü</string>
<string name="edit_list">Liste bearbeiten</string>
<string name="list_members">Mitglieder auflisten</string>
<string name="delete_list">Liste löschen</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">„%s“ löschen?</string>
<string name="list_exclusive">Mitglieder in „Folge ich“ ausblenden</string>
<string name="list_exclusive_subtitle">Wenn jemand in dieser Liste ist, sollen deren Beiträge nicht in der „Folge ich“-Timeline angezeigt werden.</string>
<string name="list_name">Listenname</string>
<string name="list_show_replies_to">Mit Antworten von</string>
<string name="list_replies_no_one">Niemandem</string>
<string name="list_replies_members">Mitgliedern der Liste</string>
<string name="list_replies_anyone">Benutzer*innen, denen ich folge</string>
<string name="confirm_remove_list_members">Mitglieder entfernen?</string>
<string name="remove">Entfernen</string>
<string name="add_list_member">Mitglied hinzufügen</string>
<string name="search_among_people_you_follow">Suche nach Leuten, denen du folgst</string>
<string name="add_user_to_list">Zur Liste hinzufügen…</string>
<string name="add_user_to_list_title">Zur Liste hinzufügen</string>
<!-- %s is a username -->
<string name="manage_user_lists">Listen mit %s verwalten</string>
<string name="remove_from_list">Aus Liste entfernen</string>
<string name="confirm_remove_list_member">Mitglied entfernen?</string>
<string name="no_followed_hashtags_title">Halte Interessen im Blick, indem du Hashtags folgst</string>
<string name="no_followed_hashtags_subtitle">Gefolge Hashtags erscheinen hier</string>
<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>
</resources>

View File

@@ -255,7 +255,7 @@
<string name="sk_expand">Erweitern</string>
<string name="sk_collapse">Einklappen</string>
<string name="sk_settings_collapse_long_posts">Sehr lange Beiträge einklappen</string>
<string name="sk_unfinished_attachments">Anhänge richtig stellen\?</string>
<string name="sk_unfinished_attachments">Anhänge laden hoch</string>
<string name="sk_settings_hide_interaction">Interaktions-Buttons verstecken</string>
<string name="sk_unfinished_attachments_message">Einige Anhänge sind nicht fertig hochgeladen.</string>
<string name="sk_followed_as">Mit %s gefolgt</string>
@@ -295,7 +295,7 @@
<string name="sk_settings_allow_remote_loading">Infos von Remote-Instanzen laden</string>
<string name="sk_no_remote_info_hint">keine Remote-Infos abrufbar</string>
<string name="sk_error_loading_profile">Konnte das Profil via %s nicht laden</string>
<string name="sk_settings_allow_remote_loading_explanation">Für vollständigere Auflistung von Follower*innen, Likes und Boosts können die Informationen von der Ursprungs-Instanz geladen werden.</string>
<string name="sk_settings_allow_remote_loading_explanation">Für vollständigere Auflistung von Follower_innen, Likes und Boosts können die Informationen von der Ursprungs-Instanz geladen werden.</string>
<string name="sk_settings_auto_reveal_equal_spoilers">Automatisches Aufdecken von gleichen CWs in Antworten von</string>
<string name="sk_settings_auto_reveal_nobody">Nie</string>
<string name="sk_settings_auto_reveal_author">Antworten, die von der gleichen Person verfasst wurden</string>
@@ -410,4 +410,10 @@
<string name="sk_settings_color_palette_default">Standardwert (%s)</string>
<string name="sk_settings_underlined_links">Unterstrichene Links</string>
<string name="sk_recently_used">Zuletzt verwendet</string>
<string name="sk_settings_clear_timeline_cache">Start-Timeline leeren</string>
<string name="sk_edit_alt_text">Bildbeschreibung bearbeiten</string>
<string name="sk_settings_default_visibility">Standard-Sichtbarkeit für Posts</string>
<string name="sk_settings_lock_account">Neue Follower_innen manuell genehmigen</string>
<string name="sk_timeline_cache_cleared">Start-Timeline geleert</string>
<string name="sk_button_mutuals">Befreundet</string>
</resources>

View File

@@ -262,7 +262,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="see_new_posts">Νέες αναρτήσεις</string>
<string name="load_missing_posts">Φόρτωση αναρτήσεων που λείπουν</string>
<string name="follow_back">Ακολούθησε και εσύ</string>
<string name="button_follow_pending">Εκκρεμεί</string>
@@ -600,7 +600,7 @@
<item quantity="other">%,d αναρτήσεις σήμερα</item>
</plurals>
<string name="error_playing_video">Σφάλμα αναπαραγωγής βίντεο</string>
<string name="timeline_following">Ακολουθείς</string>
<string name="timeline_following">Αρχική</string>
<string name="lists">Λίστες</string>
<string name="followed_hashtags">Ετικέτες που ακολουθούνται</string>
<string name="no_lists">Δεν έχεις καμία λίστα ακόμα.</string>
@@ -615,5 +615,17 @@
<!-- %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 -->
</resources>

View File

@@ -262,7 +262,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Estos son todos los mensajes de todos los usuarios de tu servidor (%s).</string>
<string name="recommended_accounts_info_banner">Es posible que te gusten estas cuentas basadas en otras que sigues.</string>
<string name="see_new_posts">Ver nuevas publicaciones</string>
<string name="see_new_posts">Nuevas publicaciones</string>
<string name="load_missing_posts">Cargar publicaciones faltantes</string>
<string name="follow_back">Seguir de vuelta</string>
<string name="button_follow_pending">Pendiente</string>
@@ -387,6 +387,7 @@
<string name="welcome_to_mastodon">Bienvenido/da a Mastodon</string>
<string name="welcome_paragraph1">Mastodon es una red social descentralizada, lo que significa que no la controla una sola compañía. Está formada por muchos servidores independientes, todos juntos conectados.</string>
<string name="what_are_servers">¿Qué son los servidores?</string>
<string name="welcome_paragraph2">Cada cuenta de Mastodon está alojada en un servidor — cada uno con sus propios valores, reglas y administradores. Sin importar cuál elijas, puedes seguir e interactuar con personas en cualquier servidor.</string>
<string name="opening_link">Abriendo enlace…</string>
<string name="link_not_supported">Este enlace no es compatible con la aplicación</string>
<string name="log_out_all_accounts">Cerrar sesión en todas las cuentas</string>
@@ -414,6 +415,7 @@
<string name="alt_text">Texto alternativo</string>
<string name="help">Ayuda</string>
<string name="what_is_alt_text">¿Qué es el texto alternativo?</string>
<string name="alt_text_help">El texto alternativo entrega descripciones de una imagen a las personas con discapacidad visual, conexiones de internet de bajo ancho de banda o a quienes buscan más contexto.\n\nPuedes mejorar la accesibilidad y la comprensión de todos al escribir texto alternativo que sea claro, conciso y objetivo.\n\n&lt;ul&gt;&lt;il&gt; Captura elementos importantes&lt;/li&gt;\n&lt;li&gt;Resume el texto en las imágenes&lt;/li&gt;\n&lt;li&gt;Construye las frases de manera normal&lt;/li&gt;\n&lt;li&gt;Evita la información redundante&lt;/li&gt;\n&lt;li&gt;Enfócate en tendencias y en hallazgos claves en imágenes complejas (como diagramas o mapas)&lt;/li&gt;&lt;/ul&gt;</string>
<string name="edit_post">Editar publicación</string>
<string name="no_verified_link">Enlace no verificado</string>
<string name="compose_autocomplete_emoji_empty">Explorar emojis</string>
@@ -433,6 +435,7 @@
<string name="forward_report_to_server">Reenviar a %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">Reportado</string>
<string name="report_unfollow_explanation">Para no ver más sus publicaciones en tu feed de inicio, deja de seguirle.</string>
<string name="muted_user">Silenciado %s</string>
<string name="report_sent_already_blocked">Ya has bloqueado a este usuario, así que no tienes nada más que hacer mientras revisamos tu informe.</string>
<string name="report_personal_already_blocked">Ya has bloqueado a este usuario, así que no tienes nada más que hacer.\n\n¡Gracias por ayudar a mantener Mastodon un lugar seguro para todos!</string>
@@ -475,9 +478,13 @@
<string name="about_server">Acerca de</string>
<string name="server_rules">Reglas</string>
<string name="server_administrator">Administrador</string>
<string name="send_email_to_server_admin">Contacta a un administrador</string>
<string name="notifications_disabled_in_system">Active las notificaciones desde la configuración de su dispositivo para ver actualizaciones desde cualquier lugar.</string>
<string name="settings_even_more">Aún más ajustes</string>
<string name="settings_show_cws">Mostrar advertencias de contenido</string>
<string name="settings_hide_sensitive_media">Esconder contenidos marcados como explícitos</string>
<string name="settings_show_interaction_counts">Contador de interacciones con una publicación</string>
<string name="settings_show_emoji_in_names">Emoji personalizado en los nombres de las pantallas</string>
<plurals name="in_x_seconds">
<item quantity="one">en %d segundo</item>
<item quantity="other">en %d segundos</item>
@@ -532,6 +539,7 @@
<string name="selection_4_or_more">%1$s, %2$s, y %3$d más</string>
<string name="filter_context_home_lists">Inicio y listas</string>
<string name="filter_context_notifications">Notificaciones</string>
<string name="filter_context_public_timelines">Líneas de tiempo públicas</string>
<string name="filter_context_threads_replies">Hilos y respuestas</string>
<string name="filter_context_profiles">Profiles</string>
<string name="settings_filter_title">Título</string>
@@ -541,6 +549,7 @@
<string name="edit_muted_word">Editar palabra silenciada</string>
<string name="add">Añadir</string>
<string name="filter_word_or_phrase">Palabra o frase</string>
<string name="filter_add_word_help">Las palabras no distinguen letras mayúsculas y solo reconocen palabras completas.\n\nSi filtras la palabra \"Agua\", se ocultarán posteos que incluyan \"agua\" o \"aGua\", pero no los que contengan \"paraguas\".</string>
<string name="settings_delete_filter_word">¿Eliminar palabra “%s”?</string>
<string name="enter_selection_mode">Seleccionar</string>
<string name="select_all">Seleccionar todo</string>
@@ -574,8 +583,45 @@
<string name="time_hours_ago_short">hace %dh</string>
<string name="time_days_ago_short">hace %dd</string>
<!-- %s is the name of the post language -->
<string name="translate_post">Traducir desde %s</string>
<!-- %1$s is the language, %2$s is the name of the translation service -->
<string name="post_translated">Traducido desde %1$s usando %2$s</string>
<string name="translation_show_original">Ver original</string>
<string name="translation_failed">Error al traducir. Tal vez el administrador no ha habilitado las traducciones en este servidor o este servidor está ejecutando una versión antigua de Mastodon donde las traducciones aún no están soportadas.</string>
<string name="settings_privacy">Privacidad y alcance</string>
<string name="settings_discoverable">Mostrar perfil y publicaciones en algoritmos de descubrimiento</string>
<string name="settings_indexable">Incluir publicaciones públicas en los resultados de búsqueda</string>
<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 -->
<string name="dropdown_menu">Menú desplegable</string>
<string name="edit_list">Editar lista</string>
<string name="list_members">Miembros de la lista</string>
<string name="delete_list">Borrar lista</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">¿Eliminar “%s”?</string>
<string name="list_exclusive">Ocultar miembros en la lista de Seguidos</string>
<string name="list_exclusive_subtitle">Si alguien está en esta lista, ocúltalos en tu línea de tiempo para evitar ver sus publicaciones dos veces.</string>
<string name="list_name">Nombre de la lista</string>
<string name="list_show_replies_to">Mostrar respuestas a</string>
<string name="list_replies_no_one">Nadie</string>
<string name="list_replies_members">Miembros de la lista</string>
<string name="list_replies_anyone">Cualquiera que yo siga</string>
<string name="confirm_remove_list_members">¿Eliminar miembros?</string>
<string name="remove">Eliminar</string>
<string name="add_list_member">Añadir miembro</string>
<string name="search_among_people_you_follow">Buscar entre las personas a las que sigues</string>
<string name="add_user_to_list">Añadir a lista…</string>
<string name="add_user_to_list_title">Añadir a lista</string>
<!-- %s is a username -->
<string name="manage_user_lists">Administrar las listas en las que %s aparece</string>
<string name="remove_from_list">Quitar de lista</string>
<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>
</resources>

View File

@@ -254,7 +254,7 @@
<string name="sk_expand">Ampliar</string>
<string name="sk_collapse">Minimizar</string>
<string name="sk_settings_collapse_long_posts">Minimizar publicaciones largas</string>
<string name="sk_unfinished_attachments">¿Corregir adjuntos\?</string>
<string name="sk_unfinished_attachments">Cargando los archivos adjuntos</string>
<string name="sk_unfinished_attachments_message">Algunos adjuntos no han terminado de subirse.</string>
<string name="sk_settings_prefix_reply_cw_with_re">Añadir \"re\" a Avisos de Contenido</string>
<string name="sk_spectator_mode">Modo espectador</string>
@@ -407,4 +407,10 @@
<string name="sk_set_as_default">Establecer por defecto</string>
<string name="sk_settings_color_palette_default">Por defecto (%s)</string>
<string name="sk_settings_underlined_links">Enlaces subrayados</string>
<string name="sk_edit_alt_text">Editar el texto alternativo</string>
<string name="sk_settings_default_visibility">Visibilidad de la publicación predeterminada</string>
<string name="sk_settings_lock_account">Aprobar nuevos seguidores manualmente</string>
<string name="sk_timeline_cache_cleared">Caché de la línea de tiempo de inicio borrada</string>
<string name="sk_settings_clear_timeline_cache">Borrar la caché de la línea de tiempo de inicio</string>
<string name="sk_button_mutuals">Amigos</string>
</resources>

View File

@@ -15,6 +15,7 @@
<string name="user_sent_follow_request">%s-(e)k jarraitzeko eskaera bidali dizu</string>
<string name="user_favorited">%s(e)k zure bidalketa gogoko du</string>
<string name="notification_boosted">%s(e)k zure bidalketa bultzatu du</string>
<string name="poll_ended">Ikusi botoa eman zunuen inkestaren emaitzak</string>
<string name="share_toot_title">Partekatu</string>
<string name="settings">Ezarpenak</string>
<string name="publish">Argitaratu</string>
@@ -84,6 +85,10 @@
<item quantity="one">%d egun falta da</item>
<item quantity="other">%d egun falta dira</item>
</plurals>
<plurals name="x_votes">
<item quantity="one">Boto %,d</item>
<item quantity="other">%,d boto</item>
</plurals>
<string name="poll_closed">Itxita</string>
<string name="confirm_mute_title">Mututu kontua</string>
<string name="confirm_mute">Berretsi %s mututzea</string>
@@ -140,8 +145,11 @@
<string name="report_comment_hint">Iruzkin gehigarriak</string>
<string name="sending_report">Txostena bidaltzen…</string>
<string name="report_sent_title">Mila esker salaketagatik, berrikusiko dugu.</string>
<string name="report_sent_subtitle">Hau berrikusten dugun bitartean, %s erabiltzailearen aurkako neurriak hartu ditzakezu:</string>
<string name="unfollow_user">%s jarraitzeari utzi</string>
<string name="unfollow">Utzi jarraitzeari</string>
<string name="mute_user_explain">Ez dituzu bere bidalketak ikusiko. Zuri jarraitu eta zure bidalketak ikusteko aukera izango dute eta ezingo dute jakin mututu dituzula.</string>
<string name="block_user_explain">Ez dituzu bere bidalketak ikusiko. Ezingo dituzte zure bidalketak ikusi eta ez jarraitu. Blokeatu dituzula jakin dezakete.</string>
<string name="report_personal_title">Ez duzu hau ikusi nahi?</string>
<string name="report_personal_subtitle">Hemen dituzu Mastodonen ikusiko duzuna kontrolatzeko aukerak:</string>
<string name="back">Atzera</string>
@@ -229,6 +237,8 @@
<string name="unfollowed_user">Utzi %s jarraitzeari</string>
<string name="followed_user">%s jarraitzen ari zara</string>
<string name="open_in_browser">Ireki nabigatzailean</string>
<string name="hide_boosts_from_user">Ezkutatu %s(r)en bultzadak</string>
<string name="show_boosts_from_user">Erakutsi @%s(r)en bultzadak</string>
<string name="signup_reason">Zergatik elkartu nahi duzu?</string>
<string name="signup_reason_note">Honek zure eskaera berrikustean lagunduko digu.</string>
<string name="clear">Garbitu</string>
@@ -246,7 +256,7 @@
<string name="local_timeline">Lokala</string>
<string name="trending_posts_info_banner">Hauek dira zure Mastodon txokoan beraien lekua hartzen ari diren argitalpenak.</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Ikusi bidalketa berriak</string>
<string name="see_new_posts">Bidalketa berriak</string>
<string name="load_missing_posts">Falta diren bidalketak kargatu</string>
<string name="follow_back">Jarraitu</string>
<string name="button_follow_pending">Zain</string>
@@ -320,6 +330,7 @@
<string name="server_url">Zerbitzariaren URLa</string>
<string name="server_filter_any_language">Edozein hizkuntza</string>
<string name="server_filter_instant_signup">Berehalako erregistroa</string>
<string name="server_filter_manual_review">Eskuzko berrikuspena</string>
<string name="server_filter_region_europe">Europa</string>
<string name="server_filter_region_north_america">Ipar Amerika</string>
<string name="server_filter_region_south_america">Hego Amerika</string>
@@ -327,9 +338,12 @@
<string name="server_filter_region_asia">Asia</string>
<string name="server_filter_region_oceania">Ozeania</string>
<string name="not_accepting_new_members">Ez da kide berririk onartzen</string>
<string name="category_special_interests">Interes bereziak</string>
<string name="signup_passwords_dont_match">Pasahitzak ez datoz bat</string>
<string name="pick_server_for_me">Aukeratu niretzat</string>
<string name="profile_add_row">Gehitu errenkada</string>
<string name="profile_setup">Profilaren konfigurazioa</string>
<string name="profile_setup_subtitle">Beti osa dezakezu hau geroago Profila fitxan.</string>
<string name="popular_on_mastodon">Mastodonen pil-pilean</string>
<string name="follow_all">Jarraitu denak</string>
<string name="server_rules_disagree">Ez ados</string>
@@ -344,6 +358,7 @@
<string name="profile_timeline">Denbora-lerroa</string>
<string name="view_all">Ikusi guztia</string>
<string name="profile_endorsed_accounts">Kontuak</string>
<string name="verified_link">Lotura egiaztatua</string>
<string name="show">Erakutsi</string>
<string name="hide">Ezkutatu</string>
<string name="pick_server">Aukeratu beste zerbitzari bat</string>
@@ -354,19 +369,29 @@
<string name="opening_link">Lotura irekitzen…</string>
<string name="retry">Berriro saiatu</string>
<!-- %s is formatted file size ("467 KB image") -->
<string name="attachment_description_image">irudi %s</string>
<string name="attachment_description_video">bideo %s</string>
<string name="attachment_description_audio">audio %s</string>
<string name="attachment_description_unknown">fitxategi %s</string>
<string name="attachment_type_image">Irudia</string>
<string name="attachment_type_video">Bideoa</string>
<string name="attachment_type_audio">Audioa</string>
<string name="attachment_type_gif">GIF-a</string>
<string name="attachment_type_unknown">Fitxategia</string>
<string name="add_poll_option">Gehitu inkesta aukera</string>
<string name="poll_length">Inkesta luzera</string>
<string name="poll_style">Estiloa</string>
<string name="compose_poll_single_choice">Aukeratu bat</string>
<string name="compose_poll_multiple_choice">Aukera anitza</string>
<string name="delete_poll_option">Ezabatu inkesta aukera</string>
<string name="poll_style_title">Inkesta estiloa</string>
<string name="alt_text">Alt testua</string>
<string name="help">Laguntza</string>
<string name="what_is_alt_text">Zer da alt testua?</string>
<string name="edit_post">Editatu argitalpena</string>
<string name="no_verified_link">Lotura ez egiaztatua</string>
<string name="compose_autocomplete_emoji_empty">Esploratu emojiak</string>
<string name="no_search_results">Ez da emaitzarik aurkitu bilaketa-termino horientzat</string>
<string name="language">Hizkuntza</string>
<string name="language_default">Lehenetsia</string>
<string name="language_system">Sistema</string>
@@ -374,7 +399,9 @@
<string name="language_cant_detect">Ezin da hizkuntza detektatu</string>
<string name="language_detected">Detektatuta</string>
<string name="media_hidden">Multimedia ezkutatua</string>
<string name="forward_report_explanation">Kontua beste zerbitzari batekoa da. Salaketaren kopia anonimo bat bidali nahi duzu zerbitzati horretara?</string>
<!-- %s is the server domain -->
<string name="forward_report_to_server">Birbidali hona: %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">Salatua</string>
<string name="muted_user">Mututu %s</string>
@@ -392,6 +419,7 @@
<string name="notifications_policy_no_one">Bat ere ez</string>
<string name="pause_all_notifications_title">Pausatu jakinarazpen guztiak</string>
<!-- %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>
<string name="yesterday">atzo</string>
<string name="tomorrow">bihar</string>
@@ -425,6 +453,7 @@
<string name="selection_2_options">%1$s eta %2$s</string>
<string name="selection_3_options">%1$s, %2$s, eta %3$s</string>
<string name="selection_4_or_more">%1$s, %2$s, eta beste %3$d</string>
<string name="filter_context_home_lists">Hasierako denbora-lerroa</string>
<string name="filter_context_notifications">Jakinarazpenak</string>
<string name="filter_context_public_timelines">Denbora-lerro publikoak</string>
<string name="filter_context_profiles">Profilak</string>
@@ -441,9 +470,45 @@
<string name="clear_all">Garbitu dena</string>
<string name="search_open_url">Ireki URLa Mastodonen</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>
<string name="time_hours_ago_short">Duela %d ordu</string>
<string name="time_days_ago_short">Duela %d egun</string>
<!-- %s is the name of the post language -->
<!-- %1$s is the language, %2$s is the name of the translation service -->
<string name="translation_show_original">Erakutsi jatorrizkoa</string>
<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>
<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 -->
<string name="dropdown_menu">Menu zabalgarria</string>
<string name="edit_list">Editatu zerrenda</string>
<string name="list_members">Kideen zerrenda</string>
<string name="delete_list">Ezabatu zerrenda</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">Ezabatu “%s”?</string>
<string name="list_name">Zerrendaren izena</string>
<string name="list_show_replies_to">Erakutsi erantzunak</string>
<string name="list_replies_no_one">Bat ere ez</string>
<string name="list_replies_members">Zerrendako kideak</string>
<string name="list_replies_anyone">Jarraitzen dudan edonor</string>
<string name="confirm_remove_list_members">Kendu kideak?</string>
<string name="remove">Kendu</string>
<string name="add_list_member">Gehitu kidea</string>
<string name="search_among_people_you_follow">Bilatu jarraitzen dituzun pertsonen artean</string>
<string name="add_user_to_list">Gehitu zerrendara…</string>
<string name="add_user_to_list_title">Gehitu zerrendara</string>
<!-- %s is a username -->
<string name="remove_from_list">Kendu zerrendatik</string>
<string name="confirm_remove_list_member">Kendu kideak?</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="list_no_members">Oraindik ez dago kiderik</string>
</resources>

View File

@@ -262,7 +262,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="see_new_posts">فرسته‌های جدید</string>
<string name="load_missing_posts">بارگذاری فرسته‌های گم شده</string>
<string name="follow_back">پی‌گیری متقابل</string>
<string name="button_follow_pending">منتظر</string>
@@ -599,7 +599,36 @@
<item quantity="one">%,d فرسته امروز</item>
<item quantity="other">%,d فرسته امروز</item>
</plurals>
<string name="error_playing_video">خطا در پخش ویدئو</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 -->
<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_name">اسم سیاهه</string>
<string name="list_show_replies_to">نمایش پاسخ‌ها به</string>
<string name="list_replies_no_one">هیچ‌کس</string>
<string name="list_replies_members">اعضای سیاهه</string>
<string name="confirm_remove_list_members">حذف اعضا؟</string>
<string name="remove">برداشتن</string>
<string name="add_list_member">افزودن عضو</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="manage_accounts">افزودن یا جابجا شدن بین حساب‌ها</string>
<plurals name="x_posts_recently">
<item quantity="one">%,d فرسته اخیرا ارسال کرده</item>
<item quantity="other">%,d فرسته اخیرا ارسال کرده</item>
</plurals>
</resources>

View File

@@ -310,7 +310,7 @@
<string name="sk_reacted">%s واکنش نشان داد</string>
<string name="sk_external_share_title">هم‌رسانی با حساب</string>
<string name="sk_settings_prefix_reply_cw_with_re">وارد کردن پیشوند CW با “re:” هنگام پاسخ دادن</string>
<string name="sk_unfinished_attachments">رفع مشکل پیوست‌ها؟</string>
<string name="sk_unfinished_attachments">درحال بارگذاری پیوست‌ها</string>
<string name="sk_settings_allow_remote_loading">بارگیری اطلاعات از نمونه های راه دور</string>
<string name="sk_error_loading_profile">بارگیری نمایه از طریق %s شکست خورد</string>
<string name="sk_settings_reply_visibility_following">پاسخ به پی‌گیر های من</string>
@@ -363,7 +363,7 @@
<string name="sk_button_react">واکنش با ایموجی</string>
<string name="sk_again_for_system_keyboard">دوباره برای کیبورد سامانه ضربه بزنید</string>
<string name="sk_enter_emoji_toast">لطفا یک ایموجی تایپ کنید</string>
<string name="sk_enter_emoji_hint">برای واکنش با ایموجی تایپ کنید</string>
<string name="sk_enter_emoji_hint">یک ایموجی بنویسید یا جستجو کنید</string>
<plurals name="sk_users_reacted_with">
<item quantity="one">یک کاربر با %2$s واکنش نشان داد</item>
<item quantity="other">%1$,d کاربر با %2$s واکنش نشان دادند</item>
@@ -388,11 +388,19 @@
<string name="sk_search_suicide_hotlines">یک راه کمکی بیابید</string>
<string name="sk_do_not_show_again">دوباره نمایش نده</string>
<string name="sk_suicide_helplines_url">https://findahelpline.com</string>
<string name="sk_trending_posts_info_banner">اینها فرسته‌هایی هستند که در کارساز شما مورد توجه قرار می گیرند.</string>
<string name="sk_trending_posts_info_banner">این فرسته‌ها در حال حاضر در فدیورس مورد توجه قرار گرفته اند.</string>
<string name="sk_load_missing_posts_below">بارگذاری فرسته‌های قدیمی‌تر</string>
<string name="sk_search_suicide_title">اگر نیازمند کمک هستید…</string>
<string name="sk_time_minutes">%d دقیقه</string>
<string name="sk_search_suicide_message">اگر به دنبال نشانه ای برای خودکشی نیستید، همین است. لطفاً اگر نیازمند کمک هستید با شماره تلفن محلی خودکشی تماس بگیرید.</string>
<string name="sk_trending_links_info_banner">اینها اخباری است که در کارساز شما در مورد آنها صحبت می شود.</string>
<string name="sk_trending_links_info_banner">این اخبار در سراسر فدیورس درباره آنها صحبت می شود.</string>
<string name="sk_post_contains_media">فرسته حاوی رسانه‌ست</string>
<string name="sk_set_as_default">تنظیم به‌عنوان پیش‌گزیده</string>
<string name="sk_settings_like_icon">استفاده از قلب به عنوان نماد برگزیدن</string>
<string name="sk_settings_color_palette_default">پیش‌گزیده (%s)</string>
<string name="sk_blocked_accounts">حساب‌های مسدود شده</string>
<string name="sk_settings_underlined_links">پیوندهای خط دار</string>
<string name="sk_muted_accounts">حساب‌های خموش شده</string>
<string name="sk_recently_used">اخیرا مورد استفاده قرار گرفته</string>
<string name="sk_edit_alt_text">ویرایش متن جایگزین</string>
</resources>

View File

@@ -14,7 +14,7 @@
<string name="user_followed_you">%s seurasi sinua</string>
<string name="user_sent_follow_request">%s lähetti sinulle seurauspyynnön</string>
<string name="user_favorited">%s tykkäsi julkaisustasi</string>
<string name="notification_boosted">%s tehosti viestiäsi</string>
<string name="notification_boosted">%s tehosti julkaisuasi</string>
<string name="poll_ended">Katso tulokset äänestyksestä johon osallistuit</string>
<string name="share_toot_title">Jaa</string>
<string name="settings">Asetukset</string>
@@ -30,8 +30,8 @@
<item quantity="one">seurataan</item>
<item quantity="other">seurataan</item>
</plurals>
<string name="posts">Viestit</string>
<string name="posts_and_replies">Viestit ja vastaukset</string>
<string name="posts">Julkaisut</string>
<string name="posts_and_replies">Julkaisut ja vastaukset</string>
<string name="media">Media</string>
<string name="profile_about">Tietoja</string>
<string name="button_follow">Seuraa</string>
@@ -148,7 +148,7 @@
<string name="report_sent_subtitle">Sillä välin kun tarkistamme tätä, voit ryhtyä toimenpiteisiin käyttäjää @%s vastaan:</string>
<string name="unfollow_user">Lopeta käyttäjän %s seuraaminen</string>
<string name="unfollow">Lopeta seuraaminen</string>
<string name="mute_user_explain">Et näe hänen viestejään. Hän voi silti seurata sinua ja nähdä viestisi. Hän ei tiedä, että on mykistetty.</string>
<string name="mute_user_explain">Et näe hänen julkaisujaan. Hän voi silti seurata sinua ja nähdä julkaisusi. Hän ei tiedä, että hänet on mykistetty.</string>
<string name="block_user_explain">Et näe hänen viestejään, eikä hän voi nähdä viestejäsi tai seurata sinua. Hän näkevät, että olet estänyt hänet.</string>
<string name="report_personal_title">Etkö halua nähdä tätä?</string>
<string name="report_personal_subtitle">Tässä on vaihtoehtosi hallita näkemääsi Mastodonissa:</string>
@@ -260,9 +260,9 @@
<string name="trending_posts_info_banner">Nämä julkaisut ovat saamassa vetoa eri puolilla Mastodonia.</string>
<string name="trending_links_info_banner">Näistä uutisista puhutaan Mastodonissa.</string>
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Nämä ovat viestit kaikilta palvelimesi (%s) käyttäjiltä.</string>
<string name="local_timeline_info_banner">Nämä ovat julkaisut kaikilta palvelimesi (%s) käyttäjiltä.</string>
<string name="recommended_accounts_info_banner">Muiden seuraamiesi perusteella saattaisit pitää näistä tileistä.</string>
<string name="see_new_posts">Uusia julkaisuja</string>
<string name="see_new_posts">Uudet julkaisut</string>
<string name="load_missing_posts">Lataa puuttuvat julkaisut</string>
<string name="follow_back">Seuraa takaisin</string>
<string name="button_follow_pending">Pyydetty</string>
@@ -299,7 +299,7 @@
<item quantity="other">%d minuuttia sitten</item>
</plurals>
<string name="edited_timestamp">muokattu %s</string>
<string name="edit_original_post">Alkuperäinen viesti</string>
<string name="edit_original_post">Alkuperäinen jukaisu</string>
<string name="edit_text_edited">Tekstiä muokattu</string>
<string name="edit_spoiler_added">Sisältövaroitus</string>
<string name="edit_spoiler_edited">Sisältövaroitus muokattu</string>
@@ -393,7 +393,7 @@
<string name="log_out_all_accounts">Kirjaudu ulos kaikista tileistä</string>
<string name="confirm_log_out_all_accounts">Kirjaudu ulos kaikista tileistä?</string>
<string name="retry">Yritä uudelleen</string>
<string name="post_failed">Viestin lähettäminen epäonnistui</string>
<string name="post_failed">Julkaiseminen epäonnistui</string>
<!-- %s is formatted file size ("467 KB image") -->
<string name="attachment_description_image">%s kuva</string>
<string name="attachment_description_video">%s video</string>
@@ -478,7 +478,7 @@
<string name="about_server">Tietoja</string>
<string name="server_rules">Säännöt</string>
<string name="server_administrator">Ylläpitäjä</string>
<string name="send_email_to_server_admin">Viestin ylläpitäjä</string>
<string name="send_email_to_server_admin">Lähetä viesti ylläpitäjälle</string>
<string name="notifications_disabled_in_system">Ota ilmoitukset käyttöön laitteesi asetuksista nähdäksesi päivityksiä mistä tahansa.</string>
<string name="settings_even_more">Vielä enemmän asetuksia</string>
<string name="settings_show_cws">Näytä sisältövaroitukset</string>
@@ -549,7 +549,7 @@
<string name="edit_muted_word">Muokkaa mykistettyä sanaa</string>
<string name="add">Lisää</string>
<string name="filter_word_or_phrase">Sana tai lause</string>
<string name="filter_add_word_help">Sanat ovat tapauskohtaisia ja vastaavat vain kokonaisia sanoja.\n\nJos suodattaa avainsana “Apple”, se piilottaa viestit sisältävät “omena” tai “aPPLe” mutta ei “ananas\".</string>
<string name="filter_add_word_help">Sanat ovat tapauskohtaisia ja vastaavat vain kokonaisia sanoja.\n\nJos suodatat avainsanat “Apple”, se piilottaa julkaisut joissa on “apple” tai “aPpLe” mutta ei “pineapple\"</string>
<string name="settings_delete_filter_word">Poista sana “%s”?</string>
<string name="enter_selection_mode">Valitse</string>
<string name="select_all">Valitse kaikki</string>
@@ -597,10 +597,53 @@
</plurals>
<plurals name="x_posts_today">
<item quantity="one">%,d viesti tänään</item>
<item quantity="other">%,d viestiä tänään</item>
<item quantity="other">%,d julkaisua tänään</item>
</plurals>
<string name="error_playing_video">Virhe videon toistossa</string>
<string name="timeline_following">Koti</string>
<string name="lists">Listat</string>
<string name="followed_hashtags">Seuratut aihetunnisteet</string>
<string name="no_lists">Sinulla ei ole vielä yhtään listaa.</string>
<string name="no_followed_hashtags">Et seuraa yhtään aihetunnistetta.</string>
<string name="manage_lists">Hallitse listoja</string>
<string name="manage_hashtags">Hallitse aihetunnisteita</string>
<!-- Screen reader description for the menu on the home timeline screen -->
<string name="dropdown_menu">Pudotusvalikko</string>
<string name="edit_list">Muokkaa listaa</string>
<string name="list_members">Listan jäsenet</string>
<string name="delete_list">Poista lista</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">Poistetaanko “%s”?</string>
<string name="list_exclusive">Piilota jäsenet Seuratuissa</string>
<string name="list_exclusive_subtitle">Jos joku on tällä listalla, piilota hänet Seuratut-aikajanalla jottet näe julkaisuja kahdesti.</string>
<string name="list_name">Listan nimi</string>
<string name="list_show_replies_to">Näytä vastaukset</string>
<string name="list_replies_no_one">Ei kellekään</string>
<string name="list_replies_members">Listan jäsenille</string>
<string name="list_replies_anyone">Kenelle tahansa seuraamalleni</string>
<string name="confirm_remove_list_members">Poista jäsenet?</string>
<string name="remove">Poista</string>
<string name="add_list_member">Lisää jäsen</string>
<string name="search_among_people_you_follow">Etsi seuraamistasi henkilöistä</string>
<string name="add_user_to_list">Lisää listalle…</string>
<string name="add_user_to_list_title">Lisää listalle</string>
<!-- %s is a username -->
<string name="manage_user_lists">Hallitse listoja joissa %s on mukana</string>
<string name="remove_from_list">Poista listalta</string>
<string name="confirm_remove_list_member">Poista jäsen?</string>
<string name="no_followed_hashtags_title">Pysy ajan tasalla seuraamalla kiinnostavia aihetunnisteita</string>
<string name="no_followed_hashtags_subtitle">Seuratut näkyvät täällä</string>
<string name="no_lists_title">Järjestä kotiaikajanasi listojen avulla</string>
<string name="no_lists_subtitle">Omasi näkyy täällä</string>
<string name="manage_accounts">Lisää tai vaihda tiliä</string>
<plurals name="x_posts_recently">
<item quantity="one">%,d äskeinen julkaisu</item>
<item quantity="other">%,d äskeistä julkaisua</item>
</plurals>
<string name="create_list">Luo lista</string>
<string name="step_x_of_y">Vaihe %1$d / %2$d</string>
<string name="create">Luo</string>
<string name="manage_list_members">Hallitse listan jäseniä</string>
<string name="list_no_members">Ei vielä jäseniä</string>
<string name="list_find_users">Etsi lisättäviä käyttäjiä</string>
</resources>

View File

@@ -8,7 +8,7 @@
<string name="sk_settings_emoji_reactions_in_lists_explanation">Näytetäänkö emojireaktiot aikajanoissa. Jos tämä on pois käytöstä, emojireaktiot näkyvät vain lankaa katsottaessa.</string>
<string name="sk_button_react">Reagoi emojilla</string>
<string name="sk_again_for_system_keyboard">Järjestelmän näppäimistö seuraavalla painalluksella</string>
<string name="sk_enter_emoji_toast">Lisää emoji</string>
<string name="sk_enter_emoji_toast">Käytäthän emojia</string>
<string name="sk_enter_emoji_hint">Lisää emoji tai etsi</string>
<string name="sk_mute_label">Kesto</string>
<string name="sk_duration_indefinite">Loputon</string>
@@ -25,13 +25,13 @@
<string name="sk_delete_and_redraft">Poista ja kirjoita uudestaan</string>
<string name="sk_pin_post">Kiinnitä profiiliin</string>
<string name="sk_unpin_post">Irrota profiilista</string>
<string name="sk_confirm_delete_and_redraft_title">Poista ja kirjoita viesti uudelleen</string>
<string name="sk_confirm_pin_post_title">Kiinnitä viesti profiiliin</string>
<string name="sk_confirm_pin_post">Haluatko kiinnittää tämän viestin profiiliisi\?</string>
<string name="sk_confirm_delete_and_redraft">Oletko varma että haluat poistaa ja kirjoittaa viestin uudelleen\?</string>
<string name="sk_confirm_unpin_post_title">Poista viestin kiinnitys profiilista</string>
<string name="sk_unpinning">Viestiä irrotetaan…</string>
<string name="sk_pinning">Viestiä kiinnitetään…</string>
<string name="sk_confirm_delete_and_redraft_title">Poista ja kirjoita julkaisu uudelleen</string>
<string name="sk_confirm_pin_post_title">Kiinnitä julkaisu profiiliin</string>
<string name="sk_confirm_pin_post">Haluatko kiinnittää tämän julkaisun profiiliisi\?</string>
<string name="sk_confirm_delete_and_redraft">Oletko varma että haluat poistaa ja kirjoittaa julkaisun uudelleen\?</string>
<string name="sk_confirm_unpin_post_title">Poista julkaisun kiinnitys profiilista</string>
<string name="sk_unpinning">Julkaisua irrotetaan…</string>
<string name="sk_pinning">Julkaisua kiinnitetään…</string>
<string name="sk_image_description">Kuvaselitys</string>
<string name="sk_visibility_unlisted">Listaamaton</string>
<string name="sk_settings_show_replies">Näytä vastaukset</string>
@@ -43,7 +43,7 @@
<string name="sk_settings_auto_reveal_nobody">Ei koskaan</string>
<string name="sk_settings_auto_reveal_author">Saman tilin vastauksissa</string>
<string name="sk_settings_auto_reveal_anyone">Kaikkien vastaukset</string>
<string name="sk_settings_translate_only_opened">Käännä vain avatut viestit</string>
<string name="sk_settings_translate_only_opened">Käännä vain avatut julkaisut</string>
<string name="sk_translate_show_original">Näytä alkuperäinen</string>
<string name="sk_available_languages">Käytettävissä olevat kielet</string>
<string name="sk_translated_using">Kännetty käyttäen %s</string>
@@ -63,12 +63,12 @@
<string name="sk_loading_fediverse_resource_title">Etsitään Fediversestä</string>
<string name="sk_undo_reblog">Peru tehostus</string>
<string name="sk_reblog_with_visibility">Tehostuksen näkyvyysasetus</string>
<string name="sk_copy_link_to_post">Kopioi linkki viestiin</string>
<string name="sk_copy_link_to_post">Kopioi linkki julkaisuun</string>
<string name="sk_open_with_account">Avaa toisella tilillä</string>
<string name="sk_resource_not_found">Kohdetta ei löytynyt</string>
<string name="sk_settings_allow_remote_loading">Hae tietoa etäinstansseista</string>
<string name="sk_forward_report_to">Lähetä edelleen kohteeseen %s</string>
<string name="sk_unsent_posts">Julkaisemattomat viestit</string>
<string name="sk_unsent_posts">Odottavat julkaisut</string>
<string name="sk_settings_prefix_replies_always">Vastaus kenelle tahansa</string>
<string name="sk_settings_prefix_replies_never">Ei koskaan</string>
<string name="sk_confirm_save_draft">Tallenna luonnos\?</string>
@@ -81,7 +81,7 @@
<string name="sk_icon_diamond">Timantti</string>
<string name="sk_icon_umbrella">Sateenverjo</string>
<string name="sk_add_timeline">Lisää aikajana</string>
<string name="sk_edit_timeline_tag_main">Viestit joissa on aihetunniste…</string>
<string name="sk_edit_timeline_tag_main">Julkaisut, joissa on aihetunniste…</string>
<string name="sk_edit_timeline_tag_any">...tai jokin näistä</string>
<string name="sk_icon_beaker">Kannu</string>
<string name="sk_content_type_unspecified">Ei määritelty</string>
@@ -105,27 +105,27 @@
<string name="sk_icon_dog">Koira</string>
<string name="sk_icon_pin">Nasta</string>
<string name="sk_searching">Etsitään…</string>
<string name="sk_settings_see_new_posts_button">”Katso uudet viestit” -painike</string>
<string name="sk_settings_see_new_posts_button">”Katso uudet julkaisut” -painike</string>
<string name="sk_icon_feed">Syöte</string>
<string name="sk_post_edited">muokattu</string>
<string name="sk_notification_type_update">Muokatut viestit</string>
<string name="sk_notification_type_update">Muokatut julkaisut</string>
<string name="sk_attach_file">Liitä tiedosto</string>
<string name="sk_settings_hide_interaction">Piilota reaktiopainikkeet</string>
<string name="sk_followed_as">Seurattu tilinä %s</string>
<string name="sk_settings_hide_fab">Piilota Julkaise-painike automaattisesti</string>
<string name="sk_follow_as">Seuraa toisena tilinä</string>
<string name="sk_notification_type_posts">Viesti-ilmoitukset</string>
<string name="sk_notification_type_posts">Ilmotukset julkaisuista</string>
<string name="sk_settings_tabs_disable_swipe">Estä välilehdestä toiseen pyyhkäiseminen</string>
<string name="sk_settings_enable_delete_notifications">Salli ilmoitusten poistaminen</string>
<string name="sk_gif_badge">GIF</string>
<string name="sk_no_alt_text">Selitys puuttuu</string>
<string name="sk_inline_direct">vain maininnat</string>
<string name="sk_settings_glitch_instance">Glitch local-only mode</string>
<string name="sk_settings_glitch_instance">Glitch vain paikallinen</string>
<string name="sk_settings_glitch_mode_explanation">Ota tämä käyttöön, jos koti-instanssisi käyttää Glitchiä. Hometown tai Akkoma eivät tarvitse tätä.</string>
<string name="sk_unfinished_attachments_message">Joitakin liitteitä ei ole vielä ladattu valmiiksi.</string>
<string name="sk_settings_content_types">Ota viestin muotoilu käyttöön</string>
<string name="sk_settings_content_types">Ota julkaisun muotoilu käyttöön</string>
<string name="sk_settings_default_content_type">Sisältötyypin oletusarvo</string>
<string name="sk_settings_default_content_type_explanation">Tämä mahdollistaa uusien viestien sisältötyypin ennaltavalinnan, ohittaa julkaisuasetuksissa asetetun arvon.</string>
<string name="sk_settings_default_content_type_explanation">Tämä mahdollistaa uusien julkaisun sisältötyypin ennaltavalinnan, ohittaa julkaisuasetusten oletusarvon.</string>
<string name="sk_instance_info_unavailable">Tietoa instanssista ei juuri nyt ole saatavilla</string>
<string name="sk_open_in_app">Avaa sovelluksessa</string>
<string name="sk_external_share_or_open_title">Jaa tai avaa tilinä</string>
@@ -139,8 +139,8 @@
<item quantity="other">%1$,d käyttäjää reagoi näin: %2$s</item>
</plurals>
<plurals name="sk_posts_count_label">
<item quantity="one">viesti</item>
<item quantity="other">viestiä</item>
<item quantity="one">julkaisu</item>
<item quantity="other">julkaisut</item>
</plurals>
<string name="sk_settings_continues_playback">Ääniraita</string>
<string name="sk_settings_reply_visibility_following">Vastaukset seuraamilleni</string>
@@ -148,9 +148,9 @@
<string name="sk_settings_show_interaction_counts">Näytä laskimet</string>
<string name="sk_settings_app_version">Megalodon v%1$s (%2$d)</string>
<string name="sk_mark_media_as_sensitive">Merkitse media arkaluontoiseksi</string>
<string name="sk_federated_timeline_info_banner">Nämä ovat uusimmat viestit yleiseltä aikajanalta.</string>
<string name="sk_federated_timeline_info_banner">Nämä ovat uusimmat julkaisut yleiseltä aikajanalta.</string>
<string name="sk_lists_with_user">Listoja joissa on %s</string>
<string name="sk_notification_type_status">Viestit</string>
<string name="sk_notification_type_status">Julkaisut</string>
<string name="sk_color_palette_blue">Sininen</string>
<string name="sk_color_palette_brown">Ruskea</string>
<string name="sk_color_palette_red">Punainen</string>
@@ -166,7 +166,7 @@
<string name="sk_settings_donate">Lahjoita</string>
<string name="sk_delete_notification_confirm">Oletko varma, että haluat poistaa ilmoituksen\?</string>
<string name="sk_settings_publish_button_text">Julkaisupainikkeen teksti</string>
<string name="sk_quote_post">Kirjoita viesti aiheenamä</string>
<string name="sk_quote_post">Kirjoita julkaisustä</string>
<string name="sk_bookmark_as">Tee kirjamerkki toiselle tilille</string>
<string name="sk_already_bookmarked">Kirjamerkki jo tallennettu</string>
<string name="sk_favorite_as">Tykkä toisena tilinä</string>
@@ -176,12 +176,12 @@
<string name="sk_draft">Luonnos</string>
<string name="sk_schedule">Ajasta</string>
<string name="sk_confirm_delete_draft_title">Poista luonnos</string>
<string name="sk_confirm_delete_draft">Oletko varma, että haluat poistaa tämän viestiluonnoksen\?</string>
<string name="sk_confirm_delete_draft">Oletko varma, että haluat poistaa tämän luonnoksen\?</string>
<string name="sk_confirm_delete_scheduled_post_title">Poista ajastettu julkaisu</string>
<string name="sk_user_post_notifications_off">Ilmoitukset käyttäjän %s viesteistä poistettu käyttöstä</string>
<string name="sk_settings_show_boosts">Näytä tehostukset</string>
<string name="sk_settings_load_new_posts">Lataa uudet viestit automaattisesti</string>
<string name="sk_draft_or_schedule">Luonnos tai ajastettu viesti</string>
<string name="sk_settings_load_new_posts">Lataa uudet julkaisut automaattisesti</string>
<string name="sk_draft_or_schedule">Luonnos tai ajastus</string>
<string name="sk_compose_scheduled">Ajastettu ajalle</string>
<string name="sk_draft_saved">Luonnos tallennettu</string>
<string name="sk_post_scheduled">Julkaisu ajastettu</string>
@@ -209,9 +209,9 @@
<string name="sk_alt_text_missing_title">Kuvaselitys puuttuu</string>
<string name="sk_publish_anyway">Julkaise silti</string>
<string name="sk_settings_disable_alt_text_reminder">Poista muistutus mediakuvauksesta</string>
<string name="sk_notify_posts_info_banner">Jos otat käyttöön ilmoitukset joidenkin henkilöiden viesteistä, heidän uudet viestinsä näkyvät täällä.</string>
<string name="sk_notify_posts_info_banner">Jos otat käyttöön ilmoitukset joidenkin henkilöiden julkaisuista, heidän uudet julkaisunsa näkyvät täällä.</string>
<string name="sk_timelines">Aikajanat</string>
<string name="sk_timeline_posts">Viestit</string>
<string name="sk_timeline_posts">Julkaisut</string>
<string name="sk_timelines_add">Lisää</string>
<string name="sk_timeline">Aikajana</string>
<string name="sk_list">Lista</string>
@@ -263,7 +263,7 @@
<string name="sk_edit_timeline_tag_none">...muttei mitään näistä</string>
<string name="sk_edit_timeline_tag_hint">Kirjoita aihetunniste…</string>
<string name="sk_edit_timeline_tags_hint">Kirjoita aihetunnisteet…</string>
<string name="sk_hashtag_timeline_local_only_switch">Näytetäänkö vain paikalliset viestit\?</string>
<string name="sk_hashtag_timeline_local_only_switch">Näytetäänkö vain paikalliset julkaisut\?</string>
<string name="sk_add_timeline_tag_error_empty">Aihetunniste ei voi olla tyhjä</string>
<string name="sk_alt_button">ALT</string>
<string name="sk_no_results">Ei tuloksia</string>
@@ -274,12 +274,12 @@
<string name="sk_inline_local_only">vain paikallinen</string>
<string name="sk_separator">·</string>
<string name="sk_local_only">Vain paikallinen instanssi</string>
<string name="sk_settings_local_only_explanation">Jotta tämä toimii, koti-instanssisi on tuettava viestien julkaisemista ainoastaan paikallisesti. Useimmat Mastodonin muunnellut versiot tukevat, mutta Mastodon ei.</string>
<string name="sk_settings_local_only_explanation">Jotta tämä toimii, koti-instanssisi on tuettava sisällön julkaisemista ainoastaan paikallisesti. Useimmat Mastodonin muunnellut versiot tukevat, mutta Mastodon ei.</string>
<string name="sk_signed_up">rekisteröity</string>
<string name="sk_reported">raportoitu</string>
<string name="sk_sign_ups">Käyttäjät rekisteröityvät</string>
<string name="sk_settings_prefix_reply_cw_with_re">Lisää sisältövaroitukseen \"re:\" kun vastaat</string>
<string name="sk_unfinished_attachments">Korjataanko liitteet\?</string>
<string name="sk_unfinished_attachments">Liitteitä ladataan</string>
<string name="sk_content_type_bbcode">BBCode</string>
<string name="sk_content_type_mfm">MFM</string>
<string name="sk_settings_prefix_replies_to_others">Vastaukset muille</string>
@@ -310,7 +310,7 @@
<string name="sk_notify_poll_results">Kyselyn tulokset</string>
<string name="sk_expand">Avaa</string>
<string name="sk_collapse">Kätke</string>
<string name="sk_settings_collapse_long_posts">Kätke pitkien viestien loppuosa</string>
<string name="sk_settings_collapse_long_posts">Kätke pitkien julkaisujen loppuosa</string>
<string name="sk_reacted_with">%1$s reagoi %2$s</string>
<string name="sk_notification_action_replied">Vastaus lähetetty käyttäjälle %s</string>
<string name="sk_update_ready">Megalodon %s on ladattu ja valmis asennettavaksi.</string>
@@ -340,8 +340,8 @@
<string name="sk_user_post_notifications_on">Ilmoitukset käyttäjän %s viesteistä otettu käyttöön</string>
<string name="sk_federated_timeline">Yleinen</string>
<string name="sk_delete_notification_confirm_action">Poista ilmoitus</string>
<string name="sk_settings_content_types_explanation">Mahdollistaa viestien sisältötyypin valinnan, esimerkiksi Markdown. Kaikki instanssit eivät tue tätä.</string>
<string name="sk_bubble_timeline_info_banner">Nämä ovat uusimmat viestit ihmisiltä, joiden tilejä sinun instanssisi isännöi.</string>
<string name="sk_settings_content_types_explanation">Mahdollistaa julkaisujen sisältötyypin valinnan, esimerkiksi Markdown. Kaikki instanssit eivät tue tätä.</string>
<string name="sk_bubble_timeline_info_banner">Nämä ovat uusimmat julkaisut ihmisiltä, joiden tilejä sinun instanssisi isännöi.</string>
<string name="sk_settings_publish_button_text_title">Muokkaa Julkaise-painikkeen tekstiä</string>
<string name="sk_no_remote_info_hint">etäinfoa ei saatavilla</string>
<string name="sk_reject_follow_request">Hylkää seuraamispyyntö</string>
@@ -357,9 +357,9 @@
<string name="sk_confirm_delete_scheduled_post">Oletko varma, että haluat poistaa tämän ajastetun julkaisun\?</string>
<string name="sk_compose_draft">Julkaisu tallennetaan luonnoksena.</string>
<string name="sk_scheduled_too_soon">Julkaisu on ajastettava vähintään 10 minuuttia tulevaisuuteen.</string>
<string name="sk_confirm_unpin_post">Oletko varma että haluat irrottaa tämän viestin\?</string>
<string name="sk_confirm_unpin_post">Oletko varma että haluat irrottaa tämän julkaisun\?</string>
<string name="sk_settings_unifiedpush_no_distributor_body">On asennettava jakelijaohjelma jotta UnifiedPush-ilmoitukset toimivat. Lisätietoja: https://unifiedpush.org/</string>
<string name="sk_settings_emoji_reactions_explanation">Näyttää viestien emojireaktiot ja mahdollistaa omien lisäämisen. Jotkin Mastodonin muokatut versiot tukevat tätä, mutta Mastodon ei.</string>
<string name="sk_settings_emoji_reactions_explanation">Näyttää julkaisujen emojireaktiot ja antaa lisätä omasi. Jotkin Fediversumin serverit tukevat tätä, mutta ei Mastodon.</string>
<string name="sk_recent_searches_placeholder">Hae kirjoittamalla tähän</string>
<string name="sk_alt_text_missing">Selitys puuttuu vähintään yhdestä liitteestä.</string>
<string name="sk_pinned_timeline">Kiinnitetty kotinäyttöön</string>
@@ -370,7 +370,7 @@
<string name="sk_icon_recycle_bin">Roskakori</string>
<string name="sk_edit_timelines">Muokkaa aikajanoja</string>
<string name="sk_edit_timeline_tags_explanation">Ota huomioon, että palvelin tekee nämä operaatiot. Niiden yhdistelyä ei välttämättä tueta.</string>
<string name="sk_notify_update">Tämä muokkaa tehostettua viestiä</string>
<string name="sk_notify_update">Tämä muokkaa tehostettua julkaisua</string>
<string name="sk_save_draft_message">Haluatko tallentaa muutokset tähän luonnokseen vai julkaista sen nyt\?</string>
<string name="sk_settings_support_local_only">Palvelin tukee paikallista julkaisemista</string>
<string name="sk_settings_continues_playback_summary">Anna mediatoiston jatkua lisäten uusi raita</string>
@@ -379,7 +379,7 @@
<item quantity="one">%d sekunti</item>
<item quantity="other">%d sekuntia</item>
</plurals>
<string name="sk_settings_show_emoji_reactions_only_opened">Vain kun julkaisu on avattu</string>
<string name="sk_settings_show_emoji_reactions_only_opened">Vain jos julkaisu on avattu</string>
<plurals name="sk_time_hours">
<item quantity="one">%d tunti</item>
<item quantity="other">%d tuntia</item>
@@ -388,26 +388,35 @@
<string name="sk_settings_show_emoji_reactions">Näytä emojireaktiot aikajanoissa</string>
<string name="sk_blocked_accounts">Estetyt tilit</string>
<string name="sk_suicide_search_terms">Itsemurha</string>
<string name="sk_load_missing_posts_above">Lataa uudempia julkaisuja</string>
<string name="sk_load_missing_posts_above">Lataa uusia viestejä</string>
<plurals name="sk_time_days">
<item quantity="one">%d päivä</item>
<item quantity="other">%d päivää</item>
</plurals>
<string name="sk_settings_show_emoji_reactions_always">Näytä lisäyspainike aina</string>
<string name="sk_settings_show_emoji_reactions_always">Näytä aina \"lisää\" -painike</string>
<string name="sk_search_suicide_hotlines">Löydä kriisipuhelin</string>
<string name="sk_muted_accounts">Hiljennetyt tilit</string>
<string name="sk_do_not_show_again">Älä näytä toista kertaa</string>
<string name="sk_do_not_show_again">Älä näytä uudelleen</string>
<string name="sk_suicide_helplines_url">https://mieli.fi/tukea-ja-apua/kriisipuhelin/</string>
<string name="sk_trending_posts_info_banner">Nämä julkaisut ovat saamassa vetoa Fediversumissa.</string>
<string name="sk_load_missing_posts_below">Lataa vanhempia julkaisuja</string>
<string name="sk_trending_posts_info_banner">Nämä julkaisut saavat huomiota Fediversumissa.</string>
<string name="sk_load_missing_posts_below">Lataa vanhoja viestejä</string>
<string name="sk_search_suicide_title">Jos tarvitset apua…</string>
<plurals name="sk_time_minutes">
<item quantity="one">%d minuutti</item>
<item quantity="other">%d minuuttia</item>
</plurals>
<string name="sk_search_suicide_message">Jos haluat merkin siitä, että elämää kannattaa jatkaa, tämä on se. Jos olet hädässä, voit ottaa yhteyttä paikalliseen kriisipuhelimeen.</string>
<string name="sk_trending_links_info_banner">Näistä uutisjutuista keskustellaan Fediversumissa.</string>
<string name="sk_post_contains_media">Julkaisussa on mediaa</string>
<string name="sk_search_suicide_message">Jos odotat merkkiä, että sinun ei kannata tehdä itsemurhaa, niin se on tämä. Harkitse yhteydenottoa valtakunnalliseen kriisipuhelimeen 09 2525 0111.</string>
<string name="sk_trending_links_info_banner">Näistä uutisista puhutaan Fediversumissa.</string>
<string name="sk_post_contains_media">Julkaisussa on mediasisältöä</string>
<string name="sk_settings_like_icon">Käytä sydäntä suosikkikuvakkeena</string>
<string name="sk_recently_used">Äskettäin käytetty</string>
<string name="sk_set_as_default">Aseta oletusarvoksi</string>
<string name="sk_settings_color_palette_default">Oletusarvo (%s)</string>
<string name="sk_settings_default_visibility">Julkaisun oletusnäkyvyys</string>
<string name="sk_settings_underlined_links">Alleviivatut linkit</string>
<string name="sk_settings_lock_account">Hyväksy uudet seuraajat käsin</string>
<string name="sk_timeline_cache_cleared">Kotiaikajanan välimuisti tyhjennetty</string>
<string name="sk_button_mutuals">Ystävät</string>
<string name="sk_settings_clear_timeline_cache">Tyhjennä kotiaikajanan välimuisti</string>
<string name="sk_edit_alt_text">Muuta selitystä</string>
</resources>

View File

@@ -199,7 +199,6 @@
<string name="file_saved">Nai-save ang File</string>
<string name="downloading">Nagda-download…</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Tingnan ang mga bagong post</string>
<string name="load_missing_posts">Mag-Load ng nawawalang mga post</string>
<string name="follow_back">Sundan Pabalik</string>
<string name="button_follow_pending">Nakabinbin</string>
@@ -289,4 +288,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<string name="see_new_posts">Tingnan ang mga bagong post</string>
</resources>

View File

@@ -262,7 +262,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Voici tous les messages de tous les comptes de votre serveur (%s).</string>
<string name="recommended_accounts_info_banner">Vous pourriez aimer ces comptes en fonction des autres que vous suivez.</string>
<string name="see_new_posts">Voir les nouveaux messages</string>
<string name="see_new_posts">Nouveaux messages </string>
<string name="load_missing_posts">Charger les messages manquants</string>
<string name="follow_back">Suivre en retour</string>
<string name="button_follow_pending">En attente</string>
@@ -588,6 +588,9 @@
<string name="post_translated">Traduit depuis %1$s via %2$s</string>
<string name="translation_show_original">Afficher loriginal</string>
<string name="translation_failed">La traduction a échoué. Peut-être que ladministrateur na pas activé les traductions sur ce serveur ou que ce serveur utilise une ancienne version de Mastodon où les traductions ne sont pas encore prises en charge.</string>
<string name="settings_privacy">Vie privée et visibilité</string>
<string name="settings_discoverable">Autoriser des algorithmes de découverte à mettre en avant votre profil et vos messages</string>
<string name="settings_indexable">Inclure mes messages publics dans les résultats de recherche</string>
<plurals name="x_participants">
<item quantity="one">%,d participant</item>
<item quantity="other">%,d participants</item>
@@ -596,7 +599,51 @@
<item quantity="one">%,d message aujourdhui</item>
<item quantity="other">%,d messages aujourdhui</item>
</plurals>
<string name="error_playing_video">Erreur lors de la lecture de la vidéo</string>
<string name="timeline_following">Accueil</string>
<string name="lists">Listes</string>
<string name="followed_hashtags">Hashtags suivis</string>
<string name="no_lists">Vous navez pas encore de listes.</string>
<string name="no_followed_hashtags">Vous ne suivez aucun hashtag.</string>
<string name="manage_lists">Gérer les listes</string>
<string name="manage_hashtags">Gérer les hashtags</string>
<!-- Screen reader description for the menu on the home timeline screen -->
<string name="dropdown_menu">Menu déroulant</string>
<string name="edit_list">Modifier la liste</string>
<string name="list_members">Membres de la liste</string>
<string name="delete_list">Supprimer la liste</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">Supprimer « %s » ?</string>
<string name="list_exclusive">Cacher les membres dans Abonné⋅e</string>
<string name="list_exclusive_subtitle">Si quelqu\'un est dans cette liste, les cacher dans votre fil pour éviter de voir leurs messages deux fois.</string>
<string name="list_name">Nom de la liste</string>
<string name="list_show_replies_to">Montrer les réponses à</string>
<string name="list_replies_no_one">Personne</string>
<string name="list_replies_members">Membres de la liste</string>
<string name="list_replies_anyone">Toute personne que je suis</string>
<string name="confirm_remove_list_members">Supprimer les membres ?</string>
<string name="remove">Supprimer</string>
<string name="add_list_member">Ajouter un membre</string>
<string name="search_among_people_you_follow">Rechercher parmi les gens que vous suivez</string>
<string name="add_user_to_list">Ajouter à la liste…</string>
<string name="add_user_to_list_title">Ajouter à la liste</string>
<!-- %s is a username -->
<string name="manage_user_lists">Gérer les listes où %s apparaît</string>
<string name="remove_from_list">Supprimer de la liste</string>
<string name="confirm_remove_list_member">Supprimer le membre ?</string>
<string name="no_followed_hashtags_title">Restez au courant des sujets qui vous intéressent en suivant des hashtags</string>
<string name="no_followed_hashtags_subtitle">Les abonnements apparaîtront ici</string>
<string name="no_lists_title">Organisez votre fil d\'accueil avec des listes</string>
<string name="no_lists_subtitle">Vos listes apparaîtront ici</string>
<string name="manage_accounts">Ajouter ou changer de compte</string>
<plurals name="x_posts_recently">
<item quantity="one">%,d message récemment</item>
<item quantity="other">%,d messages récemment</item>
</plurals>
<string name="create_list">Créer une liste</string>
<string name="step_x_of_y">Étape %1$d sur %2$d</string>
<string name="create">Créer</string>
<string name="manage_list_members">Gérer les membres de la liste</string>
<string name="list_no_members">Aucun membre pour l\'instant</string>
<string name="list_find_users">Trouver des utilisateurs à ajouter</string>
</resources>

View File

@@ -256,7 +256,7 @@
<string name="sk_settings_collapse_long_posts">Réduire les messages très longs</string>
<string name="sk_settings_prefix_reply_cw_with_re">Préfixer les CW avec \"re :\" en répondant à</string>
<string name="sk_filtered">Filtré : %s</string>
<string name="sk_unfinished_attachments">Corriger les pièces jointes \?</string>
<string name="sk_unfinished_attachments">Téléchargement de pièces jointes</string>
<string name="sk_unfinished_attachments_message">Certaines pièces jointes n\'ont pas fini de se télécharger.</string>
<string name="sk_spectator_mode">Mode spectateur</string>
<string name="sk_settings_hide_interaction">Masquer les boutons d\'interaction</string>
@@ -408,4 +408,11 @@
<string name="sk_set_as_default">Définir par défaut</string>
<string name="sk_settings_color_palette_default">Par défaut (%s)</string>
<string name="sk_settings_underlined_links">Liens soulignés</string>
<string name="sk_edit_alt_text">Modifier le texte alternatif</string>
<string name="sk_message_cache_cleared">Cache des messages vidé</string>
<string name="sk_settings_clear_timeline_cache">Effacer le cache du fil d\'accueil</string>
<string name="sk_settings_default_visibility">Visibilité de publication par défaut</string>
<string name="sk_settings_lock_account">Approuver manuellement les nouveaux abonnés</string>
<string name="sk_timeline_cache_cleared">Cache du fil d\'accueil vidé</string>
<string name="sk_button_mutuals">Amis</string>
</resources>

View File

@@ -288,7 +288,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Seo gach post o gach cleachdaiche an fhrithealaiche agad (%s).</string>
<string name="recommended_accounts_info_banner">Dhfhaoidte gun còrd na cunntasan seo riut stèidhichte air feadhainn eile a tha thu a leantainn.</string>
<string name="see_new_posts">Seall na postaichean ùra</string>
<string name="see_new_posts">Postaichean ùra</string>
<string name="load_missing_posts">Luchdaich postaichean a dhìth</string>
<string name="follow_back">Lean air ais</string>
<string name="button_follow_pending">Ri dhèiligeadh</string>
@@ -641,8 +641,40 @@
<string name="time_hours_ago_short">%du air ais</string>
<string name="time_days_ago_short">%dl air ais</string>
<!-- %s is the name of the post language -->
<string name="translate_post">Eadar-theangaich o %s</string>
<!-- %1$s is the language, %2$s is the name of the translation service -->
<string name="post_translated">Air eadar-theangachadh o %1$s le %2$s</string>
<string name="translation_show_original">Seall an tionndadh tùsail</string>
<string name="translation_failed">Dhfhàillig an t-eadar-theangachadh. Dhfhaoidte nach do chuir an rianaire na h-eadar-theangachaidhean an comas air an fhrithealaiche seo no gu bheil am frithealaiche a ruith seann-tionndadh de Mhastodon far nach eil taic ri eadar-theangachadh fhathast.</string>
<string name="settings_privacy">Prìobhaideachd s ruigse</string>
<string name="settings_discoverable">Brosnaich a phròifil is postaichean agad sna h-algairimean luirg</string>
<string name="settings_indexable">Gabh na postaichean poblach a-staigh ann an toraidhean luirg</string>
<plurals name="x_participants">
<item quantity="one">%,d chom-pàirtiche</item>
<item quantity="two">%,d chom-pàirtiche</item>
<item quantity="few">%,d com-pàirtichean</item>
<item quantity="other">%,d com-pàirtiche</item>
</plurals>
<plurals name="x_posts_today">
<item quantity="one">%,d phost an-diugh</item>
<item quantity="two">%,d phost an-diugh</item>
<item quantity="few">%,d postaichean an-diugh</item>
<item quantity="other">%,d post an-diugh</item>
</plurals>
<string name="error_playing_video">Mearachd le cluich a video</string>
<string name="timeline_following">Dachaigh</string>
<string name="lists">Liostaichean</string>
<string name="followed_hashtags">Tagaichean hais gan leantainn</string>
<string name="no_lists">Chan eil liosta agad fhathast.</string>
<string name="no_followed_hashtags">Chan eil thu a leantainn taga hais fhathast.</string>
<string name="manage_lists">Stiùirich na liostaichean</string>
<string name="manage_hashtags">Stiùirich na tagaichean hais</string>
<!-- Screen reader description for the menu on the home timeline screen -->
<string name="dropdown_menu">Clàr-taice teàrnach</string>
<string name="edit_list">Deasaich an liosta</string>
<string name="list_members">Buill na liosta</string>
<string name="delete_list">Sguab às an liosta</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">A bheil thu airson “%s” a sguabadh às?</string>
<!-- %s is a username -->
</resources>

View File

@@ -262,7 +262,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Estas son as publicacións das usuarias do teu servidor (%s).</string>
<string name="recommended_accounts_info_banner">Poderían interesarche estas contas en función doutras que segues.</string>
<string name="see_new_posts">Ver novas publicacións</string>
<string name="see_new_posts">Novas publicacións</string>
<string name="load_missing_posts">Cargar publicacións que faltan</string>
<string name="follow_back">Seguir tamén</string>
<string name="button_follow_pending">Pendente</string>
@@ -599,7 +599,44 @@
<item quantity="one">%,d publicación hoxe</item>
<item quantity="other">%,d publicacións hoxe</item>
</plurals>
<string name="error_playing_video">Erro ao reproducir o vídeo</string>
<string name="lists">Listas</string>
<string name="followed_hashtags">Cancelos seguidos</string>
<string name="no_lists">Aínda non tes ningunha lista.</string>
<string name="no_followed_hashtags">Non segues ningún cancelo.</string>
<string name="manage_lists">Xestionar listas</string>
<string name="manage_hashtags">Xestionar cancelos</string>
<!-- Screen reader description for the menu on the home timeline screen -->
<string name="dropdown_menu">Menú despregable</string>
<string name="edit_list">Editar lista</string>
<string name="list_members">Membros da lista</string>
<string name="delete_list">Eliminar lista</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">Eliminar \"%s\"?</string>
<string name="list_exclusive">Agochar aos membros no Inicio</string>
<string name="list_exclusive_subtitle">Se alguén está nesta lista, oculta as súas publicacións na Cronoloxía de inicio para non velas dúas veces.</string>
<string name="list_name">Nome da lista</string>
<string name="list_show_replies_to">Mostrar respostas a</string>
<string name="list_replies_no_one">Ninguén</string>
<string name="list_replies_members">Usuarias na lista</string>
<string name="list_replies_anyone">Alguén a quen sigo</string>
<string name="confirm_remove_list_members">Eliminar membros?</string>
<string name="remove">Eliminar</string>
<string name="add_list_member">Engadir usuaria</string>
<string name="search_among_people_you_follow">Procurar entre as persoas que segues</string>
<string name="add_user_to_list">Engadir á lista…</string>
<string name="add_user_to_list_title">Engadir á lista</string>
<!-- %s is a username -->
<string name="manage_user_lists">Xestionar as listas nas que aparece %s</string>
<string name="remove_from_list">Eliminar da lista</string>
<string name="confirm_remove_list_member">Eliminar membro?</string>
<string name="no_followed_hashtags_title">Infórmate dos teus intereses seguindo cancelos</string>
<string name="no_followed_hashtags_subtitle">Aquí verás os seguimentos</string>
<string name="no_lists_title">Organiza a cronoloxía de inicio con Listas</string>
<string name="no_lists_subtitle">Aquí verás as túas</string>
<string name="manage_accounts">Engade ou cambia de conta</string>
<plurals name="x_posts_recently">
<item quantity="one">%,d publicación recente</item>
<item quantity="other">%,d publicacións recentes</item>
</plurals>
</resources>

View File

@@ -256,7 +256,7 @@
<string name="sk_filtered">Filtrados: %s</string>
<string name="sk_expand">Expandir</string>
<string name="sk_settings_collapse_long_posts">Contraer publicacións moi longas</string>
<string name="sk_unfinished_attachments">Arranxar arquivos adxuntos\?</string>
<string name="sk_unfinished_attachments">Subindo arquivos adxuntos</string>
<string name="sk_spectator_mode">Modo espectador</string>
<string name="sk_settings_hide_interaction">Ocultar botóns de interacción</string>
<string name="sk_follow_as">Seguir dende outra conta</string>
@@ -330,10 +330,10 @@
<string name="sk_gif_badge">GIF</string>
<string name="sk_settings_unifiedpush_no_distributor_body">Debe instalar un distribuidor para que as notificacións UnifiedPush funcionen. Para máis información, visita https://unifiedpush.org/</string>
<string name="sk_settings_unifiedpush_no_distributor">Non se atopou ningún distribuidor</string>
<string name="sk_trending_posts_info_banner">Estas son publicacións que están a gañar tracción no teu servidor.</string>
<string name="sk_trending_posts_info_banner">Estas publicacións están a gañar tracción no Fediverso.</string>
<string name="sk_settings_unifiedpush_choose">Escoller un distribuidor</string>
<string name="sk_settings_continues_playback">Superposición de audio</string>
<string name="sk_trending_links_info_banner">Estas son as novas historias das que se está a falar no teu servidor.</string>
<string name="sk_trending_links_info_banner">Destas novas historias estase a falar en todo o Fediverso.</string>
<string name="sk_settings_unifiedpush">Empregar UnifiedPush</string>
<string name="sk_disable_pill_shaped_active_indicator">Desactivar o indicador de lapela activa en forma de pílula</string>
<string name="sk_tab_profile">Perfil</string>
@@ -373,7 +373,7 @@
<string name="sk_search_suicide_hotlines">Buscar unha liña de axuda</string>
<string name="sk_duration_hours_1">1 hora</string>
<string name="sk_duration_hours_6">6 horas</string>
<string name="sk_enter_emoji_hint">Escribe para reaccionar cunha emoticona</string>
<string name="sk_enter_emoji_hint">Escribe unha emoticona ou busca</string>
<string name="sk_duration_days_7">7 días</string>
<string name="sk_do_not_show_again">Non amosar outra vez</string>
<string name="sk_suicide_helplines_url">https://findahelpline.com/es</string>
@@ -396,4 +396,12 @@
<string name="sk_blocked_accounts">Contas bloqueadas</string>
<string name="sk_muted_accounts">Contas silenciadas</string>
<string name="sk_recently_used">Empregados recentemente</string>
<string name="sk_set_as_default">Establecer como predefinido</string>
<string name="sk_settings_color_palette_default">Defecto (%s)</string>
<string name="sk_settings_default_visibility">Visibilidade de publicación por defecto</string>
<string name="sk_settings_underlined_links">Ligazóns subliñadas</string>
<string name="sk_settings_lock_account">Aprobar manualmente novos seguidores</string>
<string name="sk_timeline_cache_cleared">Caché da cronoloxía de inicio borrada</string>
<string name="sk_settings_clear_timeline_cache">Borrar a caché da cronoloxía de inicio</string>
<string name="sk_edit_alt_text">Editar texto alternativo</string>
</resources>

View File

@@ -258,7 +258,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Itt található az összes bejegyzés az összes felhasznólótól a példányodon (%s).</string>
<string name="recommended_accounts_info_banner">Ezek a fiókok tetszhetnek neked azok alapján, akiket követsz.</string>
<string name="see_new_posts">Új bejegyzések megtekintése</string>
<string name="load_missing_posts">Hiányzó bejegyzések betöltése</string>
<string name="follow_back">Visszakövetés</string>
<string name="button_follow_pending">Függőben</string>
@@ -377,4 +376,5 @@
<!-- Screen reader description for the menu on the home timeline screen -->
<!-- %s is the name of the list -->
<!-- %s is a username -->
<string name="see_new_posts">Új bejegyzések megtekintése</string>
</resources>

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