Compare commits

..

1128 Commits

Author SHA1 Message Date
LucasGGamerM
e8a8691b03 Adding 90 changelog 2023-02-01 22:02:29 -03:00
LucasGGamerM
7fe3d97347 Bump version number 2023-02-01 22:01:25 -03:00
poesty
a2e932934c Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (16 of 16 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/zh_Hans/
(cherry picked from commit c34b08ffb20b1e58307b13775165728a57aaa2f8)
2023-02-01 22:00:13 -03:00
Oliebol
e82e51ca88 Translated using Weblate (Dutch)
Currently translated at 12.5% (2 of 16 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/nl/
(cherry picked from commit 10c50b8a78aba6f275e3ce01260f585c27535e46)
2023-02-01 22:00:12 -03:00
tygyh
ef561b6724 Translated using Weblate (Swedish)
Currently translated at 100.0% (16 of 16 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/sv/
(cherry picked from commit 467bde77b94623a9aff2bf1e0a5f735819f65edb)
2023-02-01 22:00:12 -03:00
poesty
2bdff65c13 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (22 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/zh_Hans/
(cherry picked from commit 1937864d90f67d1a1df40f15e1b6e900aa55fa8a)
2023-02-01 22:00:12 -03:00
LucasGGamerM
286b642101 Merge branch 'feature/filters_again' 2023-02-01 21:46:50 -03:00
LucasGGamerM
27ed78c293 Merge branch 'feature/filters' 2023-02-01 21:44:35 -03:00
LucasGGamerM
562a5aae7d Its now a much cleaner transition 2023-02-01 21:42:47 -03:00
LucasGGamerM
4940eff7f9 Its pretty much done i think 2023-02-01 21:39:54 -03:00
LucasGGamerM
cfb9854a8e Adding a little bit of polish, and also adding a title to the filters 2023-02-01 21:16:47 -03:00
LucasGGamerM
594e49cf64 Fixing a weird bug I found 2023-02-01 20:21:19 -03:00
LucasGGamerM
ad2895e297 Doing a bit of cleanup. Man, I still dont believe what i have done 2023-01-31 20:36:01 -03:00
LucasGGamerM
dae2632c18 IT WORKS, now i need to polish it :) 2023-01-31 20:30:05 -03:00
LucasGGamerM
97f09d4569 Adding missing drawables? 2023-01-30 19:13:20 -03:00
LucasGGamerM
ac1dbc0f90 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	mastodon/src/main/res/values-de-rDE/strings_mo.xml
#	metadata/es-ES/changelogs/80.txt
#	metadata/es-ES/changelogs/81.txt
#	metadata/es-ES/full_description.txt
2023-01-30 18:55:16 -03:00
LucasGGamerM
cf67175826 Translated using Weblate (Portuguese (Brazil))
Currently translated at 95.4% (21 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/pt_BR/
2023-01-30 21:51:47 +00:00
MKCOOL142
dc8f81f447 Translated using Weblate (German)
Currently translated at 100.0% (22 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/de/
2023-01-30 21:51:46 +00:00
MKCOOL142
b11b4c95d0 Translated using Weblate (German)
Currently translated at 100.0% (16 of 16 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/de/
2023-01-30 21:51:46 +00:00
Espasant3
20dc664242 Translated using Weblate (Galician)
Currently translated at 40.0% (6 of 15 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/gl/
2023-01-30 19:04:45 +00:00
ewm
5cabab368f Translated using Weblate (Polish)
Currently translated at 13.3% (2 of 15 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/pl/
2023-01-30 19:04:45 +00:00
Oliebol
e512a0b327 Translated using Weblate (Dutch)
Currently translated at 6.6% (1 of 15 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/nl/
2023-01-30 19:04:45 +00:00
Espasant3
4a96392f11 Translated using Weblate (Spanish)
Currently translated at 86.6% (13 of 15 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/es/
2023-01-30 19:04:45 +00:00
ewm
74a28cb881 Translated using Weblate (Polish)
Currently translated at 90.9% (20 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/pl/
2023-01-30 19:04:45 +00:00
dontobi
cd712f5109 Translated using Weblate (German)
Currently translated at 100.0% (15 of 15 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/de/
2023-01-30 19:04:45 +00:00
Oliebol
11d5a65f04 Translated using Weblate (Dutch)
Currently translated at 81.8% (18 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/nl/
2023-01-30 19:04:45 +00:00
ghose
efc1a0b4e3 Translated using Weblate (Galician)
Currently translated at 15.3% (2 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/gl/
2023-01-30 19:04:45 +00:00
ghose
492d9e90b8 Translated using Weblate (Galician)
Currently translated at 100.0% (22 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/gl/
2023-01-30 19:04:45 +00:00
LucasGGamerM
0928b5808f Adding 89 changelog 2023-01-30 16:03:44 -03:00
LucasGGamerM
99c2555a88 Bumping version number 2023-01-30 15:59:03 -03:00
LucasGGamerM
ede4137935 It now hides everything! It still doesnt pop up though :D 2023-01-29 18:46:39 -03:00
LucasGGamerM
b625ed7aec Now it acctually shows a missing posts warning below every filtered post. Still a long way to go 2023-01-29 18:24:34 -03:00
LucasGGamerM
03722868b1 Fixing a crash again 2023-01-29 14:19:38 -03:00
LucasGGamerM
a2a0c9801b Fixing #61 2023-01-29 10:40:39 -03:00
LucasGGamerM
9a55f847b9 Its once again almost working 2023-01-28 20:19:41 -03:00
LucasGGamerM
0473062bc2 Its almost working! 2023-01-28 19:30:21 -03:00
LucasGGamerM
9393e845b7 Removing megalodon things i accidentally merged 2023-01-28 13:56:50 -03:00
LucasGGamerM
3dc56286cc 88 changelog 2023-01-27 21:43:51 -03:00
LucasGGamerM
e22ea06d28 Bump version number 2023-01-27 21:40:42 -03:00
LucasGGamerM
6fd5b77e51 Forgot to add some stuff 2023-01-27 21:33:08 -03:00
LucasGGamerM
372de91be9 Updating the readme because its too old 2023-01-27 21:31:18 -03:00
LucasGGamerM
ce3f8ce1b5 Fixing thy icons 2023-01-27 16:08:46 -03:00
LucasGGamerM
7c01809eb3 Changing notif colors back to normal 2023-01-27 16:02:24 -03:00
LucasGGamerM
29cc73e84e Fixing npe in compose fragment, and also rearranging settings items 2023-01-27 16:01:17 -03:00
sk22
c3567bcbff It finally compiles! Though I need to fix some stuff before releasing 2023-01-27 15:51:00 -03:00
sk22
bd4ade0852 Translated using Weblate (German)
Currently translated at 100.0% (251 of 251 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-01-27 15:40:48 -03:00
sk
62649ffe60 move some settings around 2023-01-27 15:40:41 -03:00
Oliebol
b0a405337a Translated using Weblate (Dutch)
Currently translated at 93.9% (234 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/nl/
2023-01-27 15:40:19 -03:00
gallegonovato
18b6e33862 Translated using Weblate (Spanish)
Currently translated at 100.0% (249 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-01-27 15:40:18 -03:00
gallegonovato
acb5b01cbd Translated using Weblate (Spanish)
Currently translated at 100.0% (14 of 14 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/es/
2023-01-27 15:40:18 -03:00
gallegonovato
754c41389e Translated using Weblate (Spanish)
Currently translated at 95.5% (238 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-01-27 15:40:18 -03:00
McKris
d26ba6df4a Translated using Weblate (Polish)
Currently translated at 100.0% (14 of 14 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pl/
2023-01-27 15:40:18 -03:00
ihor_ck
cc9b97338d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (14 of 14 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/uk/
2023-01-27 15:40:18 -03:00
tygyh
f714a00fc4 Translated using Weblate (Swedish)
Currently translated at 42.8% (6 of 14 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/sv/
2023-01-27 15:40:18 -03:00
Choukajohn
7097b5371e Translated using Weblate (French)
Currently translated at 100.0% (14 of 14 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/fr/
2023-01-27 15:40:10 -03:00
ihor_ck
ad6ebf9e23 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (249 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-27 15:40:10 -03:00
tygyh
5436a45c5f Translated using Weblate (Swedish)
Currently translated at 16.4% (41 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/sv/
2023-01-27 15:40:10 -03:00
McKris
4ba3baf354 Translated using Weblate (Polish)
Currently translated at 100.0% (249 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2023-01-27 15:40:10 -03:00
rex07
9160a5b0e2 Translated using Weblate (Arabic)
Currently translated at 2.4% (6 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ar/
2023-01-27 15:40:10 -03:00
rex07
fdac91363e Added translation using Weblate (Arabic) 2023-01-27 15:40:10 -03:00
Linerly
70a9c91f8a Translated using Weblate (Indonesian)
Currently translated at 100.0% (14 of 14 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/id/
2023-01-27 15:40:10 -03:00
Linerly
45ca3d1b48 Translated using Weblate (Indonesian)
Currently translated at 100.0% (249 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-27 15:40:09 -03:00
Espasant3
9506d55149 Translated using Weblate (Galician)
Currently translated at 100.0% (14 of 14 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/gl/
2023-01-27 15:40:09 -03:00
Espasant3
16808b404b Translated using Weblate (Galician)
Currently translated at 98.3% (245 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-01-27 15:40:09 -03:00
sk
97a4cade1f separate notification toggle for polls 2023-01-27 15:40:01 -03:00
sk
55f3d80f3a unsubscribe from notifications when policy is none
re: mastodon#520
2023-01-27 15:39:36 -03:00
sk
10d66b732c set disabled state if policy is none
re: mastodon#520
2023-01-27 15:39:31 -03:00
sk
e62c70268a add server version to settings
closes sk22#376
2023-01-27 15:38:33 -03:00
sk
cbb10ac480 use regular lock in boost menu
closes sk22#375
2023-01-27 15:38:27 -03:00
Choukajohn
33de46130c Translated using Weblate (French)
Currently translated at 100.0% (249 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-27 15:38:18 -03:00
sk22
d1bd3a423c Translated using Weblate (German)
Currently translated at 92.8% (13 of 14 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/de/
2023-01-27 15:38:18 -03:00
sk22
2e24e443c5 Translated using Weblate (German)
Currently translated at 100.0% (249 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-01-27 15:38:18 -03:00
sk22
040b613d68 Translated using Weblate (English)
Currently translated at 100.0% (14 of 14 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/en/
2023-01-27 15:38:18 -03:00
ihor_ck
6659ca5f60 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (249 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-27 15:37:56 -03:00
edxkl
adaa09790a Translated using Weblate (Portuguese (Brazil))
Currently translated at 90.7% (226 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2023-01-27 15:37:56 -03:00
McKris
699bcc0377 Translated using Weblate (Polish)
Currently translated at 100.0% (249 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2023-01-27 15:37:56 -03:00
Linerly
b359a2bfa1 Translated using Weblate (Indonesian)
Currently translated at 100.0% (249 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-27 15:37:56 -03:00
Choukajohn
f821709afc Translated using Weblate (French)
Currently translated at 100.0% (249 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-27 15:37:56 -03:00
irure
a9899e8f9a Translated using Weblate (Basque)
Currently translated at 93.5% (233 of 249 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/eu/
2023-01-27 15:37:56 -03:00
sk
e1b1ae717f adapt upstream changes 2023-01-27 15:37:51 -03:00
sk
0fd2894a8b update comment 2023-01-27 15:37:48 -03:00
sk
05ddd2f8d9 change local-only string 2023-01-27 15:37:43 -03:00
sk
6d9639b042 fix visibility radio button 2023-01-27 15:37:40 -03:00
sk
f3ee87a815 change missing icons 2023-01-27 15:37:36 -03:00
sk
59c5ac0dd1 enable boosting local posts 2023-01-27 15:37:34 -03:00
sk
e647b37143 replace visibility icons 2023-01-27 15:37:31 -03:00
sk
d94c3e3d9b change list icon 2023-01-27 15:37:25 -03:00
Grishka
9b508bd9ca More onboarding updates 2023-01-27 15:36:27 -03:00
sk
fc49c20fff hopefully prevent some crashes 2023-01-27 15:35:55 -03:00
sk
7cc791ccd9 dividers and alignments
nobody knows the trouble i've seen
2023-01-27 15:35:01 -03:00
HudobniVolk
b527ab6e84 Translated using Weblate (Slovenian)
Currently translated at 30.7% (4 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/sl/
2023-01-27 15:34:51 -03:00
HudobniVolk
a5fb358998 Translated using Weblate (Slovenian)
Currently translated at 80.4% (189 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/sl/
2023-01-27 15:34:51 -03:00
edxkl
daa0497ce8 Translated using Weblate (Portuguese (Brazil))
Currently translated at 95.7% (225 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2023-01-27 15:34:51 -03:00
ghose
2d3f852fd6 Translated using Weblate (Galician)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/gl/
2023-01-27 15:34:44 -03:00
ihor_ck
cf288c9ba9 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (235 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-27 15:34:44 -03:00
HudobniVolk
4847eff116 Translated using Weblate (Slovenian)
Currently translated at 79.5% (187 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/sl/
2023-01-27 15:34:44 -03:00
edxkl
36430c6557 Translated using Weblate (Portuguese (Brazil))
Currently translated at 86.3% (203 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2023-01-27 15:34:44 -03:00
gicorada
3fb8470899 Translated using Weblate (Italian)
Currently translated at 100.0% (235 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/it/
2023-01-27 15:34:44 -03:00
irure
e1f7feb875 Translated using Weblate (Basque)
Currently translated at 99.1% (233 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/eu/
2023-01-27 15:34:44 -03:00
gallegonovato
0ec005d595 Translated using Weblate (Spanish)
Currently translated at 100.0% (235 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-01-27 15:34:44 -03:00
AiOO
b2bed8e6b5 Translated using Weblate (Korean)
Currently translated at 100.0% (235 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-01-27 15:34:44 -03:00
LucasGGamerM
30c6a56f25 Added translation using Weblate (Portuguese) 2023-01-27 15:34:27 -03:00
Espasant3
2ba575ecb8 Translated using Weblate (Galician)
Currently translated at 92.3% (12 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/gl/
2023-01-27 15:34:19 -03:00
McKris
d67cfe1d28 Translated using Weblate (Polish)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pl/
2023-01-27 15:34:19 -03:00
edxkl
cab36e8f79 Translated using Weblate (Portuguese (Brazil))
Currently translated at 81.7% (192 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2023-01-27 15:34:19 -03:00
McKris
d30eb0bd36 Translated using Weblate (Polish)
Currently translated at 100.0% (235 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2023-01-27 15:34:19 -03:00
Oliebol
31443d59ca Translated using Weblate (Dutch)
Currently translated at 98.2% (231 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/nl/
2023-01-27 15:34:19 -03:00
gicorada
79ccc4b14a Translated using Weblate (Italian)
Currently translated at 78.2% (184 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/it/
2023-01-27 15:34:19 -03:00
Linerly
6ce1dec467 Translated using Weblate (Indonesian)
Currently translated at 100.0% (235 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-27 15:34:19 -03:00
ghose
81cac94fac Translated using Weblate (Galician)
Currently translated at 100.0% (235 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-01-27 15:34:19 -03:00
Choukajohn
4301c82856 Translated using Weblate (French)
Currently translated at 100.0% (235 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-27 15:34:19 -03:00
gallegonovato
2856a5e6d4 Translated using Weblate (Spanish)
Currently translated at 98.2% (231 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-01-27 15:34:19 -03:00
Espasant3
a06414e3a1 Translated using Weblate (Spanish)
Currently translated at 98.2% (231 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-01-27 15:34:18 -03:00
ling0412
747edce53c Translated using Weblate (Chinese (Simplified))
Currently translated at 99.1% (233 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-01-27 15:34:14 -03:00
sk22
c407b5d504 Translated using Weblate (German)
Currently translated at 100.0% (235 of 235 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-01-27 15:34:14 -03:00
edxkl
997c277beb Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pt_BR/
2023-01-27 15:34:14 -03:00
ihor_ck
2e392f3bad Translated using Weblate (Ukrainian)
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-27 15:34:14 -03:00
HudobniVolk
db133ad8d2 Translated using Weblate (Slovenian)
Currently translated at 35.6% (81 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/sl/
2023-01-27 15:34:14 -03:00
edxkl
015479e6e0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 82.3% (187 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2023-01-27 15:34:13 -03:00
Linerly
8b26103049 Translated using Weblate (Indonesian)
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-27 15:34:07 -03:00
Choukajohn
8d095e7901 Translated using Weblate (French)
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-27 15:34:07 -03:00
ling0412
945b57681e Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-01-27 15:34:07 -03:00
Oliebol
1dcaa51f2c Translated using Weblate (Dutch)
Currently translated at 15.3% (2 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/nl/
2023-01-27 15:34:06 -03:00
sheepnik
c7b377829e Translated using Weblate (Welsh)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/cy/
2023-01-27 15:34:05 -03:00
sheepnik
63ffd53b09 Translated using Weblate (Welsh)
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/cy/
2023-01-27 15:34:05 -03:00
McKris
631f5f8691 Translated using Weblate (Polish)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pl/
2023-01-27 15:34:05 -03:00
ling0412
89976d1894 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/zh_Hans/
2023-01-27 15:34:05 -03:00
ihor_ck
ff7305da8b Translated using Weblate (Ukrainian)
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-27 15:34:05 -03:00
HudobniVolk
6593c43c1c Translated using Weblate (Slovenian)
Currently translated at 23.7% (54 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/sl/
2023-01-27 15:34:04 -03:00
McKris
cf36c6ca83 Translated using Weblate (Polish)
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2023-01-27 15:34:04 -03:00
Oliebol
92fb0272f0 Translated using Weblate (Dutch)
Currently translated at 93.3% (212 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/nl/
2023-01-27 15:34:04 -03:00
Linerly
aad7b5d703 Translated using Weblate (Indonesian)
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-27 15:33:59 -03:00
ghose
eb5f82af2a Translated using Weblate (Galician)
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-01-27 15:33:59 -03:00
Choukajohn
cf8cfd8093 Translated using Weblate (French)
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-27 15:33:59 -03:00
ling0412
2538c8b689 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-01-27 15:33:58 -03:00
AiOO
36d78abd1e Translated using Weblate (Korean)
Currently translated at 66.9% (152 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-01-27 15:33:53 -03:00
sk22
072e78a89a Translated using Weblate (German)
Currently translated at 100.0% (227 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-01-27 15:33:53 -03:00
sk
58dee464e5 support admin notifications 2023-01-27 15:33:40 -03:00
sk
21f816860f improve local visibility compatibility 2023-01-27 15:33:10 -03:00
sk
84e5983c4c fix null pointer exception 2023-01-27 15:33:07 -03:00
sk
1a6ad6c029 re-arrange settings 2023-01-27 15:32:10 -03:00
sk
f8ecbb8936 tweak no alt indicator 2023-01-27 15:31:07 -03:00
sk
1c98bba7d2 update string 2023-01-27 15:29:52 -03:00
LucasGGamerM
b94e927439 support akkoma local visibility / but it still doesnt compile 2023-01-27 15:29:44 -03:00
sk
eb0fcda3cc support akkoma local visibility 2023-01-27 15:28:17 -03:00
sk
d7feb78197 fix non-local-only posting (which i broke) 2023-01-27 15:24:56 -03:00
Grishka
acf1988827 Update onboarding 2023-01-27 15:24:48 -03:00
LucasGGamerM
3822263b1c Making it compile again 2023-01-27 15:24:17 -03:00
sk
1af82fde61 implement local-only posting 2023-01-27 15:20:47 -03:00
sk
6062510844 use notification icon 2023-01-27 15:19:24 -03:00
sk
27c34461bf add indicator for direct and local-only posts 2023-01-27 15:19:19 -03:00
sk
abf801742f don't apply title for hashtags/lists
closes sk22#343
2023-01-27 15:18:58 -03:00
sk
186604931d no hashtag header in list timeline
closes sk22#366
2023-01-27 15:18:56 -03:00
sk
a726bf6101 add option to disable show new posts button 2023-01-27 15:18:52 -03:00
sk
0008b07072 tweak no alt indicator background 2023-01-27 15:18:13 -03:00
sk
527267b315 Revert "bigger hitbox for alt indicator"
This reverts commit 1b04440546.

this commit just wasn't working properly. animation would have a
frame of stuttering and i don't know where that came from or how i
could fix that. also, the code was a mess anyway
2023-01-27 15:18:07 -03:00
sk
396836760a fix loading default visibility 2023-01-27 15:18:03 -03:00
sk
a5a293be78 add null check 2023-01-27 15:17:58 -03:00
LucasGGamerM
ea8107d33e implement pre-release toggle 2023-01-27 15:17:18 -03:00
sk
430dd6164c implement pre-release toggle 2023-01-27 15:13:38 -03:00
sk
7588143ec6 fix navigation bumpiness
closes sk22#347
2023-01-27 15:10:56 -03:00
sk
1f97fa9447 don't override visibility when replying to self
closes sk22#348
2023-01-27 15:10:53 -03:00
sk
fff7949e51 bigger hitbox for alt indicator
closes sk22#353
2023-01-27 15:10:47 -03:00
LucasGGamerM
ce6b928964 Fixing the settings page again 2023-01-27 15:10:42 -03:00
sk
0604326f3f add indicator for missing alt texts
closes sk22#355
2023-01-27 15:06:52 -03:00
sk
338de2699f hide scheduling options when editing
closes sk22#364
2023-01-27 15:05:17 -03:00
sk
0b0fe98e2d fix current language getting overwritten 2023-01-27 15:05:13 -03:00
LucasGGamerM
84d412645f decrease margin between items in the compose bottom bar 2023-01-27 15:05:09 -03:00
LucasGGamerM
c565f6779d Changing stuff from the alt text reminder 2023-01-27 14:59:32 -03:00
sk
1733b1b065 prompt when saving edited draft
closes sk22#319
2023-01-27 14:53:25 -03:00
sk
49cff20785 bigger hitbox for items in compose toolbar 2023-01-27 14:51:36 -03:00
sk
65232b3b1e change add media icon
closes sk22#351
2023-01-27 14:50:39 -03:00
sk
ac6177f3de display header for followed hashtags
closes sk22#323
2023-01-27 14:50:34 -03:00
sk
48e6a6f624 update hashtags/lists in home
closes sk22#312
2023-01-27 14:50:32 -03:00
sk
73db5907fe display header for followed hashtags
closes sk22#323
2023-01-27 14:50:18 -03:00
sk
69114b9f57 update hashtags/lists in home
closes sk22#312
2023-01-27 14:49:53 -03:00
sk
114283846c enable scrolling to top via toolbar 2023-01-27 14:49:50 -03:00
sk
e0dd2e3a08 improve search empty text 2023-01-27 14:49:45 -03:00
sk
648c3a0c0d fix crash when recycler view is null 2023-01-27 14:49:14 -03:00
sk
dd3bf1d1e0 improve header icons
* align more button to action overflow button
* use different background to better reflect hitbox
2023-01-27 14:49:01 -03:00
sk
5280ba1930 use fluent more icon, correct padding
closes sk22#350
2023-01-27 14:48:58 -03:00
sk
5c8c888024 fix akkoma crash on list edit
closes sk22#352
2023-01-27 14:48:54 -03:00
sk
b9a997730a move edit timelines option 2023-01-27 14:48:18 -03:00
sk
446a2f8206 clean up code 2023-01-27 14:48:15 -03:00
sk
ea4c7dc51d probably fix options menu issue
closes sk22#360
2023-01-27 14:48:12 -03:00
sk
16c0ff2f0b fix wrong status bar color
closes sk22#363
2023-01-27 14:48:09 -03:00
sk
8941c2bc1d fix double-click icon button 2023-01-27 14:48:03 -03:00
sk22
aa4a1648af Update blocks.tsv 2023-01-27 14:48:01 -03:00
sk22
5e27a43471 Adding a 12 hour option for polls (#346)
Co-authored-by: Pleclown <pleclown+github@gmail.com>

closes #346
2023-01-27 14:47:57 -03:00
sk22
12a51eb51f Translated using Weblate (German)
Currently translated at 99.1% (225 of 227 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-01-27 14:47:54 -03:00
sk
5fd17778f4 remove add media string 2023-01-27 14:47:50 -03:00
sk
a6028e06ea add a few icons 2023-01-27 14:47:45 -03:00
ihor_ck
8a0f95affe Translated using Weblate (Ukrainian)
Currently translated at 100.0% (174 of 174 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-27 14:47:23 -03:00
Linerly
1221a5622f Translated using Weblate (Indonesian)
Currently translated at 100.0% (174 of 174 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-27 14:47:18 -03:00
Choukajohn
b776b0bc1b Translated using Weblate (French)
Currently translated at 100.0% (174 of 174 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-27 14:47:13 -03:00
florian-obernberger
09bf0f2c3c Translated using Weblate (German)
Currently translated at 91.9% (160 of 174 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-01-27 14:47:08 -03:00
sheepnik
42dc6b7425 Translated using Weblate (Welsh)
Currently translated at 15.3% (2 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/cy/
2023-01-27 14:47:04 -03:00
sheepnik
1b31284a95 Translated using Weblate (Welsh)
Currently translated at 100.0% (149 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/cy/
2023-01-27 14:47:04 -03:00
gicorada
672ed86630 Translated using Weblate (Italian)
Currently translated at 100.0% (149 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/it/
2023-01-27 14:46:59 -03:00
sk
862a23af5d add a few icons 2023-01-27 14:46:53 -03:00
sk
d49733695d add back file opener
closes sk22#328
2023-01-27 14:46:49 -03:00
sk
d79c4ad650 rearrange home menus 2023-01-27 14:46:16 -03:00
Grishka
6e314f0ea5 Fix #509 2023-01-27 14:44:46 -03:00
Grishka
e5a6dc33b4 Fix #510 2023-01-27 14:44:43 -03:00
sk
8c6ac9e22b Revert "work around crash onHidden"
This reverts commit 763c5fe2a7.
2023-01-27 14:43:23 -03:00
Grishka
8d827054bf Fix #512 2023-01-27 14:42:57 -03:00
sk
55a2ae8748 fix wrong "hasSpoiler" value on restore
closes sk22#324
2023-01-27 14:42:37 -03:00
sk
55640dddb9 fix typo in string 2023-01-27 14:42:33 -03:00
sk
9a2df814c5 scroll image in alt text editor
closes sk22#315
2023-01-27 14:42:30 -03:00
sk
0fcbf02a2c notifications for edited posts
closes sk22#331
2023-01-27 14:41:54 -03:00
sk
bc9edf1f69 fix redrafting empty posts
closes sk22#325
2023-01-27 14:37:46 -03:00
sk
50baffefbe add lists to status header 2023-01-27 14:37:41 -03:00
sk
3622eba057 remove pivot for timeline title 2023-01-27 14:37:32 -03:00
sk
9df738831f work around crash onHidden
re: mastodon#512
2023-01-27 14:37:28 -03:00
sk
7939380172 different icon for post notifs 2023-01-27 14:34:04 -03:00
sk
b36b1b2a28 tweak alt button 2023-01-27 14:32:54 -03:00
sk22
b63c0010a9 Pinnable timelines (#338)
* implement draggable list

* implement pinning timelines

* fix TimelineDefinition equals not working

* implement removing timelines

* implement pinned lists/hashtags

* per-account pinned timelines

* implement pin button

* fix issues with pinning

* improve pin button

* improve pinning timelines

* implement custom icons

* fix home switcher menu

* make hashtags pinnable

* edit timelines in options menu
2023-01-27 14:32:04 -03:00
Espasant3
901f1763ab Translated using Weblate (Galician)
Currently translated at 61.5% (8 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/gl/
2023-01-27 14:29:12 -03:00
McKris
cf22096e35 Translated using Weblate (Polish)
Currently translated at 96.6% (144 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2023-01-27 14:29:12 -03:00
ghose
c96e5cde7b Translated using Weblate (Galician)
Currently translated at 100.0% (149 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-01-27 14:29:12 -03:00
Jippang
5538d5af6c Translated using Weblate (Korean)
Currently translated at 100.0% (149 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-01-27 14:29:07 -03:00
Grishka
662fbbf8b6 Fix #69 (nice) 2023-01-27 14:28:17 -03:00
LucasGGamerM
247dea3af0 Chaging string in title 2023-01-27 14:24:44 -03:00
LucasGGamerM
efff075bbc Fixing weird fab behavior on quickly jittering the main screen 2023-01-27 14:23:09 -03:00
LucasGGamerM
45832355a3 Refactoring the enableHideFab option, and increasing the threshold for the fab popping up from 400 to 800 2023-01-26 20:15:50 -03:00
FineFindus
51d4fd63db refactor(compose-fab): code cleanup 2023-01-26 20:11:08 -03:00
FineFindus
ececa7aa2f refactor(compose-fab): show fab after small scroll distance 2023-01-26 20:11:05 -03:00
tygyh
6cf8793efe Translated using Weblate (Swedish)
Currently translated at 38.4% (5 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/sv/
2023-01-26 19:53:02 -03:00
HudobniVolk
57251d58cb Translated using Weblate (Slovenian)
Currently translated at 46.1% (6 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/sl/
2023-01-26 19:53:02 -03:00
LamaEpik
cf1f8e8d1a Translated using Weblate (French)
Currently translated at 15.3% (2 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/fr/
2023-01-26 19:53:02 -03:00
Andrewblasco
c77cb14602 Translated using Weblate (Spanish)
Currently translated at 100.0% (13 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/es/
2023-01-26 19:53:02 -03:00
tygyh
de864edb33 Translated using Weblate (Swedish)
Currently translated at 31.8% (7 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/sv/
2023-01-26 19:53:02 -03:00
Andrewblasco
699925ac9b Translated using Weblate (Spanish)
Currently translated at 100.0% (22 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-01-26 19:53:02 -03:00
Kevin
e367b7711f Translated using Weblate (German)
Currently translated at 100.0% (22 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/de/
2023-01-26 19:53:02 -03:00
Kevin
b0e4f707aa Translated using Weblate (German)
Currently translated at 100.0% (13 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/de/
2023-01-26 19:53:01 -03:00
LucasGGamerM
2749ffb6f2 Reverting the other irrelevant thing. 2023-01-26 16:23:54 -03:00
LucasGGamerM
47f57bab17 Testing the hooks for weblate 2023-01-26 14:50:52 -03:00
sk
f1b0f828ac Fixing up name of the setting, and making it disabled by default 2023-01-26 14:42:10 -03:00
tygyh
afbf13ef95 Translated using Weblate (Swedish)
Currently translated at 38.4% (5 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/sv/
2023-01-26 17:12:42 +00:00
HudobniVolk
8e4cff17a5 Translated using Weblate (Slovenian)
Currently translated at 46.1% (6 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/sl/
2023-01-26 17:12:42 +00:00
LamaEpik
da954ed3fd Translated using Weblate (French)
Currently translated at 15.3% (2 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/fr/
2023-01-26 17:12:42 +00:00
Andrewblasco
9d48beaebb Translated using Weblate (Spanish)
Currently translated at 100.0% (13 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/es/
2023-01-26 17:12:42 +00:00
tygyh
e607118347 Translated using Weblate (Swedish)
Currently translated at 31.8% (7 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/sv/
2023-01-26 17:12:42 +00:00
Andrewblasco
5f6dafb763 Translated using Weblate (Spanish)
Currently translated at 100.0% (22 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-01-26 17:12:42 +00:00
Kevin
052a000d3c Translated using Weblate (German)
Currently translated at 100.0% (22 of 22 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/de/
2023-01-26 17:12:42 +00:00
Kevin
59315f81ec Translated using Weblate (German)
Currently translated at 100.0% (13 of 13 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/de/
2023-01-26 17:12:42 +00:00
LucasGGamerM
5b1188ce97 Merge pull request #55 from FineFindus/feat/profile-menu
feat(profile): move options to overflow menu
2023-01-24 18:16:50 -03:00
LucasGGamerM
c11863388d Putting stuff back to sk_ instead of mo_ on sk strings.
Relevant command: find values*/strings_sk.xml -type f -exec sed -i 's/mo_/sk_/g' {} \;
2023-01-24 17:47:12 -03:00
LucasGGamerM
476b462e86 Fixing a weird crash on the onHidden method added in a commit from upstream 2023-01-24 17:36:15 -03:00
LucasGGamerM
f69b308936 Merge pull request #54
Updated german translation
2023-01-24 17:29:59 -03:00
FineFindus
bdcafd2564 feat(profile): move options to overflow menu 2023-01-24 20:42:41 +01:00
dontobi
3455aab3ba Updated german translation 2023-01-24 11:13:02 +01:00
LucasGGamerM
aac4f412bd Finishing moving all the relevant strings to strings_mo.xml 2023-01-23 18:56:50 -03:00
LucasGGamerM
26831c3375 Updating somethings 2023-01-23 18:49:33 -03:00
LucasGGamerM
d7004824fb Decoupling moshidon strings from megalodon 2023-01-23 18:47:07 -03:00
LucasGGamerM
53d93764b0 Adding an icon and text to the hide compose button while scrolling setting 2023-01-23 17:50:07 -03:00
LucasGGamerM
6a84462b79 Adding an option for enabling/disabling the fab. Still missing an icon and text 2023-01-23 17:39:59 -03:00
Grishka
739d30c887 Save last seen home timeline post via markers API 2023-01-23 17:26:06 -03:00
Grishka
aa3aa8a5f9 Save last seen home timeline post via markers API 2023-01-23 17:20:47 -03:00
Grishka
be48719f52 remove log 2023-01-23 17:19:50 -03:00
Grishka
8e60d107fe Allow viewing alt text on images
closes #100
2023-01-23 17:19:46 -03:00
Grishka
c618feabe9 Workaround to fix #497 2023-01-23 17:19:34 -03:00
Grishka
87164dc469 Minor fixes from our boy grishka himself 2023-01-23 17:18:05 -03:00
sk
4ab1c61262 work around black screen opening notifs
closes sk22#342
2023-01-23 17:08:15 -03:00
LucasGGamerM
fe519f10a1 Failed try to fix the fabled fab problem 2023-01-22 19:41:17 -03:00
LucasGGamerM
901c7c3806 Revert "Fixing the bug of the fab reloading every time the user profile loads"
This reverts commit 211e6cdee2.
2023-01-22 19:08:24 -03:00
LucasGGamerM
211e6cdee2 Fixing the bug of the fab reloading every time the user profile loads 2023-01-22 18:36:31 -03:00
LucasGGamerM
394699c072 Fixing fab behavior on profile page when notes are selected 2023-01-22 18:26:53 -03:00
sk
c9766defff Removing the banners from the local and federated timelines 2023-01-22 18:18:14 -03:00
LucasGGamerM
737aa95bf5 Revert "Making it so the fab doesnt reappear when the notes is in edit mode"
This reverts commit 870ac2b946.
2023-01-22 15:19:52 -03:00
LucasGGamerM
38e035d792 Fixing #53 2023-01-22 13:33:45 -03:00
LucasGGamerM
4aa750c05e Update README.md
Adding a link to the official matrix chatrooom
2023-01-21 17:37:57 -03:00
LucasGGamerM
c3e5f4d254 Changelog for 87 2023-01-21 16:11:14 -03:00
LucasGGamerM
2e5ff452fd Bumping version number 2023-01-21 16:03:52 -03:00
LucasGGamerM
c397c08e40 In the process of trying to make them stack I just couldnt. So I guess this is the new release then 2023-01-21 16:02:11 -03:00
LucasGGamerM
a4d2101f54 a little less broken 2023-01-20 22:12:24 -03:00
sk
f956a17797 Experimental notifications improvement, still a long while to go 2023-01-20 22:06:42 -03:00
sk
1c1d1772a3 Adding needAppRestart to reduceMotion setting 2023-01-20 17:30:12 -03:00
sk
4db87feec4 Making sure it compiles! 2023-01-20 17:30:12 -03:00
sk
bef3c72513 fix "0" reply to ID 2023-01-20 17:30:12 -03:00
sk
4fa641b482 fix null-pointer when switching themes 2023-01-20 17:30:12 -03:00
sk
885b5d781a tweak timeline title animation 2023-01-20 17:30:12 -03:00
sk
2f3bfb3e74 fix clearing notifications
closes sk22#292
2023-01-20 17:30:12 -03:00
sk
2be625fd76 add missing draft params
closes sk22#302
2023-01-20 17:30:12 -03:00
sk
134a371263 only show new posts button at home 2023-01-20 17:30:12 -03:00
sk
8b0eddb8e1 set pivot of timeline title
closes sk22#296
2023-01-20 17:30:12 -03:00
sk
bd2d56b953 remove debug statements 2023-01-20 17:30:12 -03:00
sk
38e429f738 improve multi-line style 2023-01-20 17:30:12 -03:00
sk
de8b15d447 don't cut off multi-line strings 2023-01-20 17:30:12 -03:00
sk
0df1bcce31 fix new posts centered layout 2023-01-20 17:30:12 -03:00
sk
4e17256cfa fix centering button in rtl 2023-01-20 17:30:12 -03:00
sk
e12c3e2d68 fix rtl direction 2023-01-20 17:30:12 -03:00
sk
aec2704f15 restore current tab 2023-01-20 17:30:12 -03:00
sk
31f9173126 don't use old fragments 2023-01-20 17:30:12 -03:00
sk
90196df65d simplify method 2023-01-20 17:30:12 -03:00
sk
6b9fa71806 change crash workaround 2023-01-20 17:30:12 -03:00
sk
130085f804 Revert "work around crash theme switch"
This reverts commit 58fd0c444f30aa5352486b97cab34b2aca6ce8ab.
2023-01-20 17:30:12 -03:00
sk
f4356e74a4 add pager title transition 2023-01-20 17:30:12 -03:00
sk
9c8a4b7a8e Fixing some compile problems 2023-01-20 17:30:12 -03:00
sk22
b7ccf1144c New home layout with public timelines (#288)
* add dummy popup menu
* add pager to home fragment
* reduce pager sensitivity
* remove timelines from discover fragment
* add fabs to timelines
* change info banner color
* add back toolbar functionality
* update icons on navigate
* handle back press
* add lists and hashtags
* use tabs
* improve timeline title
* tweak switcher behavior
* fix show new posts button appearance
* hide show new posts button on reload
* tweak show new posts animations
* work around crash theme switch
* enable disabling federated timeline
Thanks @sk22!
2023-01-20 17:30:11 -03:00
sk
87d5b92a99 change crash workaround 2023-01-20 17:29:23 -03:00
LucasGGamerM
29f8260852 Merge remote-tracking branch 'origin/master' 2023-01-20 11:26:10 -03:00
LucasGGamerM
060745869b Revert "New home layout with public timelines (#288)"
This reverts commit 78d0add808.
2023-01-20 11:19:20 -03:00
LucasGGamerM
1aff3eacd8 Revert "New home layout with public timelines (#288)"
This reverts commit 0207ddb774.
2023-01-20 11:19:16 -03:00
LucasGGamerM
0207ddb774 New home layout with public timelines (#288)
* add dummy popup menu
* add pager to home fragment
* reduce pager sensitivity
* remove timelines from discover fragment
* add fabs to timelines
* change info banner color
* add back toolbar functionality
* update icons on navigate
* handle back press
* add lists and hashtags
* use tabs
* improve timeline title
* tweak switcher behavior
* fix show new posts button appearance
* hide show new posts button on reload
* tweak show new posts animations
* work around crash theme switch
* enable disabling federated timeline
2023-01-20 11:19:09 -03:00
sk22
78d0add808 New home layout with public timelines (#288)
* add dummy popup menu
* add pager to home fragment
* reduce pager sensitivity
* remove timelines from discover fragment
* add fabs to timelines
* change info banner color
* add back toolbar functionality
* update icons on navigate
* handle back press
* add lists and hashtags
* use tabs
* improve timeline title
* tweak switcher behavior
* fix show new posts button appearance
* hide show new posts button on reload
* tweak show new posts animations
* work around crash theme switch
* enable disabling federated timeline
2023-01-20 11:17:26 -03:00
LucasGGamerM
2fa042490a Revert "feat(status/footer): add tooltips to icons"
This reverts commit 707c51e4d6.
2023-01-20 11:09:16 -03:00
LucasGGamerM
885f559092 Revert "Revert "click "replying to" to scroll up""
This reverts commit 77af7ceae3.
2023-01-20 11:01:39 -03:00
sk
77af7ceae3 Revert "click "replying to" to scroll up"
This reverts commit cd0cfba7
2023-01-20 11:00:53 -03:00
sk
09d4188d54 click "replying to" to scroll up
closes #241
2023-01-20 10:59:02 -03:00
LucasGGamerM
1ad03828e3 Merge pull request #49 from dontobi/master
Update german translation
2023-01-19 20:36:22 -03:00
LucasGGamerM
870ac2b946 Making it so the fab doesnt reappear when the notes is in edit mode 2023-01-19 20:19:33 -03:00
FineFindus
394a3eebb1 feat(composeButton): hide when scrolling in profile fragment 2023-01-19 20:01:39 -03:00
FineFindus
95c10a9fea feat(composeButton): hide fab on scroll 2023-01-19 20:00:54 -03:00
dontobi
f0e14c5a13 Update german translation 2023-01-18 21:26:47 +01:00
LucasGGamerM
b79b69d961 Adding a todo 2023-01-18 15:46:15 -03:00
LucasGGamerM
5118a1fb1e Reverting TextStatusDisplayItem to master's, as I have figured out a better way to do filters 2023-01-18 15:36:22 -03:00
LucasGGamerM
18275183d0 Merge branch 'master' into feature/filters 2023-01-18 15:28:07 -03:00
LucasGGamerM
616049bff2 Fixing weird icon in the profile 2023-01-18 14:15:07 -03:00
sk
1a79bc0b61 Changing Megalodon to Moshidon in the strings.
The command I use for automating this is "find values* -type f -exec sed -i 's/Megalodon/Moshidon/g' {} \;". Run this in the resources folder and it should all be changed
2023-01-18 14:10:38 -03:00
sk
d43cbe642f disable translating scheduled posts
closes sk22#318
2023-01-18 14:07:12 -03:00
sk
77cee4c46a fix "0" reply to ID 2023-01-18 14:07:07 -03:00
sk22
0949ad1ce6 Translated using Weblate (German)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/de/
2023-01-18 14:07:00 -03:00
sk22
1e411c0c23 Translated using Weblate (German)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/de/
2023-01-18 14:07:00 -03:00
ling0412
76d306aef7 Translated using Weblate (Chinese (Simplified))
Currently translated at 97.9% (146 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-01-18 14:07:00 -03:00
sk22
7ff19ef481 Translated using Weblate (German)
Currently translated at 100.0% (149 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-01-18 14:07:00 -03:00
ihor_ck
6650bb946f Translated using Weblate (Ukrainian)
Currently translated at 100.0% (144 of 144 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-18 14:06:50 -03:00
Linerly
bbbf1683aa Translated using Weblate (Indonesian)
Currently translated at 100.0% (144 of 144 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-18 14:06:50 -03:00
Choukajohn
5cdea99eb0 Translated using Weblate (French)
Currently translated at 100.0% (144 of 144 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-18 14:06:50 -03:00
ling0412
356426b5fc Translated using Weblate (Chinese (Simplified))
Currently translated at 98.6% (142 of 144 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-01-18 14:06:49 -03:00
gicorada
7577d60f42 Translated using Weblate (Italian)
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/it/
2023-01-18 14:06:49 -03:00
ihor_ck
8c7364d57d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-18 14:06:49 -03:00
Oliebol
c0a2945378 Translated using Weblate (Dutch)
Currently translated at 93.7% (134 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/nl/
2023-01-18 14:06:49 -03:00
gicorada
1af9a71210 Translated using Weblate (Italian)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/it/
2023-01-18 14:06:48 -03:00
Choukajohn
dc859fe91c Translated using Weblate (French)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-18 14:06:42 -03:00
Nicolas_Horvath
d50c37af23 Translated using Weblate (Czech)
Currently translated at 13.9% (20 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/cs/
2023-01-18 14:06:42 -03:00
ca
00c8a03b80 Translated using Weblate (Catalan)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ca/
2023-01-18 14:06:42 -03:00
ca
d15d222b72 Translated using Weblate (Catalan)
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ca/
2023-01-18 14:06:41 -03:00
ca
34d134cb57 Translated using Weblate (Catalan)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ca/
2023-01-18 14:06:34 -03:00
EifionLlwyd
40eb3e2400 Translated using Weblate (Welsh)
Currently translated at 48.2% (69 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/cy/
2023-01-18 14:06:34 -03:00
McKris
0af45e5f56 Translated using Weblate (Polish)
Currently translated at 58.3% (7 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pl/
2023-01-18 14:06:34 -03:00
ihor_ck
82e3250623 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-18 14:06:31 -03:00
HudobniVolk
533a51fc77 Translated using Weblate (Slovenian)
Currently translated at 15.3% (22 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/sl/
2023-01-18 14:06:31 -03:00
edxkl
6fc82cf26b Translated using Weblate (Portuguese (Brazil))
Currently translated at 95.1% (136 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2023-01-18 14:06:31 -03:00
McKris
6dcfdb9735 Translated using Weblate (Polish)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2023-01-18 14:06:30 -03:00
Linerly
217d8348d4 Translated using Weblate (Indonesian)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-18 14:06:22 -03:00
ghose
9bce934944 Translated using Weblate (Galician)
Currently translated at 25.1% (36 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-01-18 14:06:21 -03:00
Choukajohn
a1ef3e1cae Translated using Weblate (French)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-18 14:06:21 -03:00
gallegonovato
978c1cfdc4 Translated using Weblate (Spanish)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-01-18 14:06:20 -03:00
ling0412
9fb9ffc269 Translated using Weblate (Chinese (Simplified))
Currently translated at 98.6% (141 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-01-18 14:06:20 -03:00
AiOO
4f357637de Translated using Weblate (Korean)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-01-18 14:06:20 -03:00
maxocito
1acd177e81 Translated using Weblate (German)
Currently translated at 100.0% (143 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-01-18 14:06:20 -03:00
ca
e4b1bf452f Translated using Weblate (Catalan)
Currently translated at 98.6% (141 of 143 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ca/
2023-01-18 14:06:20 -03:00
Anonymous
ce22cb4678 Translated using Weblate (Burmese)
Currently translated at 71.4% (100 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/my/
2023-01-18 14:06:20 -03:00
Linerly
3c45215fca Translated using Weblate (Indonesian)
Currently translated at 100.0% (140 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-18 14:06:20 -03:00
ghose
b17e63acae Translated using Weblate (Galician)
Currently translated at 10.7% (15 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-01-18 14:06:20 -03:00
mondstern
859ba5ebb9 Translated using Weblate (Czech)
Currently translated at 13.5% (19 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/cs/
2023-01-18 14:06:20 -03:00
NovaQ64
164579cbb5 Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.1% (136 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2023-01-18 14:06:20 -03:00
EifionLlwyd
990f8189e4 Translated using Weblate (Welsh)
Currently translated at 23.5% (33 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/cy/
2023-01-18 14:06:20 -03:00
ihor_ck
4d0a642fd9 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (140 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-18 14:06:16 -03:00
brenno
84b2994b99 Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.4% (135 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2023-01-18 14:06:15 -03:00
Linerly
efbca327c1 Translated using Weblate (Indonesian)
Currently translated at 88.5% (124 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-18 14:06:06 -03:00
Choukajohn
aa4b007d25 Translated using Weblate (French)
Currently translated at 100.0% (140 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-18 14:06:06 -03:00
gallegonovato
23dccef4b4 Translated using Weblate (Spanish)
Currently translated at 100.0% (140 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-01-18 14:06:06 -03:00
ling0412
1ef96ed5e6 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (140 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-01-18 14:06:06 -03:00
sk22
31e2a32233 Translated using Weblate (German)
Currently translated at 100.0% (140 of 140 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-01-18 14:06:06 -03:00
irure
168ae80743 Translated using Weblate (Basque)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/eu/
2023-01-18 14:06:06 -03:00
Hiajen
8acf23ddac Translated using Weblate (German)
Currently translated at 97.6% (122 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-01-18 14:06:05 -03:00
AiOO
eb40211582 Translated using Weblate (Korean)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-01-18 14:06:00 -03:00
irure
bf35161c9f Translated using Weblate (Basque)
Currently translated at 93.6% (117 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/eu/
2023-01-18 14:05:59 -03:00
Linerly
456c50f69e Translated using Weblate (Indonesian)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-18 14:05:44 -03:00
Choukajohn
587212cf46 Translated using Weblate (French)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-18 14:05:44 -03:00
AiOO
fe800a259d Translated using Weblate (Korean)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-01-18 14:05:44 -03:00
Linerly
c193741013 Translated using Weblate (Indonesian)
Currently translated at 100.0% (124 of 124 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-18 14:05:39 -03:00
Choukajohn
a7b752264f Translated using Weblate (French)
Currently translated at 100.0% (124 of 124 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-18 14:05:31 -03:00
AiOO
9075027f69 Translated using Weblate (Korean)
Currently translated at 100.0% (124 of 124 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-01-18 14:05:25 -03:00
EifionLlwyd
28faf4277a Added translation using Weblate (Welsh) 2023-01-18 14:04:53 -03:00
irure
120ab8ca54 Translated using Weblate (Basque)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/eu/
2023-01-18 14:04:53 -03:00
AiOO
a3fc1a6a74 Translated using Weblate (Korean)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-01-18 14:04:51 -03:00
irure
ec1fe07fea Translated using Weblate (Basque)
Currently translated at 93.6% (117 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/eu/
2023-01-18 14:04:51 -03:00
mondstern
e3d054ae3e Translated using Weblate (Hungarian)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/hu/
2023-01-18 14:04:51 -03:00
edxkl
795d4b0801 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pt_BR/
2023-01-18 14:04:51 -03:00
khant
0cf0f07f2d Translated using Weblate (Burmese)
Currently translated at 16.6% (2 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/my/
2023-01-18 14:04:51 -03:00
AiOO
2cc5872ec7 Translated using Weblate (Korean)
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ko/
2023-01-18 14:04:51 -03:00
HitaloM
6a151e00ac Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pt_BR/
2023-01-18 14:04:47 -03:00
ling0412
1e99862d40 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/zh_Hans/
2023-01-18 14:04:41 -03:00
khant
3a1b12306b Translated using Weblate (Burmese)
Currently translated at 80.0% (100 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/my/
2023-01-18 14:04:31 -03:00
ihor_ck
e31db6d506 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-18 14:04:31 -03:00
edxkl
b22c0a5d3d Translated using Weblate (Portuguese (Brazil))
Currently translated at 84.0% (105 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2023-01-18 14:04:31 -03:00
Linerly
e7d856acf4 Translated using Weblate (Indonesian)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-18 14:04:31 -03:00
Choukajohn
ee8b087b61 Translated using Weblate (French)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-18 14:04:31 -03:00
gallegonovato
4e86314df5 Translated using Weblate (Spanish)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-01-18 14:04:31 -03:00
ling0412
cf5fbe3b55 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-01-18 14:04:31 -03:00
AiOO
952416fefc Translated using Weblate (Korean)
Currently translated at 100.0% (125 of 125 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-01-18 14:04:31 -03:00
AiOO
1645ce4486 Translated using Weblate (Korean)
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ko/
2023-01-18 14:04:30 -03:00
Linerly
2bde95b4d2 Translated using Weblate (Indonesian)
Currently translated at 100.0% (124 of 124 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-18 14:04:21 -03:00
Choukajohn
2de003c5bb Translated using Weblate (French)
Currently translated at 100.0% (124 of 124 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-18 14:04:21 -03:00
AiOO
a04e16c572 Translated using Weblate (Korean)
Currently translated at 100.0% (124 of 124 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2023-01-18 14:04:21 -03:00
sk
eb41d77d54 implement soft-blocking
sk22#297
2023-01-18 14:03:36 -03:00
sk
9325590319 change search placeholder string 2023-01-18 14:03:15 -03:00
sk
d32a57a18d fix akkoma link previews not showing
closes sk22#183
2023-01-18 14:02:53 -03:00
sk
13b5462f63 fix images not loading on akkoma
closes sk22#25
2023-01-18 14:02:50 -03:00
sk
480d4ad904 make announcements selectable
closes sk22#275
2023-01-18 14:02:23 -03:00
sk
7fa52247e8 display unread announcements first
closes sk22#274
2023-01-18 14:02:20 -03:00
sk
5a547015e6 include list title in delete prompt
closes sk22#304
2023-01-18 14:02:11 -03:00
LucasGGamerM
513736f765 Fixing duplicate settings item 2023-01-18 14:02:04 -03:00
sk
c6164b1bcd display image cache size
closes sk22#301
2023-01-18 14:00:15 -03:00
sk
87342782d7 fix clearing notifications
closes sk22#292
2023-01-18 13:58:03 -03:00
sk
a4b18de72c add missing draft params
closes sk22#302
2023-01-18 13:57:59 -03:00
sk
3064b549cd fix cut off text
closes sk22#295
2023-01-18 13:57:50 -03:00
sk
6666f82329 don't require unused fields 2023-01-18 13:55:49 -03:00
Grishka
ad87efa7e2 Fix #484 2023-01-18 13:55:34 -03:00
Grishka
d06cf1bb1e Paginate trending posts 2023-01-18 13:55:29 -03:00
sk
096aa23f69 don't use person icon for unblock
close #245
2023-01-18 13:54:25 -03:00
Grishka
2464042329 Fix #499 2023-01-18 13:54:06 -03:00
sk
928b04eda6 tweak list decoration
closes sk22#273
2023-01-18 13:54:03 -03:00
sk
a31e33415e fix edit user lists always visible
closes sk22#272
2023-01-18 13:53:59 -03:00
Grishka
87ce6b8bb1 Fix #498 2023-01-18 13:53:45 -03:00
sk
bb08d6585c disable more button when read
closes #262
2023-01-18 13:53:33 -03:00
sk
94fa1133fd fix editing sensitive option
closes sk22#260
2023-01-18 13:52:58 -03:00
sk
83822b8f69 add more domains 2023-01-18 13:52:50 -03:00
sk
9f3bd186ba improve domain check logic 2023-01-18 13:52:46 -03:00
sk
58cb338cb2 add missing icons to popup 2023-01-18 13:52:16 -03:00
sk
6f447909eb add dividers to lists 2023-01-18 13:52:11 -03:00
sk
af953e294d move lists and change icons 2023-01-18 13:51:39 -03:00
LucasGGamerM
7504a1b9cb Revert "move lists and change icons"
This reverts commit 3842ecb0d1.
2023-01-18 13:47:29 -03:00
LucasGGamerM
60ee781004 Revert "Revert "move lists and change icons""
This reverts commit 4b88ce5115.
2023-01-18 13:47:29 -03:00
LucasGGamerM
4b88ce5115 Revert "move lists and change icons"
This reverts commit d0ad5561
2023-01-18 13:45:41 -03:00
sk
3842ecb0d1 move lists and change icons 2023-01-18 13:44:30 -03:00
sk
3713063ce3 implement editing lists
re: sk22#30
2023-01-18 13:35:26 -03:00
sk
83b089457e implement deleting lists
re: sk22#30
2023-01-18 13:34:54 -03:00
sk
ed9813f093 implement creating lists
re: sk22#30
2023-01-18 13:34:34 -03:00
sk
e45f3f30f3 change lists string 2023-01-18 13:33:02 -03:00
sk
df44d4cc4f don't overwrite notifications
re: sk22#219
2023-01-18 13:32:58 -03:00
sk
b666048603 add missing margin 2023-01-18 13:29:48 -03:00
FineFindus
153542e1b4 feat(settings): add about instance link (#263) 2023-01-18 13:29:45 -03:00
Tyler Saunders
57e0b96f36 Update ComposeFragment to use the photopicker.
The android platform has a great photopicker, and this change checks
for the current device's sdk version, and uses the photopicker if it's
available on the device.

For pre Android R sdkrev2 devices, the experience remains unchanged.
2023-01-18 13:27:08 -03:00
mishnz
ff65d150e3 serverKey assignment was missing, corrected. 2023-01-18 13:23:23 -03:00
mishnz
88474ba826 Second fix for MIME64 inconsistency in serverKey.
The previous fix https://github.com/mastodon/mastodon-android/pull/486 would break any connections to any instances using WEB_SAFE MIME64 encoding on the serverKey, which actually appears to be the usual case.
This update reverts to the previous logic, but also converts standard MIME64 characters ('/' and '+') to their WEB_SAFE equivalents.
This ensures the standard case of WEB_SAFE BASE64 serverKeys and the anomolous case of DEFAULT BASE64 keys both work.
2023-01-18 13:23:17 -03:00
mishnz
dd92f1b66f The Mastodon server does not currently use URL_SAFE encoding on its serverKey. Using URL_SAFE in this client means the client will crash for any server that uses a key that generates a Mime64 string containing a "+" or "/". This change removes the URL_SAFE logic. See: https://github.com/mastodon/mastodon-android/issues/483 2023-01-18 13:23:10 -03:00
LucasGGamerM
7c7f3cc42a Properly Fixing the bot icon at the end of the username on the header of posts. 2023-01-17 22:26:54 -03:00
LucasGGamerM
734a8049a5 Taking the notes out of the about section until further notice 2023-01-17 21:38:01 -03:00
LucasGGamerM
417faa66f9 Deleting some old stuff 2023-01-17 21:35:58 -03:00
LucasGGamerM
7223a13d08 Editing the padding so that text doesnt go below the button to save 2023-01-17 21:29:51 -03:00
LucasGGamerM
a55002da0c Messing a bit with the colors, I think I like this one 2023-01-17 21:26:44 -03:00
LucasGGamerM
ce89733f2d Making the notes thing more beautiful, and also saves when back button is pressed. i love this. Try it later @FineFindus! 2023-01-17 21:12:04 -03:00
LucasGGamerM
18811ec32a Adding a bigger margin for consistency 2023-01-17 20:42:02 -03:00
LucasGGamerM
e65e6163ba Successfully putting it back where it was. Still need to add a toggle for it 2023-01-16 21:32:54 -03:00
LucasGGamerM
9c3db24d2f Little improvement on the note field 2023-01-16 21:10:06 -03:00
LucasGGamerM
19abbe199b Fixing the Bot icon. Look at how gorgeous this is @FineFindus! 2023-01-16 20:57:05 -03:00
LucasGGamerM
b33003f7b0 Merge pull request #46
Feat/private notes
2023-01-16 20:24:53 -03:00
LucasGGamerM
9a5747efc8 Revert "Fixing it"
This reverts commit 1a075e32de.
2023-01-16 15:26:27 -03:00
LucasGGamerM
980503ed57 Merge remote-tracking branch 'origin/master' 2023-01-16 14:49:59 -03:00
LucasGGamerM
c2dd858de8 Merge pull request #47
refactor(settings): reorder settings
2023-01-16 14:49:53 -03:00
LucasGGamerM
d2ef6fb567 Merge remote-tracking branch 'origin/master' 2023-01-16 14:48:34 -03:00
LucasGGamerM
9c996b3568 Merge pull request #45 from FineFindus/feat/tooltips
feat(status/footer): add tooltips to icons
2023-01-16 14:48:26 -03:00
FineFindus
2387d84bc0 fix(settings): reorder settings 2023-01-14 22:48:03 +01:00
FineFindus
3bd69b5447 fix(note/confirm): animation not displaying 2023-01-14 14:58:31 +01:00
FineFindus
71f6311598 merge: update to latest master 2023-01-14 12:51:29 +01:00
FineFindus
e808977717 refactor(profile/note): rephrase confirm tooltip 2023-01-14 12:50:06 +01:00
FineFindus
8594e34bb5 refactor(profile/note): move note in about tab 2023-01-14 12:46:40 +01:00
FineFindus
4591f06d63 refactor(profile/note): rework edit text hint 2023-01-14 12:44:57 +01:00
FineFindus
b9c3143c6f feat(profile/note): increase animation duration 2023-01-14 11:01:29 +01:00
FineFindus
adefb0e567 feat(profile/note): add fade animation to confirm icon 2023-01-13 23:46:58 +01:00
FineFindus
5a8fed3c06 feat(profile/note): add toast on save failure 2023-01-13 23:41:57 +01:00
FineFindus
2c1b8da475 feat(profile): add private notes textfield 2023-01-13 23:38:40 +01:00
FineFindus
707c51e4d6 feat(status/footer): add tooltips to icons 2023-01-12 19:32:30 +01:00
LucasGGamerM
1a075e32de Fixing it 2023-01-11 20:10:14 -03:00
LucasGGamerM
73869b6ea2 86 changelog 2023-01-11 11:28:29 -03:00
LucasGGamerM
3980329112 Merge remote-tracking branch 'origin/master' 2023-01-11 11:26:21 -03:00
LucasGGamerM
6107b21d3b Merge pull request #43
Update german translation
2023-01-11 11:26:14 -03:00
LucasGGamerM
42a0b881af Bumping version number 2023-01-11 11:23:00 -03:00
LucasGGamerM
2076818220 Now its fixed for good. That was easier than I thought 2023-01-11 11:19:30 -03:00
Tobias S
513bea7959 Merge branch 'LucasGGamerM:master' into master 2023-01-11 05:52:06 +01:00
LucasGGamerM
a48dc18df5 Possibly fixing #29 for good, but the mastodon servers of the accounts I own are slow, so there is basically no way to test it 2023-01-10 21:45:35 -03:00
dontobi
c55639e966 Update german translation 2023-01-10 17:28:26 +01:00
Tobias S
1fc89d7448 Merge branch 'LucasGGamerM:master' into master 2023-01-10 17:20:37 +01:00
LucasGGamerM
4fcc07fcd6 Adding a margin to the char counter when its on the top 2023-01-10 12:24:01 -03:00
LucasGGamerM
b50b1c33da Renaming custom login fragment to custom welcome fragment 2023-01-10 12:11:11 -03:00
LucasGGamerM
25460191b0 Merge pull request #44
feat(compose): move charCounter to action bar if relocatePublishButto…
2023-01-10 12:09:44 -03:00
FineFindus
1206ce6efc feat(compose): move charCounter to action bar if relocatePublishButton is enabled 2023-01-10 15:43:26 +01:00
sk
3cdcffe03d implement announcements
closes #127
2023-01-10 11:16:14 -03:00
sk
b09aab4a1d don't connect to fascists 2023-01-10 11:13:30 -03:00
sk
d27fe4ebd1 tweak header text margin 2023-01-10 11:13:27 -03:00
sk
ab2cee08fe hide keyboard when navigating
closes #227
2023-01-10 11:13:14 -03:00
sk
1fa42fd20f scale text according to system
closes #244
2023-01-10 11:13:04 -03:00
sk
e343131670 fix wrong pin icon
closes #230
2023-01-10 11:11:32 -03:00
sk
f157313d9a click "replying to" to scroll up
closes #241
2023-01-10 11:11:28 -03:00
sk
9bd4433942 tweak reply animation
closes #237
2023-01-10 11:08:56 -03:00
sk
c9cc8e23c1 don't add subject if blank
closes #240
2023-01-10 11:08:53 -03:00
Thiago 'Jedi' Abreu
786dbaf92c Filter all status, even if filters are empty (#255) 2023-01-10 11:08:40 -03:00
mishnz
8dd22e1853 serverKey assignment was missing, corrected. 2023-01-10 11:08:33 -03:00
mishnz
34a4dd6d1f Second fix for MIME64 inconsistency in serverKey.
The previous fix https://github.com/mastodon/mastodon-android/pull/486 would break any connections to any instances using WEB_SAFE MIME64 encoding on the serverKey, which actually appears to be the usual case.
This update reverts to the previous logic, but also converts standard MIME64 characters ('/' and '+') to their WEB_SAFE equivalents.
This ensures the standard case of WEB_SAFE BASE64 serverKeys and the anomolous case of DEFAULT BASE64 keys both work.
2023-01-10 11:08:27 -03:00
mishnz
6e13e592d0 The Mastodon server does not currently use URL_SAFE encoding on its serverKey. Using URL_SAFE in this client means the client will crash for any server that uses a key that generates a Mime64 string containing a "+" or "/". This change removes the URL_SAFE logic. See: https://github.com/mastodon/mastodon-android/issues/483 2023-01-10 11:08:20 -03:00
Tobias S
485ab4ee22 Update german translation 2023-01-10 10:09:11 +01:00
dontobi
59a8d1d462 Update german translation 2023-01-10 06:24:10 +01:00
LucasGGamerM
f4e5baf94d Merge pull request #41
feat(accessibility) add missing toolTipTexts and contentDescriptions
2023-01-09 18:32:21 -03:00
FineFindus
a782160dd3 refactor: use getContentDescription instead of duplicate code 2023-01-09 21:30:52 +01:00
FineFindus
871c17cbe2 merge: update to latest master 2023-01-09 21:18:43 +01:00
FineFindus
047e72ce9c refactor(compose): use UiUtils.getVisibiltyText 2023-01-09 21:05:58 +01:00
FineFindus
6c1424055f feat(StatusDisplay): add toolTip/ContentDescription to visibilty icon 2023-01-09 21:02:00 +01:00
FineFindus
369902ffe5 feat(compose): add toolTip/ContentDescription to error icon 2023-01-09 20:19:29 +01:00
LucasGGamerM
6c778d05ea Its half working++ 2023-01-09 16:16:38 -03:00
FineFindus
747439999d feat(profile): add toolTip/ContentDescription to fab 2023-01-09 19:23:38 +01:00
FineFindus
4d836f8032 feat(instanceCategory): set (unused) emoji importantForAccessibility to no 2023-01-09 19:21:54 +01:00
FineFindus
f97ab73c5d feat(reportChoice): set radioIcon importantForAccessibility to no 2023-01-09 19:21:20 +01:00
FineFindus
147fb94442 feat(settingsItem): set icon to not importantForAccessibility 2023-01-09 19:20:07 +01:00
FineFindus
975dc94d41 feat(settingsThemeItem): hide image for accessibility 2023-01-09 19:12:19 +01:00
FineFindus
a5c1053c58 feat(recycler_fragment_with_fab): add toolTip/ContentDescription 2023-01-09 17:46:27 +01:00
FineFindus
1bfbb4bf38 fix(composeMedia): change sk_remove_attachment to delete 2023-01-09 17:42:01 +01:00
FineFindus
c2950ace90 feat(tabBar): accessibilty hide profile avatar
Sets the `importantForAccessibility` to no on the profile avatar, since the parent already has a contentDescription.
2023-01-09 17:36:04 +01:00
FineFindus
f0846465c2 feat(accessibility): add contentDesc/toolTip to remove attachment 2023-01-09 17:22:54 +01:00
FineFindus
ddc4512116 feat(accessibility): add contentDesc/toolTip to poll options 2023-01-09 17:22:33 +01:00
FineFindus
1c9e4fe561 feat(accessibility): add contentDesc/toolTip to poll options 2023-01-09 17:21:38 +01:00
FineFindus
35299a7b3f feat(accessibility): add contentDesc and toolTip to audioItem 2023-01-09 17:19:20 +01:00
LucasGGamerM
2d9938e8b2 Its half working 2023-01-08 21:31:01 -03:00
LucasGGamerM
1e99940c1d I have figured out something, I dont know what it is though 2023-01-08 21:01:59 -03:00
LucasGGamerM
2827bcffe3 Merge branch 'master' into feature/filters 2023-01-08 20:56:22 -03:00
LucasGGamerM
3a1b71e95c Adding a small little different icon for when the toot has replies. Thanks @sk22 2023-01-08 20:55:41 -03:00
LucasGGamerM
ce4e762cd5 Trying my best to make this work 2023-01-07 21:29:03 -03:00
LucasGGamerM
54ec1a6cf7 Merge pull request #38
Update german translation
2023-01-07 20:46:23 -03:00
FineFindus
bed3e987b7 feat(compose/poll): add contentDescription to addPoll 2023-01-07 11:38:00 +01:00
Tobias S
639ddb3f80 Update german translation 2023-01-06 19:43:28 +01:00
LucasGGamerM
e645abb771 Merge pull request #35
Update german translation
2023-01-06 14:51:00 -03:00
LucasGGamerM
762adce054 Merge branch 'bugfix/#29' 2023-01-06 14:47:37 -03:00
LucasGGamerM
263bde658e Fixing #29 for good 2023-01-06 14:47:06 -03:00
Florian Obernberger
3951acf12e Add new and custom icon
(cherry picked from commit 13a80fb536)
2023-01-06 14:43:17 -03:00
LucasGGamerM
5cb640a387 Merge pull request #36
Add new and custom icon
2023-01-06 14:42:46 -03:00
FineFindus
c65b9ff873 fix: remove change 2023-01-06 18:40:28 +01:00
Florian Obernberger
13a80fb536 Add new and custom icon 2023-01-06 18:12:42 +01:00
LucasGGamerM
23e49c52e5 Its working, but it still needs a better icon 2023-01-06 12:26:52 -03:00
Tobias S
9fcc73984b Merge branch 'LucasGGamerM:master' into master 2023-01-06 15:51:29 +01:00
LucasGGamerM
67338b6c85 Allowing multiple notifications by default 2023-01-06 11:31:25 -03:00
LucasGGamerM
101e7efd74 Fixing #34 2023-01-06 11:18:51 -03:00
Tobias S
a996a24b7f Update german translation 2023-01-06 06:22:25 +01:00
Tobias S
44dcc9fe2b Merge branch 'LucasGGamerM:master' into master 2023-01-06 06:20:35 +01:00
LucasGGamerM
58f79e06ef Idk what these are, but testing commits 2023-01-05 21:16:03 -03:00
FineFindus
f197c8201d merge: update to newest master 2023-01-05 19:45:03 +01:00
dontobi
2fc5669203 Update german translation 2023-01-05 18:53:12 +01:00
LucasGGamerM
0065b93060 Adding 85 changelog 2023-01-05 13:44:24 -03:00
LucasGGamerM
3f9dbd6fe2 Bump version number 2023-01-05 13:39:53 -03:00
LucasGGamerM
7ceff3eaa4 Fixing #28 2023-01-05 13:24:09 -03:00
FineFindus
7cdddf06bc feat(compose/add-poll): add contentLabel for more option 2023-01-05 16:24:44 +01:00
LucasGGamerM
77e7b136ff Changing megalodon to moshidon 2023-01-05 12:23:20 -03:00
LucasGGamerM
c8d160fc35 Changing too to post. Fixing #26 2023-01-05 12:19:13 -03:00
LucasGGamerM
ee0737c9c7 Adding the ability to long click or to double click the search icon to bring up the keyboard 2023-01-04 21:54:03 -03:00
LucasGGamerM
0f85be7114 Merge branch 'feature/long_press_discover' 2023-01-04 21:33:19 -03:00
LucasGGamerM
34ba4ceb16 Fixing #31 2023-01-04 21:28:06 -03:00
LucasGGamerM
f2a536d0ea Fixing #31 2023-01-04 18:30:12 -03:00
LucasGGamerM
815c4d4cc9 Merge pull request #32
feat: share links
2023-01-04 18:20:29 -03:00
LucasGGamerM
969b91bba9 Merging stuff and adding more icons 2023-01-04 18:18:58 -03:00
LucasGGamerM
f24abde76e Merge pull request #30
feat(profile/bot-icon): prepend icon to username
2023-01-04 18:04:41 -03:00
LucasGGamerM
f486b1a9ce Merge pull request #24
Feat/favourite animation
2023-01-04 17:59:12 -03:00
LucasGGamerM
3dd6638ef3 Merge pull request #25
German translation - suggested by FineFindus
2023-01-04 17:58:37 -03:00
FineFindus
bcfb63b57c feat(linkSpan/longClick): use share intent istead of copy text 2023-01-04 20:53:30 +01:00
FineFindus
c7f5f6827a refactor(drawables/botIcon): decrease size and change color 2023-01-04 17:25:30 +01:00
FineFindus
8ed88b2b29 refactor(HeaderStatusDisplayItem): add bot icon to username 2023-01-04 17:24:53 +01:00
FineFindus
75db9f4623 refactor(profile/botIcon): move icon to username 2023-01-04 17:24:09 +01:00
LucasGGamerM
b69015a25a Its closer to working 2023-01-03 15:18:34 -03:00
LucasGGamerM
1cdcc8794c Maybe it will work one day? 2023-01-03 11:21:30 -03:00
LucasGGamerM
a0c26b748a It already works, although not to my standard yet 2023-01-03 11:10:53 -03:00
FineFindus
ce5e733c05 fix(drawable/bot): remove unused icons 2023-01-03 14:18:18 +01:00
FineFindus
de485272c5 feat(profile/bot): add bot icon before name 2023-01-03 13:53:04 +01:00
FineFindus
eab53b805e feat(drawable) add filled bot icon 2023-01-03 13:52:09 +01:00
dontobi
a60046f6ef German translation - suggested by FineFindus 2023-01-02 22:15:00 +01:00
FineFindus
b0d223c47c Merge branch 'master' of https://github.com/LucasGGamerM/moshidon into feat/favourite-animation 2023-01-02 21:59:39 +01:00
FineFindus
185a8c776b feat(StatusDisplayItem/favouriteIcon): add spin animation when clicked 2023-01-02 21:57:19 +01:00
LucasGGamerM
f510ee3b4d Merge pull request #23
Update german translation
2023-01-02 17:56:59 -03:00
dontobi
e7a29824e8 Update german translation 2023-01-02 21:54:35 +01:00
LucasGGamerM
69b86dd98c Merge pull request #21
feat(compose/emoji) add a recent category to the emoji keyboard
2023-01-02 17:48:39 -03:00
LucasGGamerM
55807dc7c6 Merge pull request #22
small update of the german translation
2023-01-02 17:45:43 -03:00
dontobi
9a6ee719c4 small update of the german translation 2023-01-02 20:57:23 +01:00
FineFindus
1b02af382c fix(emoji/recent): remove unused imports 2023-01-02 19:43:30 +01:00
FineFindus
4fe87a9888 merge: merge newest upstream/master 2023-01-02 19:42:42 +01:00
LucasGGamerM
91995155e9 Updating 84 changelog 2023-01-02 13:47:42 -03:00
LucasGGamerM
aae0ff5aa7 Fixing the bug with the german translation 2023-01-02 13:42:45 -03:00
LucasGGamerM
821d9b8a5e 84 changelog 2023-01-02 13:41:51 -03:00
LucasGGamerM
2070aed38f Bumping version number 2023-01-02 13:40:03 -03:00
LucasGGamerM
986979eefc Merge remote-tracking branch 'origin/master' 2023-01-02 13:38:59 -03:00
LucasGGamerM
ed3ce54b24 Merge pull request #20
German translation
2023-01-02 13:38:52 -03:00
LucasGGamerM
c80ebf2eda Fixing the login error 2023-01-02 13:38:29 -03:00
FineFindus
42fcd6df51 refactor(emoji/recent): rename NEW_RECENT to NEW_RECENT_VALUE 2023-01-02 16:58:31 +01:00
LucasGGamerM
1f4031da61 Editing the 83 changelog once more 2023-01-02 12:53:39 -03:00
Tobias S
d0ebee74ca Merge branch 'LucasGGamerM:master' into master 2023-01-02 16:52:51 +01:00
Tobias S
e8ec042d96 German translation 2023-01-02 16:52:11 +01:00
LucasGGamerM
bd61bf32b6 Changing the 83 changelog 2023-01-02 12:49:17 -03:00
FineFindus
8b12fac766 feat(emoji/recent): add clear recent emoji setting 2023-01-02 16:47:41 +01:00
LucasGGamerM
ab7e6b3332 Bump version number 2023-01-02 12:45:27 -03:00
LucasGGamerM
548da48615 Adding 83 changelog 2023-01-02 12:44:57 -03:00
FineFindus
0b6128bcdd feat(compose/emojis): add category of recent emojis 2023-01-02 16:44:14 +01:00
LucasGGamerM
198a7d5ad3 Merge pull request #18
feat(compose/publish): Add warning dialog when no image description is provided
2023-01-02 12:33:10 -03:00
LucasGGamerM
040f244e15 Fixing up the bot icon for good 2023-01-02 12:28:07 -03:00
LucasGGamerM
98bc6f14a9 Fixing some icons again 2023-01-02 12:14:27 -03:00
LucasGGamerM
b92e6d2c48 Fixing some icons 2023-01-02 12:12:55 -03:00
LucasGGamerM
ac3875fe08 Fixing #19 2023-01-02 11:46:15 -03:00
FineFindus
6fdbafc67b fix(compose/publish): remove unnecessary import 2023-01-02 12:57:18 +01:00
FineFindus
5aebdcaa6a feat(compose/publish): add warning when no image description provided 2023-01-02 12:53:34 +01:00
LucasGGamerM
2969a3e4fd Including @FineFindus on the changelog 2023-01-01 19:41:42 -03:00
LucasGGamerM
e1fcf44aa6 Adding more stuff onto the changelog 2023-01-01 19:28:26 -03:00
LucasGGamerM
ddbfe9de57 Changelog for 82 and updating screenshots 2023-01-01 19:25:17 -03:00
LucasGGamerM
b2ee1527af Bump version number 2023-01-01 19:17:40 -03:00
LucasGGamerM
c94706745f Merge pull request #17
German translation
2023-01-01 19:13:13 -03:00
LucasGGamerM
8aef61ff09 Second iteration of the bot icon 2023-01-01 19:12:29 -03:00
Tobias S
5d6e245ec2 Merge branch 'LucasGGamerM:master' into master 2023-01-01 22:13:11 +01:00
dontobi
8dd4d1a41d German translation 2023-01-01 22:12:36 +01:00
LucasGGamerM
10f9230139 First iteration of the bot account tag 2023-01-01 18:06:26 -03:00
LucasGGamerM
32c94c8948 Merge remote-tracking branch 'origin/master' 2023-01-01 17:24:23 -03:00
LucasGGamerM
4b947dd1f9 Merge pull request #16
feat(profile) add icon to bot accounts
2023-01-01 17:24:06 -03:00
LucasGGamerM
93a7d86f78 Merge branch 'development'
# Conflicts:
#	mastodon/src/main/res/values-de-rDE/strings_sk.xml
2023-01-01 17:21:32 -03:00
LucasGGamerM
6ed3a57c58 Rebranding Megalodon to Moshidon.
Here is the command in case anyone is interested
find values* -type f -exec sed -i 's/Megalodon/Moshidon/g' {} \;
2023-01-01 17:16:45 -03:00
LucasGGamerM
ecdba3898f Merge pull request #15
German translation fix
2023-01-01 17:14:36 -03:00
LucasGGamerM
d82a9b25cf Revert "Revert "match navigation bar color with toolbar""
This reverts commit 0fdae0c775.
2023-01-01 17:12:29 -03:00
LucasGGamerM
da4849e526 Removing unnecessary needAppRestart on the relocatePublishButton setting 2023-01-01 17:11:33 -03:00
LucasGGamerM
da1b47ea0d Adds a whole lot of icons for the relocated publish button 2023-01-01 17:09:49 -03:00
LucasGGamerM
a617693f93 Add a drafts icon on the relocated publish button 2023-01-01 16:53:31 -03:00
LucasGGamerM
f4c573a95e Readding the relocated publish button 2023-01-01 16:28:04 -03:00
LucasGGamerM
d3476c1473 Deleting metadata 2023-01-01 10:49:48 -03:00
LucasGGamerM
d58247d996 Editing the padding and making the 3 dot menu invisible 2023-01-01 10:49:34 -03:00
LucasGGamerM
ee441d5b4a Glory! it finally works! 2022-12-31 21:46:37 -03:00
LucasGGamerM
97a5c6f5cb Bringing back the verify for updates button 2022-12-31 21:27:12 -03:00
LucasGGamerM
b6566a2bcc It works now? 2022-12-31 21:23:50 -03:00
LucasGGamerM
af389f7a47 Its as broken as it was before 2022-12-31 20:35:29 -03:00
LucasGGamerM
45577fc423 The settings page is unfucked again 2022-12-31 20:24:14 -03:00
sk
c00b9b3035 fix empty space when no text 2022-12-31 20:05:12 -03:00
sk
f17879783c tweak scroll height/timing 2022-12-31 20:05:08 -03:00
sk
08dfcdf508 Revert "match navigation bar color with toolbar"
This reverts commit 43d334259b.
2022-12-31 20:05:03 -03:00
sk
c97e8fffc4 add option to reduce motion 2022-12-31 20:04:53 -03:00
sk
120585954f peek original post before scrolling 2022-12-31 20:00:12 -03:00
sk
247669644c display original post when replying
closes sk22#193
2022-12-31 20:00:05 -03:00
sk
ff15bdeaea change interact with strings 2022-12-31 20:00:02 -03:00
ihor_ck
8b67320e20 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/uk/
2022-12-31 19:59:00 -03:00
gallegonovato
48828ed1b7 Translated using Weblate (Spanish)
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/es/
2022-12-31 19:58:53 -03:00
Linerly
1e615db77e Translated using Weblate (Indonesian)
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/id/
2022-12-31 19:58:47 -03:00
Choukajohn
629416ef2f Translated using Weblate (French)
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/fr/
2022-12-31 19:58:40 -03:00
ihor_ck
d6b1c88085 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (121 of 121 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2022-12-31 19:58:34 -03:00
Linerly
3b7079be17 Translated using Weblate (Indonesian)
Currently translated at 100.0% (121 of 121 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-31 19:58:34 -03:00
Choukajohn
48d26017b6 Translated using Weblate (French)
Currently translated at 100.0% (121 of 121 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-31 19:58:34 -03:00
gallegonovato
8bdbe1c4d7 Translated using Weblate (Spanish)
Currently translated at 100.0% (121 of 121 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-31 19:58:33 -03:00
bubblineyuri
4093443bf8 Translated using Weblate (German)
Currently translated at 100.0% (12 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/de/
2022-12-31 19:58:32 -03:00
bubblineyuri
c6709aba56 Translated using Weblate (German)
Currently translated at 100.0% (121 of 121 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-31 19:58:24 -03:00
ihor_ck
a817e03fa0 Translated using Weblate (Ukrainian)
Currently translated at 96.6% (115 of 119 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2022-12-31 19:58:08 -03:00
Linerly
a757607f35 Translated using Weblate (Indonesian)
Currently translated at 100.0% (119 of 119 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-31 19:58:07 -03:00
ling0412
ecc9c45f6e Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (119 of 119 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2022-12-31 19:58:07 -03:00
irure
2e157a9e68 Translated using Weblate (Basque)
Currently translated at 18.1% (2 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/eu/
2022-12-31 19:58:07 -03:00
AiOO
8a39154bd3 Translated using Weblate (Korean)
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ko/
2022-12-31 19:58:06 -03:00
nkufideal
b5e2aa8b7f Translated using Weblate (Russian)
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ru/
2022-12-31 19:58:05 -03:00
nkufideal
aaea709201 Translated using Weblate (Russian)
Currently translated at 100.0% (102 of 102 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2022-12-31 19:57:56 -03:00
itslameni
c2a0f5e8bc Translated using Weblate (Russian)
Currently translated at 100.0% (102 of 102 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2022-12-31 19:57:56 -03:00
edxkl
2873a66450 Translated using Weblate (Portuguese (Brazil))
Currently translated at 80.3% (82 of 102 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2022-12-31 19:57:54 -03:00
irure
7331a5a0cd Translated using Weblate (Basque)
Currently translated at 100.0% (102 of 102 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/eu/
2022-12-31 19:57:41 -03:00
AiOO
c331cc95c2 Translated using Weblate (Korean)
Currently translated at 100.0% (102 of 102 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2022-12-31 19:57:41 -03:00
edxkl
91aa425f43 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pt_BR/
2022-12-31 19:57:40 -03:00
ihor_ck
fd5165428e Translated using Weblate (Ukrainian)
Currently translated at 100.0% (102 of 102 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2022-12-31 19:57:40 -03:00
Linerly
6df57aebf4 Translated using Weblate (Indonesian)
Currently translated at 100.0% (102 of 102 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-31 19:57:40 -03:00
Choukajohn
40b2e4c42e Translated using Weblate (French)
Currently translated at 100.0% (102 of 102 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-31 19:57:40 -03:00
gallegonovato
a762408df8 Translated using Weblate (Spanish)
Currently translated at 100.0% (102 of 102 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-31 19:57:40 -03:00
ling0412
9fb6a0261b Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (102 of 102 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2022-12-31 19:57:40 -03:00
sk
d90edc8cf1 add compose fab to drafts list 2022-12-31 19:57:29 -03:00
sk
eecc1242be handle recursive compose/drafts list 2022-12-31 19:57:25 -03:00
sk
6eedb0e156 move and refine scheduling and drafting 2022-12-31 19:57:22 -03:00
sk
519894a461 Adding a whole lot of stuff 2022-12-31 19:55:53 -03:00
sk
fe3052a359 schedule/draft in overflow menu 2022-12-31 19:53:50 -03:00
sk
245b91bebd don't finish compose fragment 2022-12-31 19:53:21 -03:00
sk
2e47147367 offer to save when scheduledAt changed
closes sk22#218
2022-12-31 19:53:09 -03:00
LucasGGamerM
8fec3fe56c Making it not show the text when the publishButton is relocated 2022-12-31 14:52:19 -03:00
LucasGGamerM
c4d56179f3 Fixing the icons on the bottom row of the compose fragment 2022-12-31 14:42:57 -03:00
LucasGGamerM
64d24f6002 Drafts and scheduled posts (#217)
closes #100
closes #59

* enable saving as draft (scheduled)
* add scheduled posts list
* fix NoSuchMethodError
* editable drafts/scheduled posts
* ui for drafts
* use instants between 9999-01-01 and 9999-12-31
* use save and draft strings
* map scheduled status params to status
* implement scheduling posts
* improve save/discard draft dialog
* persist scheduled date in state
* add unsent posts button to toolbar
* clean up imports
2022-12-31 14:28:06 -03:00
sk22
074efb0813 Drafts and scheduled posts (#217)
closes #100
closes #59

* enable saving as draft (scheduled)
* add scheduled posts list
* fix NoSuchMethodError
* editable drafts/scheduled posts
* ui for drafts
* use instants between 9999-01-01 and 9999-12-31
* use save and draft strings
* map scheduled status params to status
* implement scheduling posts
* improve save/discard draft dialog
* persist scheduled date in state
* add unsent posts button to toolbar
* clean up imports
2022-12-31 14:05:03 -03:00
Thiago 'Jedi' Abreu
98b96c78d7 Better handling of filter expiration date (#212)
* Better handling of filter expiration date
* Simplify Thread and Home Timeline filtering
2022-12-31 13:53:33 -03:00
LucasGGamerM
3a962c7c05 Refactoring the uniform notification icon setting 2022-12-31 13:47:55 -03:00
LucasGGamerM
99e3658938 Making fab feel better on light themes. Merging this might be good for you too, @sk22 2022-12-31 12:49:16 -03:00
FineFindus
9cd7ad3601 feat(profile) add icon to bot accounts 2022-12-31 15:11:52 +01:00
FineFindus
96db2b7a8b feat(icons) add bot icon 2022-12-31 15:01:24 +01:00
LucasGGamerM
a881f23253 Fixing the PublishButton background and also fixing the Fab icon background on trueblack theme. Its a relevant thing, i beliebe you shall merge this @sk22 2022-12-30 20:23:13 -03:00
LucasGGamerM
54106c497b Unfucking your own profile icons. They now look how they should 2022-12-30 20:00:11 -03:00
LucasGGamerM
1554c6d422 Editing settings page 2022-12-30 19:43:07 -03:00
LucasGGamerM
dccd9dcb97 Editing the InstanceRulesFragment for allowing a more coherent color scheme 2022-12-30 19:42:16 -03:00
LucasGGamerM
16c0866f7f It fucking compiles. Still a whole lot of stuff to be done 2022-12-30 14:12:10 -03:00
sk
db88de206b add mention with quasi-quoting 2022-12-30 13:32:51 -03:00
dontobi
92f353e1c5 Updated german translation 2022-12-30 12:06:20 +01:00
sk
71c80dd381 I want to fucking die 2022-12-29 18:01:59 -03:00
sk
d2be917bd4 fix akkoma crash on edit 2022-12-29 17:56:15 -03:00
ihor_ck
ea3dc32e98 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/uk/
2022-12-29 17:56:06 -03:00
edxkl
be86f1e96f Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pt_BR/
2022-12-29 17:55:48 -03:00
ihor_ck
d626d45f5c Translated using Weblate (Ukrainian)
Currently translated at 100.0% (91 of 91 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2022-12-29 17:55:48 -03:00
sk
f007bdb39c revert broken color attribute for notif icon
closes #190
2022-12-29 17:55:19 -03:00
sk
a0cbfe9a36 fix #200 2022-12-29 17:54:01 -03:00
sk
21f99081f2 long-click to compose from other account 2022-12-29 17:53:32 -03:00
Pointifurry
45952ef143 Translated using Weblate (Spanish)
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/es/
2022-12-29 17:50:16 -03:00
Linerly
fedaaa6fc8 Translated using Weblate (Indonesian)
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/id/
2022-12-29 17:50:16 -03:00
ling0412
1eb08e40be Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/zh_Hans/
2022-12-29 17:50:16 -03:00
Choukajohn
6a4936853b Translated using Weblate (French)
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/fr/
2022-12-29 17:50:16 -03:00
nitrogenez
b277eb4990 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (91 of 91 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2022-12-29 17:50:16 -03:00
itslameni
74efc5c332 Translated using Weblate (Russian)
Currently translated at 96.7% (88 of 91 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2022-12-29 17:50:15 -03:00
goliv
6653dd97a6 Translated using Weblate (Portuguese (Brazil))
Currently translated at 74.7% (68 of 91 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2022-12-29 17:50:08 -03:00
Linerly
d031acabf5 Translated using Weblate (Indonesian)
Currently translated at 100.0% (91 of 91 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-29 17:49:57 -03:00
Choukajohn
852f666b78 Translated using Weblate (French)
Currently translated at 100.0% (91 of 91 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-29 17:49:57 -03:00
Pointifurry
9f729e9ef0 Translated using Weblate (Spanish)
Currently translated at 100.0% (91 of 91 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-29 17:49:57 -03:00
ling0412
027f19e710 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (91 of 91 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2022-12-29 17:49:57 -03:00
sk22
14786f796b Translated using Weblate (German)
Currently translated at 100.0% (91 of 91 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-29 17:49:56 -03:00
sk
411e39a096 fix default reblog visibility 2022-12-29 17:49:28 -03:00
Linerly
8a72c5b9ca Translated using Weblate (Indonesian)
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/id/
2022-12-29 17:49:22 -03:00
Choukajohn
9e88e28a59 Translated using Weblate (French)
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/fr/
2022-12-29 17:49:22 -03:00
Linerly
df73c5ad8d Translated using Weblate (Indonesian)
Currently translated at 100.0% (89 of 89 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-29 17:49:22 -03:00
Choukajohn
98707dde76 Translated using Weblate (French)
Currently translated at 100.0% (89 of 89 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-29 17:49:22 -03:00
sk
444a9afabe disable block domain from post 2022-12-29 17:49:15 -03:00
sk
315bcd5b1a fix instance info v2 never getting saved 2022-12-29 17:48:51 -03:00
sk
c719ac22da improve settings items 2022-12-29 17:48:44 -03:00
nitrogenez
f4596998aa Translated using Weblate (Ukrainian)
Currently translated at 90.0% (9 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/uk/
2022-12-29 17:46:40 -03:00
ling0412
5414f5cf41 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (10 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/zh_Hans/
2022-12-29 17:46:39 -03:00
nitrogenez
d919827bc8 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (86 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2022-12-29 17:46:36 -03:00
Linerly
7b40bc157d Translated using Weblate (Indonesian)
Currently translated at 100.0% (86 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-29 17:46:36 -03:00
Choukajohn
c3ec64d1ff Translated using Weblate (French)
Currently translated at 100.0% (86 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-29 17:46:36 -03:00
gallegonovato
3464cb4a05 Translated using Weblate (Spanish)
Currently translated at 100.0% (86 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-29 17:46:36 -03:00
ling0412
21f40e5b42 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (86 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2022-12-29 17:46:36 -03:00
benjaminwolkchen
6d8ecab766 Translated using Weblate (German)
Currently translated at 98.8% (85 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-29 17:46:36 -03:00
sk
fc2e5112c0 add option to open post with other account
closes #182
2022-12-29 17:45:09 -03:00
sk
8f6c57d5c9 use popup background color for dialogs 2022-12-29 17:44:15 -03:00
sk
8455dc7bd2 implement long-click to copy links
closes sk22#84
2022-12-29 17:44:05 -03:00
sk
4677cef580 remove selectable background for username
closes sk22#187
2022-12-29 17:44:01 -03:00
sk
9ab6bf3da1 only show boost visibility for own posts 2022-12-29 17:43:57 -03:00
sk
bc65fa6654 remove selectable background 2022-12-29 17:43:45 -03:00
AiOO
9fe5960449 Translated using Weblate (Korean)
Currently translated at 100.0% (10 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ko/
2022-12-29 17:43:23 -03:00
Linerly
b684dd5a3b Translated using Weblate (Indonesian)
Currently translated at 100.0% (10 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/id/
2022-12-29 17:43:18 -03:00
Christian Elbrianno
5fff0cbdb0 Translated using Weblate (Indonesian)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-29 17:43:17 -03:00
Linerly
99dc479d78 Translated using Weblate (Indonesian)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-29 17:43:17 -03:00
Choukajohn
275eef912c Translated using Weblate (French)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-29 17:43:17 -03:00
gallegonovato
b9de7632e6 Translated using Weblate (Spanish)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-29 17:43:12 -03:00
AiOO
7a000f2a44 Translated using Weblate (Korean)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2022-12-29 17:43:01 -03:00
braydofficial
9d91b8c0fb Translated using Weblate (German)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-29 17:42:41 -03:00
sk
84d213bdd1 add missing fedi url format 2022-12-29 17:41:57 -03:00
sk
a2302ad318 implement setting boost visibility 2022-12-29 17:41:51 -03:00
sk
42eacea4be use color attributes instead of fixed colors 2022-12-29 17:39:36 -03:00
LucasGGamerM
664bfe895e Trying to process wtf happened here 2022-12-29 17:38:19 -03:00
LucasGGamerM
9c1812ce08 Trying to process wtf happened here 2022-12-29 17:38:01 -03:00
sk
49c83581f9 Trying to process wtf happened here 2022-12-29 17:31:22 -03:00
gallegonovato
6aa0428879 Translated using Weblate (Spanish)
Currently translated at 100.0% (10 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/es/
2022-12-29 17:24:41 -03:00
Choukajohn
838d0c678b Translated using Weblate (French)
Currently translated at 100.0% (10 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/fr/
2022-12-29 17:24:40 -03:00
Choukajohn
35555d1362 Translated using Weblate (French)
Currently translated at 100.0% (70 of 70 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-29 17:24:40 -03:00
gallegonovato
6c6b5d7be9 Translated using Weblate (Spanish)
Currently translated at 100.0% (70 of 70 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-29 17:24:34 -03:00
sk
037b8cc54e no ellipsis for settings items 2022-12-29 17:23:50 -03:00
sk
afb518cf8e animate translate button opacity 2022-12-29 17:23:15 -03:00
LucasGGamerM
b36c7375dd Fixing the compile problems 2022-12-29 17:22:37 -03:00
sk
069356418d Replace custom symbol with fluent mention symbol 2022-12-29 17:18:55 -03:00
sk
6b1c725ebd fix toolbar inset not applying in true black 2022-12-29 17:14:58 -03:00
LucasGGamerM
a46f8f1c20 Adding a new fluent edit icon for the fab 2022-12-29 17:13:44 -03:00
Tobias S
3b3d98c4be Merge branch 'LucasGGamerM:master' into master 2022-12-29 19:05:21 +01:00
LucasGGamerM
3d4742e8f7 Metada improvements for 81 2022-12-29 14:08:19 -03:00
LucasGGamerM
a6f1c21e1c Bumping version number 2022-12-29 14:06:33 -03:00
LucasGGamerM
a0b62ab434 Merge branch 'feature/publish_button_improvements' 2022-12-29 14:04:08 -03:00
LucasGGamerM
0b8501e92b Merge branch 'feature/show_changelog_button' 2022-12-29 14:01:34 -03:00
LucasGGamerM
9a0851cb06 Fixing some padding issues with the changelog 2022-12-29 14:00:53 -03:00
LucasGGamerM
e4340f5015 After hours of looking at the code, i found how to fix it 2022-12-29 13:56:18 -03:00
dontobi
0cd5d12d42 German translation 2022-12-29 07:41:19 +01:00
LucasGGamerM
014398e050 I dont know what i am doing with my life 2022-12-28 22:54:40 -03:00
LucasGGamerM
4f77370977 Its a lot less broken than before 2022-12-28 22:26:49 -03:00
LucasGGamerM
5937215d3a I have done something here 2022-12-28 21:50:59 -03:00
LucasGGamerM
ade1ce8e05 Adding a send icon. Still havent made use of it though 2022-12-28 21:33:55 -03:00
LucasGGamerM
a4581dc61b More changes to the 80 changelog 2022-12-28 20:33:19 -03:00
LucasGGamerM
50d4130b3f Making the relocated button default 2022-12-28 20:14:45 -03:00
LucasGGamerM
1147087531 Update settings page screenshot 2022-12-28 20:07:22 -03:00
LucasGGamerM
4653a22635 Merge pull request #12 from dontobi/master
Adding some german translation
2022-12-28 20:06:29 -03:00
LucasGGamerM
e79501857f Adding changelog for the 80th release of Moshidon! 2022-12-28 19:58:53 -03:00
LucasGGamerM
a8c05f6a32 Bump version number 2022-12-28 19:55:27 -03:00
LucasGGamerM
c1d98cad00 Its now optional! 2022-12-28 19:49:38 -03:00
LucasGGamerM
fb54948f86 Its now in the bottom. Time to make it optional 2022-12-28 18:42:13 -03:00
LucasGGamerM
26297fbb5b Lastcomm 2022-12-28 18:02:38 -03:00
LucasGGamerM
cd342d1034 I am trying my best 2022-12-28 14:56:49 -03:00
LucasGGamerM
029650ef2d Its almost working, the UI side is done. But the request is being canceled when the back button is pressed. 2022-12-28 12:34:00 -03:00
dontobi
ca5f189e70 German translation 2022-12-28 16:24:58 +01:00
LucasGGamerM
ac24f636df Its a little less broken 2022-12-28 11:15:12 -03:00
LucasGGamerM
1688168bc1 The ui is less broken 2022-12-28 11:05:33 -03:00
LucasGGamerM
46b842afc4 It still does not work, but its one step closer to working 2022-12-28 10:45:15 -03:00
LucasGGamerM
3f773a52cc Created the class. Lets leave this for tomorrow 2022-12-27 21:43:42 -03:00
LucasGGamerM
48664bb580 Idk what to call this commit, so Note Improver it is 2022-12-27 21:42:21 -03:00
LucasGGamerM
094cd67728 Now adding a confirm button 2022-12-27 21:19:54 -03:00
LucasGGamerM
a70bd4f906 Merge remote-tracking branch 'origin/master' 2022-12-27 20:41:34 -03:00
LucasGGamerM
4adac359e3 Adding changelog for 79 2022-12-27 20:41:22 -03:00
LucasGGamerM
9adaf12c00 Bump version number 2022-12-27 20:40:27 -03:00
LucasGGamerM
8bbfa2e417 Adding a donate button 2022-12-27 20:39:52 -03:00
LucasGGamerM
9d800106cc Added a framelayout just for adding the confirm button 2022-12-27 20:20:44 -03:00
LucasGGamerM
e1ca97f323 Update FUNDING.yml 2022-12-27 19:28:55 -03:00
LucasGGamerM
68bb23e3b4 It actually loads something. Perfect 2022-12-27 18:48:08 -03:00
LucasGGamerM
68397bd487 How did I add some many lines? Removing them 2022-12-27 18:27:57 -03:00
LucasGGamerM
3104ddb4b6 More polishes the UI side a little more, now also hides the private note on the personal profile 2022-12-27 18:26:35 -03:00
LucasGGamerM
9bddd6b274 The ui side is ready somehow. Still need to handle it all 2022-12-27 16:53:21 -03:00
LucasGGamerM
677621f2da Update _config.yml
Rebranding
2022-12-27 15:18:55 -03:00
LucasGGamerM
d40138dd99 Getting screenshots and icon metadata ready 2022-12-27 14:46:15 -03:00
LucasGGamerM
d957e8f2fc Making changelogs and stuff ready for fdroid release 2022-12-26 20:23:31 -03:00
LucasGGamerM
681c327306 Bump version number 2022-12-26 11:11:23 -03:00
LucasGGamerM
80c9afec7b Found an icon and changed the name of the setting. 2022-12-26 11:05:29 -03:00
LucasGGamerM
eea8041abe Its in the settings page as well. All I need to do now is find an icon for it 2022-12-26 10:41:03 -03:00
LucasGGamerM
1309bfe1ee Its in the global user preferences now, still not in the settings page 2022-12-26 10:33:04 -03:00
LucasGGamerM
70d3ef9984 Removing the divider by making it invisible 2022-12-26 10:27:13 -03:00
LucasGGamerM
52ac5f16e5 Rebumping version number twice, because of the downgrade made so I could test the show changelog feature. 2022-12-25 16:03:04 -03:00
LucasGGamerM
ea43070e6d More polishes over the Changelog feature 2022-12-25 16:01:22 -03:00
LucasGGamerM
14cd23c28b Its working. Still needs some polish though! 2022-12-25 15:39:45 -03:00
LucasGGamerM
793668021e Rolling back version graddle for testing the changelog thing. Will bump it later 2022-12-25 15:03:02 -03:00
LucasGGamerM
f0ea6ef43e Revert "Getting changelogs commit number 1"
This reverts commit e8a31cf867.
2022-12-25 14:21:09 -03:00
LucasGGamerM
2b2e4845a1 Revert "Its some steps done"
This reverts commit d66a4c0920.
2022-12-25 14:21:09 -03:00
LucasGGamerM
2dccec99cc Revert "Just no"
This reverts commit c5fcf49eda.
2022-12-25 14:21:09 -03:00
LucasGGamerM
b060894a6c Merge remote-tracking branch 'origin/feature/show_changelog_button' into feature/show_changelog_button 2022-12-25 14:18:59 -03:00
LucasGGamerM
92872edb58 Something is gonna come out of it this time. I am sure of it 2022-12-25 14:16:50 -03:00
LucasGGamerM
c5fcf49eda Just no 2022-12-25 11:58:23 -03:00
LucasGGamerM
d66a4c0920 Its some steps done 2022-12-25 11:11:30 -03:00
LucasGGamerM
e8a31cf867 Getting changelogs commit number 1 2022-12-24 23:41:41 -03:00
LucasGGamerM
c1f9a88ef4 Bump version number 2022-12-24 11:48:44 -03:00
LucasGGamerM
e6200e186b Merge pull request #10
feat(theme/nord): add favourite and bookmark icon
2022-12-24 11:25:03 -03:00
FineFindus
5564502125 feat(theme/nord): add favourite and bookmark icon 2022-12-24 13:40:06 +01:00
LucasGGamerM
7947e7689c Bump version number 2022-12-23 12:39:37 -03:00
LucasGGamerM
b53ada7ea2 Fixing color preference not saved loaded on android 11 and below devices 2022-12-23 12:39:14 -03:00
LucasGGamerM
584f28534a Merge branch 'development_of_the_nord_theme' 2022-12-23 12:03:31 -03:00
LucasGGamerM
770fde7aac Fixing the background of the disabled button on light themes and dark themes 2022-12-23 12:03:17 -03:00
LucasGGamerM
3d7f918132 Merge branch 'development_of_the_nord_theme' 2022-12-23 11:58:49 -03:00
LucasGGamerM
29b8cedc7c Merge remote-tracking branch 'origin/development_of_the_nord_theme' into development_of_the_nord_theme
# Conflicts:
#	mastodon/src/main/res/values/colors.xml
2022-12-23 11:55:22 -03:00
LucasGGamerM
33b65c3bf3 Merge pull request #9 from FineFindus/development_of_the_nord_theme
feat(theme/nord): change popup color
2022-12-23 11:54:49 -03:00
LucasGGamerM
34ab1bcd9c Change the accent color back to default 2022-12-23 11:54:47 -03:00
LucasGGamerM
cfdc88174b Bumping version number 2022-12-23 11:47:51 -03:00
LucasGGamerM
15123d8924 Merge branch 'development_of_the_nord_theme' 2022-12-23 11:46:38 -03:00
LucasGGamerM
20086d76ce Fixing the accent color for the nord theme 2022-12-23 11:46:11 -03:00
FineFindus
1ca4fb5c37 feat(theme/nord): change popup color 2022-12-23 15:41:28 +01:00
LucasGGamerM
009016a835 Adding a toggle for custom notification icons 2022-12-23 11:33:08 -03:00
LucasGGamerM
33dfb2a30d Merge branch 'development_of_the_nord_theme' 2022-12-23 11:04:32 -03:00
LucasGGamerM
1604c067fd Fixing up the nord theme 2022-12-23 10:59:12 -03:00
LucasGGamerM
0c7419e2b3 Its less broken, but I still found some bugs 2022-12-23 10:37:14 -03:00
LucasGGamerM
7cf30ccb98 Maybe fixing the nord theme. Still a lot of work that needs to be done 2022-12-23 08:29:01 -03:00
LucasGGamerM
aa2c8c5624 Bump the version number 2022-12-22 20:21:27 -03:00
LucasGGamerM
875695c239 Fixing up the nord theme 2022-12-22 20:17:05 -03:00
LucasGGamerM
61049a1302 Adding the nord theme 2022-12-22 19:27:02 -03:00
LucasGGamerM
28db90aa82 Its going there 2022-12-22 18:59:28 -03:00
LucasGGamerM
f0e7fc5e3b Its almost working 2022-12-22 18:58:20 -03:00
LucasGGamerM
2169afa8e7 Merge remote-tracking branch 'origin/master' 2022-12-22 15:49:09 -03:00
LucasGGamerM
508ec06d93 Bump version number 2022-12-22 15:48:38 -03:00
LucasGGamerM
9fb39d9403 Making it compile again 2022-12-22 15:46:09 -03:00
sk
4879d74f80 implement followed hashtags list
closes sk22/megalodon#162
2022-12-22 15:36:02 -03:00
LucasGGamerM
ba3f6c4f95 Changing stuff back to moshidon again 2022-12-22 15:32:32 -03:00
LucasGGamerM
481241c4f6 Using fluent icon instead of normal icon for the color picker 2022-12-22 14:58:16 -03:00
LucasGGamerM
5798587dc6 merge branch 'feature/more_html_tags' 2022-12-22 14:50:15 -03:00
sk
066e3e08a2 disable boost button if disabled
closes #180
2022-12-22 14:49:21 -03:00
sk
16d6c14633 try to open link previews in app 2022-12-22 14:49:16 -03:00
sk
80a4a3551c match navigation bar color with toolbar 2022-12-22 14:47:57 -03:00
LucasGGamerM
74f3bb8708 Adding notification icons for different stuff, and fixing the color of the compose_shortcut thing 2022-12-22 14:46:06 -03:00
sk
c3e398b3c2 use color attributes instead of fixed colors 2022-12-22 14:33:46 -03:00
sk
dcfa812c83 fix media upload colors 2022-12-22 14:30:41 -03:00
sk
065e65d708 reset state on boost long click 2022-12-22 14:30:37 -03:00
sk
bca0dab381 add long-click to "quote" 2022-12-22 14:29:34 -03:00
sk
4a45c1055e only perform fedi lookup if looks like fedi url 2022-12-22 14:19:04 -03:00
sk
7c789746ce resolve fediverse links in app
closes sk22#177
closes sk22#96
2022-12-22 14:19:03 -03:00
sk
f46ce5576c reuse old brownish gray and move colors 2022-12-22 14:15:36 -03:00
sk
730e6fc1fa fix wrong default visibility in popup
closes sk22#174
2022-12-22 14:15:18 -03:00
sk
cb36cc042c move button text/background to styles 2022-12-22 14:15:05 -03:00
sk
5d586418f9 add toolbar background color 2022-12-22 14:15:05 -03:00
sk22
44f1d026d6 Translated using Weblate (German)
Currently translated at 100.0% (70 of 70 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-22 14:14:41 -03:00
jonta
defaa1095c Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2022-12-22 14:14:34 -03:00
gallegonovato
c67f2f8027 Translated using Weblate (Spanish)
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-22 14:14:28 -03:00
Radiquum
452128565f Translated using Weblate (Russian)
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2022-12-22 14:14:23 -03:00
Linerly
6322d3c984 Translated using Weblate (Indonesian)
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-22 14:14:18 -03:00
Choukajohn
d68c820e58 Translated using Weblate (French)
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-22 14:14:13 -03:00
AiOO
79f37b4813 Translated using Weblate (Korean)
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2022-12-22 14:14:07 -03:00
LucasGGamerM
87460a2fb6 Making it work again just in case idk 2022-12-22 11:52:43 -03:00
LucasGGamerM
6774a642d9 Setting purple as default and making it work idk 2022-12-22 11:49:07 -03:00
LucasGGamerM
f0bd9233b7 IT FINALLY FUCKING COMPILES 2022-12-22 11:27:52 -03:00
LucasGGamerM
66efe750a8 Trying to make it compile properly idek wtf to do anymore 2022-12-22 11:24:36 -03:00
sk
3658fc423b simplify themes 2022-12-22 11:08:26 -03:00
sk
3c3ad7447e only load default visibility if not editing
fix mastodon#306
2022-12-22 09:07:41 -03:00
LucasGGamerM
b570064b99 Fixing missing error toast message 2022-12-22 09:03:14 -03:00
LucasGGamerM
d9f6ef69fe Revert "Whatever the fuck this is. Hopefully it compiles on the first try"
This reverts commit bdac1d5bb4.
2022-12-22 09:01:30 -03:00
sk
bdac1d5bb4 Whatever the fuck this is. Hopefully it compiles on the first try 2022-12-22 09:00:51 -03:00
sk
1eee1ead5e merge miui fix for copying text 2022-12-22 08:58:08 -03:00
sk
0ec51f5b34 set pivot point once 2022-12-22 08:57:13 -03:00
sk
6c6fb05a7a fix broken long click 2022-12-22 08:57:08 -03:00
sk
09a0faacba fix bug in bookmark button
closes #167
2022-12-22 08:51:32 -03:00
sk
d0d1d15de5 add option to disable swiping
closes sk22#165
2022-12-22 08:50:25 -03:00
sk
e4e9516d5d copy post URL on long click 2022-12-22 08:48:05 -03:00
sk
05eceecbea move copy text to UiUtils 2022-12-22 08:48:01 -03:00
sk
71ba1bb0d5 restore toast message for android 13+ 2022-12-22 08:47:56 -03:00
sk
2160a26648 add vibration when copying username 2022-12-22 08:47:52 -03:00
sk
5433eac9c9 fix updating wrong status when interacting with reblog
see mastodon#467
2022-12-22 08:45:55 -03:00
LucasGGamerM
0a68f86200 Update default.html 2022-12-21 19:50:47 -03:00
LucasGGamerM
c91dae0346 Update README.md 2022-12-21 18:04:21 -03:00
LucasGGamerM
e1df7e5077 Update README.md 2022-12-21 18:03:52 -03:00
LucasGGamerM
0560b54559 Bump version number 2022-12-21 17:19:55 -03:00
LucasGGamerM
c78db7e835 Fixing the visibility of the translate button... again. This time I scrolled a lot, so i know its not broken 2022-12-21 17:19:28 -03:00
LucasGGamerM
c837a2d4b6 Bumping version number 2022-12-21 09:28:19 -03:00
LucasGGamerM
70b91b7a9a Fixing npe on timeline 2022-12-21 09:27:16 -03:00
LucasGGamerM
27079a7ec5 Version 69 is special, lmao 2022-12-20 19:56:49 -03:00
LucasGGamerM
9563df0574 Making it appear in every post that isnt on the default language and that allows translation. Merge this as well @sk22, as its a rather useful thing 2022-12-20 19:22:42 -03:00
LucasGGamerM
638209cc13 Renaming string to fix the translate_post error message 2022-12-20 18:51:59 -03:00
LucasGGamerM
224c731afa Merge remote-tracking branch 'origin/develop' into develop 2022-12-20 17:43:38 -03:00
LucasGGamerM
0bbf937531 Please merge this @sk22, its a transparency filter for when the translation is loading 2022-12-20 17:42:47 -03:00
LucasGGamerM
3556c92c3e Please merge this @sk22 2022-12-20 17:35:40 -03:00
LucasGGamerM
87c5b23196 Re-re-cleaning unused things. 2022-12-20 17:13:17 -03:00
LucasGGamerM
c83910c885 Cleaning up the old implementation 2022-12-20 17:09:34 -03:00
LucasGGamerM
586622e90d Its barely working. Huge thanks to @sk22 btw 2022-12-20 16:52:48 -03:00
sk
e5e2430e03 check if server supports translation earlier
closes #172
2022-12-20 16:28:22 -03:00
sk
04bfdba50e Adding translate button from megalodon 2022-12-20 16:28:19 -03:00
sk
7abf15e9e0 use primary color for update notification
closes #169
2022-12-20 16:16:52 -03:00
Grishka
6b680831b8 Fix #472 2022-12-20 16:12:54 -03:00
sk
6cbf100828 fire counter updated event for content status
see mastodon#467
closes sk22#173
2022-12-20 14:12:46 -03:00
sk
3e7bbebe7f fix counter updates for preloaded data
re: mastodon#467
see fb5289372d
2022-12-20 14:12:46 -03:00
sk
56d344045a add drag to open to visibility button 2022-12-20 14:12:45 -03:00
LucasGGamerM
7ab634cc08 Renaming megalodon to moshidon 2022-12-20 14:12:01 -03:00
sk
9f0db3ebb5 update strings 2022-12-20 13:58:41 -03:00
sk22
6415eb8590 Translated using Weblate (German)
Currently translated at 100.0% (70 of 70 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-20 13:58:30 -03:00
AiOO
87c77b84a4 Translated using Weblate (Korean)
Currently translated at 100.0% (8 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ko/
2022-12-20 13:57:37 -03:00
jonta
0b7bb16f22 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (8 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pt_BR/
2022-12-20 13:57:37 -03:00
jonta
5164b5ba78 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2022-12-20 13:57:37 -03:00
gallegonovato
f3c28bc66a Translated using Weblate (Spanish)
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-20 13:57:36 -03:00
itslameni
239f7eb9e7 Translated using Weblate (Russian)
Currently translated at 37.5% (3 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ru/
2022-12-20 13:57:21 -03:00
Linerly
d6daf7a553 Translated using Weblate (Indonesian)
Currently translated at 100.0% (8 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/id/
2022-12-20 13:57:21 -03:00
Radiquum
dfb3b230e6 Translated using Weblate (Russian)
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2022-12-20 13:57:21 -03:00
Linerly
484a5c878f Translated using Weblate (Indonesian)
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-20 13:57:20 -03:00
Choukajohn
3f27cfb13b Translated using Weblate (French)
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-20 13:57:15 -03:00
AiOO
38e2ba6ccd Translated using Weblate (Korean)
Currently translated at 100.0% (62 of 62 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2022-12-20 13:57:03 -03:00
sk
3dad38e614 update strings 2022-12-20 13:57:02 -03:00
sk
0865c9d1bd update german 2022-12-20 13:57:02 -03:00
LucasGGamerM
20a8783d84 Making the icons good again in the profile page 2022-12-20 13:45:10 -03:00
LucasGGamerM
0b96fb05fc Bumping version number 2022-12-18 20:57:47 -03:00
LucasGGamerM
8767d62de7 Fixing a fucking NPE 2022-12-18 20:54:42 -03:00
LucasGGamerM
74fb04e2d4 Disabling the Translate button on statuses that are from the same default language, or that are private or direct messages. 2022-12-18 20:04:32 -03:00
LucasGGamerM
2537460e16 Tis broken 2022-12-18 19:43:48 -03:00
LucasGGamerM
be3dfde3be Changing out (again) the link back to moshidons github 2022-12-18 17:58:21 -03:00
LucasGGamerM
42025035ad Caching the status translation for easier use 2022-12-18 17:57:09 -03:00
LucasGGamerM
6a667fdf32 Bump version number 2022-12-18 14:11:18 -03:00
LucasGGamerM
bfafac3d4f Fixing the translate icon tint, changing translate icon to fluent icon. Making it better overall 2022-12-18 14:09:21 -03:00
LucasGGamerM
0cafbe9f91 Logic side done for the red theme. 2022-12-18 12:54:17 -03:00
LucasGGamerM
2fbf172729 Styles and colors.xml side done. Putting a string in there as well :D 2022-12-18 12:41:40 -03:00
sk
bb9755f4af Making the boost icon better 2022-12-18 11:12:55 -03:00
LucasGGamerM
2a01377a8a Why tf did this revert to the old thing? 2022-12-18 11:04:47 -03:00
LucasGGamerM
61cc6d5d07 Checking out of the account list fragment thing 2022-12-18 11:04:32 -03:00
LucasGGamerM
1d74a37f60 Dunno why, just want to commit this 2022-12-18 11:04:05 -03:00
LucasGGamerM
ef9645f9e7 Ranaming stuffs back to moshidon 2022-12-18 11:02:51 -03:00
sk
6a103ca3f3 fix text view cutting off text
closes #157
2022-12-18 10:52:01 -03:00
LucasGGamerM
c22772121b Ranaming stuffs back to moshidon 2022-12-17 21:23:52 -03:00
kaea
de7bc69d2a Translated using Weblate (Polish)
Currently translated at 100.0% (59 of 59 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2022-12-17 21:21:55 -03:00
itslameni
2eccd572c9 Translated using Weblate (Russian)
Currently translated at 37.5% (3 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ru/
2022-12-17 21:21:55 -03:00
itslameni
824a62024b A whole lot of stuffs, including merging stuffs from weblate 2022-12-17 21:21:54 -03:00
tippete
3a3cfda919 Translated using Weblate (Italian)
Currently translated at 100.0% (59 of 59 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/it/
2022-12-17 21:21:05 -03:00
AiOO
e29120cc51 Translated using Weblate (Korean)
Currently translated at 100.0% (8 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ko/
2022-12-17 21:21:03 -03:00
nitrogenez
197d5c6bc3 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (59 of 59 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2022-12-17 21:21:00 -03:00
jonta
d143cc75db Translated using Weblate (Portuguese (Brazil))
Currently translated at 93.2% (55 of 59 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2022-12-17 21:21:00 -03:00
kaea
1635a06c54 Translated using Weblate (Polish)
Currently translated at 100.0% (59 of 59 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2022-12-17 21:21:00 -03:00
Choukajohn
76de0d8c70 Translated using Weblate (French)
Currently translated at 100.0% (59 of 59 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-17 21:21:00 -03:00
AiOO
402a995b8f Translated using Weblate (Korean)
Currently translated at 100.0% (59 of 59 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2022-12-17 21:21:00 -03:00
sk
f580ba7779 Refactoring names to custom. Thank you @sk22 for this amazing piece of commit 2022-12-17 21:19:40 -03:00
sk
bc3869b920 fix follow request list issues
closes #153
2022-12-17 21:09:56 -03:00
LucasGGamerM
020f4a5a1a Hiding material you in older android versions fix 2022-12-17 21:00:02 -03:00
sk
b054caa967 Hiding material you in older android versions 2022-12-17 20:52:11 -03:00
LucasGGamerM
82b7633650 Renaming stuff 2022-12-16 19:13:11 -03:00
LucasGGamerM
33497864f2 Bumping version number 2022-12-16 12:47:17 -03:00
LucasGGamerM
4c9d1544fa Refactoring the purple/pink theme. Merge this @sk22, as its exactly what you asked earlier 2022-12-16 12:43:43 -03:00
LucasGGamerM
bce2367cfc Making material you default for devices that support it. For devices that dont, still setting purple as the main theme. 2022-12-16 12:07:29 -03:00
sk
390ecc48fb Refactoring a string for easier translation 2022-12-16 11:44:18 -03:00
LucasGGamerM
9ed99edd6e Its unbroken now! ITS WORKING! 2022-12-16 11:28:48 -03:00
LucasGGamerM
4362490539 Fixing the instance thing again 2022-12-16 11:17:43 -03:00
LucasGGamerM
f5d225fc3e Still broken 2022-12-16 11:16:10 -03:00
LucasGGamerM
063e9287fd A little better. Some refactoring done. 2022-12-16 11:09:42 -03:00
LucasGGamerM
ba376908cd Get instance things. Still figuring out the merge 2022-12-16 11:03:24 -03:00
sk
caddf0021c A bunch of stuff. I dont know wtf I am doing 2022-12-16 10:54:50 -03:00
Grishka
90645f4d90 Adding stuff from upstream 2022-12-16 10:30:42 -03:00
LucasGGamerM
1316fcae22 Fixing compile problems. Adding another one 2022-12-16 10:23:45 -03:00
LucasGGamerM
27dee7297b Changing things back to default 2022-12-16 10:13:26 -03:00
sk
13ecba40ae use default posting language from server 2022-12-16 10:08:19 -03:00
LucasGGamerM
e15dd0d8b3 Merge remote-tracking branch 'origin/master' 2022-12-15 15:31:16 -03:00
LucasGGamerM
1ab26bc665 Merge pull request #7
Add Android 13 monochrome icon
2022-12-15 15:28:33 -03:00
LucasGGamerM
e6758d8c01 Merge branch 'fork' 2022-12-15 15:25:01 -03:00
LucasGGamerM
4621787e34 Imma just wait until @sk22 works on this again 2022-12-15 15:24:47 -03:00
LucasGGamerM
10ad35a285 Deleting the entries for the default language, as I will instead get them from the server 2022-12-15 15:05:22 -03:00
LucasGGamerM
d10145a6ba Removing this function call because its useless as i will get the default language from the server, and not from this. 2022-12-15 15:03:33 -03:00
LucasGGamerM
c9792ced32 Merge remote-tracking branch 'origin/fork' into fork 2022-12-15 15:01:21 -03:00
LucasGGamerM
a3fb09a33c Tis broken. Just need to fix MastodonLanguage.java getDefaultLanguge. I am still trying to figure out where it is stored 2022-12-15 14:56:11 -03:00
LucasGGamerM
6d875fd890 It now properly sets a default on every change. Not the final implementation yet 2022-12-14 20:39:02 -03:00
LucasGGamerM
5d87fb7b67 MastodonLanguage util side done 2022-12-14 20:15:29 -03:00
LucasGGamerM
4cbb59850b Superduper buggy. But the preferences side is done, so make sure to merge this commit as well @sk22 2022-12-14 19:59:53 -03:00
LucasGGamerM
a2022b25e5 Fixing compile problems. Merging the language picker from megalodon. 2022-12-14 19:23:06 -03:00
Florian Obernberger
0d168f93ed Add Android 13 monochrome icon 2022-12-14 23:03:41 +01:00
LucasGGamerM
94ac5b9bb7 Merge branch 'feature/language-selector' into fork
# Conflicts:
#	mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/ComposeFragment.java
#	mastodon/src/main/res/values/strings.xml
2022-12-14 19:03:15 -03:00
LucasGGamerM
024d358213 Bump version number 2022-12-13 15:56:38 -03:00
LucasGGamerM
5562c93855 Merge branch 'fork' 2022-12-13 15:49:06 -03:00
LucasGGamerM
98e897d6a8 Merge branch 'material3_dynamic_color_theme' 2022-12-13 15:36:41 -03:00
LucasGGamerM
4aac6aa4f4 Fixing the material you theme. 2022-12-13 15:34:34 -03:00
LucasGGamerM
2bb4616e40 Rebranding the strings.
Useful command: "find values* -type f -exec sed -i 's/Megalodon/Moshidon/g' {} \;"
2022-12-13 14:10:10 -03:00
LucasGGamerM
56e8476d2e Rebranding the welcome screen 2022-12-13 12:39:29 -03:00
LucasGGamerM
97d81eb1b2 Rebranding 2022-12-13 12:36:06 -03:00
sk
ffa21b26af add custom login fragment 2022-12-13 12:24:39 -03:00
lunarna
9917712f66 Translated using Weblate (Polish)
Currently translated at 25.0% (2 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pl/
2022-12-13 12:19:52 -03:00
AiOO
11cdce6c90 Translated using Weblate (Korean)
Currently translated at 100.0% (8 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ko/
2022-12-13 12:19:50 -03:00
Adolfo Jayme Barrientos
8e82cf1e99 Translated using Weblate (Spanish)
Currently translated at 100.0% (8 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/es/
2022-12-13 12:19:49 -03:00
edxkl
9767b11626 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (8 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pt_BR/
2022-12-13 12:19:49 -03:00
Choukajohn
0f95694083 Translated using Weblate (French)
Currently translated at 100.0% (8 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/fr/
2022-12-13 12:19:47 -03:00
nitrogenez
7dfc7dd9ef Translated using Weblate (Ukrainian)
Currently translated at 100.0% (56 of 56 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2022-12-13 12:19:46 -03:00
edxkl
0407e958f1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.4% (54 of 56 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2022-12-13 12:19:44 -03:00
lunarna
e6a5fa1c3f Translated using Weblate (Polish)
Currently translated at 100.0% (56 of 56 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2022-12-13 12:19:43 -03:00
Choukajohn
6f48a7c4a4 Translated using Weblate (French)
Currently translated at 100.0% (56 of 56 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-13 12:19:43 -03:00
Adolfo Jayme Barrientos
80c56d71cb Translated using Weblate (Spanish)
Currently translated at 100.0% (56 of 56 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-13 12:19:43 -03:00
AiOO
f77d9dcee2 Translated using Weblate (Korean)
Currently translated at 100.0% (56 of 56 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2022-12-13 12:19:42 -03:00
sk22
f7195c7787 Translated using Weblate (German)
Currently translated at 100.0% (56 of 56 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-13 12:19:41 -03:00
sk22
ca92cc6dc1 Translated using Weblate (English)
Currently translated at 100.0% (56 of 56 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/en/
2022-12-13 12:19:07 -03:00
AiOO
cd31b2ae5a Translated using Weblate (Korean)
Currently translated at 100.0% (7 of 7 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ko/
2022-12-13 12:18:31 -03:00
edxkl
00bec7174a Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (7 of 7 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pt_BR/
2022-12-13 12:18:31 -03:00
edxkl
236acab54f Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.8% (46 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2022-12-13 12:18:31 -03:00
kaea
ba362f4457 Translated using Weblate (Polish)
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2022-12-13 12:18:31 -03:00
Adolfo Jayme Barrientos
8ed93baf8d Translated using Weblate (Spanish)
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-13 12:18:31 -03:00
plutonemhikari
bf953e96fa Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2022-12-13 12:18:30 -03:00
AiOO
6b89a747e2 Translated using Weblate (Korean)
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2022-12-13 12:18:29 -03:00
gallegonovato
2fa1d54268 Translated using Weblate (Spanish)
Currently translated at 100.0% (7 of 7 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/es/
2022-12-13 12:18:25 -03:00
Christian Elbrianno
02ef34b451 Translated using Weblate (Indonesian)
Currently translated at 71.4% (5 of 7 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/id/
2022-12-13 12:18:25 -03:00
Choukajohn
1701fc71c4 Translated using Weblate (French)
Currently translated at 100.0% (7 of 7 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/fr/
2022-12-13 12:18:25 -03:00
edxkl
fe200996db Translated using Weblate (Portuguese (Brazil))
Currently translated at 93.6% (44 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2022-12-13 12:18:25 -03:00
tippete
659333342f Translated using Weblate (Italian)
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/it/
2022-12-13 12:18:25 -03:00
Christian Elbrianno
1ca5b6def2 Translated using Weblate (Indonesian)
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-13 12:18:24 -03:00
Choukajohn
4e8e3ee440 Translated using Weblate (French)
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-13 12:18:24 -03:00
Adolfo Jayme Barrientos
86dd724222 Translated using Weblate (Spanish)
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-13 12:18:24 -03:00
gallegonovato
8242995027 Translated using Weblate (Spanish)
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-13 12:18:24 -03:00
ca
49962a4734 Translated using Weblate (Catalan)
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ca/
2022-12-13 12:18:24 -03:00
sk
509b16aee1 remove strings 2022-12-13 12:18:22 -03:00
LucasGGamerM
f3f5e4a887 Revert "Revert "Fix #443 again""
This reverts commit f63bbeee79.
2022-12-13 12:02:30 -03:00
LucasGGamerM
7aabc1fa76 Revert "Revert "This is quite brokey""
This reverts commit 0231903868.
2022-12-13 12:02:28 -03:00
LucasGGamerM
dcb5e36041 Revert "Revert "Fix #443""
This reverts commit e0c072ab9c.
2022-12-13 12:02:21 -03:00
LucasGGamerM
e0c072ab9c Revert "Fix #443"
This reverts commit 65dbbb3d61.
2022-12-13 12:00:55 -03:00
LucasGGamerM
0231903868 Revert "This is quite brokey"
This reverts commit f352c20ed9.
2022-12-13 12:00:55 -03:00
LucasGGamerM
f63bbeee79 Revert "Fix #443 again"
This reverts commit b34e34de51.
2022-12-13 12:00:55 -03:00
LucasGGamerM
db9e427444 Bump version number 2022-12-12 21:45:48 -03:00
LucasGGamerM
4474a584df Fixed the lists tab order. This should partially fix #3 2022-12-12 21:11:15 -03:00
LucasGGamerM
ab00ad68f1 Fixed the lists tab order. This should partially fix #3 2022-12-12 20:43:42 -03:00
LucasGGamerM
d1e77efa1c Revert "Adding a tab on the tabbar and showing lists. Its still an early alpha though"
This reverts commit bfd87cf94e.
2022-12-12 20:40:11 -03:00
LucasGGamerM
de00353864 Revert "Why doesnt this work"
This reverts commit be3c12dfb3.
2022-12-12 20:40:10 -03:00
LucasGGamerM
feec459d47 Revert "Fixed the lists tab order. This should partially fix #3"
This reverts commit 1f51331f67.
2022-12-12 20:40:10 -03:00
LucasGGamerM
ad68d7e4f2 Revert "The placeholders are now there."
This reverts commit 0ca9c536cd.
2022-12-12 20:40:10 -03:00
LucasGGamerM
cf27c6bbf3 Revert "The placeholders are better. But the api thing isnt working"
This reverts commit a3267f6cd3.
2022-12-12 20:40:10 -03:00
LucasGGamerM
0115656d67 Revert "And it still doesnt work"
This reverts commit 002687d2b1.
2022-12-12 20:40:10 -03:00
LucasGGamerM
002687d2b1 And it still doesnt work 2022-12-12 17:12:55 -03:00
LucasGGamerM
a3267f6cd3 The placeholders are better. But the api thing isnt working 2022-12-12 16:10:27 -03:00
LucasGGamerM
0ca9c536cd The placeholders are now there. 2022-12-12 14:20:56 -03:00
LucasGGamerM
382a23c0b6 Tests 2022-12-12 14:03:44 -03:00
LucasGGamerM
1f51331f67 Fixed the lists tab order. This should partially fix #3 2022-12-11 20:12:27 -03:00
LucasGGamerM
cce6ba0746 Undoing all the stuff that was broken 2022-12-11 15:55:28 -03:00
LucasGGamerM
be3c12dfb3 Why doesnt this work 2022-12-11 14:06:22 -03:00
LucasGGamerM
bfd87cf94e Adding a tab on the tabbar and showing lists. Its still an early alpha though 2022-12-11 11:58:28 -03:00
LucasGGamerM
857bb1e483 Forgot the edit entry 2022-12-10 20:17:31 -03:00
LucasGGamerM
75a131b675 Api side done 2022-12-10 20:06:45 -03:00
LucasGGamerM
d98b1c5ee1 Update readme 2022-12-10 17:38:08 -03:00
LucasGGamerM
1eeab25b7d Bumping version number 2022-12-10 17:30:11 -03:00
sk
82cc0c3c09 add option to allow multiple poll choices 2022-12-10 17:15:41 -03:00
sk
e102faff6c improve semantics for poll options 2022-12-10 17:10:56 -03:00
sk
34369bd7e9 fix poll option displaying wrong own vote
fixes #132
2022-12-10 17:10:56 -03:00
sk
c71b620402 fix poll option displaying wrong own vote
fixes #132
2022-12-10 17:10:55 -03:00
sk
21b4bf23a1 update description 2022-12-10 17:10:06 -03:00
sk
d034311f2d Fixing the changelog ig 2022-12-10 17:10:06 -03:00
sk22
2deed69766 Translated using Weblate (German)
Currently translated at 100.0% (7 of 7 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/de/
2022-12-10 17:09:43 -03:00
sk22
bfbd21b826 Translated using Weblate (German)
Currently translated at 100.0% (47 of 47 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-10 17:09:37 -03:00
sk
ba8683301d remove upstream fastlane changes 2022-12-10 17:09:37 -03:00
sk22
0ed178167b Translated using Weblate (German)
Currently translated at 100.0% (7 of 7 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/de/
2022-12-10 17:09:27 -03:00
Grishka
b34e34de51 Fix #443 again 2022-12-10 17:08:40 -03:00
LucasGGamerM
ba38e21e07 Changing back the link on settings to Moshidon 2022-12-10 16:43:03 -03:00
LucasGGamerM
90bef7fddb Merge branch 'material3_dynamic_color_theme' 2022-12-10 13:18:06 -03:00
LucasGGamerM
c1b382ef34 Fixing some minor inconsistencies 2022-12-10 13:17:28 -03:00
LucasGGamerM
028b88aa24 Bumping version code 2022-12-10 13:02:28 -03:00
LucasGGamerM
9d0ce33f5e Making material you setting work fine. Its ready for release 2022-12-10 12:59:24 -03:00
LucasGGamerM
dbb23d952c Adding the color things 2022-12-10 11:58:29 -03:00
LucasGGamerM
7fe7e47d53 Updating the readme again 2022-12-10 10:21:15 -03:00
LucasGGamerM
d0c93dfd4d Updating the readme 2022-12-10 10:18:19 -03:00
LucasGGamerM
acdccaf80a Bumping version code 2022-12-10 10:01:57 -03:00
LucasGGamerM
769293ce1a Changing translate icon 2022-12-10 09:56:53 -03:00
LucasGGamerM
8d0fe18b70 Fixing the notification color, and app name 2022-12-10 09:33:36 -03:00
LucasGGamerM
6926432a6c Bumping version number 2022-12-09 20:10:06 -03:00
LucasGGamerM
83f12b0840 Fixing the sk references. Readding them for easier translation 2022-12-09 19:58:33 -03:00
LucasGGamerM
290b7db7e4 This is unbrokey. Merged changes from upstream. 2022-12-09 19:35:15 -03:00
LucasGGamerM
f352c20ed9 This is quite brokey 2022-12-09 19:20:47 -03:00
LucasGGamerM
2ccbffa165 Merge branch 'main' into fork
# Conflicts:
#	README.md
#	mastodon/build.gradle
#	mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/SettingsFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java
#	mastodon/src/main/res/color/button_text_primary_light_on_dark.xml
#	mastodon/src/main/res/drawable/logo.xml
#	mastodon/src/main/res/layout/item_settings_color_picker.xml
#	mastodon/src/main/res/menu/color_picker.xml
#	mastodon/src/main/res/values-night/styles.xml
#	mastodon/src/main/res/values-v27/colors.xml
#	mastodon/src/main/res/values/colors.xml
#	mastodon/src/main/res/values/strings.xml
#	mastodon/src/main/res/values/styles.xml
2022-12-09 19:08:35 -03:00
LucasGGamerM
06cd80a352 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java
2022-12-09 18:35:52 -03:00
LucasGGamerM
de97493e6a Update README.md 2022-12-09 14:04:38 -03:00
LucasGGamerM
3a24ff0d15 Bumping version code 2022-12-09 13:44:46 -03:00
LucasGGamerM
c463a3fc39 The front end if finally ready! 2022-12-09 13:42:29 -03:00
LucasGGamerM
fc845685cc Almost there 2022-12-09 12:25:17 -03:00
LucasGGamerM
0ef0aa1a44 The api side is finally working perfectly! 2022-12-09 10:30:24 -03:00
LucasGGamerM
337689aa45 The api side is actually working! 2022-12-08 21:17:11 -03:00
LucasGGamerM
f7e3423f9c Bumping version number 2022-12-08 15:16:22 -03:00
LucasGGamerM
b465c09cc8 Fixing the "Megalodon" name on logging into a new account 2022-12-08 15:01:46 -03:00
LucasGGamerM
ac6c0651d6 Update README.md 2022-12-07 14:32:42 -03:00
LucasGGamerM
18af6f5a12 Bumping version code 2022-12-07 14:24:52 -03:00
LucasGGamerM
d11ee3a702 Update README.md 2022-12-07 14:16:48 -03:00
LucasGGamerM
6d9f9ce2d2 Update README.md 2022-12-07 14:14:34 -03:00
LucasGGamerM
ec1496a4cc Editing the readme 2022-12-07 14:08:28 -03:00
LucasGGamerM
41e19185e8 Edited the color of the new instance search box 2022-12-07 14:06:28 -03:00
LucasGGamerM
e15dd6024f Bumped version number 2022-12-07 13:28:07 -03:00
LucasGGamerM
e52dffeece Fix notification logo and lets start splash screen button color 2022-12-07 12:46:26 -03:00
LucasGGamerM
5b85bb427d bumping version code 2022-12-07 09:50:03 -03:00
LucasGGamerM
4d62388617 Fixing the notification icon once again... 2022-12-07 09:36:50 -03:00
LucasGGamerM
04b8055474 Fixing the notification icon once more 2022-12-07 09:22:18 -03:00
LucasGGamerM
3c34b6a7d2 Upping the version code once more, and fixing the self updater 2022-12-06 22:06:49 -03:00
LucasGGamerM
de4964c2cd Upping the version code and changing notification icon. This should be the first release 2022-12-06 21:58:35 -03:00
LucasGGamerM
fbcaa05c03 Changing the name of the archivesBaseName 2022-12-06 21:49:46 -03:00
LucasGGamerM
883f28696e Editing a while lot of files. New icon, new notification icon, a bunch of new stuff! 2022-12-06 21:21:43 -03:00
LucasGGamerM
df52230837 Editing the readme just in case 2022-12-06 19:23:28 -03:00
LucasGGamerM
a90f26a37a Setting update client 2022-12-06 19:20:47 -03:00
LucasGGamerM
8c1f76d7fa Initial Moshidon "release" 2022-12-06 19:17:07 -03:00
LucasGGamerM
f384d44f8f Changing my app id 2022-12-06 13:03:26 -03:00
LucasGGamerM
4ab6ed55f5 Changing my version number and string 2022-12-06 12:41:03 -03:00
LucasGGamerM
cf99bf5152 Merge branch 'proper_implementation_of_the_color_picker'
Just fixing stuff here and there
2022-12-05 17:47:03 -03:00
LucasGGamerM
10779717cf Make follow requests icon badge follow the color scheme and also make it that the profile top bar menu also follows the theme. This should be it 2022-12-05 17:20:40 -03:00
LucasGGamerM
4e5c2a9ecf add new megalodon logo text
closes #129
2022-12-05 18:29:03 +01:00
LucasGGamerM
db4c1bfe47 Merge branch 'proper_implementation_of_the_color_picker'
Just making it tidy and better :D
2022-12-05 14:11:20 -03:00
LucasGGamerM
27afba1cf2 Making it so that the boost icon is also following the theme when clicked 2022-12-05 14:10:34 -03:00
LucasGGamerM
4895425b40 Adding a proper logo to the top of the home timeline 2022-12-05 13:27:09 -03:00
LucasGGamerM
004c414fba Editing some drawable files to make them also follow the theme 2022-12-05 09:41:56 -03:00
LucasGGamerM
c8e38b134c Fixing weird bug with the buttons for the second time 2022-12-05 09:03:48 -03:00
LucasGGamerM
de5a911286 Fixing weird bug with the buttons 2022-12-04 22:52:27 -03:00
LucasGGamerM
606cd7442e Make it so that the publish button also follows the theme 2022-12-04 14:45:42 -03:00
LucasGGamerM
3ebc972268 Fixing the TrueBlack themes for everything 2022-12-04 14:00:10 -03:00
LucasGGamerM
4e39bb381c Making it so that the fab follows the theme 2022-12-04 13:14:38 -03:00
LucasGGamerM
b6178681b0 Adding yellow theme 2022-12-04 11:42:41 -03:00
LucasGGamerM
29abf70cec Adding orange theme, tweaking the blue and green theme 2022-12-04 11:16:58 -03:00
LucasGGamerM
8d63be513d Fix readability issue on the light blue theme 2022-12-04 10:24:51 -03:00
LucasGGamerM
e63b9d0dd6 Adding an icon to the color picker setting 2022-12-03 22:29:41 -03:00
LucasGGamerM
b1fda17ac7 Make badged settings icon follow accent colors 2022-12-03 16:48:12 -03:00
LucasGGamerM
bad44b145c Adding blue theme and refactoring styles.xml 2022-12-03 16:25:28 -03:00
LucasGGamerM
77669cedf6 More polishes over the green theme 2022-12-03 13:44:40 -03:00
LucasGGamerM
19238c389f Making the green theme more readable 2022-12-03 12:29:51 -03:00
LucasGGamerM
1747ff98b5 Adding a green theme 2022-12-02 14:00:58 -03:00
LucasGGamerM
8fa5824e3e Disabling the icons for the color picker menu 2022-12-02 11:58:40 -03:00
LucasGGamerM
6a674d7a7e Polishes 2022-12-01 19:55:53 -03:00
LucasGGamerM
dad3b8cd6b Proper implementation on the color picker. 2022-12-01 19:42:21 -03:00
LucasGGamerM
9179d2198d Fully fixed now, it should be ready to release. 2022-11-29 13:09:32 -03:00
LucasGGamerM
d096bef234 Fixing the fix of the bug I found. 2022-11-28 21:30:32 -03:00
LucasGGamerM
f2c47a1b84 Fixing another bug I found. 2022-11-28 21:24:00 -03:00
LucasGGamerM
bc2ac4e915 Fixed a few bugs from the earlier commit. 2022-11-28 16:47:04 -03:00
LucasGGamerM
ff215412c8 Adding mastodon original colors toggle. Partially fixing #90 2022-11-28 15:40:29 -03:00
882 changed files with 7237 additions and 20569 deletions

3
.github/FUNDING.yml vendored
View File

@@ -1,9 +1,8 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
github: LucasGGamerM
patreon: # mastodon
open_collective: # Replace with a single Open Collective username e.g., user1
ko_fi: xsk22
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username e.g., user1

View File

@@ -8,35 +8,25 @@ assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To reproduce**
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Does this happen in the official app?**
Does this issue also occur with the respective upstream release?
(Please test using the respective `upstream-xxxxxx.apk` provided in [Releases](https://github.com/sk22/megalodon/releases) or at least using the current Mastodon version from the Play Store)
> No / Yes
> In case it does, please consider filing an [upstream bug report](https://github.com/mastodon/mastodon-android/issues) instead.
> If this bug is seriously impacting your usage or you think I might want to try to fix it for Megalodon, feel free to still create this issue!
**Screenshots and screen recordings**
If applicable, add screenshots (and screen recordings, if possible) to help explain your problem.
**Version**
Megalodon version: [e.g. v1.1.4+fork.#]
**Crash log**
**Additional context**
- Does this issue also occur with the respective upstream release? (Please test using the respective `upstream-xxxxxx.apk` provided in [Releases](https://github.com/sk22/megalodon/releases)) No / Yes (`mastodon#…`)
> In this case, please consider filing an [upstream bug report](https://github.com/mastodon/mastodon-android/issues) instead. If this bug is seriously impacting your usage or you think I might want to try to fix it for Megalodon, feel free to still create this issue!
**Crash log**
If you know your way around Android development tools, please consider attaching a crash log, if possible.

View File

@@ -1,11 +0,0 @@
name: Validate Gradle Wrapper
on: [pull_request, push]
jobs:
validation:
name: Validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: gradle/wrapper-validation-action@v1

177
README.md
View File

@@ -1,122 +1,74 @@
![Pink logo with pink shark](mastodon/src/main/res/mipmap-xhdpi/ic_launcher_round.png)
![MoshidonLogo](mastodon/src/main/res/mipmap-xhdpi/ic_launcher_round.png)
# Megalodon
# Moshidon, the material you mastodon client!
[![Translation status](https://translate.codeberg.org/widgets/megalodon/-/svg-badge.svg)](https://translate.codeberg.org/engage/megalodon/)
&nbsp;
[![Download latest release](https://img.shields.io/badge/dynamic/json?color=d92aad&label=Download%20APK&query=%24.tag_name&url=https%3A%2F%2Fapi.github.com%2Frepos%2Fsk22%2Fmegalodon%2Freleases%2Flatest&style=flat)](https://github.com/sk22/megalodon/releases/latest/download/megalodon.apk)
> A fork of [megalodon](https://github.com/sk22/megalodon) which is a fork of [official Mastodon Android app](https://github.com/mastodon/mastodon-android) adding important features that are missing in the official app and possibly wont ever be implemented, such as the federated timeline, unlisted posting, bookmarks and an image description viewer.
<a href="https://play.google.com/store/apps/details?id=org.joinmastodon.android.sk"><img height="50" alt="Get it on Google Play" src="img/google-play-badge.png"></a>
&nbsp;
<a href="#installation"><img height="50" alt="Get it on IzzyOnDroid" src="img/izzy-badge.png"></a>
> A fork of the [Mastodon Android app](https://github.com/mastodon/mastodon-android) adding important features that are missing in the official app, focusing on [Glitch](https://glitch-soc.github.io/docs) compatibility, a pretty UI and adding new features that I feel make using the Fediverse a more pleasent experience.
[![Download latest release](https://img.shields.io/badge/dynamic/json?color=282C37&label=download%20apk&query=%24.tag_name&url=https%3A%2F%2Fapi.github.com%2Frepos%2FLucasGGamerM%2Fmoshidon%2Freleases%2Flatest&style=for-the-badge)](https://github.com/LucasGGamerM/moshidon/releases/latest/download/moshidon.apk)
---
## Key features
### **Material you theme support on Android 12+ devices!**
### **Color themes**
**Allows you to change theme within the app. Supports Purple, pink, green, blue, orange and yellow!**
### **Unlisted posting**
<details>
<p><summary>Allows you to post publicly without having your post show up in trends, hashtags or public timelines (i.e., in the tabs “Community”, “Federated” and “Posts”).</summary></p>
When posting with Unlisted visibility, your posts will still be publicly accessible in your profile. They will also be shown in peoples Home timelines, but only if they follow you or someone they follow reblogged/replied to your post.
**Allows you to post publicly without having your post show up in trends, hashtags or public timelines (i.e., in the tabs “Local”, “Community” and “Posts”).**
When posting with Unlisted visibility, your posts will still be publicly accessible in your profile. They will also be shown in peoples Home timelines, but only if they follow you or someone they follow reposted/replied to your post.
The Mastodon documentation has some more information about [Unlisted posting](https://docs.joinmastodon.org/user/posting/#unlisted) and [Public timelines](https://docs.joinmastodon.org/user/network/#timelines).
</details>
### **Federated timeline**
<details>
<p><summary>This allows you to chronologically see all Public posts from people on all other Fediverse neighborhoods your home instance is connected to.</summary></p>
**This allows you to chronologically see all Public posts from people on all other Fediverse neighborhoods your home instance is connected to.**
Despite being one of the main features of federated social media, the Federated timeline wasnt included in the official Mastodon app supposedly, because this conflicts with Googles safety requirements for apps on the Play Store.
Thats one of the reasons why choosing a small, **well-moderated instance is important**. Instance admins and moderators should always make sure to ban abusive users and stop federating with instances who platform them. On well-moderated instances, the Federated timeline can be a welcoming place to meet new people!
</details>
### **Customizable timelines**
### **Image description viewer**
<details>
<p><summary>You can customize Megalodons home tab and not only add local and federated timelines, but also pin lists and hashtags.</summary></p>
**Allows you to quickly check whether an image or video has an alternative text attached to it.**
Even better: You can rename every timeline however you please and pick a distinct icon for each timeline. This way, you can pin the hashtag “#Caturday”, rename your timeline to “CUTENESS OVERLOAD” and set <img src="img/ic_fluent_animal_cat_24_regular.svg" alt="Cat icon from Microsoft Fluent UI icons"> as its icon. :3 You can find the timelines editor by opening your home tab, tapping the `⋮` button in the top right and going to “Edit timelines”.
</details>
This is important to **ensure the content youre sharing is as accessible as possible** to people who cant see the images and rely on software to read back the provided content descriptions. Thankfully, its quite common for people on the Fediverse to provide such alt texts, and hopefully things stay this way!
### **Draft and schedule posts**
### **Pinning posts**
<details>
<p><summary>
Allows to prepare a post and schedule it to send it automatically at a specific time.</summary></p>
**This lets you can highlight important posts on your profile. A dedicated “Pinned” tab in peoples profiles shows all the posts they pinned.**
You can create drafts, edit them, send them manually later or set a scheduled date. Drafts are technically saved as scheduled posts, so you can view and edit them from other apps that support scheduled posts. Scheduled posts are handled by your home instance, so they'll work even if you uninstall Megalodon.
</details>
On the Fediverse, its quite common for people to pin posts they want others to read before following them. You can pin/unpin posts yourself by clicking the `⋯` button in the top right corner of your posts.
### **Bookmarks**
**They allow for quickly saving posts and viewing them through the Bookmarks button on the top right of your profile.**
To bookmark a post, press the button between the Favorite and Share buttons on the bottom of the post. Bookmarks are saved privately, so the post authors wont know you saved their post the list of bookmarked posts is only visible to you.
## Installation
### IzzyOnDroid
**Press the download button above to download the APK. Open the downloaded file on your Android device to install it. Moshidon will automatically notify you about new updates inside the app.**
[apt.izzysoft.de/fdroid/index/apk/org.joinmastodon.android.sk](https://apt.izzysoft.de/fdroid/index/apk/org.joinmastodon.android.sk)
To install this app on your Android device, download the [latest release from GitHub](https://github.com/LucasGGamerM/moshidon/releases/latest/download/moshidon.apk) and open it. You might have to accept installing APK files from your browser when trying to install it. You can also take a look at all releases on the [Releases](https://github.com/LucasGGamerM/moshidon/releases) page.
<a href="https://apt.izzysoft.de/fdroid/index/apk/org.joinmastodon.android.sk"><img height="50" alt="Get it on IzzyOnDroid" src="img/izzy-badge.png"></a>
Moshidon makes use of [Mastodon for Android](https://github.com/mastodon/mastodon-android)s automatic update checker. Megalodon will check for new updates available on GitHub and offer to download and install them. You can also manually press “Check for updates” at the bottom of the settings page!
Note that you'll need to add Izzy's F-Droid repository to your F-Droid app first:
[`https://apt.izzysoft.de/fdroid/repo`](https://apt.izzysoft.de/fdroid/repo)
### Google Play Store
[play.google.com/store/apps/details?id=org.joinmastodon.android.sk](https://play.google.com/store/apps/details?id=org.joinmastodon.android.sk)
<a href="https://play.google.com/store/apps/details?id=org.joinmastodon.android.sk"><img height="50" alt="Get it on Google Play" src="img/google-play-badge.png"></a>
### F-Droid
**[F-Droid.org?](https://f-droid.org)** Not yet, sorry!
If you want, you can help me figure out if something's missing in the [Issue #47: F-Droid.org](https://github.com/sk22/megalodon/issues/47)
### Direct
Press the download button to download the APK. Open the downloaded file on your Android device to install it. Megalodon will automatically notify you about new updates inside the app.
[![Download latest release](https://img.shields.io/badge/dynamic/json?color=d92aad&label=Download%20APK&query=%24.tag_name&url=https%3A%2F%2Fapi.github.com%2Frepos%2Fsk22%2Fmegalodon%2Freleases%2Flatest&style=flat)](https://github.com/sk22/megalodon/releases/latest/download/megalodon.apk)
You might have to accept installing APK files from your browser when trying to install it. You can also take a look at all releases on the [Releases](https://github.com/sk22/megalodon/releases) page.
Megalodon makes use of [Mastodon for Android](https://github.com/mastodon/mastodon-android)s automatic update checker. Megalodon will check for new updates available on GitHub and offer to download and install them. You can also manually press “Check for updates” at the bottom of the settings page!
---
## Release variants
All downloads can be found on the [Releases](https://github.com/sk22/megalodon/releases) page. When downloading a pre-release, expect to see unfinished features and bugs. If you dont want that, just download the [latest full release](https://github.com/sk22/megalodon/releases/latest/download/megalodon.apk).
All downloads can be found on the [Releases](https://github.com/LucasGGamerM/moshidon/releases) page.
**`megalodon.apk`**
Variant with an integrated updater. If you download Megalodon from here (and not from an app store), just download the regular `megalodon.apk`.
**`upstream-1234abc.apk`**
This is an **unmodified version** of the official [Mastodon for Android](https://github.com/mastodon/mastodon-android) app the respective Megalodon release is based on. Should you find any bugs in Megalodon (which you will), try to see if it occurs with this variant, too. The last 7 digits of the file name are important to know which version of the official app you're using.
<!-- **`megalodon-fdroid.apk`**
Variant without the integrated updater. This is the variant to be published to F-Droid.org where an integrated updater is not necessary. -->
---
## Contribution
### Translation
The translation for the base of the app is sourced from the upstream **Mastodon for Android** project, which you can contribute to on its Crowdin project: [https://crowdin.com/project/mastodon-for-android](https://crowdin.com/project/mastodon-for-android)
There's also a bunch of custom strings exclusive to this project that need to be translated. You can help translate **Megalodon** on Weblate: [https://translate.codeberg.org/projects/megalodon](https://translate.codeberg.org/projects/megalodon)
[![Translation status](https://translate.codeberg.org/widgets/megalodon/-/horizontal-auto.svg)](https://translate.codeberg.org/engage/megalodon)
**`moshidon.apk`**
Variant with an integrated updater. If you download Moshidon from here (and not from an app store), just download the regular `moshidon.apk`.
---
@@ -127,14 +79,19 @@ There's also a bunch of custom strings exclusive to this project that need to be
* [Add “Unlisted” as a post visibility option](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/enable-unlisted)
([Pull request](https://github.com/mastodon/mastodon-android/pull/103))
* [Add “Federation” tab and change Discover tab order](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/add-federated-timeline) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/8))
* Adding a useful private profile note box!*
* Auto hiding the compose button on scroll!*
* Adding the hability to remind yourself to add alt text to images!*
* Adding the ability to have drafts!*
* Also adding the ability to view announcements from your instance!*
* Adding the ability to post for local timeline only (Only on instances that support it!)*
* [Add image description button and viewer](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/display-alt-text) ([Pull request](https://github.com/mastodon/mastodon-android/pull/129))
* [Implement pinning posts and displaying pinned posts](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/pin-posts) ([Pull request](https://github.com/mastodon/mastodon-android/pull/140))
* [Implement deleting and re-drafting](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/delete-redraft) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/21))
* [Implement a bookmark button and list](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/bookmarks) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/22))
* [Add “Check for update” button in addition to integrated update checker](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/check-for-update-button)
* [Add “Mark media as sensitive” option](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/mark-media-as-sensitive)
* [Add settings to hide replies and reblogs from the timeline](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/filter-home-timeline) ([Pull request](https://github.com/mastodon/mastodon-android/pull/317))
* [Add settings to hide replies and reposts from the timeline](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/filter-home-timeline) ([Pull request](https://github.com/mastodon/mastodon-android/pull/317))
* [Follow and unfollow hashtags](https://github.com/sk22/megalodon/commit/7d38f031f197aa6cefaf53e39d929538689c1e4e) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/233))
* [Notification bell for posts](https://github.com/sk22/megalodon/commit/b166ca705eb9169025ef32bbe6315b42491b57ea) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/81))
* [Viewing lists and adding/removing users from lists](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:list-timeline-views) based on [@obstsalatschuessel](https://github.com/obstsalatschuessel)'s [Pull request](https://github.com/mastodon/mastodon-android/pull/286)
@@ -144,27 +101,12 @@ There's also a bunch of custom strings exclusive to this project that need to be
* [Add notifications tab for posts](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/posts-notifications-tab)
* [Show visibility of original post when replying](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/display-reply-visibility)
* [Clickable reply/boost line above posts](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:clickable-boost-reply-line)
* [Add push notification setting for post notifications](https://github.com/sk22/megalodon/commit/b190480d7739be47f23543d9e7644660f9b4b4ee)
* [Add option to allow voting for multiple options on polls](https://github.com/sk22/megalodon/commit/5b28468efd49387b4f8b83f142f3adf3104ca60c)
* [Add translate function](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/translate-button)
* [Add language selector](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/language-selector)
* [Implement deleting notifications](https://github.com/sk22/megalodon/commit/b0f9ce081f69f29ad59658fc00ca41372cd2677d) (disabled by default)
* [Long-click boost button to "quote" a post](https://github.com/sk22/megalodon/commit/b25a237c20c6a924ed4d9b357999867c3a32b32b)
* [Draft and schedule posts](https://github.com/sk22/megalodon/pull/217)
* [Display original post when replying](https://github.com/sk22/megalodon/commit/375f8ceb2747705fedf43686681cc0e0b812f899)
* [Display server announcements](https://github.com/sk22/megalodon/commit/84179bc207d6b69cc2a770a3c28fa0a39b0b54e8)
* [Create](https://github.com/sk22/megalodon/commit/294595513a45037359b31377aafc25ae5b58d8e7), [edit](https://github.com/sk22/megalodon/commit/d47797bf7ac8cff3f9ba1cfee219a1bb2af21da6) and [delete](https://github.com/sk22/megalodon/commit/54c29fd787fc2cd0dfd2787ad796b8190f795973) lists
* [Soft-blocking (by blocking and immediately unblocking)](https://github.com/sk22/megalodon/commit/e75d350b7a2709259e9fc5138e0e1f361bdb0972)
* [Pinnable custom timelines](https://github.com/sk22/megalodon/pull/338/commits)
* Support for local-only posts
* Support for copying the URL to posts/accounts/… in Pixel launchers Recent apps view
* Compatibility for Akkoma Bubble timeline
* Listings of followers/following/favorites/boosts can be loaded from the origin instance (theres an option to disable this in in the settings)
* Allow opening posts/accounts in-app by sharing a URL/handle to Megalodon (Originally implemented in [Moshidon](https://github.com/LucasGGamerM/moshidon), [PR](https://github.com/sk22/megalodon/pull/531))
* [Clickable reply line while replying to open original post](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/clickable-reply-line-compose)
### Behavior
* Adding a bottom option for the publish button, allowing for easier user on larger screens!
* [Make back button return to the home tab before exiting the app](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/back-returns-home) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/118))
* [Always preserve content warnings when replying](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/always-preserve-cw) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/113))
* [Display full image when adding image description](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/compose-image-description-full-image) ([Pull request](https://github.com/mastodon/mastodon-android/pull/182))
@@ -172,22 +114,6 @@ There's also a bunch of custom strings exclusive to this project that need to be
* [Option to hide interaction numbers](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:settings/hide-interaction-numbers)
* [Option to always reveal content warnings](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/cw-above-text)
* [Option to disable scrolling title bars](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:settings/disable-marquee)
* [No ellipsis for long poll answers](https://github.com/mastodon/mastodon-android/commit/c9aae828e2518adccdc092e41f8d1f0489636271)
* [Show poll vote button for multiple and single answer polls](https://github.com/mastodon/mastodon-android/commit/e14dfda2fdf32f0fa3043504ac5831683a87559a)
* [Show own vote after voting](https://github.com/mastodon/mastodon-android/commit/4ab9e25fec4fd9c10b7a8ddd1be522b3cc12cf28) ([Closes issue](https://github.com/mastodon/mastodon-android/commit/4ab9e25fec4fd9c10b7a8ddd1be522b3cc12cf28))
* [Make inline emoji search case-insensitive and don't only search from start of emoji names](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:better-inline-emoji-search) ([Pull request](https://github.com/mastodon/mastodon-android/pull/445))
* [Include subject line when sharing e.g. a website to Megalodon](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:external-share-include-subject)
* [Improve semantics for voting on polls (radio buttons and checkboxes)](https://github.com/sk22/megalodon/commit/6fd58c96827cb1d2da329cebdc170a1425dd18d7)
* [Copy post URL when long-pressing share button](https://github.com/sk22/megalodon/commit/ba36347f03278763ecec617b1ce57ba89db7be72)
* [Add option to disable swiping between tabs](https://github.com/sk22/megalodon/commit/1f20b21fc84bf006c1ec14bd2229cbfad5215ec8)
* [Resolve Fediverse links in the app](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/open-urls-in-app)
* [Preserve whitespaces in HTML](https://github.com/sk22/megalodon/commit/7d876bddc7a07d98f0fecbf62b13bdb9fcce3412)
* [Long-click to copy links](https://github.com/sk22/megalodon/commit/b32e32274923a94742a9926ef38785f746d41405)
* Improved filtering using Mastodon 4.0 API: [#202](https://github.com/sk22/megalodon/pull/202), [#212](https://github.com/sk22/megalodon/pull/212), [#255](https://github.com/sk22/megalodon/pull/255) by [@thiagojedi](https://github.com/thiagojedi)
* [Support admin notifications](https://github.com/sk22/megalodon/commit/c12a6eaee6b609bc53eb0a45d9199f37d5241801) and [notifications for edited reblogged posts](https://github.com/sk22/megalodon/commit/900e8fb2e9353002c16d15e06b78d2731e121601)
* [Android file opener added back in addition to image picker](https://github.com/sk22/megalodon/commit/3a6ace53d5ab01e28077c9c930cb6ed487b78031)
* [Replies are inserted below the replied-to post in thread view](https://github.com/sk22/megalodon/commit/87c37df370ec24aeea0d2dbaeb29468aa4fb5808)
* Option to auto-reveal equal content warnings in threads
### Visual
@@ -195,17 +121,6 @@ There's also a bunch of custom strings exclusive to this project that need to be
* [Custom extended footer redesign](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:compact-extended-footer)
* [Improvements to the true black mode](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:true-black-improvements)
* [Profile header tweaks](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:ui/profile-header-tweaks)
* [Custom color themes](https://github.com/sk22/megalodon/pull/124) by [@LucasGGamerM](https://github.com/LucasGGamerM)
* [Custom "megalodon" text logo](https://github.com/sk22/megalodon/commit/563afd487ca5c608cfbb00fa3909d3c27384acc0) by [@LucasGGamerM](https://github.com/LucasGGamerM)
* [Custom login screen](https://github.com/sk22/megalodon/commit/9bbf8c4618dbe13accaeb3b5482bf3fe88cac4c0)
* [More distinct filled boost icon](https://github.com/sk22/megalodon/commits/more-distinct-filled-boost-icon)
* Material You color theme by [@LucasGGamerM](https://github.com/LucasGGamerM)
* [Animations for interaction buttons](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/animate-buttons)
* [Dedicated icons for different notification types](https://github.com/sk22/megalodon/pull/178) by [@florian-obernberger](https://github.com/florian-obernberger)
* Scale text according to system settings
* Header in timeline for followed hashtags
* [Indicator for missing alt texts](https://github.com/sk22/megalodon/commit/c0c276f03e793b78c478c17dfdef24a66ef7cedb)
* Visually grouped (by removing divider lines and reducing padding) threaded replies in thread view
## Building
@@ -216,12 +131,12 @@ As this app is using Java 17 features, you need JDK 17 or newer to build it. Oth
./gradlew assembleRelease
```
Note that Megalodon might be depending on an in-development version of [AppKit](https://github.com/grishka/appkit) a library by Mastodon for Androids developer. In case the used AppKit version isnt published to Maven Central yet, you might have to clone, build and publish it to your local Maven repository. For more information, see [this GitHub issue](https://github.com/mastodon/mastodon-android/issues/375#issuecomment-1507678585).
## License
This project is released under the [GPL-3 License](./LICENSE).
## Links
<a rel="me" href="https://floss.social/@megalodon">@megalodon<wbr>@floss.social</a>
[Official matrix chatroom:](https://matrix.to/#/#moshidon:matrix.org) https://matrix.to/#/#moshidon:matrix.org
<a rel="me" href="https://floss.social/@moshidon">@moshidon<wbr>@floss.social</a>

View File

@@ -1,2 +1,2 @@
title: Megalodon
title: Moshidon
layout: default

View File

@@ -4,9 +4,9 @@
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Megalodon</title>
<title>Moshidon</title>
<link rel="icon" href="mastodon/src/main/res/mipmap-mdpi/ic_launcher_round.png">
<link rel="me" href="https://floss.social/@megalodon">
<link rel="me" href="https://floss.social/@mastodon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.1.0/github-markdown.min.css">
</head>
<body class="markdown-body">
@@ -14,4 +14,4 @@
{{ content }}
</div>
</body>
</html>
</html>

View File

@@ -5,7 +5,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.0.0'
classpath 'com.android.tools.build:gradle:7.3.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}

5
crowdin.yml Normal file
View File

@@ -0,0 +1,5 @@
files:
- source: /mastodon/src/main/res/values/strings.xml
translation: /mastodon/src/main/res/values-%android_code%/strings.xml
- source: /fastlane/metadata/android/en-US/*.txt
translation: /fastlane/metadata/android/%locale%/%original_file_name%

View File

@@ -1,3 +0,0 @@
#!/bin/bash
find metadata -name '*.txt' -exec sed -Ei 's/^[–—─•·*]\s+/- /' {} \;

View File

@@ -16,7 +16,4 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=false
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=true
android.nonFinalResIds=false
android.enableJetifier=true

Binary file not shown.

View File

@@ -1,7 +1,6 @@
#Thu Jan 13 11:33:43 MSK 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionPath=wrapper/dists
distributionSha256Sum=e111cb9948407e26351227dabce49822fb88c37ee72f1d1582a69c68af2e702f
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

276
gradlew vendored
View File

@@ -1,7 +1,7 @@
#!/bin/sh
#!/usr/bin/env sh
#
# Copyright © 2015-2021 the original authors.
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,98 +17,67 @@
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
MAX_FD="maximum"
warn () {
echo "$*"
} >&2
}
die () {
echo
echo "$*"
echo
exit 1
} >&2
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -118,9 +87,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD=$JAVA_HOME/bin/java
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -129,7 +98,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@@ -137,109 +106,80 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=$( cygpath --unix "$JAVACMD" )
JAVACMD=`cygpath --unix "$JAVACMD"`
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

15
gradlew.bat vendored
View File

@@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,8 +25,7 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -41,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -76,15 +75,13 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal

View File

@@ -1,9 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<style>
path { fill: black; }
@media (prefers-color-scheme: dark) {
path { fill: white; }
}
</style>
<path d="M15.4925 3.50673C14.652 3.58251 13.9933 4.28929 13.9933 5.15V10C13.9933 10.4142 13.6577 10.75 13.2437 10.75C11.8002 10.75 10.7863 11.3378 10.0365 12.238C9.26389 13.1656 8.7607 14.444 8.44554 15.7954C8.13254 17.1376 8.01871 18.4912 7.98453 19.5172C7.97182 19.8987 7.9702 20.2324 7.97313 20.5H14.9928V19.75C14.9928 18.5074 13.986 17.5 12.744 17.5H11.4947C11.0807 17.5 10.7451 17.1642 10.7451 16.75C10.7451 16.3358 11.0807 16 11.4947 16H12.744C14.8139 16 16.4919 17.6789 16.4919 19.75V20.5H17.2415C17.6555 20.5 17.9911 20.1642 17.9911 19.75V9.75C17.9911 9.33579 18.3267 9 18.7407 9H19.2472C20.2264 9 20.8249 7.92404 20.309 7.09132L19.6893 6.09132C19.4615 5.72367 19.0599 5.5 18.6275 5.5H16.2421C15.8281 5.5 15.4925 5.16421 15.4925 4.75V3.50673ZM6.47388 20.5C6.47098 20.2156 6.47293 19.8655 6.4862 19.4672C6.52229 18.3838 6.64271 16.9249 6.98559 15.4546C7.32631 13.9935 7.90065 12.4594 8.88484 11.2777C9.75681 10.2307 10.9399 9.47669 12.4942 9.29318V5.15C12.4942 3.4103 13.9037 2 15.6424 2C16.3876 2 16.9916 2.60442 16.9916 3.35V4H18.6275C19.5787 4 20.4622 4.49207 20.9634 5.30092L21.5831 6.30092C22.6749 8.06291 21.4985 10.32 19.4903 10.4898V19.75C19.4903 20.9926 18.4835 22 17.2415 22H7.24708L7.24537 22H5.79625C3.69964 22 2 20.2994 2 18.2016C2 17.2395 2.36489 16.3133 3.02098 15.6099L4.15612 14.393C4.92005 13.5741 5.17521 12.4027 4.82117 11.3399C4.67114 10.8896 4.41837 10.4804 4.08288 10.1447L2.96914 9.03042C2.67641 8.73753 2.67639 8.26266 2.96912 7.96976C3.26184 7.67686 3.73645 7.67685 4.02919 7.96974L5.14293 9.08405C5.643 9.58438 6.01977 10.1943 6.2434 10.8656C6.77114 12.4497 6.3908 14.1958 5.25209 15.4165L4.11695 16.6334C3.71996 17.059 3.49916 17.6195 3.49916 18.2016C3.49916 19.471 4.52761 20.5 5.79625 20.5H6.47388Z" fill="#212121"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -2,24 +2,18 @@ plugins {
id 'com.android.application'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
android {
compileSdk 33
defaultConfig {
archivesBaseName = "megalodon"
applicationId "org.joinmastodon.android.sk"
archivesBaseName = "moshidon"
applicationId "org.joinmastodon.android.moshinda"
minSdk 23
targetSdk 33
versionCode 94
versionName "1.2.3+fork.94"
versionCode 90
versionName "1.1.4+fork.90.moshinda"
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']
}
resConfigs "ar-rSA", "be-rBY", "bn-rBD", "bs-rBA", "ca-rES", "cs-rCZ", "de-rDE", "el-rGR", "es-rES", "eu-rES", "fi-rFI", "fil-rPH", "fr-rFR", "ga-rIE", "gd-rGB", "gl-rES", "hi-rIN", "hr-rHR", "hu-rHU", "hy-rAM", "in-rID", "is-rIS", "it-rIT", "iw-rIL", "ja-rJP", "kab", "ko-rKR", "nl-rNL", "oc-rFR", "pl-rPL", "pt-rBR", "pt-rPT", "ro-rRO", "ru-rRU", "si-rLK", "sl-rSI", "sv-rSE", "th-rTH", "tr-rTR", "uk-rUA", "vi-rVN", "zh-rCN", "zh-rTW"
}
buildTypes {
release {
@@ -55,19 +49,14 @@ android {
setRoot "src/github"
}
}
namespace 'org.joinmastodon.android'
lint {
abortOnError false
lintOptions{
checkReleaseBuilds false
}
buildFeatures {
buildConfig true
abortOnError false
}
}
dependencies {
api 'androidx.annotation:annotation:1.6.0'
api 'androidx.annotation:annotation:1.3.0'
implementation 'com.squareup.okhttp3:okhttp:3.14.9'
implementation 'me.grishka.litex:recyclerview:1.2.1.1'
implementation 'me.grishka.litex:swiperefreshlayout:1.1.0.1'
@@ -75,13 +64,12 @@ dependencies {
implementation 'me.grishka.litex:dynamicanimation:1.1.0-alpha03'
implementation 'me.grishka.litex:viewpager:1.0.0'
implementation 'me.grishka.litex:viewpager2:1.0.0'
implementation 'me.grishka.appkit:appkit:1.2.8'
implementation 'com.google.code.gson:gson:2.9.0'
implementation 'me.grishka.appkit:appkit:1.2.7'
implementation 'com.google.code.gson:gson:2.8.9'
implementation 'org.jsoup:jsoup:1.14.3'
implementation 'com.squareup:otto:1.3.8'
implementation 'de.psdev:async-otto:1.0.3'
implementation 'org.parceler:parceler-api:1.1.12'
implementation 'com.github.bottom-software-foundation:bottom-java:2.1.0'
annotationProcessor 'org.parceler:parceler:1.1.12'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'

View File

@@ -46,7 +46,3 @@
-keep interface org.parceler.Parcel
-keep @org.parceler.Parcel class * { *; }
-keep class **$$Parcelable { *; }
-keep class com.google.gson.reflect.TypeToken
-keep class * extends com.google.gson.reflect.TypeToken
-keep public class * implements java.lang.reflect.Type

View File

@@ -1,113 +0,0 @@
package org.joinmastodon.android.fragments;
import static org.junit.Assert.*;
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.events.StatusUpdatedEvent;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.StatusContext;
import org.junit.Test;
import java.time.Instant;
import java.util.List;
public class ThreadFragmentTest {
private Status fakeStatus(String id, String inReplyTo) {
Status status = Status.ofFake(id, null, null);
status.inReplyToId = inReplyTo;
return status;
}
private ThreadFragment.NeighborAncestryInfo fakeInfo(Status s, Status d, Status a) {
return new ThreadFragment.NeighborAncestryInfo(s, d, a);
}
@Test
public void mapNeighborhoodAncestry() {
StatusContext context = new StatusContext();
context.ancestors = List.of(
fakeStatus("oldest ancestor", null),
fakeStatus("younger ancestor", "oldest ancestor")
);
Status mainStatus = fakeStatus("main status", "younger ancestor");
context.descendants = List.of(
fakeStatus("first reply", "main status"),
fakeStatus("reply to first reply", "first reply"),
fakeStatus("third level reply", "reply to first reply"),
fakeStatus("another reply", "main status")
);
List<ThreadFragment.NeighborAncestryInfo> neighbors =
ThreadFragment.mapNeighborhoodAncestry(mainStatus, context);
assertEquals(List.of(
fakeInfo(context.ancestors.get(0), context.ancestors.get(1), null),
fakeInfo(context.ancestors.get(1), mainStatus, context.ancestors.get(0)),
fakeInfo(mainStatus, context.descendants.get(0), context.ancestors.get(1)),
fakeInfo(context.descendants.get(0), context.descendants.get(1), mainStatus),
fakeInfo(context.descendants.get(1), context.descendants.get(2), context.descendants.get(0)),
fakeInfo(context.descendants.get(2), null, context.descendants.get(1)),
fakeInfo(context.descendants.get(3), null, null)
), neighbors);
}
@Test
public void maybeApplyMainStatus() {
ThreadFragment fragment = new ThreadFragment();
fragment.contextInitiallyRendered = true;
fragment.mainStatus = Status.ofFake("123456", "original text", Instant.EPOCH);
Status update1 = Status.ofFake("123456", "updated text", Instant.EPOCH);
update1.editedAt = Instant.ofEpochSecond(1);
fragment.updatedStatus = update1;
StatusUpdatedEvent event1 = (StatusUpdatedEvent) fragment.maybeApplyMainStatus();
assertEquals("fired update event", update1, event1.status);
assertEquals("updated main status", update1, fragment.mainStatus);
Status update2 = Status.ofFake("123456", "updated text", Instant.EPOCH);
update2.favouritesCount = 123;
fragment.updatedStatus = update2;
StatusCountersUpdatedEvent event2 = (StatusCountersUpdatedEvent) fragment.maybeApplyMainStatus();
assertEquals("only fired counter update event", update2.id, event2.id);
assertEquals("updated counter is correct", 123, event2.favorites);
assertEquals("updated main status", update2, fragment.mainStatus);
Status update3 = Status.ofFake("123456", "whatever", Instant.EPOCH);
fragment.contextInitiallyRendered = false;
fragment.updatedStatus = update3;
assertNull("no update when context hasn't been rendered", fragment.maybeApplyMainStatus());
}
@Test
public void sortStatusContext() {
StatusContext context = new StatusContext();
context.ancestors = List.of(
fakeStatus("younger ancestor", "oldest ancestor"),
fakeStatus("oldest ancestor", null)
);
context.descendants = List.of(
fakeStatus("reply to first reply", "first reply"),
fakeStatus("third level reply", "reply to first reply"),
fakeStatus("first reply", "main status"),
fakeStatus("another reply", "main status")
);
ThreadFragment.sortStatusContext(
fakeStatus("main status", "younger ancestor"),
context
);
List<Status> expectedAncestors = List.of(
fakeStatus("oldest ancestor", null),
fakeStatus("younger ancestor", "oldest ancestor")
);
List<Status> expectedDescendants = List.of(
fakeStatus("first reply", "main status"),
fakeStatus("reply to first reply", "first reply"),
fakeStatus("third level reply", "reply to first reply"),
fakeStatus("another reply", "main status")
);
// TODO: ??? i have no idea how this code works. it certainly doesn't return what i'd expect
}
}

View File

@@ -1,106 +0,0 @@
package org.joinmastodon.android.ui.utils;
import static org.junit.Assert.*;
import android.util.Pair;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Instance;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Optional;
public class UiUtilsTest {
@BeforeClass
public static void createDummySession() {
Instance dummyInstance = new Instance();
dummyInstance.uri = "test.tld";
Account dummyAccount = new Account();
dummyAccount.id = "123456";
AccountSessionManager.getInstance().addAccount(dummyInstance, null, dummyAccount, null, null);
}
@AfterClass
public static void cleanUp() {
AccountSessionManager.getInstance().removeAccount("test.tld_123456");
}
@Test
public void parseFediverseHandle() {
assertEquals(
Optional.of(Pair.create("megalodon", Optional.of("floss.social"))),
UiUtils.parseFediverseHandle("megalodon@floss.social")
);
assertEquals(
Optional.of(Pair.create("megalodon", Optional.of("floss.social"))),
UiUtils.parseFediverseHandle("@megalodon@floss.social")
);
assertEquals(
Optional.of(Pair.create("megalodon", Optional.empty())),
UiUtils.parseFediverseHandle("@megalodon")
);
assertEquals(
Optional.of(Pair.create("megalodon", Optional.of("floss.social"))),
UiUtils.parseFediverseHandle("mailto:megalodon@floss.social")
);
assertEquals(
Optional.empty(),
UiUtils.parseFediverseHandle("megalodon")
);
assertEquals(
Optional.empty(),
UiUtils.parseFediverseHandle("this is not a fedi handle")
);
assertEquals(
Optional.empty(),
UiUtils.parseFediverseHandle("not@a-domain")
);
}
@Test
public void acctMatches() {
assertTrue("local account, domain not specified", UiUtils.acctMatches(
"test.tld_123456",
"someone",
"someone",
null
));
assertTrue("domain not specified", UiUtils.acctMatches(
"test.tld_123456",
"someone@somewhere.social",
"someone",
null
));
assertTrue("local account, domain specified, different casing", UiUtils.acctMatches(
"test.tld_123456",
"SomeOne",
"someone",
"Test.TLD"
));
assertFalse("username doesn't match", UiUtils.acctMatches(
"test.tld_123456",
"someone-else@somewhere.social",
"someone",
"somewhere.social"
));
assertFalse("domain doesn't match", UiUtils.acctMatches(
"test.tld_123456",
"someone@somewhere.social",
"someone",
"somewhere.else"
));
}
}

View File

@@ -1,81 +0,0 @@
package org.joinmastodon.android.utils;
import static org.joinmastodon.android.model.Filter.FilterAction.*;
import static org.joinmastodon.android.model.Filter.FilterContext.*;
import static org.junit.Assert.*;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status;
import org.junit.Test;
import java.time.Instant;
import java.util.EnumSet;
import java.util.List;
public class StatusFilterPredicateTest {
private static final Filter hideMeFilter = new Filter(), warnMeFilter = new Filter();
private static final List<Filter> allFilters = List.of(hideMeFilter, warnMeFilter);
private static final Status
hideInHomePublic = Status.ofFake(null, "hide me, please", Instant.now()),
warnInHomePublic = Status.ofFake(null, "display me with a warning", Instant.now());
static {
hideMeFilter.phrase = "hide me";
hideMeFilter.filterAction = HIDE;
hideMeFilter.context = EnumSet.of(PUBLIC, HOME);
warnMeFilter.phrase = "warning";
warnMeFilter.filterAction = WARN;
warnMeFilter.context = EnumSet.of(PUBLIC, HOME);
}
@Test
public void testHide() {
assertFalse("should not pass because matching filter applies to given context",
new StatusFilterPredicate(allFilters, HOME).test(hideInHomePublic));
}
@Test
public void testHideRegardlessOfContext() {
assertTrue("filters without context should always pass",
new StatusFilterPredicate(allFilters, null).test(hideInHomePublic));
}
@Test
public void testHideInDifferentContext() {
assertTrue("should pass because matching filter does not apply to given context",
new StatusFilterPredicate(allFilters, THREAD).test(hideInHomePublic));
}
@Test
public void testHideWithWarningText() {
assertTrue("should pass because matching filter is for warnings",
new StatusFilterPredicate(allFilters, HOME).test(warnInHomePublic));
}
@Test
public void testWarn() {
assertFalse("should not pass because filter applies to given context",
new StatusFilterPredicate(allFilters, HOME, WARN).test(warnInHomePublic));
}
@Test
public void testWarnRegardlessOfContext() {
assertTrue("filters without context should always pass",
new StatusFilterPredicate(allFilters, null, WARN).test(warnInHomePublic));
}
@Test
public void testWarnInDifferentContext() {
assertTrue("should pass because filter does not apply to given context",
new StatusFilterPredicate(allFilters, THREAD, WARN).test(warnInHomePublic));
}
@Test
public void testWarnWithHideText() {
assertTrue("should pass because matching filter is for hiding",
new StatusFilterPredicate(allFilters, HOME, WARN).test(hideInHomePublic));
}
}

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.joinmastodon.android">
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -115,7 +115,7 @@ public class GithubSelfUpdaterImpl extends GithubSelfUpdater{
private void actuallyCheckForUpdates(){
Request req=new Request.Builder()
.url("https://api.github.com/repos/sk22/megalodon/releases")
.url("https://api.github.com/repos/LucasGGamerM/moshidon/releases/latest")
.build();
Call call=MastodonAPIController.getHttpClient().newCall(req);
try(Response resp=call.execute()){
@@ -153,7 +153,7 @@ public class GithubSelfUpdaterImpl extends GithubSelfUpdater{
Log.d(TAG, "actuallyCheckForUpdates: new version: "+version);
for(JsonElement el:obj.getAsJsonArray("assets")){
JsonObject asset=el.getAsJsonObject();
if("megalodon.apk".equals(asset.get("name").getAsString()) && "application/vnd.android.package-archive".equals(asset.get("content_type").getAsString()) && "uploaded".equals(asset.get("state").getAsString())){
if("moshidon.apk".equals(asset.get("name").getAsString()) && "application/vnd.android.package-archive".equals(asset.get("content_type").getAsString()) && "uploaded".equals(asset.get("state").getAsString())){
long size=asset.get("size").getAsLong();
String url=asset.get("browser_download_url").getAsString();

View File

@@ -0,0 +1,3 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20">
<path android:pathData="M3.897 4.054L3.97 3.97c0.266-0.267 0.683-0.29 0.976-0.073L5.03 3.97 10 8.939l4.97-4.97c0.266-0.266 0.683-0.29 0.976-0.072L16.03 3.97c0.267 0.266 0.29 0.683 0.073 0.976L16.03 5.03 11.061 10l4.97 4.97c0.266 0.266 0.29 0.683 0.072 0.976L16.03 16.03c-0.266 0.267-0.683 0.29-0.976 0.073L14.97 16.03 10 11.061l-4.97 4.97c-0.266 0.266-0.683 0.29-0.976 0.072L3.97 16.03c-0.267-0.266-0.29-0.683-0.073-0.976L3.97 14.97 8.939 10l-4.97-4.97C3.704 4.764 3.68 4.347 3.898 4.054L3.97 3.97 3.897 4.054z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

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="M22 6.5c0 3.038-2.462 5.5-5.5 5.5S11 9.538 11 6.5 13.462 1 16.5 1 22 3.462 22 6.5zm-7.146-2.354c-0.196-0.195-0.512-0.195-0.708 0-0.195 0.196-0.195 0.512 0 0.708L15.793 6.5l-1.647 1.646c-0.195 0.196-0.195 0.512 0 0.707 0.196 0.196 0.512 0.196 0.708 0L16.5 7.208l1.646 1.647c0.196 0.195 0.512 0.195 0.708 0 0.195-0.196 0.195-0.512 0-0.707L17.207 6.5l1.647-1.646c0.195-0.196 0.195-0.512 0-0.708-0.196-0.195-0.512-0.195-0.708 0L16.5 5.793l-1.646-1.647zM19.5 14v-1.732c0.551-0.287 1.056-0.651 1.5-1.078v7.56c0 1.733-1.357 3.15-3.066 3.245L17.75 22H6.25c-1.733 0-3.15-1.357-3.245-3.066L3 18.75V7.25C3 5.517 4.356 4.1 6.066 4.005L6.25 4h4.248c-0.198 0.474-0.34 0.977-0.422 1.5H6.25c-0.918 0-1.671 0.707-1.744 1.606L4.5 7.25V14H9c0.38 0 0.694 0.282 0.743 0.648L9.75 14.75C9.75 15.993 10.757 17 12 17c1.19 0 2.166-0.925 2.245-2.096l0.005-0.154c0-0.38 0.282-0.694 0.648-0.743L15 14h4.5zm-15 1.5v3.25c0 0.918 0.707 1.671 1.606 1.744L6.25 20.5h11.5c0.918 0 1.671-0.707 1.744-1.607L19.5 18.75V15.5h-3.825c-0.335 1.648-1.75 2.904-3.475 2.995L12 18.5c-1.747 0-3.215-1.195-3.632-2.812L8.325 15.5H4.5z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

View File

@@ -0,0 +1,3 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="28dp" android:height="28dp" android:viewportWidth="28" android:viewportHeight="28">
<path android:pathData="M26 7.5c0 3.59-2.91 6.5-6.5 6.5S13 11.09 13 7.5 15.91 1 19.5 1 26 3.91 26 7.5zm-9.146-3.354c-0.196-0.195-0.512-0.195-0.708 0-0.195 0.196-0.195 0.512 0 0.708L18.793 7.5l-2.647 2.646c-0.195 0.196-0.195 0.512 0 0.708 0.196 0.195 0.512 0.195 0.708 0L19.5 8.207l2.646 2.647c0.196 0.195 0.512 0.195 0.708 0 0.195-0.196 0.195-0.512 0-0.708L20.207 7.5l2.647-2.646c0.195-0.196 0.195-0.512 0-0.708-0.196-0.195-0.512-0.195-0.708 0L19.5 6.793l-2.646-2.647zM25 22.75V12.6c-0.443 0.476-0.947 0.896-1.5 1.245V16h-6l-0.102 0.007c-0.366 0.05-0.648 0.363-0.648 0.743 0 1.519-1.231 2.75-2.75 2.75s-2.75-1.231-2.75-2.75l-0.007-0.102C11.193 16.282 10.88 16 10.5 16h-6V7.25c0-0.966 0.784-1.75 1.75-1.75h6.02c0.145-0.525 0.345-1.028 0.595-1.5H6.25C4.455 4 3 5.455 3 7.25v15.5C3 24.545 4.455 26 6.25 26h15.5c1.795 0 3.25-1.455 3.25-3.25zm-20.5 0V17.5h5.316l0.041 0.204C10.291 19.592 11.982 21 14 21l0.215-0.005c1.994-0.1 3.627-1.574 3.969-3.495H23.5v5.25c0 0.966-0.784 1.75-1.75 1.75H6.25c-0.966 0-1.75-0.784-1.75-1.75z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.joinmastodon.android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
@@ -16,15 +17,12 @@
<action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain" />
</intent>
<intent>
<action android:name="android.intent.action.TRANSLATE" />
</intent>
</queries>
<application
android:name=".MastodonApp"
android:allowBackup="true"
android:label="@string/sk_app_name"
android:label="@string/mo_app_name"
android:supportsRtl="true"
android:localeConfig="@xml/locales_config"
android:icon="@mipmap/ic_launcher"
@@ -38,32 +36,15 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".PanicResponderActivity"
android:exported="true"
android:launchMode="singleInstance"
android:noHistory="true"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="info.guardianproject.panic.action.TRIGGER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".ExitActivity"
android:exported="false"
android:theme="@android:style/Theme.NoDisplay" />
<activity android:name=".OAuthActivity" android:exported="true" android:configChanges="orientation|screenSize" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="megalodon-android-auth" android:host="callback"/>
<data android:scheme="moshidon-android-auth" android:host="callback"/>
</intent-filter>
</activity>
<activity android:name=".ExternalShareActivity" android:exported="true" android:configChanges="orientation|screenSize" android:windowSoftInputMode="adjustResize"
android:theme="@style/TransparentDialog">
<activity android:name=".ExternalShareActivity" android:exported="true" android:configChanges="orientation|screenSize" android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>

View File

@@ -0,0 +1,89 @@
# lists.d Mastodon Blocklist (c) 2022 Greyhat Academy LICENSED UNDER: CC-BY-NC-SA 4.0
# https://raw.githubusercontent.com/greyhat-academy/lists.d/main/mastodon.domains.block.list.tsv
# This list contains domains of toxic mastodon instances
# Last-Modified: 1672044500
# gab - a neonazi social network
gab.ai
gab.com
gab.protohype.net
# consequence-free speech
social.unzensiert.to
freeatlantis.com
# reactionary bigotry and hatespeech against magrinalized groups
poa.st
freespeechextremist.com
rdrama.cc
outpoa.st
anime.website
gameliberty.club
social.byoblu.com
yggdrasil.social
smuglo.li
dogeposting.social
unsafe.space
freezepeach.xyz
# + CSAM
rojogato.com
# antivaxxer shitposting & fearmongering
shadowsocial.org
# Kiwifarms
kiwifarms.net
kiwifarms.cc
kiwifarms.is
kiwifarms.pleroma.net
# https://mastodon.art/@Curator/109649354849593592
poa.st antisemitic racist homophobic
nicecrew.digital antisemitic
beefyboys.win antisemitic racist homophobic harassment
cawfee.club antisemitic racist homophobic
comfyboy.club antisemitic racist homophobic
freespeechextremist.com racist homophobic
cum.salon racist misogynist
bae.st racist
natehiggers.online racist
rapemeat.solutions misogynist
rapist.town misogynist
rapefeminists.network misogynist
kiwifarms.cc harassment
noagendasocial.com noagenda
posting.lolicon.rocks underage
urchan.org harassment homophobic racist
ryona.agency harassment
yggdrasil.social antisemitic homophobic racist
genderheretics.xyz transphobic
baraag.net underage
lolison.top underage
shota.house underage
shota.social underage
aethy.com underage
taullo.social underage
childpawn.shop underage
posting.lolicon.rocks underage
loli.best underage
gothloli.club underage
smuglo.li underage
youjo.love underage
pedo.school underage
lolison.network underage
freak.university underage
mirr0r.city underage
xhais.love underage
refusal.biz underage
refusal.llc underage
mirr0r.city underage
nnia.space underage
ignorelist.com malicious
repl.co malicious
# custom
pawoo.net csam
1 # lists.d Mastodon Blocklist (c) 2022 Greyhat Academy LICENSED UNDER: CC-BY-NC-SA 4.0
2 # https://raw.githubusercontent.com/greyhat-academy/lists.d/main/mastodon.domains.block.list.tsv
3 # This list contains domains of toxic mastodon instances
4 # Last-Modified: 1672044500
5 # gab - a neonazi social network
6 gab.ai
7 gab.com
8 gab.protohype.net
9 # consequence-free speech
10 social.unzensiert.to
11 freeatlantis.com
12 # reactionary bigotry and hatespeech against magrinalized groups
13 poa.st
14 freespeechextremist.com
15 rdrama.cc
16 outpoa.st
17 anime.website
18 gameliberty.club
19 social.byoblu.com
20 yggdrasil.social
21 smuglo.li
22 dogeposting.social
23 unsafe.space
24 freezepeach.xyz
25 # + CSAM
26 rojogato.com
27 # antivaxxer shitposting & fearmongering
28 shadowsocial.org
29 # Kiwifarms
30 kiwifarms.net
31 kiwifarms.cc
32 kiwifarms.is
33 kiwifarms.pleroma.net
34 # https://mastodon.art/@Curator/109649354849593592
35 poa.st antisemitic racist homophobic
36 nicecrew.digital antisemitic
37 beefyboys.win antisemitic racist homophobic harassment
38 cawfee.club antisemitic racist homophobic
39 comfyboy.club antisemitic racist homophobic
40 freespeechextremist.com racist homophobic
41 cum.salon racist misogynist
42 bae.st racist
43 natehiggers.online racist
44 rapemeat.solutions misogynist
45 rapist.town misogynist
46 rapefeminists.network misogynist
47 kiwifarms.cc harassment
48 noagendasocial.com noagenda
49 posting.lolicon.rocks underage
50 urchan.org harassment homophobic racist
51 ryona.agency harassment
52 yggdrasil.social antisemitic homophobic racist
53 genderheretics.xyz transphobic
54 baraag.net underage
55 lolison.top underage
56 shota.house underage
57 shota.social underage
58 aethy.com underage
59 taullo.social underage
60 childpawn.shop underage
61 posting.lolicon.rocks underage
62 loli.best underage
63 gothloli.club underage
64 smuglo.li underage
65 youjo.love underage
66 pedo.school underage
67 lolison.network underage
68 freak.university underage
69 mirr0r.city underage
70 xhais.love underage
71 refusal.biz underage
72 refusal.llc underage
73 mirr0r.city underage
74 nnia.space underage
75 ignorelist.com malicious
76 repl.co malicious
77 # custom
78 pawoo.net csam

View File

@@ -1,171 +0,0 @@
13bells.com
4aem.com
aethy.com
anime.website
annihilation.social
anon-kenkai.com
asbestos.cafe
bae.st
bajax.us
banepo.st
baraag.net
beefyboys.win
beepboop.ga
berserker.town
bikeshed.party
boks.moe
brainsoap.net
breastmilk.club
brighteon.social
cawfee.club
clew.lol
clubcyberia.co
collapsitarian.io
comfyboy.club
contrapointsfan.club
cum.camp
cum.salon
cybercriminal.eu
darknight-coffee.org
dembased.xyz
desupost.soy
detroitriotcity.com
eatthebugs.social
eientei.org
elementality.org
eveningzoo.club
firedragonstudios.com
firefaithfellowship.com
fluf.club
foxfam.club
freak.university
freeatlantis.com
freecumextremist.com
freedomstrike.org
freesoftwareextremist.com
freespeech.group
freespeechextremist.com
freetalklive.com
froth.zone
fulltermprivacy.com
gameliberty.club
gearlandia.haus
genderheretics.xyz
geofront.rocks
gleasonator.com
glee.li
glindr.org
goyim.app
goyslop.cafe
haeder.net
handholding.io
hidamari.apartments
hitchhiker.social
hunk.city
iddqd.social
intkos.link
justicewarrior.social
kawa-kun.com
kitsunemimi.club
kiwifarms.cc
kompost.cz
kurosawa.moe
leafposter.club
leftychan.net
lewdieheaven.com
liberdon.com
ligma.pro
lizards.live
lolicon.rocks
lolison.top
lovingexpressions.net
lucasvl.nl
mahodou.moe
makemysarcophagus.com
maladaptive.art
masochi.st
mastinator.com
merovingian.club
midwaytrades.com
mirr0r.city
moa.st
mouse.services
mugicha.club
narrativerry.xyz
natehiggers.online
neckbeard.xyz
needs.vodka
neenster.org
nicecrew.digital
nnia.space
noagendasocial.com
noagendasocial.nl
noagendatube.com
nobodyhasthe.biz
nukem.biz
obo.sh
onionfarms.org
outpoa.st
pawlicker.com
pawoo.net
pedo.school
piazza.today
pibvt.net
pieville.net
pisskey.io
plagu.ee
pmth.us
poa.st
poast.org
poast.tv
poster.place
prospeech.space
quodverum.com
rakket.app
rapemeat.solutions
rdrama.cc
rebelbase.site
retardedniggers.forsale
rojogato.com
ryona.agency
schwartzwelt.xyz
seal.cafe
shigusegubu.club
shitpost.cloud
shitposter.club
shota.house
silliness.observer
skinheads.eu
skinheads.io
skinheads.social
skinheads.uk
skippers-bin.com
skyshanty.xyz
slash.cl
sleepy.cafe
smuglo.li
sneed.social
sonichu.com
spinster.xyz
springbo.cc
starnix.network
stereophonic.space
strelizia.net
syspxl.xyz
tastingtraffic.net
teci.world
theapex.social
thepostearthdestination.com
tkammer.de
trumpislovetrumpis.life
truthsocial.co.in
urchan.org
varishangout.net
whinge.house
whinge.town
wideboys.org
wolfgirl.bar
xn--p1abe3d.xn--80asehdb
yggdrasil.social
youjo.love
zztails.gay

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,24 +0,0 @@
package org.joinmastodon.android;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
public class ExitActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finishAndRemoveTask();
}
public static void exit(Context context) {
Intent intent = new Intent(context, ExitActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
}
}

View File

@@ -3,25 +3,21 @@ package org.joinmastodon.android;
import android.app.Fragment;
import android.content.ClipData;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Pair;
import android.widget.Toast;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.ComposeFragment;
import org.joinmastodon.android.ui.AccountSwitcherSheet;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.jsoup.internal.StringUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import androidx.annotation.Nullable;
import me.grishka.appkit.FragmentStackActivity;
@@ -32,52 +28,21 @@ public class ExternalShareActivity extends FragmentStackActivity{
UiUtils.setUserPreferredTheme(this);
super.onCreate(savedInstanceState);
if(savedInstanceState==null){
Optional<String> text = Optional.ofNullable(getIntent().getStringExtra(Intent.EXTRA_TEXT));
Optional<Pair<String, Optional<String>>> fediHandle = text.flatMap(UiUtils::parseFediverseHandle);
boolean isFediUrl = text.map(UiUtils::looksLikeFediverseUrl).orElse(false);
boolean isOpenable = isFediUrl || fediHandle.isPresent();
List<AccountSession> sessions=AccountSessionManager.getInstance().getLoggedInAccounts();
if (sessions.isEmpty()){
if(sessions.isEmpty()){
Toast.makeText(this, R.string.err_not_logged_in, Toast.LENGTH_SHORT).show();
finish();
} else if (isOpenable || sessions.size() > 1) {
AccountSwitcherSheet sheet = new AccountSwitcherSheet(this, null, true, isOpenable);
sheet.setOnClick((accountId, open) -> {
if (open && text.isPresent()) {
BiConsumer<Class<? extends Fragment>, Bundle> callback = (clazz, args) -> {
if (clazz == null) {
Toast.makeText(this, R.string.sk_open_in_app_failed, Toast.LENGTH_SHORT).show();
// TODO: do something about the window getting leaked
sheet.dismiss();
finish();
return;
}
args.putString("fromExternalShare", clazz.getSimpleName());
Intent intent = new Intent(this, MainActivity.class);
intent.putExtras(args);
finish();
startActivity(intent);
};
fediHandle
.<MastodonAPIRequest<?>>map(handle ->
UiUtils.lookupAccountHandle(this, accountId, handle, callback))
.or(() ->
UiUtils.lookupURL(this, accountId, text.get(), callback))
.ifPresent(req ->
req.wrapProgress(this, R.string.loading, true, d -> {
UiUtils.transformDialogForLookup(this, accountId, isFediUrl ? text.get() : null, d);
d.setOnDismissListener((x) -> finish());
}));
} else {
openComposeFragment(accountId);
}
});
sheet.show();
} else if (sessions.size() == 1) {
}else if(sessions.size()==1){
openComposeFragment(sessions.get(0).getID());
}else{
getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000));
new M3AlertDialogBuilder(this)
.setItems(sessions.stream().map(as->"@"+as.self.username+"@"+as.domain).toArray(String[]::new), (dialog, which)->{
openComposeFragment(sessions.get(which).getID());
})
.setTitle(R.string.choose_account)
.setOnCancelListener(dialog -> finish())
.show();
}
}
}
@@ -90,15 +55,9 @@ public class ExternalShareActivity extends FragmentStackActivity{
String subject = "";
if (intent.hasExtra(Intent.EXTRA_SUBJECT)) {
subject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
if (!StringUtil.isBlank(subject)) builder.append(subject).append("\n\n");
}
if (intent.hasExtra(Intent.EXTRA_TEXT)) {
String extra = intent.getStringExtra(Intent.EXTRA_TEXT);
if (!StringUtil.isBlank(extra)) {
if (extra.startsWith(subject)) extra = extra.substring(subject.length()).trim();
builder.append(extra).append("\n\n");
}
if (!subject.isBlank()) builder.append(subject).append("\n\n");
}
if (intent.hasExtra(Intent.EXTRA_TEXT)) builder.append(intent.getStringExtra(Intent.EXTRA_TEXT)).append("\n");
String text=builder.toString();
List<Uri> mediaUris;
if(Intent.ACTION_SEND.equals(intent.getAction())){
@@ -125,7 +84,8 @@ public class ExternalShareActivity extends FragmentStackActivity{
args.putString("account", accountID);
if(!TextUtils.isEmpty(text))
args.putString("prefilledText", text);
args.putInt("selectionStart", StringUtil.isBlank(subject) ? 0 : subject.length());
if(!subject.isBlank())
args.putInt("selectionEnd", subject.length());
if(mediaUris!=null && !mediaUris.isEmpty())
args.putParcelableArrayList("mediaAttachments", toArrayList(mediaUris));
Fragment fragment=new ComposeFragment();

View File

@@ -4,11 +4,11 @@ import static org.joinmastodon.android.api.MastodonAPIController.gson;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.model.ContentType;
import org.joinmastodon.android.model.TimelineDefinition;
import java.lang.reflect.Type;
@@ -30,46 +30,31 @@ public class GlobalUserPreferences{
public static boolean alwaysExpandContentWarnings;
public static boolean disableMarquee;
public static boolean disableSwipe;
public static boolean disableDividers;
public static boolean voteButtonForSingleChoice;
public static boolean enableDeleteNotifications;
public static boolean translateButtonOpenedOnly;
public static boolean uniformNotificationIcon;
public static boolean enableDeleteNotifications;
public static boolean relocatePublishButton;
public static boolean reduceMotion;
public static boolean keepOnlyLatestNotification;
public static boolean enableFabAutoHide;
public static boolean disableAltTextReminder;
public static boolean showAltIndicator;
public static boolean showNoAltIndicator;
public static boolean enablePreReleases;
public static PrefixRepliesMode prefixReplies;
public static boolean bottomEncoding;
public static boolean collapseLongPosts;
public static boolean spectatorMode;
public static boolean autoHideFab;
public static boolean replyLineAboveHeader;
public static boolean compactReblogReplyLine;
public static boolean confirmBeforeReblog;
public static boolean allowRemoteLoading;
public static boolean forwardReportDefault;
public static AutoRevealMode autoRevealEqualSpoilers;
public static String publishButtonText;
public static ThemePreference theme;
public static ColorPreference color;
private final static Type recentLanguagesType = new TypeToken<Map<String, List<String>>>() {}.getType();
private final static Type pinnedTimelinesType = new TypeToken<Map<String, List<TimelineDefinition>>>() {}.getType();
public static Map<String, List<String>> recentLanguages;
public static Map<String, List<TimelineDefinition>> pinnedTimelines;
public static Set<String> accountsWithLocalOnlySupport;
public static Set<String> accountsInGlitchMode;
public static Set<String> accountsWithContentTypesEnabled;
public static Map<String, ContentType> accountsDefaultContentTypes;
private final static Type recentLanguagesType = new TypeToken<Map<String, List<String>>>() {}.getType();
private final static Type pinnedTimelinesType = new TypeToken<Map<String, List<TimelineDefinition>>>() {}.getType();
private final static Type accountsDefaultContentTypesType = new TypeToken<Map<String, ContentType>>() {}.getType();
/**
* Pleroma
*/
public static String replyVisibility;
private final static Type recentEmojisType = new TypeToken<Map<String, Integer>>() {}.getType();
public static Map<String, Integer> recentEmojis;
private static SharedPreferences getPrefs(){
return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE);
@@ -81,16 +66,6 @@ public class GlobalUserPreferences{
catch (JsonSyntaxException ignored) { return orElse; }
}
public static void removeAccount(String accountId) {
recentLanguages.remove(accountId);
pinnedTimelines.remove(accountId);
accountsInGlitchMode.remove(accountId);
accountsWithLocalOnlySupport.remove(accountId);
accountsWithContentTypesEnabled.remove(accountId);
accountsDefaultContentTypes.remove(accountId);
save();
}
public static void load(){
SharedPreferences prefs=getPrefs();
playGifs=prefs.getBoolean("playGifs", true);
@@ -100,55 +75,40 @@ public class GlobalUserPreferences{
showBoosts=prefs.getBoolean("showBoosts", true);
loadNewPosts=prefs.getBoolean("loadNewPosts", true);
showNewPostsButton=prefs.getBoolean("showNewPostsButton", true);
uniformNotificationIcon=prefs.getBoolean("uniformNotificationIcon", true);
showInteractionCounts=prefs.getBoolean("showInteractionCounts", false);
alwaysExpandContentWarnings=prefs.getBoolean("alwaysExpandContentWarnings", false);
disableMarquee=prefs.getBoolean("disableMarquee", false);
disableSwipe=prefs.getBoolean("disableSwipe", false);
disableDividers=prefs.getBoolean("disableDividers", true);
relocatePublishButton=prefs.getBoolean("relocatePublishButton", true);
voteButtonForSingleChoice=prefs.getBoolean("voteButtonForSingleChoice", true);
enableDeleteNotifications=prefs.getBoolean("enableDeleteNotifications", false);
translateButtonOpenedOnly=prefs.getBoolean("translateButtonOpenedOnly", false);
uniformNotificationIcon=prefs.getBoolean("uniformNotificationIcon", false);
enableDeleteNotifications=prefs.getBoolean("enableDeleteNotifications", true);
reduceMotion=prefs.getBoolean("reduceMotion", false);
keepOnlyLatestNotification=prefs.getBoolean("keepOnlyLatestNotification", false);
enableFabAutoHide=prefs.getBoolean("enableFabAutoHide", true);
disableAltTextReminder=prefs.getBoolean("disableAltTextReminder", false);
showAltIndicator=prefs.getBoolean("showAltIndicator", true);
showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true);
enablePreReleases=prefs.getBoolean("enablePreReleases", false);
prefixReplies=PrefixRepliesMode.valueOf(prefs.getString("prefixReplies", PrefixRepliesMode.NEVER.name()));
bottomEncoding=prefs.getBoolean("bottomEncoding", false);
collapseLongPosts=prefs.getBoolean("collapseLongPosts", true);
spectatorMode=prefs.getBoolean("spectatorMode", false);
autoHideFab=prefs.getBoolean("autoHideFab", true);
replyLineAboveHeader=prefs.getBoolean("replyLineAboveHeader", true);
compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true);
confirmBeforeReblog=prefs.getBoolean("confirmBeforeReblog", false);
publishButtonText=prefs.getString("publishButtonText", "");
theme=ThemePreference.values()[prefs.getInt("theme", 0)];
recentLanguages=fromJson(prefs.getString("recentLanguages", null), recentLanguagesType, new HashMap<>());
recentLanguages=fromJson(prefs.getString("recentLanguages", "{}"), recentLanguagesType, new HashMap<>());
recentEmojis=fromJson(prefs.getString("recentEmojis", "{}"), recentEmojisType, new HashMap<>());
publishButtonText=prefs.getString("publishButtonText", "");
pinnedTimelines=fromJson(prefs.getString("pinnedTimelines", null), pinnedTimelinesType, new HashMap<>());
accountsWithLocalOnlySupport=prefs.getStringSet("accountsWithLocalOnlySupport", new HashSet<>());
accountsInGlitchMode=prefs.getStringSet("accountsInGlitchMode", new HashSet<>());
replyVisibility=prefs.getString("replyVisibility", null);
accountsWithContentTypesEnabled=prefs.getStringSet("accountsWithContentTypesEnabled", new HashSet<>());
accountsDefaultContentTypes=fromJson(prefs.getString("accountsDefaultContentTypes", null), accountsDefaultContentTypesType, new HashMap<>());
allowRemoteLoading=prefs.getBoolean("allowRemoteLoading", true);
autoRevealEqualSpoilers=AutoRevealMode.valueOf(prefs.getString("autoRevealEqualSpoilers", AutoRevealMode.THREADS.name()));
forwardReportDefault=prefs.getBoolean("forwardReportDefault", true);
if (prefs.contains("prefixRepliesWithRe")) {
prefixReplies = prefs.getBoolean("prefixRepliesWithRe", false)
? PrefixRepliesMode.TO_OTHERS : PrefixRepliesMode.NEVER;
prefs.edit()
.putString("prefixReplies", prefixReplies.name())
.remove("prefixRepliesWithRe")
.apply();
}
try {
color=ColorPreference.valueOf(prefs.getString("color", ColorPreference.PINK.name()));
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
color=ColorPreference.valueOf(prefs.getString("color", ColorPreference.MATERIAL3.name()));
}else{
color=ColorPreference.valueOf(prefs.getString("color", ColorPreference.PURPLE.name()));
}
} catch (IllegalArgumentException|ClassCastException ignored) {
// invalid color name or color was previously saved as integer
color=ColorPreference.PINK;
color=ColorPreference.PURPLE;
}
}
@@ -165,36 +125,25 @@ public class GlobalUserPreferences{
.putBoolean("alwaysExpandContentWarnings", alwaysExpandContentWarnings)
.putBoolean("disableMarquee", disableMarquee)
.putBoolean("disableSwipe", disableSwipe)
.putBoolean("enableDeleteNotifications", enableDeleteNotifications)
.putBoolean("translateButtonOpenedOnly", translateButtonOpenedOnly)
.putBoolean("disableDividers", disableDividers)
.putBoolean("relocatePublishButton", relocatePublishButton)
.putBoolean("uniformNotificationIcon", uniformNotificationIcon)
.putBoolean("enableDeleteNotifications", enableDeleteNotifications)
.putBoolean("reduceMotion", reduceMotion)
.putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification)
.putBoolean("enableFabAutoHide", enableFabAutoHide)
.putBoolean("disableAltTextReminder", disableAltTextReminder)
.putBoolean("showAltIndicator", showAltIndicator)
.putBoolean("showNoAltIndicator", showNoAltIndicator)
.putBoolean("enablePreReleases", enablePreReleases)
.putString("prefixReplies", prefixReplies.name())
.putBoolean("collapseLongPosts", collapseLongPosts)
.putBoolean("spectatorMode", spectatorMode)
.putBoolean("autoHideFab", autoHideFab)
.putBoolean("compactReblogReplyLine", compactReblogReplyLine)
.putString("publishButtonText", publishButtonText)
.putBoolean("bottomEncoding", bottomEncoding)
.putBoolean("replyLineAboveHeader", replyLineAboveHeader)
.putBoolean("confirmBeforeReblog", confirmBeforeReblog)
.putInt("theme", theme.ordinal())
.putString("color", color.name())
.putString("recentLanguages", gson.toJson(recentLanguages))
.putString("pinnedTimelines", gson.toJson(pinnedTimelines))
.putString("recentEmojis", gson.toJson(recentEmojis))
.putStringSet("accountsWithLocalOnlySupport", accountsWithLocalOnlySupport)
.putStringSet("accountsInGlitchMode", accountsInGlitchMode)
.putString("replyVisibility", replyVisibility)
.putStringSet("accountsWithContentTypesEnabled", accountsWithContentTypesEnabled)
.putString("accountsDefaultContentTypes", gson.toJson(accountsDefaultContentTypes))
.putBoolean("allowRemoteLoading", allowRemoteLoading)
.putString("autoRevealEqualSpoilers", autoRevealEqualSpoilers.name())
.putBoolean("forwardReportDefault", forwardReportDefault)
.apply();
}
@@ -206,7 +155,8 @@ public class GlobalUserPreferences{
BLUE,
BROWN,
RED,
YELLOW
YELLOW,
NORD
}
public enum ThemePreference{
@@ -214,16 +164,5 @@ public class GlobalUserPreferences{
LIGHT,
DARK
}
public enum AutoRevealMode {
NEVER,
THREADS,
DISCUSSIONS
}
public enum PrefixRepliesMode {
NEVER,
ALWAYS,
TO_OTHERS
}
}

View File

@@ -2,14 +2,11 @@ package org.joinmastodon.android;
import android.Manifest;
import android.app.Fragment;
import android.app.assist.AssistContent;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import org.joinmastodon.android.api.ObjectValidationException;
import org.joinmastodon.android.api.session.AccountSession;
@@ -20,16 +17,16 @@ import org.joinmastodon.android.fragments.ProfileFragment;
import org.joinmastodon.android.fragments.ThreadFragment;
import org.joinmastodon.android.fragments.onboarding.AccountActivationFragment;
import org.joinmastodon.android.fragments.onboarding.CustomWelcomeFragment;
import org.joinmastodon.android.fragments.onboarding.CustomWelcomeFragment;
import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.updater.GithubSelfUpdater;
import org.joinmastodon.android.utils.ProvidesAssistContent;
import org.parceler.Parcels;
import androidx.annotation.Nullable;
import me.grishka.appkit.FragmentStackActivity;
public class MainActivity extends FragmentStackActivity implements ProvidesAssistContent {
public class MainActivity extends FragmentStackActivity{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState){
UiUtils.setUserPreferredTheme(this);
@@ -39,18 +36,10 @@ public class MainActivity extends FragmentStackActivity implements ProvidesAssis
if(AccountSessionManager.getInstance().getLoggedInAccounts().isEmpty()){
showFragmentClearingBackStack(new CustomWelcomeFragment());
}else{
AccountSessionManager.getInstance().maybeUpdateLocalInfo();
AccountSession session;
Bundle args=new Bundle();
Intent intent=getIntent();
if(intent.hasExtra("fromExternalShare")) {
AccountSessionManager.getInstance()
.setLastActiveAccountID(intent.getStringExtra("account"));
AccountSessionManager.getInstance().maybeUpdateLocalInfo(
AccountSessionManager.getInstance().getLastActiveAccount());
showFragmentForExternalShare(intent.getExtras());
return;
}
boolean fromNotification = intent.getBooleanExtra("fromNotification", false);
boolean hasNotification = intent.hasExtra("notification");
if(fromNotification){
@@ -64,7 +53,6 @@ public class MainActivity extends FragmentStackActivity implements ProvidesAssis
}else{
session=AccountSessionManager.getInstance().getLastActiveAccount();
}
AccountSessionManager.getInstance().maybeUpdateLocalInfo(session);
args.putString("account", session.getID());
Fragment fragment=session.activated ? new HomeFragment() : new AccountActivationFragment();
fragment.setArguments(args);
@@ -88,12 +76,11 @@ public class MainActivity extends FragmentStackActivity implements ProvidesAssis
@Override
protected void onNewIntent(Intent intent){
super.onNewIntent(intent);
AccountSessionManager.getInstance().maybeUpdateLocalInfo();
if (intent.hasExtra("fromExternalShare")) showFragmentForExternalShare(intent.getExtras());
else if (intent.getBooleanExtra("fromNotification", false)) {
if(intent.getBooleanExtra("fromNotification", false)){
String accountID=intent.getStringExtra("accountID");
AccountSession accountSession;
try{
AccountSessionManager.getInstance().getAccount(accountID);
accountSession=AccountSessionManager.getInstance().getAccount(accountID);
}catch(IllegalStateException x){
return;
}
@@ -117,24 +104,23 @@ public class MainActivity extends FragmentStackActivity implements ProvidesAssis
}
private void showFragmentForNotification(Notification notification, String accountID){
Fragment fragment;
Bundle args=new Bundle();
args.putString("account", accountID);
args.putBoolean("_can_go_back", true);
try{
notification.postprocess();
}catch(ObjectValidationException x){
Log.w("MainActivity", x);
return;
}
UiUtils.showFragmentForNotification(this, notification, accountID, null);
}
private void showFragmentForExternalShare(Bundle args) {
String className = args.getString("fromExternalShare");
Fragment fragment = switch (className) {
case "ThreadFragment" -> new ThreadFragment();
case "ProfileFragment" -> new ProfileFragment();
default -> null;
};
if (fragment == null) return;
args.putBoolean("_can_go_back", true);
if(notification.status!=null){
fragment=new ThreadFragment();
args.putParcelable("status", Parcels.wrap(notification.status));
}else{
fragment=new ProfileFragment();
args.putParcelable("profileAccount", Parcels.wrap(notification.account));
}
fragment.setArguments(args);
showFragment(fragment);
}
@@ -168,40 +154,17 @@ public class MainActivity extends FragmentStackActivity implements ProvidesAssis
(fragmentContainers.get(fragmentContainers.size() - 1)).getId()
);
Bundle currentArgs = currentFragment.getArguments();
if (fragmentContainers.size() != 1
|| currentArgs == null
|| !currentArgs.getBoolean("_can_go_back", false)) {
super.onBackPressed();
return;
}
if (currentArgs.getBoolean("_finish_on_back", false)) {
finish();
} else if (currentArgs.containsKey("account")) {
if (this.fragmentContainers.size() == 1
&& currentArgs.getBoolean("_can_go_back", false)
&& currentArgs.containsKey("account")) {
Bundle args = new Bundle();
args.putString("account", currentArgs.getString("account"));
if (getIntent().getBooleanExtra("fromNotification", false)) {
args.putString("tab", "notifications");
}
args.putString("tab", "notifications");
Fragment fragment=new HomeFragment();
fragment.setArguments(args);
showFragmentClearingBackStack(fragment);
} else {
super.onBackPressed();
}
}
public Fragment getCurrentFragment() {
for (int i = fragmentContainers.size() - 1; i >= 0; i--) {
FrameLayout fl = fragmentContainers.get(i);
if (fl.getVisibility() == View.VISIBLE) {
return getFragmentManager().findFragmentById(fl.getId());
}
}
return null;
}
@Override
public void onProvideAssistContent(AssistContent assistContent) {
super.onProvideAssistContent(assistContent);
Fragment fragment = getCurrentFragment();
if (fragment != null) callFragmentToProvideAssistContent(fragment, assistContent);
}
}

View File

@@ -61,9 +61,6 @@ public class OAuthActivity extends Activity{
@Override
public void onSuccess(Token token){
new GetOwnAccount()
// in case the instance (looking at pixelfed) wants to redirect to a
// website, we need to pass a context so we can launch a browser
.setContext(OAuthActivity.this)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Account account){

View File

@@ -1,49 +0,0 @@
package org.joinmastodon.android;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import org.joinmastodon.android.api.requests.oauth.RevokeOauthToken;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
public class PanicResponderActivity extends Activity {
public static final String PANIC_TRIGGER_ACTION = "info.guardianproject.panic.action.TRIGGER";
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
if (intent != null && PANIC_TRIGGER_ACTION.equals(intent.getAction())) {
AccountSessionManager.getInstance().getLoggedInAccounts().forEach(accountSession -> logOut(accountSession.getID()));
ExitActivity.exit(this);
}
finishAndRemoveTask();
}
private void logOut(String accountID){
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
new RevokeOauthToken(session.app.clientId, session.app.clientSecret, session.token.accessToken)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Object result){
onLoggedOut(accountID);
}
@Override
public void onError(ErrorResponse error){
onLoggedOut(accountID);
}
})
.exec(accountID);
}
private void onLoggedOut(String accountID){
AccountSessionManager.getInstance().removeAccount(accountID);
}
}

View File

@@ -1,13 +1,10 @@
package org.joinmastodon.android;
import static org.joinmastodon.android.GlobalUserPreferences.PrefixRepliesMode.*;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -19,28 +16,15 @@ import android.util.Log;
import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.requests.notifications.GetNotificationByID;
import org.joinmastodon.android.api.requests.statuses.CreateStatus;
import org.joinmastodon.android.api.requests.statuses.SetStatusBookmarked;
import org.joinmastodon.android.api.requests.statuses.SetStatusFavorited;
import org.joinmastodon.android.api.requests.statuses.SetStatusReblogged;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.NotificationReceivedEvent;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Mention;
import org.joinmastodon.android.model.NotificationAction;
import org.joinmastodon.android.model.Preferences;
import org.joinmastodon.android.model.PushNotification;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.StatusPrivacy;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.parceler.Parcels;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.stream.Collectors;
import me.grishka.appkit.api.Callback;
@@ -53,14 +37,11 @@ public class PushNotificationReceiver extends BroadcastReceiver{
private static final String TAG="PushNotificationReceive";
public static final int NOTIFICATION_ID=178;
private static final String ACTION_KEY_TEXT_REPLY = "ACTION_KEY_TEXT_REPLY";
private static final int SUMMARY_ID = 791;
private static int notificationId = 0;
@Override
public void onReceive(Context context, Intent intent){
UiUtils.setUserPreferredTheme(context);
if(BuildConfig.DEBUG){
Log.e(TAG, "received: "+intent);
Bundle extras=intent.getExtras();
@@ -90,7 +71,6 @@ public class PushNotificationReceiver extends BroadcastReceiver{
}
String accountID=account.getID();
PushNotification pn=AccountSessionManager.getInstance().getAccount(accountID).getPushSubscriptionManager().decryptNotification(k, p, s);
E.post(new NotificationReceivedEvent(accountID, pn.notificationId+""));
new GetNotificationByID(pn.notificationId+"")
.setCallback(new Callback<>(){
@Override
@@ -112,35 +92,6 @@ public class PushNotificationReceiver extends BroadcastReceiver{
Log.w(TAG, "onReceive: invalid push notification format");
}
}
if(intent.getBooleanExtra("fromNotificationAction", false)){
String accountID=intent.getStringExtra("accountID");
int notificationId=intent.getIntExtra("notificationId", -1);
if (notificationId >= 0){
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(accountID, notificationId);
}
if(intent.hasExtra("notification")){
org.joinmastodon.android.model.Notification notification=Parcels.unwrap(intent.getParcelableExtra("notification"));
String statusID=notification.status.id;
if (statusID != null) {
AccountSessionManager accountSessionManager = AccountSessionManager.getInstance();
Preferences preferences = accountSessionManager.getAccount(accountID).preferences;
switch (NotificationAction.values()[intent.getIntExtra("notificationAction", 0)]) {
case FAVORITE -> new SetStatusFavorited(statusID, true).exec(accountID);
case BOOKMARK -> new SetStatusBookmarked(statusID, true).exec(accountID);
case REBLOG -> new SetStatusReblogged(notification.status.id, true, preferences.postingDefaultVisibility).exec(accountID);
case UNDO_REBLOG -> new SetStatusReblogged(notification.status.id, false, preferences.postingDefaultVisibility).exec(accountID);
case REPLY -> handleReplyAction(context, accountID, intent, notification, notificationId, preferences);
default -> Log.w(TAG, "onReceive: Failed to get NotificationAction");
}
}
}else{
Log.e(TAG, "onReceive: Failed to load notification");
}
}
}
private void notify(Context context, PushNotification pn, String accountID, org.joinmastodon.android.model.Notification notification){
@@ -148,6 +99,7 @@ public class PushNotificationReceiver extends BroadcastReceiver{
Account self=AccountSessionManager.getInstance().getAccount(accountID).self;
String accountName="@"+self.username+"@"+AccountSessionManager.getInstance().getAccount(accountID).domain;
Notification.Builder builder;
Notification.Builder summaryNotification;
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
boolean hasGroup=false;
List<NotificationChannelGroup> channelGroups=nm.getNotificationChannelGroups();
@@ -170,21 +122,28 @@ public class PushNotificationReceiver extends BroadcastReceiver{
nm.createNotificationChannels(channels);
}
builder=new Notification.Builder(context, accountID+"_"+pn.notificationType);
// summaryNotification=new Notification.Builder(context, accountID);
}else{
builder=new Notification.Builder(context)
.setPriority(Notification.PRIORITY_DEFAULT)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);
summaryNotification=new Notification.Builder(context)
.setPriority(Notification.PRIORITY_DEFAULT)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);
}
Drawable avatar=ImageCache.getInstance(context).get(new UrlImageLoaderRequest(pn.icon, V.dp(50), V.dp(50)));
Intent contentIntent=new Intent(context, MainActivity.class);
contentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
contentIntent.putExtra("fromNotification", true);
contentIntent.putExtra("accountID", accountID);
contentIntent.putExtra("notificationID", notificationId);
if(notification!=null){
contentIntent.putExtra("notification", Parcels.wrap(notification));
}
builder.setContentTitle(pn.title)
.setContentText(pn.body)
.setContentTitle(pn.title)
.setStyle(new Notification.BigTextStyle().bigText(pn.body))
.setSmallIcon(R.drawable.ic_ntf_logo)
.setContentIntent(PendingIntent.getActivity(context, notificationId, contentIntent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT))
@@ -192,7 +151,8 @@ public class PushNotificationReceiver extends BroadcastReceiver{
.setShowWhen(true)
.setCategory(Notification.CATEGORY_SOCIAL)
.setAutoCancel(true)
.setColor(UiUtils.getThemeColor(context, android.R.attr.colorAccent));
.setColor(context.getColor(R.color.shortcut_icon_background))
.setGroup(accountID);
if (!GlobalUserPreferences.uniformNotificationIcon) {
builder.setSmallIcon(switch (pn.notificationType) {
@@ -215,126 +175,8 @@ public class PushNotificationReceiver extends BroadcastReceiver{
builder.setSubText(accountName);
}
int id = GlobalUserPreferences.keepOnlyLatestNotification ? NOTIFICATION_ID : notificationId++;
notificationId++;
nm.notify(accountID, GlobalUserPreferences.keepOnlyLatestNotification ? NOTIFICATION_ID : notificationId, builder.build());
if (notification != null){
switch (pn.notificationType){
case MENTION, STATUS -> {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
builder.addAction(buildReplyAction(context, id, accountID, notification));
}
builder.addAction(buildNotificationAction(context, id, accountID, notification, context.getString(R.string.button_favorite), NotificationAction.FAVORITE));
builder.addAction(buildNotificationAction(context, id, accountID, notification, context.getString(R.string.add_bookmark), NotificationAction.BOOKMARK));
if(notification.status.visibility != StatusPrivacy.DIRECT) {
builder.addAction(buildNotificationAction(context, id, accountID, notification, context.getString(R.string.button_reblog), NotificationAction.REBLOG));
}
}
case UPDATE -> {
if(notification.status.reblogged)
builder.addAction(buildNotificationAction(context, id, accountID, notification, context.getString(R.string.sk_undo_reblog), NotificationAction.UNDO_REBLOG));
}
}
}
nm.notify(accountID, id, builder.build());
}
private Notification.Action buildNotificationAction(Context context, int notificationId, String accountID, org.joinmastodon.android.model.Notification notification, String title, NotificationAction action){
Intent notificationIntent=new Intent(context, PushNotificationReceiver.class);
notificationIntent.putExtra("notificationId", notificationId);
notificationIntent.putExtra("fromNotificationAction", true);
notificationIntent.putExtra("accountID", accountID);
notificationIntent.putExtra("notificationAction", action.ordinal());
notificationIntent.putExtra("notification", Parcels.wrap(notification));
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, new Random().nextInt(), notificationIntent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);
return new Notification.Action.Builder(null, title, actionPendingIntent).build();
}
private Notification.Action buildReplyAction(Context context, int notificationId, String accountID, org.joinmastodon.android.model.Notification notification){
String replyLabel = context.getResources().getString(R.string.button_reply);
RemoteInput remoteInput = new RemoteInput.Builder(ACTION_KEY_TEXT_REPLY)
.setLabel(replyLabel)
.build();
Intent notificationIntent=new Intent(context, PushNotificationReceiver.class);
notificationIntent.putExtra("notificationId", notificationId);
notificationIntent.putExtra("fromNotificationAction", true);
notificationIntent.putExtra("accountID", accountID);
notificationIntent.putExtra("notificationAction", NotificationAction.REPLY.ordinal());
notificationIntent.putExtra("notification", Parcels.wrap(notification));
int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT : PendingIntent.FLAG_UPDATE_CURRENT;
PendingIntent replyPendingIntent = PendingIntent.getBroadcast(context, new Random().nextInt(), notificationIntent,flags);
return new Notification.Action.Builder(null, replyLabel, replyPendingIntent).addRemoteInput(remoteInput).build();
}
private void handleReplyAction(Context context, String accountID, Intent intent, org.joinmastodon.android.model.Notification notification, int notificationId, Preferences preferences) {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput == null) {
Log.e(TAG, "handleReplyAction: Could not get reply input");
return;
}
CharSequence input = remoteInput.getCharSequence(ACTION_KEY_TEXT_REPLY);
// copied from ComposeFragment - TODO: generalize?
ArrayList<String> mentions=new ArrayList<>();
Status status = notification.status;
String ownID=AccountSessionManager.getInstance().getAccount(accountID).self.id;
if(!status.account.id.equals(ownID))
mentions.add('@'+status.account.acct);
for(Mention mention:status.mentions){
if(mention.id.equals(ownID))
continue;
String m='@'+mention.acct;
if(!mentions.contains(m))
mentions.add(m);
}
String initialText=mentions.isEmpty() ? "" : TextUtils.join(" ", mentions)+" ";
CreateStatus.Request req=new CreateStatus.Request();
req.status = initialText + input.toString();
req.language = preferences.postingDefaultLanguage;
req.visibility = preferences.postingDefaultVisibility;
req.inReplyToId = notification.status.id;
if (!notification.status.spoilerText.isEmpty() &&
(GlobalUserPreferences.prefixReplies == ALWAYS
|| (GlobalUserPreferences.prefixReplies == TO_OTHERS && !ownID.equals(notification.status.account.id)))
&& !notification.status.spoilerText.startsWith("re: ")) {
req.spoilerText = "re: " + notification.status.spoilerText;
}
new CreateStatus(req, UUID.randomUUID().toString()).setCallback(new Callback<>() {
@Override
public void onSuccess(Status status) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ?
new Notification.Builder(context, accountID+"_"+notification.type) :
new Notification.Builder(context)
.setPriority(Notification.PRIORITY_DEFAULT)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);
notification.status = status;
Intent contentIntent=new Intent(context, MainActivity.class);
contentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
contentIntent.putExtra("fromNotification", true);
contentIntent.putExtra("accountID", accountID);
contentIntent.putExtra("notification", Parcels.wrap(notification));
Notification repliedNotification = builder.setSmallIcon(R.drawable.ic_ntf_logo)
.setContentTitle(context.getString(R.string.sk_notification_action_replied, notification.status.account.displayName))
.setContentText(status.getStrippedText())
.setCategory(Notification.CATEGORY_SOCIAL)
.setContentIntent(PendingIntent.getActivity(context, notificationId, contentIntent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT))
.build();
notificationManager.notify(accountID, notificationId, repliedNotification);
}
@Override
public void onError(ErrorResponse errorResponse) {
}
}).exec(accountID);
}
}

View File

@@ -11,7 +11,7 @@ public class ApiUtils{
//no instance
}
public static <E extends Enum<E>> List<String> enumSetToStrings(EnumSet<E> e, Class<E> cls){
public static <E extends Enum<E>> List<String> enumSetToStrings(EnumSet<E> e, Class<E> cls){
return e.stream().map(ev->{
try{
SerializedName annotation=cls.getField(ev.name()).getAnnotation(SerializedName.class);

View File

@@ -13,12 +13,11 @@ import org.joinmastodon.android.BuildConfig;
import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.api.requests.notifications.GetNotifications;
import org.joinmastodon.android.api.requests.timelines.GetHomeTimeline;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.CacheablePaginatedResponse;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.model.PaginatedResponse;
import org.joinmastodon.android.model.SearchResult;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.utils.StatusFilterPredicate;
@@ -36,7 +35,7 @@ import me.grishka.appkit.utils.WorkerThread;
public class CacheController{
private static final String TAG="CacheController";
private static final int DB_VERSION=4;
private static final int DB_VERSION=3;
private static final WorkerThread databaseThread=new WorkerThread("databaseThread");
private static final Handler uiHandler=new Handler(Looper.getMainLooper());
@@ -61,7 +60,7 @@ public class CacheController{
List<Filter> filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(Filter.FilterContext.HOME)).collect(Collectors.toList());
if(!forceReload){
SQLiteDatabase db=getOrOpenDatabase();
try(Cursor cursor=db.query("home_timeline", new String[]{"json", "flags"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`time` DESC", count+"")){
try(Cursor cursor=db.query("home_timeline", new String[]{"json", "flags"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`id` DESC", count+"")){
if(cursor.getCount()==count){
ArrayList<Status> result=new ArrayList<>();
cursor.moveToFirst();
@@ -73,8 +72,10 @@ public class CacheController{
int flags=cursor.getInt(1);
status.hasGapAfter=((flags & POST_FLAG_GAP_AFTER)!=0);
newMaxID=status.id;
if (!new StatusFilterPredicate(filters, Filter.FilterContext.HOME).test(status))
continue outer;
for(Filter filter:filters){
if(filter.matches(status))
continue outer;
}
result.add(status);
}while(cursor.moveToNext());
String _newMaxID=newMaxID;
@@ -89,7 +90,7 @@ public class CacheController{
.setCallback(new Callback<>(){
@Override
public void onSuccess(List<Status> result){
callback.onSuccess(new CacheablePaginatedResponse<>(result.stream().filter(new StatusFilterPredicate(filters, Filter.FilterContext.HOME)).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id, false));
callback.onSuccess(new CacheablePaginatedResponse<>(result.stream().filter(new StatusFilterPredicate(filters)).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id, false));
putHomeTimeline(result, maxID==null);
}
@@ -112,7 +113,7 @@ public class CacheController{
runOnDbThread((db)->{
if(clear)
db.delete("home_timeline", null, null);
ContentValues values=new ContentValues(4);
ContentValues values=new ContentValues(3);
for(Status s:posts){
values.put("id", s.id);
values.put("json", MastodonAPIController.gson.toJson(s));
@@ -120,22 +121,20 @@ public class CacheController{
if(s.hasGapAfter)
flags|=POST_FLAG_GAP_AFTER;
values.put("flags", flags);
values.put("time", s.createdAt.getEpochSecond());
db.insertWithOnConflict("home_timeline", null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
});
}
public void getNotifications(String maxID, int count, boolean onlyMentions, boolean onlyPosts, boolean forceReload, Callback<CacheablePaginatedResponse<List<Notification>>> callback){
public void getNotifications(String maxID, int count, boolean onlyMentions, boolean onlyPosts, boolean forceReload, Callback<PaginatedResponse<List<Notification>>> callback){
cancelDelayedClose();
databaseThread.postRunnable(()->{
try{
AccountSession accountSession=AccountSessionManager.getInstance().getAccount(accountID);
List<Filter> filters=accountSession.wordFilters.stream().filter(f->f.context.contains(Filter.FilterContext.NOTIFICATIONS)).collect(Collectors.toList());
List<Filter> filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(Filter.FilterContext.NOTIFICATIONS)).collect(Collectors.toList());
if(!forceReload){
SQLiteDatabase db=getOrOpenDatabase();
String table=onlyPosts ? "notifications_posts" : onlyMentions ? "notifications_mentions" : "notifications_all";
try(Cursor cursor=db.query(table, new String[]{"json"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`time` DESC", count+"")){
try(Cursor cursor=db.query(table, new String[]{"json"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`id` DESC", count+"")){
if(cursor.getCount()==count){
ArrayList<Notification> result=new ArrayList<>();
cursor.moveToFirst();
@@ -146,30 +145,35 @@ public class CacheController{
ntf.postprocess();
newMaxID=ntf.id;
if(ntf.status!=null){
if (!new StatusFilterPredicate(filters, Filter.FilterContext.NOTIFICATIONS).test(ntf.status))
continue outer;
for(Filter filter:filters){
if(filter.matches(ntf.status))
continue outer;
}
}
result.add(ntf);
}while(cursor.moveToNext());
String _newMaxID=newMaxID;
uiHandler.post(()->callback.onSuccess(new CacheablePaginatedResponse<>(result, _newMaxID, true)));
uiHandler.post(()->callback.onSuccess(new PaginatedResponse<>(result, _newMaxID)));
return;
}
}catch(IOException x){
Log.w(TAG, "getNotifications: corrupted notification object in database", x);
}
}
Instance instance=AccountSessionManager.getInstance().getInstanceInfo(accountSession.domain);
new GetNotifications(maxID, count, onlyPosts ? EnumSet.of(Notification.Type.STATUS) : onlyMentions ? EnumSet.of(Notification.Type.MENTION): EnumSet.allOf(Notification.Type.class), instance.isAkkoma())
new GetNotifications(maxID, count, onlyPosts ? EnumSet.of(Notification.Type.STATUS) : onlyMentions ? EnumSet.of(Notification.Type.MENTION): EnumSet.allOf(Notification.Type.class))
.setCallback(new Callback<>(){
@Override
public void onSuccess(List<Notification> result){
callback.onSuccess(new CacheablePaginatedResponse<>(result.stream().filter(ntf->{
callback.onSuccess(new PaginatedResponse<>(result.stream().filter(ntf->{
if(ntf.status!=null){
return new StatusFilterPredicate(filters, Filter.FilterContext.NOTIFICATIONS).test(ntf.status);
for(Filter filter:filters){
if(filter.matches(ntf.status)){
return false;
}
}
}
return true;
}).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id, false));
}).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id));
putNotifications(result, onlyMentions, onlyPosts, maxID==null);
}
@@ -193,7 +197,7 @@ public class CacheController{
String table=onlyPosts ? "notifications_posts" : onlyMentions ? "notifications_mentions" : "notifications_all";
if(clear)
db.delete(table, null, null);
ContentValues values=new ContentValues(4);
ContentValues values=new ContentValues(3);
for(Notification n:notifications){
if(n.type==null){
continue;
@@ -201,7 +205,6 @@ public class CacheController{
values.put("id", n.id);
values.put("json", MastodonAPIController.gson.toJson(n));
values.put("type", n.type.ordinal());
values.put("time", n.createdAt.getEpochSecond());
db.insertWithOnConflict(table, null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
});
@@ -298,24 +301,21 @@ public class CacheController{
CREATE TABLE `home_timeline` (
`id` VARCHAR(25) NOT NULL PRIMARY KEY,
`json` TEXT NOT NULL,
`flags` INTEGER NOT NULL DEFAULT 0,
`time` INTEGER NOT NULL
`flags` INTEGER NOT NULL DEFAULT 0
)""");
db.execSQL("""
CREATE TABLE `notifications_all` (
`id` VARCHAR(25) NOT NULL PRIMARY KEY,
`json` TEXT NOT NULL,
`flags` INTEGER NOT NULL DEFAULT 0,
`type` INTEGER NOT NULL,
`time` INTEGER NOT NULL
`type` INTEGER NOT NULL
)""");
db.execSQL("""
CREATE TABLE `notifications_mentions` (
`id` VARCHAR(25) NOT NULL PRIMARY KEY,
`json` TEXT NOT NULL,
`flags` INTEGER NOT NULL DEFAULT 0,
`type` INTEGER NOT NULL,
`time` INTEGER NOT NULL
`type` INTEGER NOT NULL
)""");
createRecentSearchesTable(db);
createPostsNotificationsTable(db);
@@ -323,16 +323,12 @@ public class CacheController{
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
if(oldVersion<2){
if(oldVersion==1){
createRecentSearchesTable(db);
}
if(oldVersion<3){
// MEGALODON-SPECIFIC
if(oldVersion==2){
createPostsNotificationsTable(db);
}
if(oldVersion<4){
addTimeColumns(db);
}
}
private void createRecentSearchesTable(SQLiteDatabase db){
@@ -350,21 +346,9 @@ public class CacheController{
`id` VARCHAR(25) NOT NULL PRIMARY KEY,
`json` TEXT NOT NULL,
`flags` INTEGER NOT NULL DEFAULT 0,
`type` INTEGER NOT NULL,
`time` INTEGER NOT NULL
`type` INTEGER NOT NULL
)""");
}
private void addTimeColumns(SQLiteDatabase db){
db.execSQL("DELETE FROM `home_timeline`");
db.execSQL("DELETE FROM `notifications_all`");
db.execSQL("DELETE FROM `notifications_mentions`");
db.execSQL("DELETE FROM `notifications_posts`");
db.execSQL("ALTER TABLE `home_timeline` ADD `time` INTEGER NOT NULL DEFAULT 0");
db.execSQL("ALTER TABLE `notifications_all` ADD `time` INTEGER NOT NULL DEFAULT 0");
db.execSQL("ALTER TABLE `notifications_mentions` ADD `time` INTEGER NOT NULL DEFAULT 0");
db.execSQL("ALTER TABLE `notifications_posts` ADD `time` INTEGER NOT NULL DEFAULT 0");
}
}
@FunctionalInterface

View File

@@ -16,8 +16,6 @@ import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.api.gson.IsoInstantTypeAdapter;
import org.joinmastodon.android.api.gson.IsoLocalDateTypeAdapter;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.utils.UiUtils;
import java.io.BufferedReader;
import java.io.IOException;
@@ -29,7 +27,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -43,19 +40,14 @@ import okhttp3.ResponseBody;
public class MastodonAPIController{
private static final String TAG="MastodonAPIController";
public static final Gson gsonWithoutDeserializer = new GsonBuilder()
public static final Gson gson=new GsonBuilder()
.disableHtmlEscaping()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.registerTypeAdapter(Instant.class, new IsoInstantTypeAdapter())
.registerTypeAdapter(LocalDate.class, new IsoLocalDateTypeAdapter())
.create();
public static final Gson gson = gsonWithoutDeserializer.newBuilder()
.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<>();
@@ -64,7 +56,7 @@ public class MastodonAPIController{
thread.start();
try {
final BufferedReader reader = new BufferedReader(new InputStreamReader(
MastodonApp.context.getAssets().open("blocks.txt")
MastodonApp.context.getAssets().open("blocks.tsv")
));
String line;
while ((line = reader.readLine()) != null) {
@@ -95,7 +87,7 @@ public class MastodonAPIController{
Request.Builder builder=new Request.Builder()
.url(req.getURL().toString())
.method(req.getMethod(), req.getRequestBody())
.header("User-Agent", "MegalodonAndroid/"+BuildConfig.VERSION_NAME);
.header("User-Agent", "MastodonAndroid/"+BuildConfig.VERSION_NAME);
String token=null;
if(session!=null)
@@ -162,11 +154,6 @@ public class MastodonAPIController{
respObj=gson.fromJson(reader, req.respClass);
}
}catch(JsonIOException|JsonSyntaxException x){
if (req.context != null && response.body().contentType().subtype().equals("html")) {
UiUtils.launchWebBrowser(req.context, response.request().url().toString());
req.cancel();
return;
}
if(BuildConfig.DEBUG)
Log.w(TAG, "["+(session==null ? "no-auth" : session.getID())+"] "+response+" error parsing or reading body", x);
req.onError(x.getLocalizedMessage(), response.code(), x);

View File

@@ -2,7 +2,6 @@ package org.joinmastodon.android.api;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import android.util.Pair;
@@ -21,11 +20,9 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import me.grishka.appkit.api.APIRequest;
import me.grishka.appkit.api.Callback;
@@ -47,11 +44,10 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
TypeToken<T> respTypeToken;
Call okhttpCall;
Token token;
boolean canceled, isRemote;
boolean canceled;
Map<String, String> headers;
private ProgressDialog progressDialog;
protected boolean removeUnsupportedItems;
@Nullable Context context;
public MastodonAPIRequest(HttpMethod method, String path, Class<T> respClass){
this.path=path;
@@ -105,21 +101,6 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
return this;
}
public MastodonAPIRequest<T> execRemote(String domain) {
return execRemote(domain, null);
}
public MastodonAPIRequest<T> execRemote(String domain, @Nullable AccountSession remoteSession) {
this.isRemote = true;
return Optional.ofNullable(remoteSession)
.or(() -> AccountSessionManager.getInstance().getLoggedInAccounts().stream()
.filter(acc -> acc.domain.equals(domain))
.findAny())
.map(AccountSession::getID)
.map(this::exec)
.orElse(this.execNoAuth(domain));
}
public MastodonAPIRequest<T> wrapProgress(Activity activity, @StringRes int message, boolean cancelable){
return wrapProgress(activity, message, cancelable, null);
}
@@ -183,20 +164,9 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
return this;
}
public MastodonAPIRequest<T> setContext(Context context) {
this.context = context;
return this;
}
@Nullable
public Context getContext() {
return context;
}
@CallSuper
public void validateAndPostprocessResponse(T respObj, Response httpResponse) throws IOException{
if(respObj instanceof BaseModel){
((BaseModel) respObj).isRemote = isRemote;
((BaseModel) respObj).postprocess();
}else if(respObj instanceof List){
if(removeUnsupportedItems){
@@ -205,7 +175,6 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
Object item=itr.next();
if(item instanceof BaseModel){
try{
((BaseModel) item).isRemote = isRemote;
((BaseModel) item).postprocess();
}catch(ObjectValidationException x){
Log.w(TAG, "Removing invalid object from list", x);
@@ -213,20 +182,15 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
}
}
}
// no idea why we're post-processing twice, but well, as long
// as upstream does it like this, i don't wanna break anything
for(Object item:((List<?>) respObj)){
if(item instanceof BaseModel){
((BaseModel) item).isRemote = isRemote;
((BaseModel) item).postprocess();
}
}
}else{
for(Object item:((List<?>) respObj)){
if(item instanceof BaseModel) {
((BaseModel) item).isRemote = isRemote;
if(item instanceof BaseModel)
((BaseModel) item).postprocess();
}
}
}
}

View File

@@ -5,6 +5,8 @@ import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import org.joinmastodon.android.R;
import me.grishka.appkit.api.ErrorResponse;
public class MastodonErrorResponse extends ErrorResponse{
@@ -20,7 +22,7 @@ public class MastodonErrorResponse extends ErrorResponse{
@Override
public void bindErrorView(View view){
TextView text=view.findViewById(me.grishka.appkit.R.id.error_text);
TextView text=view.findViewById(R.id.error_text);
text.setText(error);
}

View File

@@ -372,7 +372,7 @@ public class PushSubscriptionManager{
for(AccountSession session:AccountSessionManager.getInstance().getLoggedInAccounts()){
if(session.pushSubscription==null || forceReRegister)
session.getPushSubscriptionManager().registerAccountForPush(session.pushSubscription);
else
else if(session.needUpdatePushSettings)
session.getPushSubscriptionManager().updatePushSettings(session.pushSubscription);
}
}

View File

@@ -46,7 +46,7 @@ public class StatusInteractionController{
@Override
public void onSuccess(Status result){
runningFavoriteRequests.remove(status.id);
result.favouritesCount = Math.max(0, status.favouritesCount + (favorited ? 1 : -1));
result.favouritesCount = Math.max(0, status.favouritesCount) + (favorited ? 1 : -1);
cb.accept(result);
if (updateCounters) E.post(new StatusCountersUpdatedEvent(result));
}
@@ -80,7 +80,7 @@ public class StatusInteractionController{
public void onSuccess(Status reblog){
Status result = reblog.getContentStatus();
runningReblogRequests.remove(status.id);
result.reblogsCount = Math.max(0, status.reblogsCount + (reblogged ? 1 : -1));
result.reblogsCount = Math.max(0, status.reblogsCount) + (reblogged ? 1 : -1);
cb.accept(result);
if (updateCounters) E.post(new StatusCountersUpdatedEvent(result));
}

View File

@@ -1,15 +0,0 @@
package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Account;
public class GetAccountByHandle extends MastodonAPIRequest<Account>{
/**
* note that this method usually only returns a result if the instance already knows about an
* account - so it makes sense for looking up local users, search might be preferred otherwise
*/
public GetAccountByHandle(String acct){
super(HttpMethod.GET, "/accounts/lookup", Account.class);
addQueryParameter("acct", acct);
}
}

View File

@@ -4,10 +4,6 @@ import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Relationship;
public class SetAccountFollowed extends MastodonAPIRequest<Relationship>{
public SetAccountFollowed(String id, boolean followed, boolean showReblogs){
this(id, followed, showReblogs, false);
}
public SetAccountFollowed(String id, boolean followed, boolean showReblogs, boolean notify){
super(HttpMethod.POST, "/accounts/"+id+"/"+(followed ? "follow" : "unfollow"), Relationship.class);
if(followed)

View File

@@ -0,0 +1,19 @@
package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Relationship;
public class SetPrivateNote extends MastodonAPIRequest<Relationship>{
public SetPrivateNote(String id, String comment){
super(MastodonAPIRequest.HttpMethod.POST, "/accounts/"+id+"/note", Relationship.class);
Request req = new Request(comment);
setRequestBody(req);
}
private static class Request{
public String comment;
public Request(String comment){
this.comment=comment;
}
}
}

View File

@@ -0,0 +1,17 @@
package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest;
import java.util.List;
public class AddList extends MastodonAPIRequest<Object> {
public AddList(String listName){
super(HttpMethod.POST, "/lists", Object.class);
Request req = new Request();
req.title = listName;
setRequestBody(req);
}
public static class Request{
public String title;
}
}

View File

@@ -0,0 +1,17 @@
package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest;
import java.util.List;
public class EditListName extends MastodonAPIRequest<Object> {
public EditListName(String newListName, String listId){
super(HttpMethod.PUT, "/lists/"+listId, Object.class);
Request req = new Request();
req.title = newListName;
setRequestBody(req);
}
public static class Request{
public String title;
}
}

View File

@@ -0,0 +1,10 @@
package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest;
import java.util.List;
public class RemoveList extends MastodonAPIRequest<Object> {
public RemoveList(String listId){
super(HttpMethod.DELETE, "/lists/"+listId, Object.class);
}
}

View File

@@ -1,17 +0,0 @@
package org.joinmastodon.android.api.requests.markers;
import org.joinmastodon.android.api.ApiUtils;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Marker;
import org.joinmastodon.android.model.Markers;
import java.util.EnumSet;
public class GetMarkers extends MastodonAPIRequest<Markers> {
public GetMarkers(EnumSet<Marker.Type> timelines) {
super(HttpMethod.GET, "/markers", Markers.class);
for (String type : ApiUtils.enumSetToStrings(timelines, Marker.Type.class)){
addQueryParameter("timeline[]", type);
}
}
}

View File

@@ -10,8 +10,8 @@ import java.util.EnumSet;
import java.util.List;
public class DismissNotification extends MastodonAPIRequest<Object>{
public DismissNotification(String id){
super(HttpMethod.POST, "/notifications/" + (id != null ? id + "/dismiss" : "clear"), Object.class);
setRequestBody(new Object());
}
public DismissNotification(String id){
super(HttpMethod.POST, "/notifications/" + (id != null ? id + "/dismiss" : "clear"), Object.class);
setRequestBody(new Object());
}
}

View File

@@ -1,5 +1,6 @@
package org.joinmastodon.android.api.requests.notifications;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.ApiUtils;
@@ -10,24 +11,18 @@ import java.util.EnumSet;
import java.util.List;
public class GetNotifications extends MastodonAPIRequest<List<Notification>>{
public GetNotifications(String maxID, int limit, EnumSet<Notification.Type> includeTypes, boolean isPleromaInstance){
public GetNotifications(String maxID, int limit, EnumSet<Notification.Type> includeTypes){
super(HttpMethod.GET, "/notifications", new TypeToken<>(){});
if(maxID!=null)
addQueryParameter("max_id", maxID);
if(limit>0)
addQueryParameter("limit", ""+limit);
if(includeTypes!=null){
if(!isPleromaInstance) {
for(String type:ApiUtils.enumSetToStrings(includeTypes, Notification.Type.class)){
addQueryParameter("types[]", type);
}
for(String type:ApiUtils.enumSetToStrings(EnumSet.complementOf(includeTypes), Notification.Type.class)){
addQueryParameter("exclude_types[]", type);
}
}else{
for(String type:ApiUtils.enumSetToStrings(includeTypes, Notification.Type.class)){
addQueryParameter("include_types[]", type);
}
for(String type:ApiUtils.enumSetToStrings(includeTypes, Notification.Type.class)){
addQueryParameter("types[]", type);
}
for(String type:ApiUtils.enumSetToStrings(EnumSet.complementOf(includeTypes), Notification.Type.class)){
addQueryParameter("exclude_types[]", type);
}
}
removeUnsupportedItems=true;

View File

@@ -1,30 +0,0 @@
package org.joinmastodon.android.api.requests.notifications;
import android.text.TextUtils;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Notification;
import java.util.List;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
public class PleromaMarkNotificationsRead extends MastodonAPIRequest<List<Notification>> {
private String maxID;
public PleromaMarkNotificationsRead(String maxID) {
super(HttpMethod.POST, "/pleroma/notifications/read", new TypeToken<>(){});
this.maxID = maxID;
}
@Override
public RequestBody getRequestBody() {
MultipartBody.Builder builder=new MultipartBody.Builder()
.setType(MultipartBody.FORM);
if(!TextUtils.isEmpty(maxID))
builder.addFormDataPart("max_id", maxID);
return builder.build();
}
}

View File

@@ -11,9 +11,9 @@ public class CreateOAuthApp extends MastodonAPIRequest<Application>{
}
private static class Request{
public String clientName="Megalodon";
public String clientName="Moshidon";
public String redirectUris=AccountSessionManager.REDIRECT_URI;
public String scopes=AccountSessionManager.SCOPE;
public String website="https://sk22.github.io/megalodon";
public String website="https://github.com/LucasGGamerM/moshidon";
}
}

View File

@@ -1,7 +1,6 @@
package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.ContentType;
import org.joinmastodon.android.model.ScheduledStatus;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.StatusPrivacy;
@@ -46,9 +45,6 @@ public class CreateStatus extends MastodonAPIRequest<Status>{
public Instant scheduledAt;
public String language;
public String quoteId;
public ContentType contentType;
public static class Poll{
public ArrayList<String> options=new ArrayList<>();
public int expiresIn;

View File

@@ -2,22 +2,17 @@ package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.AllFieldsAreRequired;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.RequiredField;
import org.joinmastodon.android.model.BaseModel;
import org.joinmastodon.android.model.ContentType;
public class GetStatusSourceText extends MastodonAPIRequest<GetStatusSourceText.Response>{
public GetStatusSourceText(String id){
super(HttpMethod.GET, "/statuses/"+id+"/source", Response.class);
}
@AllFieldsAreRequired
public static class Response extends BaseModel{
@RequiredField
public String id;
@RequiredField
public String text;
@RequiredField
public String spoilerText;
public ContentType contentType;
}
}

View File

@@ -1,23 +0,0 @@
package org.joinmastodon.android.api.requests.timelines;
import android.text.TextUtils;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status;
import java.util.List;
public class GetBubbleTimeline extends MastodonAPIRequest<List<Status>> {
public GetBubbleTimeline(String maxID, int limit) {
super(HttpMethod.GET, "/timelines/bubble", new TypeToken<>(){});
if(!TextUtils.isEmpty(maxID))
addQueryParameter("max_id", maxID);
if(limit>0)
addQueryParameter("limit", limit+"");
if(GlobalUserPreferences.replyVisibility != null)
addQueryParameter("reply_visibility", GlobalUserPreferences.replyVisibility);
}
}

View File

@@ -2,7 +2,6 @@ package org.joinmastodon.android.api.requests.timelines;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status;
@@ -17,7 +16,5 @@ public class GetHashtagTimeline extends MastodonAPIRequest<List<Status>>{
addQueryParameter("min_id", minID);
if(limit>0)
addQueryParameter("limit", ""+limit);
if(GlobalUserPreferences.replyVisibility != null)
addQueryParameter("reply_visibility", GlobalUserPreferences.replyVisibility);
}
}

View File

@@ -2,7 +2,6 @@ package org.joinmastodon.android.api.requests.timelines;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status;
@@ -19,7 +18,5 @@ public class GetHomeTimeline extends MastodonAPIRequest<List<Status>>{
addQueryParameter("since_id", sinceID);
if(limit>0)
addQueryParameter("limit", ""+limit);
if(GlobalUserPreferences.replyVisibility != null)
addQueryParameter("reply_visibility", GlobalUserPreferences.replyVisibility);
}
}

View File

@@ -2,7 +2,6 @@ package org.joinmastodon.android.api.requests.timelines;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status;
@@ -19,7 +18,5 @@ public class GetListTimeline extends MastodonAPIRequest<List<Status>> {
addQueryParameter("limit", ""+limit);
if(sinceID!=null)
addQueryParameter("since_id", sinceID);
if(GlobalUserPreferences.replyVisibility != null)
addQueryParameter("reply_visibility", GlobalUserPreferences.replyVisibility);
}
}

View File

@@ -4,7 +4,6 @@ import android.text.TextUtils;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status;
@@ -21,7 +20,5 @@ public class GetPublicTimeline extends MastodonAPIRequest<List<Status>>{
addQueryParameter("max_id", maxID);
if(limit>0)
addQueryParameter("limit", limit+"");
if(GlobalUserPreferences.replyVisibility != null)
addQueryParameter("reply_visibility", GlobalUserPreferences.replyVisibility);
}
}

View File

@@ -1,7 +1,5 @@
package org.joinmastodon.android.api.session;
import android.net.Uri;
import org.joinmastodon.android.api.CacheController;
import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.PushSubscriptionManager;
@@ -9,15 +7,12 @@ import org.joinmastodon.android.api.StatusInteractionController;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Application;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Markers;
import org.joinmastodon.android.model.Preferences;
import org.joinmastodon.android.model.PushSubscription;
import org.joinmastodon.android.model.Token;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class AccountSession{
public Token token;
@@ -36,7 +31,6 @@ public class AccountSession{
public String pushAccountID;
public Preferences preferences;
public AccountActivationInfo activationInfo;
public Markers markers;
private transient MastodonAPIController apiController;
private transient StatusInteractionController statusInteractionController, remoteStatusInteractionController;
private transient CacheController cacheController;
@@ -91,15 +85,4 @@ public class AccountSession{
pushSubscriptionManager=new PushSubscriptionManager(getID());
return pushSubscriptionManager;
}
public Optional<Instance> getInstance() {
return Optional.ofNullable(AccountSessionManager.getInstance().getInstanceInfo(domain));
}
public Uri getInstanceUri() {
return new Uri.Builder()
.scheme("https")
.authority(getInstance().map(i -> i.normalizedUri).orElse(domain))
.build();
}
}

View File

@@ -15,7 +15,6 @@ import android.util.Log;
import org.joinmastodon.android.BuildConfig;
import org.joinmastodon.android.E;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.MainActivity;
import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.R;
@@ -26,7 +25,6 @@ import org.joinmastodon.android.api.requests.accounts.GetWordFilters;
import org.joinmastodon.android.api.requests.instance.GetCustomEmojis;
import org.joinmastodon.android.api.requests.accounts.GetOwnAccount;
import org.joinmastodon.android.api.requests.instance.GetInstance;
import org.joinmastodon.android.api.requests.markers.GetMarkers;
import org.joinmastodon.android.api.requests.oauth.CreateOAuthApp;
import org.joinmastodon.android.events.EmojiUpdatedEvent;
import org.joinmastodon.android.model.Account;
@@ -35,8 +33,6 @@ import org.joinmastodon.android.model.Emoji;
import org.joinmastodon.android.model.EmojiCategory;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Marker;
import org.joinmastodon.android.model.Markers;
import org.joinmastodon.android.model.Preferences;
import org.joinmastodon.android.model.Token;
@@ -50,7 +46,6 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -66,7 +61,7 @@ import me.grishka.appkit.api.ErrorResponse;
public class AccountSessionManager{
private static final String TAG="AccountSessionManager";
public static final String SCOPE="read write follow push";
public static final String REDIRECT_URI="megalodon-android-auth://callback";
public static final String REDIRECT_URI="moshidon-android-auth://callback";
private static final AccountSessionManager instance=new AccountSessionManager();
@@ -111,12 +106,6 @@ public class AccountSessionManager{
sessions.put(session.getID(), session);
lastActiveAccountID=session.getID();
writeAccountsFile();
// write initial instance info to file immediately to avoid sessions without instance info
InstanceInfoStorageWrapper wrapper = new InstanceInfoStorageWrapper();
wrapper.instance = instance;
MastodonAPIController.runInBackground(()->writeInstanceInfoFile(wrapper, instance.uri));
updateMoreInstanceInfo(instance, instance.uri);
if(PushSubscriptionManager.arePushNotificationsAvailable()){
session.getPushSubscriptionManager().registerAccountForPush(null);
@@ -125,16 +114,14 @@ public class AccountSessionManager{
}
public synchronized void writeAccountsFile(){
File tmpFile = new File(MastodonApp.context.getFilesDir(), "accounts.json~");
File file = new File(MastodonApp.context.getFilesDir(), "accounts.json");
File file=new File(MastodonApp.context.getFilesDir(), "accounts.json");
try{
try(FileOutputStream out=new FileOutputStream(tmpFile)){
try(FileOutputStream out=new FileOutputStream(file)){
SessionsStorageWrapper w=new SessionsStorageWrapper();
w.accounts=new ArrayList<>(sessions.values());
OutputStreamWriter writer=new OutputStreamWriter(out, StandardCharsets.UTF_8);
MastodonAPIController.gson.toJson(w, writer);
writer.flush();
if (!tmpFile.renameTo(file)) Log.e(TAG, "Error renaming " + tmpFile.getPath() + " to " + file.getPath());
}
}catch(IOException x){
Log.e(TAG, "Error writing accounts file", x);
@@ -160,11 +147,6 @@ public class AccountSessionManager{
return sessions.get(id);
}
@Nullable
public AccountSession tryGetAccount(Account account) {
return sessions.get(account.getDomainFromURL() + "_" + account.id);
}
@Nullable
public AccountSession getLastActiveAccount(){
if(sessions.isEmpty() || lastActiveAccountID==null)
@@ -192,7 +174,6 @@ public class AccountSessionManager{
AccountSession session=getAccount(id);
session.getCacheController().closeDatabase();
MastodonApp.context.deleteDatabase(id+".db");
GlobalUserPreferences.removeAccount(id);
sessions.remove(id);
if(lastActiveAccountID.equals(id)){
if(sessions.isEmpty())
@@ -230,7 +211,7 @@ public class AccountSessionManager{
.path("/oauth/authorize")
.appendQueryParameter("response_type", "code")
.appendQueryParameter("client_id", result.clientId)
.appendQueryParameter("redirect_uri", "megalodon-android-auth://callback")
.appendQueryParameter("redirect_uri", "moshidon-android-auth://callback")
.appendQueryParameter("scope", SCOPE)
.build();
@@ -263,44 +244,30 @@ public class AccountSessionManager{
}
public void maybeUpdateLocalInfo(){
maybeUpdateLocalInfo(null);
}
public void maybeUpdateLocalInfo(AccountSession activeSession){
long now=System.currentTimeMillis();
HashSet<String> domains=new HashSet<>();
for(AccountSession session:sessions.values()){
domains.add(session.domain.toLowerCase());
if(now-session.infoLastUpdated>24L*3600_000L || session == activeSession){
updateSessionPreferences(session);
updateSessionLocalInfo(session);
}
if(now-session.filtersLastUpdated>3600_000L || session == activeSession){
updateSessionWordFilters(session);
}
updateSessionMarkers(session);
// if(now-session.infoLastUpdated>24L*3600_000L){
updateSessionPreferences(session);
updateSessionLocalInfo(session);
// }
// if(now-session.filtersLastUpdated>3600_000L){
updateSessionWordFilters(session);
// }
}
if(loadedInstances){
maybeUpdateCustomEmojis(domains, activeSession != null ? activeSession.domain : null);
maybeUpdateCustomEmojis(domains);
}
}
private void maybeUpdateCustomEmojis(Set<String> domains, String activeDomain){
private void maybeUpdateCustomEmojis(Set<String> domains){
long now=System.currentTimeMillis();
for(String domain:domains){
Long lastUpdated=instancesLastUpdated.get(domain);
if(lastUpdated==null || now-lastUpdated>24L*3600_000L || domain.equals(activeDomain)){
updateInstanceInfo(domain);
}
}
}
private void preferencesFromSource(AccountSession session, Account account) {
if (account != null && account.source != null && session.preferences != null) {
if (account.source.privacy != null)
session.preferences.postingDefaultVisibility = account.source.privacy;
if (account.source.language != null)
session.preferences.postingDefaultLanguage = account.source.language;
// Long lastUpdated=instancesLastUpdated.get(domain);
// if(lastUpdated==null || now-lastUpdated>24L*3600_000L){
updateInstanceInfo(domain);
// }
}
}
@@ -311,12 +278,13 @@ public class AccountSessionManager{
public void onSuccess(Account result){
session.self=result;
session.infoLastUpdated=System.currentTimeMillis();
preferencesFromSource(session, result);
writeAccountsFile();
}
@Override
public void onError(ErrorResponse error){}
public void onError(ErrorResponse error){
}
})
.exec(session.getID());
}
@@ -326,14 +294,10 @@ public class AccountSessionManager{
@Override
public void onSuccess(Preferences preferences) {
session.preferences=preferences;
preferencesFromSource(session, session.self);
}
@Override
public void onError(ErrorResponse error) {
session.preferences = new Preferences();
preferencesFromSource(session, session.self);
}
public void onError(ErrorResponse error) {}
}).exec(session.getID());
}
@@ -355,21 +319,6 @@ public class AccountSessionManager{
.exec(session.getID());
}
private void updateSessionMarkers(AccountSession session) {
new GetMarkers(EnumSet.allOf(Marker.Type.class)).setCallback(new Callback<>() {
@Override
public void onSuccess(Markers markers) {
session.markers = markers;
writeAccountsFile();
}
@Override
public void onError(ErrorResponse error) {
}
}).exec(session.getID());
}
public void updateInstanceInfo(String domain){
new GetInstance()
.setCallback(new Callback<>(){
@@ -419,9 +368,7 @@ public class AccountSessionManager{
@Override
public void onError(ErrorResponse error){
InstanceInfoStorageWrapper wrapper=new InstanceInfoStorageWrapper();
wrapper.instance = instance;
MastodonAPIController.runInBackground(()->writeInstanceInfoFile(wrapper, domain));
}
})
.execNoAuth(domain);
@@ -432,13 +379,10 @@ public class AccountSessionManager{
}
private void writeInstanceInfoFile(InstanceInfoStorageWrapper emojis, String domain){
File file = getInstanceInfoFile(domain);
File tmpFile = new File(file.getPath() + "~");
try(FileOutputStream out=new FileOutputStream(tmpFile)){
try(FileOutputStream out=new FileOutputStream(getInstanceInfoFile(domain))){
OutputStreamWriter writer=new OutputStreamWriter(out, StandardCharsets.UTF_8);
MastodonAPIController.gson.toJson(emojis, writer);
writer.flush();
if (!tmpFile.renameTo(file)) Log.e(TAG, "Error renaming " + tmpFile.getPath() + " to " + file.getPath());
}catch(IOException x){
Log.w(TAG, "Error writing instance info file for "+domain, x);
}
@@ -458,7 +402,7 @@ public class AccountSessionManager{
}
if(!loadedInstances){
loadedInstances=true;
maybeUpdateCustomEmojis(domains, null);
maybeUpdateCustomEmojis(domains);
}
}
@@ -482,6 +426,10 @@ public class AccountSessionManager{
return instances.get(domain);
}
public Instance getInstanceInfoForAccount(String account) {
return AccountSessionManager.getInstance().getInstanceInfo(instance.getAccount(account).domain);
}
public void updateAccountInfo(String id, Account account){
AccountSession session=getAccount(id);
session.self=account;

View File

@@ -1,4 +0,0 @@
package org.joinmastodon.android.events;
public class AllNotificationsSeenEvent {
}

View File

@@ -1,9 +0,0 @@
package org.joinmastodon.android.events;
public class NotificationReceivedEvent {
public String account, id;
public NotificationReceivedEvent(String account, String id) {
this.account = account;
this.id = id;
}
}

View File

@@ -1,9 +1,12 @@
package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.animation.TranslateAnimation;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses;
@@ -12,16 +15,12 @@ import org.joinmastodon.android.events.RemoveAccountPostsEvent;
import org.joinmastodon.android.events.StatusCreatedEvent;
import org.joinmastodon.android.events.StatusUnpinnedEvent;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem;
import org.joinmastodon.android.utils.StatusFilterPredicate;
import org.parceler.Parcels;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import me.grishka.appkit.api.SimpleCallback;
@@ -62,12 +61,6 @@ public class AccountTimelineFragment extends StatusListFragment{
@Override
public void onSuccess(List<Status> result){
if(getActivity()==null) return;
AccountSessionManager asm = AccountSessionManager.getInstance();
result=result.stream().filter(status -> {
// don't hide own posts in own profile
if (asm.isSelf(accountID, user) && asm.isSelf(accountID, status.account)) return true;
else return new StatusFilterPredicate(accountID, getFilterContext()).test(status);
}).collect(Collectors.toList());
onDataLoaded(result, !result.isEmpty());
}
})
@@ -77,6 +70,7 @@ public class AccountTimelineFragment extends StatusListFragment{
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
fab = ((ProfileFragment) getParentFragment()).getFab();
}
@Override
@@ -87,8 +81,7 @@ public class AccountTimelineFragment extends StatusListFragment{
}
protected void onStatusCreated(StatusCreatedEvent ev){
AccountSessionManager asm = AccountSessionManager.getInstance();
if(!asm.isSelf(accountID, ev.status.account) || !asm.isSelf(accountID, user))
if(!AccountSessionManager.getInstance().isSelf(accountID, ev.status.account))
return;
if(filter==GetAccountStatuses.Filter.PINNED) return;
if(filter==GetAccountStatuses.Filter.DEFAULT){
@@ -96,11 +89,10 @@ public class AccountTimelineFragment extends StatusListFragment{
if(ev.status.inReplyToAccountId!=null && !ev.status.inReplyToAccountId.equals(AccountSessionManager.getInstance().getAccount(accountID).self.id))
return;
}else if(filter==GetAccountStatuses.Filter.MEDIA){
if(Optional.ofNullable(ev.status.mediaAttachments).map(List::isEmpty).orElse(true))
if(ev.status.mediaAttachments.isEmpty())
return;
}
prependItems(Collections.singletonList(ev.status), true);
if (isOnTop()) scrollToTop();
}
protected void onStatusUnpinned(StatusUnpinnedEvent ev){
@@ -127,19 +119,4 @@ public class AccountTimelineFragment extends StatusListFragment{
protected void onRemoveAccountPostsEvent(RemoveAccountPostsEvent ev){
// no-op
}
@Override
protected Filter.FilterContext getFilterContext() {
return Filter.FilterContext.ACCOUNT;
}
@Override
public Uri getWebUri(Uri.Builder base) {
// could return different uris based on filter (e.g. media -> "/media"), but i want to
// return the remote url to the user, and i don't know whether i'd need to append
// '#media' (akkoma/pleroma) or '/media' (glitch/mastodon) since i don't know anything
// about the remote instance. so, just returning the base url to the user instead
return Uri.parse(user.url);
}
}

View File

@@ -3,7 +3,6 @@ package org.joinmastodon.android.fragments;
import static java.util.stream.Collectors.toList;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
@@ -94,22 +93,14 @@ public class AnnouncementsFragment extends BaseStatusListFragment<Announcement>
@Override
public void onSuccess(List<Announcement> result){
if (getActivity() == null) return;
// get unread items first
List<Announcement> data = result.stream().filter(a -> !a.read).collect(toList());
if (data.isEmpty()) setResult(true, null);
else unreadIDs = data.stream().map(a -> a.id).collect(toList());
// append read items at the end
data.addAll(result.stream().filter(a -> a.read).collect(toList()));
onDataLoaded(data, false);
List<Announcement> unread = result.stream().filter(a -> !a.read).collect(toList());
List<Announcement> read = result.stream().filter(a -> a.read).collect(toList());
onDataLoaded(unread, true);
onDataLoaded(read, false);
if (unread.isEmpty()) setResult(true, null);
else unreadIDs = unread.stream().map(a -> a.id).collect(toList());
}
})
.exec(accountID);
}
@Override
public Uri getWebUri(Uri.Builder base) {
return isInstanceAkkoma() ? base.path("/announcements").build() : null;
}
}

View File

@@ -1,7 +1,6 @@
package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.app.assist.AssistContent;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Paint;
@@ -33,11 +32,12 @@ import org.joinmastodon.android.model.Poll;
import org.joinmastodon.android.model.Relationship;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.BetterItemAnimator;
import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.TileGridLayoutManager;
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.HeaderStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.MediaGridStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ImageStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.PollFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.PollOptionStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
@@ -45,10 +45,8 @@ import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.WarningFilteredStatusDisplayItem;
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
import org.joinmastodon.android.ui.utils.MediaAttachmentViewController;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.utils.ProvidesAssistContent;
import org.joinmastodon.android.utils.TypedObjectPool;
import org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout;
import java.util.ArrayList;
import java.util.Collections;
@@ -59,11 +57,11 @@ import java.util.stream.Collectors;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
@@ -71,7 +69,7 @@ import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.UsableRecyclerView;
public abstract class BaseStatusListFragment<T extends DisplayItemsParent> extends RecyclerFragment<T> implements PhotoViewerHost, ScrollableToTop, IsOnTop, HasFab, ProvidesAssistContent.ProvidesWebUri {
public abstract class BaseStatusListFragment<T extends DisplayItemsParent> extends BaseRecyclerFragment<T> implements PhotoViewerHost, ScrollableToTop{
protected ArrayList<StatusDisplayItem> displayItems=new ArrayList<>();
protected DisplayItemsAdapter adapter;
protected String accountID;
@@ -81,16 +79,9 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
protected HashMap<String, Account> knownAccounts=new HashMap<>();
protected HashMap<String, Relationship> relationships=new HashMap<>();
protected Rect tmpRect=new Rect();
protected TypedObjectPool<MediaGridStatusDisplayItem.GridItemType, MediaAttachmentViewController> attachmentViewsPool=new TypedObjectPool<>(this::makeNewMediaAttachmentView);
protected boolean currentlyScrolling;
public BaseStatusListFragment(){
super(20);
if (wantsComposeButton()) setListLayoutId(R.layout.recycler_fragment_with_fab);
}
protected boolean wantsComposeButton() {
return false;
}
@Override
@@ -132,7 +123,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
displayItems.clear();
}
protected int prependItems(List<T> items, boolean notify){
protected void prependItems(List<T> items, boolean notify){
data.addAll(0, items);
int offset=0;
for(T s:items){
@@ -145,7 +136,6 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
if(notify)
adapter.notifyItemRangeInserted(0, offset);
return offset;
}
protected String getMaxID(){
@@ -191,30 +181,29 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
@Override
public void openPhotoViewer(String parentID, Status _status, int attachmentIndex, MediaGridStatusDisplayItem.Holder gridHolder){
final Status status=_status.getContentStatus();
public void openPhotoViewer(String parentID, Status _status, int attachmentIndex){
final Status status=_status.reblog!=null ? _status.reblog : _status;
currentPhotoViewer=new PhotoViewer(getActivity(), status.mediaAttachments, attachmentIndex, new PhotoViewer.Listener(){
private MediaAttachmentViewController transitioningHolder;
private ImageStatusDisplayItem.Holder<?> transitioningHolder;
@Override
public void setPhotoViewVisibility(int index, boolean visible){
MediaAttachmentViewController holder=findPhotoViewHolder(index);
ImageStatusDisplayItem.Holder<?> holder=findPhotoViewHolder(index);
if(holder!=null)
holder.photo.setAlpha(visible ? 1f : 0f);
}
@Override
public boolean startPhotoViewTransition(int index, @NonNull Rect outRect, @NonNull int[] outCornerRadius){
MediaAttachmentViewController holder=findPhotoViewHolder(index);
if(holder!=null && list!=null){
ImageStatusDisplayItem.Holder<?> holder=findPhotoViewHolder(index);
if(holder!=null){
transitioningHolder=holder;
View view=transitioningHolder.photo;
int[] pos={0, 0};
view.getLocationOnScreen(pos);
outRect.set(pos[0], pos[1], pos[0]+view.getWidth(), pos[1]+view.getHeight());
list.setClipChildren(false);
gridHolder.setClipChildren(false);
transitioningHolder.view.setElevation(1f);
transitioningHolder.itemView.setElevation(1f);
return true;
}
return false;
@@ -241,16 +230,15 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
view.setTranslationY(0f);
view.setScaleX(1f);
view.setScaleY(1f);
transitioningHolder.view.setElevation(0f);
transitioningHolder.itemView.setElevation(0f);
if(list!=null)
list.setClipChildren(true);
gridHolder.setClipChildren(true);
transitioningHolder=null;
}
@Override
public Drawable getPhotoViewCurrentDrawable(int index){
MediaAttachmentViewController holder=findPhotoViewHolder(index);
ImageStatusDisplayItem.Holder<?> holder=findPhotoViewHolder(index);
if(holder!=null)
return holder.photo.getDrawable();
return null;
@@ -266,51 +254,27 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
requestPermissions(permissions, PhotoViewer.PERMISSION_REQUEST);
}
private MediaAttachmentViewController findPhotoViewHolder(int index){
return gridHolder.getViewController(index);
private ImageStatusDisplayItem.Holder<?> findPhotoViewHolder(int index){
if(list==null)
return null;
int offset=0;
for(StatusDisplayItem item:displayItems){
if(item.parentID.equals(parentID)){
if(item instanceof ImageStatusDisplayItem){
RecyclerView.ViewHolder holder=list.findViewHolderForAdapterPosition(getMainAdapterOffset()+offset+index);
if(holder instanceof ImageStatusDisplayItem.Holder<?> imgHolder){
return imgHolder;
}
return null;
}
}
offset++;
}
return null;
}
});
}
@Override
public @Nullable View getFab() {
if (getParentFragment() instanceof HasFab l) return l.getFab();
else return fab;
}
@Override
public void showFab() {
View fab = getFab();
if (fab == null || fab.getVisibility() == View.VISIBLE) return;
fab.setVisibility(View.VISIBLE);
TranslateAnimation animate = new TranslateAnimation(
0,
0,
fab.getHeight() * 2,
0);
animate.setDuration(300);
fab.startAnimation(animate);
}
public boolean isScrolling() {
return currentlyScrolling;
}
@Override
public void hideFab() {
View fab = getFab();
if (fab == null || fab.getVisibility() != View.VISIBLE) return;
TranslateAnimation animate = new TranslateAnimation(
0,
0,
0,
fab.getHeight() * 2);
animate.setDuration(300);
fab.startAnimation(animate);
fab.setVisibility(View.INVISIBLE);
scrollDiff = 0;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
@@ -322,13 +286,32 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
if(currentPhotoViewer!=null)
currentPhotoViewer.offsetView(-dx, -dy);
View fab = getFab();
if (fab!=null && GlobalUserPreferences.autoHideFab && dy != UiUtils.SCROLL_TO_TOP_DELTA) {
if (fab!=null && GlobalUserPreferences.enableFabAutoHide) {
if(dy > 0){
scrollDiff = 0;
}
if (dy > 0 && fab.getVisibility() == View.VISIBLE) {
hideFab();
TranslateAnimation animate = new TranslateAnimation(
0,
0,
0,
fab.getHeight() * 2);
animate.setDuration(300);
animate.setFillAfter(true);
fab.startAnimation(animate);
fab.setVisibility(View.INVISIBLE);
scrollDiff = 0;
} else if (dy < 0 && fab.getVisibility() != View.VISIBLE) {
if (list.getChildAt(0).getTop() == 0 || scrollDiff > 400) {
showFab();
if (scrollDiff > 800) {
fab.setVisibility(View.VISIBLE);
TranslateAnimation animate = new TranslateAnimation(
0,
0,
fab.getHeight() * 2,
0);
animate.setDuration(300);
animate.setFillAfter(true);
fab.startAnimation(animate);
scrollDiff = 0;
} else {
scrollDiff += Math.abs(dy);
@@ -336,20 +319,12 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
}
}
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
currentlyScrolling = newState != RecyclerView.SCROLL_STATE_IDLE;
}
});
list.addItemDecoration(new StatusListItemDecoration());
((UsableRecyclerView)list).setSelectorBoundsProvider(new UsableRecyclerView.SelectorBoundsProvider(){
private Rect tmpRect=new Rect();
@Override
public void getSelectorBounds(View view, Rect outRect){
boolean hasDescendant = false, hasAncestor = false, isWarning = false;
int lastIndex = -1, firstIndex = -1;
list.getDecoratedBoundsWithMargins(view, outRect);
RecyclerView.ViewHolder holder=list.getChildViewHolder(view);
if(holder instanceof StatusDisplayItem.Holder){
@@ -361,55 +336,48 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
for(int i=0;i<list.getChildCount();i++){
View child=list.getChildAt(i);
holder=list.getChildViewHolder(child);
if(holder instanceof StatusDisplayItem.Holder<?> h){
if(holder instanceof StatusDisplayItem.Holder){
String otherID=((StatusDisplayItem.Holder<?>) holder).getItemID();
if(otherID.equals(id)){
if (firstIndex < 0) firstIndex = i;
lastIndex = i;
StatusDisplayItem item = h.getItem();
hasDescendant = item.hasDescendantNeighbor;
// no for direct descendants because main status (right above) is
// being displayed with an extended footer - no connected layout
hasAncestor = item.hasAncestoringNeighbor && !item.isDirectDescendant;
list.getDecoratedBoundsWithMargins(child, tmpRect);
outRect.left=Math.min(outRect.left, tmpRect.left);
outRect.top=Math.min(outRect.top, tmpRect.top);
outRect.right=Math.max(outRect.right, tmpRect.right);
outRect.bottom=Math.max(outRect.bottom, tmpRect.bottom);
if (holder instanceof WarningFilteredStatusDisplayItem.Holder) {
isWarning = true;
}
}
}
}
}
// shifting the selection box down
// see also: FooterStatusDisplayItem#onBind (setMargins)
if (isWarning || firstIndex < 0 || lastIndex < 0 ||
!(list.getChildViewHolder(list.getChildAt(lastIndex))
instanceof FooterStatusDisplayItem.Holder)) return;
int prevIndex = firstIndex - 1, nextIndex = lastIndex + 1;
boolean prevIsWarning = prevIndex > 0 && prevIndex < list.getChildCount() &&
list.getChildViewHolder(list.getChildAt(prevIndex))
instanceof WarningFilteredStatusDisplayItem.Holder;
boolean nextIsWarning = nextIndex > 0 && nextIndex < list.getChildCount() &&
list.getChildViewHolder(list.getChildAt(nextIndex))
instanceof WarningFilteredStatusDisplayItem.Holder;
if (!prevIsWarning && hasAncestor) outRect.top += V.dp(4);
if (!nextIsWarning && hasDescendant) outRect.bottom += V.dp(4);
}
});
list.setItemAnimator(new BetterItemAnimator());
((UsableRecyclerView) list).setIncludeMarginsInItemHitbox(true);
updateToolbar();
}
if (wantsComposeButton() && !getArguments().getBoolean("__disable_fab", false)) {
fab.setVisibility(View.VISIBLE);
fab.setOnClickListener(this::onFabClick);
fab.setOnLongClickListener(this::onFabLongClick);
} else if (fab != null) {
fab.setVisibility(View.GONE);
}
@Override
protected RecyclerView.LayoutManager onCreateLayoutManager(){
GridLayoutManager lm=new TileGridLayoutManager(getActivity(), 1000);
lm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup(){
@Override
public int getSpanSize(int position){
position-=getMainAdapterOffset();
if(position>=0 && position<displayItems.size()){
StatusDisplayItem item=displayItems.get(position);
if(item instanceof ImageStatusDisplayItem imgItem){
PhotoLayoutHelper.TiledLayoutResult layout=imgItem.tiledLayout;
PhotoLayoutHelper.TiledLayoutResult.Tile tile=imgItem.thisTile;
int spans=0;
for(int i=0;i<tile.colSpan;i++){
spans+=layout.columnSizes[tile.startCol+i];
}
return spans;
}
}
return 1000;
}
});
return lm;
}
@Override
@@ -530,7 +498,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
revealSpoiler(status, holder.getItemID());
}
public void onRevealSpoilerClick(MediaGridStatusDisplayItem.Holder holder){
public void onRevealSpoilerClick(ImageStatusDisplayItem.Holder<?> holder){
Status status=holder.getItem().status;
revealSpoiler(status, holder.getItemID());
}
@@ -546,11 +514,31 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
updateImagesSpoilerState(status, itemID);
}
// public void onRevealFilteredClick(TextStatusDisplayItem.Holder holder){
// Status status=holder.getItem().status;
// revealFiltered(status, holder.getItemID());
// }
public void onRevealFilteredClick(WarningFilteredStatusDisplayItem.Holder holder){
Status status=holder.getItem().status;
// revealFiltered(status, holder.getItemID());
}
protected void revealFiltered(Status status, ArrayList<StatusDisplayItem> showedItems){
status.filterRevealed=true;
}
// public void notifyItemsChanged(int adapterPosition){
// adapter.notifyItemChanged(adapterPosition);
// }
public void onVisibilityIconClick(HeaderStatusDisplayItem.Holder holder){
Status status=holder.getItem().status;
status.spoilerRevealed=!status.spoilerRevealed;
if(!TextUtils.isEmpty(status.spoilerText)){
TextStatusDisplayItem.Holder text = findHolderOfType(holder.getItemID(), TextStatusDisplayItem.Holder.class);
TextStatusDisplayItem.Holder text=findHolderOfType(holder.getItemID(), TextStatusDisplayItem.Holder.class);
if(text!=null){
adapter.notifyItemChanged(text.getAbsoluteAdapterPosition());
}
@@ -559,58 +547,33 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
updateImagesSpoilerState(status, holder.getItemID());
}
public void onEnableExpandable(TextStatusDisplayItem.Holder holder, boolean expandable) {
if (holder.getItem().status.textExpandable != expandable && list != null) {
holder.getItem().status.textExpandable = expandable;
HeaderStatusDisplayItem.Holder header = findHolderOfType(holder.getItemID(), HeaderStatusDisplayItem.Holder.class);
if (header != null) header.rebind();
}
}
public void onToggleExpanded(Status status, String itemID) {
status.textExpanded = !status.textExpanded;
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class);
if (text != null) text.rebind();
if (header != null) header.rebind();
}
protected void updateImagesSpoilerState(Status status, String itemID){
ArrayList<Integer> updatedPositions=new ArrayList<>();
MediaGridStatusDisplayItem.Holder mediaGrid=findHolderOfType(itemID, MediaGridStatusDisplayItem.Holder.class);
if(mediaGrid!=null){
mediaGrid.setRevealed(status.spoilerRevealed);
updatedPositions.add(mediaGrid.getAbsoluteAdapterPosition()-getMainAdapterOffset());
for(ImageStatusDisplayItem.Holder photo:(List<ImageStatusDisplayItem.Holder>)findAllHoldersOfType(itemID, ImageStatusDisplayItem.Holder.class)){
photo.setRevealed(status.spoilerRevealed);
updatedPositions.add(photo.getAbsoluteAdapterPosition()-getMainAdapterOffset());
}
int i=0;
for(StatusDisplayItem item:displayItems){
if(itemID.equals(item.parentID) && item instanceof MediaGridStatusDisplayItem && !updatedPositions.contains(i)){
if(itemID.equals(item.parentID) && item instanceof ImageStatusDisplayItem && !updatedPositions.contains(i)){
adapter.notifyItemChanged(i);
}
i++;
}
}
public void onImageUpdated(MediaGridStatusDisplayItem.Holder holder, int index) {
holder.rebind();
MediaGridStatusDisplayItem.Holder mediaGrid = findHolderOfType(holder.getItemID(), MediaGridStatusDisplayItem.Holder.class);
if(mediaGrid!=null){
adapter.notifyItemChanged(mediaGrid.getAbsoluteAdapterPosition());
}
}
public void onGapClick(GapStatusDisplayItem.Holder item){}
public void onWarningClick(WarningFilteredStatusDisplayItem.Holder warning){
int startPos = warning.getAbsoluteAdapterPosition();
displayItems.remove(startPos);
displayItems.addAll(startPos, warning.filteredItems);
adapter.notifyItemRangeInserted(startPos, warning.filteredItems.size() - 1);
if (startPos == 0) scrollToTop();
warning.getItem().status.filterRevealed = true;
public void onWarningClick(WarningFilteredStatusDisplayItem.Holder warningItem){
int i = warningItem.getAbsoluteAdapterPosition();
displayItems.remove(warningItem.getAbsoluteAdapterPosition());
for(StatusDisplayItem item:warningItem.filteredItems){
displayItems.add(i, item);
i++;
}
adapter.notifyItemChanged(warningItem.getAbsoluteAdapterPosition());
}
@Override
public String getAccountID(){
return accountID;
}
@@ -680,11 +643,6 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
smoothScrollRecyclerViewToTop(list);
}
@Override
public boolean isOnTop() {
return isRecyclerViewOnTop(list);
}
protected int getListWidthForMediaLayout(){
return list.getWidth();
}
@@ -731,36 +689,6 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
currentPhotoViewer.onPause();
}
public void onFabClick(View v){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), ComposeFragment.class, args);
}
public boolean onFabLongClick(View v) {
return UiUtils.pickAccountForCompose(getActivity(), accountID);
}
private MediaAttachmentViewController makeNewMediaAttachmentView(MediaGridStatusDisplayItem.GridItemType type){
return new MediaAttachmentViewController(getActivity(), type);
}
public TypedObjectPool<MediaGridStatusDisplayItem.GridItemType, MediaAttachmentViewController> getAttachmentViewsPool(){
return attachmentViewsPool;
}
@Override
public void onProvideAssistContent(AssistContent assistContent) {
assistContent.setWebUri(getWebUri(getSession().getInstanceUri().buildUpon()));
}
@Override
protected void onDataLoaded(List<T> d, boolean more) {
super.onDataLoaded(d, more);
// more available, but the page isn't even full yet? seems wrong, let's load some more
if (more && d.size() < itemsPerPage) preloader.onScrolledToLastItem();
}
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
public DisplayItemsAdapter(){
@@ -798,6 +726,16 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
public ImageLoaderRequest getImageRequest(int position, int image){
return displayItems.get(position).getImageRequest(image);
}
// @Override
// public void onViewDetachedFromWindow(@NonNull BindableViewHolder<StatusDisplayItem> holder){
// if(holder instanceof ImageLoaderViewHolder){
// int count=holder.getItem().getImageCount();
// for(int i=0;i<count;i++){
// ((ImageLoaderViewHolder) holder).clearImage(i);
// }
// }
// }
}
private class StatusListItemDecoration extends RecyclerView.ItemDecoration{
@@ -807,7 +745,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
private int currentMediaHiddenLayoutsWidth=0;
{
dividerPaint.setColor(UiUtils.getThemeColor(getActivity(), R.attr.colorPollVoted));
dividerPaint.setColor(UiUtils.getThemeColor(getActivity(), GlobalUserPreferences.disableDividers ? R.attr.colorWindowBackground : R.attr.colorPollVoted));
dividerPaint.setStyle(Paint.Style.STROKE);
dividerPaint.setStrokeWidth(V.dp(1));
}
@@ -821,7 +759,6 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
RecyclerView.ViewHolder siblingHolder=parent.getChildViewHolder(bottomSibling);
if(holder instanceof StatusDisplayItem.Holder<?> ih && siblingHolder instanceof StatusDisplayItem.Holder<?> sh
&& (!ih.getItemID().equals(sh.getItemID()) || sh instanceof ExtendedFooterStatusDisplayItem.Holder) && ih.getItem().getType()!=StatusDisplayItem.Type.GAP){
if (!ih.getItem().isMainStatus && ih.getItem().hasDescendantNeighbor) continue;
drawDivider(child, bottomSibling, holder, siblingHolder, parent, c, dividerPaint);
}
}
@@ -832,21 +769,25 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
for(int i=0;i<parent.getChildCount();i++){
View child=parent.getChildAt(i);
RecyclerView.ViewHolder holder=parent.getChildViewHolder(child);
if(holder instanceof MediaGridStatusDisplayItem.Holder imgHolder){
if(holder instanceof ImageStatusDisplayItem.Holder<?> imgHolder){
if(!imgHolder.getItem().status.spoilerRevealed && TextUtils.isEmpty(imgHolder.getItem().status.spoilerText)){
hiddenMediaPaint.setColor(0x80000000);
c.drawRect(child.getX(), child.getY(), child.getX()+child.getWidth(), child.getY()+child.getHeight(), hiddenMediaPaint);
PhotoLayoutHelper.TiledLayoutResult.Tile tile=imgHolder.getItem().thisTile;
float hGap=tile.startCol>0 ? V.dp(1) : 0;
float vGap=tile.startRow>0 ? V.dp(1) : 0;
c.drawRect(child.getX()-hGap, child.getY()-vGap, child.getX()+child.getWidth(), child.getY()+child.getHeight(), hiddenMediaPaint);
}
}
}
for(int i=0;i<parent.getChildCount();i++){
View child=parent.getChildAt(i);
RecyclerView.ViewHolder holder=parent.getChildViewHolder(child);
if(holder instanceof MediaGridStatusDisplayItem.Holder imgHolder){
if(holder instanceof ImageStatusDisplayItem.Holder<?> imgHolder){
if(!imgHolder.getItem().status.spoilerRevealed){
if(TextUtils.isEmpty(imgHolder.getItem().status.spoilerText)){
PhotoLayoutHelper.TiledLayoutResult.Tile tile=imgHolder.getItem().thisTile;
if(tile.startCol==0 && tile.startRow==0 && TextUtils.isEmpty(imgHolder.getItem().status.spoilerText)){
int listWidth=getListWidthForMediaLayout();
int width=Math.min(listWidth, UiUtils.MAX_WIDTH);
int width=Math.min(listWidth, V.dp(ImageAttachmentFrameLayout.MAX_WIDTH));
if(currentMediaHiddenLayoutsWidth!=width)
rebuildMediaHiddenLayouts(width-V.dp(32));
c.save();
@@ -871,6 +812,47 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state){
RecyclerView.ViewHolder holder=parent.getChildViewHolder(view);
if(holder instanceof ImageStatusDisplayItem.Holder){
int listWidth=getListWidthForMediaLayout();
int width=Math.min(listWidth, V.dp(ImageAttachmentFrameLayout.MAX_WIDTH));
PhotoLayoutHelper.TiledLayoutResult layout=((ImageStatusDisplayItem.Holder<?>) holder).getItem().tiledLayout;
PhotoLayoutHelper.TiledLayoutResult.Tile tile=((ImageStatusDisplayItem.Holder<?>) holder).getItem().thisTile;
if(tile.startCol+tile.colSpan<layout.columnSizes.length){
outRect.right=V.dp(1);
}
if(tile.startRow+tile.rowSpan<layout.rowSizes.length){
outRect.bottom=V.dp(1);
}
// For a view that spans rows, compensate its additional height so the row it's in stays the right height
if(tile.rowSpan>1){
outRect.bottom=-(Math.round(tile.height/1000f*width)-Math.round(layout.rowSizes[tile.startRow]/1000f*width));
}
// ...and for its siblings, offset those on rows below first to the right where they belong
if(tile.startCol>0 && layout.tiles[0].rowSpan>1 && tile.startRow>layout.tiles[0].startRow){
int xOffset=Math.round(layout.tiles[0].width/1000f*listWidth);
outRect.left=xOffset;
outRect.right=-xOffset;
}
// If the width of the media block is smaller than that of the RecyclerView, offset the views horizontally to center them
if(listWidth>width){
outRect.left+=(listWidth-V.dp(ImageAttachmentFrameLayout.MAX_WIDTH))/2;
if(tile.startCol>0){
int spanOffset=0;
for(int i=0;i<tile.startCol;i++){
spanOffset+=layout.columnSizes[i];
}
outRect.left-=Math.round(spanOffset/1000f*listWidth);
outRect.left+=Math.round(spanOffset/1000f*width);
}
}
}
}
private void rebuildMediaHiddenLayouts(int width){
currentMediaHiddenLayoutsWidth=width;
String title=getString(R.string.sensitive_content);

View File

@@ -1,11 +1,9 @@
package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.net.Uri;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.statuses.GetBookmarkedStatuses;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.HeaderPaginationList;
import org.joinmastodon.android.model.Status;
@@ -37,14 +35,4 @@ public class BookmarkedStatusListFragment extends StatusListFragment{
})
.exec(accountID);
}
@Override
protected Filter.FilterContext getFilterContext() {
return Filter.FilterContext.ACCOUNT;
}
@Override
public Uri getWebUri(Uri.Builder base) {
return base.path("/bookmarks").build();
}
}

View File

@@ -1,10 +1,10 @@
package org.joinmastodon.android.fragments;
import static org.joinmastodon.android.GlobalUserPreferences.PrefixRepliesMode.*;
import static android.os.ext.SdkExtensions.getExtensionVersion;
import static org.joinmastodon.android.GlobalUserPreferences.recentLanguages;
import static org.joinmastodon.android.api.requests.statuses.CreateStatus.DRAFTS_AFTER_INSTANT;
import static org.joinmastodon.android.api.requests.statuses.CreateStatus.getDraftInstant;
import static org.joinmastodon.android.ui.utils.UiUtils.isPhotoPickerAvailable;
import static org.joinmastodon.android.utils.MastodonLanguage.allLanguages;
import static org.joinmastodon.android.utils.MastodonLanguage.defaultRecentLanguages;
@@ -43,7 +43,6 @@ import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -68,7 +67,6 @@ import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.github.bottomSoftwareFoundation.bottom.Bottom;
import com.twitter.twittertext.TwitterTextEmojiRegex;
import org.joinmastodon.android.E;
@@ -92,7 +90,6 @@ import org.joinmastodon.android.events.StatusCreatedEvent;
import org.joinmastodon.android.events.StatusUpdatedEvent;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.ContentType;
import org.joinmastodon.android.model.Emoji;
import org.joinmastodon.android.model.EmojiCategory;
import org.joinmastodon.android.model.Instance;
@@ -111,7 +108,7 @@ import org.joinmastodon.android.ui.text.ComposeAutocompleteSpan;
import org.joinmastodon.android.ui.text.ComposeHashtagOrMentionSpan;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
import org.joinmastodon.android.utils.TransferSpeedTracker;
import org.joinmastodon.android.ui.utils.TransferSpeedTracker;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ComposeEditText;
import org.joinmastodon.android.ui.views.ComposeMediaLayout;
@@ -119,7 +116,6 @@ import org.joinmastodon.android.ui.views.LinkedTextView;
import org.joinmastodon.android.ui.views.ReorderableLinearLayout;
import org.joinmastodon.android.ui.views.SizeListenerLinearLayout;
import org.joinmastodon.android.utils.MastodonLanguage;
import org.joinmastodon.android.utils.StatusTextEncoder;
import org.parceler.Parcel;
import org.parceler.Parcels;
@@ -150,7 +146,7 @@ import me.grishka.appkit.imageloader.ViewImageLoader;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.V;
public class ComposeFragment extends MastodonToolbarFragment implements OnBackPressedListener, ComposeEditText.SelectionListener, HasAccountID {
public class ComposeFragment extends MastodonToolbarFragment implements OnBackPressedListener, ComposeEditText.SelectionListener{
private static final int MEDIA_RESULT=717;
private static final int IMAGE_DESCRIPTION_RESULT=363;
@@ -160,11 +156,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private static final Pattern GLITCH_LOCAL_ONLY_PATTERN = Pattern.compile("[\\s\\S]*" + GLITCH_LOCAL_ONLY_SUFFIX + "[\uFE00-\uFE0F]*");
private static final String TAG="ComposeFragment";
public static final Pattern MENTION_PATTERN=Pattern.compile("(^|[^\\/\\w])@(([a-z0-9_]+)@[a-z0-9\\.\\-]+[a-z0-9]+)", Pattern.CASE_INSENSITIVE);
private static final Pattern MENTION_PATTERN=Pattern.compile("(^|[^\\/\\w])@(([a-z0-9_]+)@[a-z0-9\\.\\-]+[a-z0-9]+)", Pattern.CASE_INSENSITIVE);
// from https://github.com/mastodon/mastodon-ios/blob/main/Mastodon/Helper/MastodonRegex.swift
public static final Pattern AUTO_COMPLETE_PATTERN=Pattern.compile("(?<!\\w)(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+)|:([a-zA-Z0-9_]+))");
public static final Pattern HIGHLIGHT_PATTERN=Pattern.compile("(?<!\\w)(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+))");
private static final Pattern AUTO_COMPLETE_PATTERN=Pattern.compile("(?<!\\w)(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+)|:([a-zA-Z0-9_]+))");
private static final Pattern HIGHLIGHT_PATTERN=Pattern.compile("(?<!\\w)(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+))");
@SuppressLint("NewApi") // this class actually exists on 6.0
private final BreakIterator breakIterator=BreakIterator.getCharacterInstance();
@@ -181,8 +177,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private int charCount, charLimit, trimmedCharCount;
private Button publishButton, languageButton, scheduleTimeBtn, draftsBtn;
private PopupMenu languagePopup, contentTypePopup, visibilityPopup, draftOptionsPopup;
private ImageButton mediaBtn, pollBtn, emojiBtn, spoilerBtn, visibilityBtn, scheduleDraftDismiss, contentTypeBtn;
private PopupMenu languagePopup, visibilityPopup, draftOptionsPopup;
private ImageButton mediaBtn, pollBtn, emojiBtn, spoilerBtn, visibilityBtn, scheduleDraftDismiss;
private ImageView sensitiveIcon;
private ComposeMediaLayout attachmentsView;
private TextView replyText;
@@ -206,7 +202,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private List<EmojiCategory> customEmojis;
private CustomEmojiPopupKeyboard emojiKeyboard;
private Status replyTo;
private Status quote;
private String initialText;
private String uuid;
private int pollDuration=24*3600;
@@ -235,18 +230,19 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private boolean ignoreSelectionChanges=false;
private Runnable updateUploadEtaRunnable;
private String language, encoding;
private ContentType contentType;
private String language;
private MastodonLanguage.LanguageResolver languageResolver;
private int navigationBarColorBefore;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setRetainInstance(true);
navigationBarColorBefore = getActivity().getWindow().getNavigationBarColor();
getActivity().getWindow().setNavigationBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorBackgroundLightest));
accountID=getArguments().getString("account");
contentType = GlobalUserPreferences.accountsDefaultContentTypes.get(accountID);
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
self=session.self;
instanceDomain=session.domain;
@@ -258,12 +254,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
editingStatus=Parcels.unwrap(getArguments().getParcelable("editStatus"));
if(getArguments().containsKey("replyTo"))
replyTo=Parcels.unwrap(getArguments().getParcelable("replyTo"));
if(getArguments().containsKey("quote"))
quote=Parcels.unwrap(getArguments().getParcelable("quote"));
if(instance==null){
Nav.finish(this);
return;
}
if(customEmojis.isEmpty()){
AccountSessionManager.getInstance().updateInstanceInfo(instanceDomain);
}
Bundle bundle = savedInstanceState != null ? savedInstanceState : getArguments();
if (bundle.containsKey("scheduledStatus")) scheduledStatus=Parcels.unwrap(bundle.getParcelable("scheduledStatus"));
@@ -288,6 +285,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
UiUtils.removeCallbacks(updateUploadEtaRunnable);
updateUploadEtaRunnable=null;
}
getActivity().getWindow().setNavigationBarColor(navigationBarColorBefore);
}
@Override
@@ -305,10 +303,25 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
emojiKeyboard.setListener(this::onCustomEmojiClick);
View view=inflater.inflate(R.layout.fragment_compose, container, false);
if(GlobalUserPreferences.relocatePublishButton){
publishButton=view.findViewById(R.id.publish);
// publishButton.setText(editingStatus==null || redraftStatus ? R.string.publish : R.string.save);
publishButton.setEllipsize(TextUtils.TruncateAt.END);
publishButton.setOnClickListener(this::onPublishClick);
publishButton.setSingleLine(true);
publishButton.setVisibility(View.VISIBLE);
draftsBtn=view.findViewById(R.id.drafts_btn);
draftsBtn.setVisibility(View.VISIBLE);
} else {
charCounter=view.findViewById(R.id.char_counter);
charCounter.setVisibility(View.VISIBLE);
charCounter.setText(String.valueOf(charLimit));
}
mainEditText=view.findViewById(R.id.toot_text);
mainEditTextWrap=view.findViewById(R.id.toot_text_wrap);
charCounter=view.findViewById(R.id.char_counter);
charCounter.setText(String.valueOf(charLimit));
scrollView=view.findViewById(R.id.scroll_view);
selfName=view.findViewById(R.id.self_name);
@@ -332,16 +345,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
emojiBtn=view.findViewById(R.id.btn_emoji);
spoilerBtn=view.findViewById(R.id.btn_spoiler);
visibilityBtn=view.findViewById(R.id.btn_visibility);
contentTypeBtn=view.findViewById(R.id.btn_content_type);
scheduleDraftView=view.findViewById(R.id.schedule_draft_view);
scheduleDraftText=view.findViewById(R.id.schedule_draft_text);
scheduleDraftDismiss=view.findViewById(R.id.schedule_draft_dismiss);
scheduleTimeBtn=view.findViewById(R.id.scheduled_time_btn);
sensitiveIcon=view.findViewById(R.id.sensitive_icon);
sensitiveItem=view.findViewById(R.id.sensitive_item);
replyText=view.findViewById(GlobalUserPreferences.replyLineAboveHeader ? R.id.reply_text : R.id.reply_text_below);
view.findViewById(GlobalUserPreferences.replyLineAboveHeader ? R.id.reply_text_below : R.id.reply_text)
.setVisibility(View.GONE);
replyText=view.findViewById(R.id.reply_text);
if (isPhotoPickerAvailable()) {
PopupMenu attachPopup = new PopupMenu(getContext(), mediaBtn);
@@ -356,7 +366,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
} else {
mediaBtn.setOnClickListener(v -> openFilePicker(false));
}
if (isInstancePixelfed()) pollBtn.setVisibility(View.GONE);
pollBtn.setOnClickListener(v->togglePoll());
emojiBtn.setOnClickListener(v->emojiKeyboard.toggleKeyboardPopup(mainEditText));
spoilerBtn.setOnClickListener(v->toggleSpoiler());
@@ -368,10 +377,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
visibilityBtn.setOnClickListener(v->visibilityPopup.show());
visibilityBtn.setOnTouchListener(visibilityPopup.getDragToOpenListener());
buildContentTypePopup(contentTypeBtn);
contentTypeBtn.setOnClickListener(v->contentTypePopup.show());
contentTypeBtn.setOnTouchListener(contentTypePopup.getDragToOpenListener());
scheduleDraftDismiss.setOnClickListener(v->updateScheduledAt(null));
scheduleTimeBtn.setOnClickListener(v->pickScheduledDateTime());
@@ -474,10 +479,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
}
if (savedInstanceState != null) {
statusVisibility = (StatusPrivacy) savedInstanceState.getSerializable("visibility");
} else if (editingStatus != null && editingStatus.visibility != null) {
statusVisibility = editingStatus.visibility;
if(editingStatus!=null && editingStatus.visibility!=null) {
statusVisibility=editingStatus.visibility;
} else {
loadDefaultStatusVisibility(savedInstanceState);
}
@@ -492,20 +495,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}).setChecked(true);
visibilityPopup.getMenu().findItem(R.id.local_only).setChecked(localOnly);
if (savedInstanceState != null && savedInstanceState.containsKey("contentType")) {
contentType = (ContentType) savedInstanceState.getSerializable("contentType");
} else if (getArguments().containsKey("sourceContentType")) {
try {
String val = getArguments().getString("sourceContentType");
contentType = val == null ? null : ContentType.valueOf(val);
} catch (IllegalArgumentException ignored) {}
}
int contentTypeId = ContentType.getContentTypeRes(contentType);
contentTypePopup.getMenu().findItem(contentTypeId).setChecked(true);
contentTypeBtn.setSelected(contentTypeId != R.id.content_type_null && contentTypeId != R.id.content_type_plain);
autocompleteViewController=new ComposeAutocompleteViewController(getActivity(), accountID);
autocompleteViewController.setCompletionSelectedListener(this::onAutocompleteOptionSelected);
View autocompleteView=autocompleteViewController.getView();
@@ -542,7 +531,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
outState.putParcelableArrayList("attachments", serializedAttachments);
}
outState.putSerializable("visibility", statusVisibility);
outState.putSerializable("contentType", contentType);
if (scheduledAt != null) outState.putSerializable("scheduledAt", scheduledAt);
if (scheduledStatus != null) outState.putParcelable("scheduledStatus", Parcels.wrap(scheduledStatus));
}
@@ -581,10 +569,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
@Override
public void afterTextChanged(Editable s){
if(s.length()==0){
updateCharCounter();
if(s.length()==0)
return;
}
int start=lastChangeStart;
int count=lastChangeCount;
// offset one char back to catch an already typed '@' or '#' or ':'
@@ -637,8 +623,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
});
spoilerEdit.addTextChangedListener(new SimpleTextWatcher(e->updateCharCounter()));
if(replyTo!=null || quote!=null){
Status status = quote!=null ? quote : replyTo;
if(replyTo!=null){
View replyWrap = view.findViewById(R.id.reply_wrap);
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
int scrollHeight = scrollView.getHeight();
@@ -664,13 +649,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
originalPost.setOnClickListener(v->{
Bundle args=new Bundle();
args.putString("account", accountID);
args.putParcelable("status", Parcels.wrap(status));
args.putParcelable("status", Parcels.wrap(replyTo));
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
Nav.go(getActivity(), ThreadFragment.class, args);
});
ImageView avatar = view.findViewById(R.id.avatar);
ViewImageLoader.load(avatar, null, new UrlImageLoaderRequest(status.account.avatar));
ViewImageLoader.load(avatar, null, new UrlImageLoaderRequest(replyTo.account.avatar));
ViewOutlineProvider roundCornersOutline=new ViewOutlineProvider(){
@Override
public void getOutline(View view, Outline outline){
@@ -682,15 +667,15 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
avatar.setOnClickListener(v->{
Bundle args=new Bundle();
args.putString("account", accountID);
args.putParcelable("profileAccount", Parcels.wrap(status.account));
args.putParcelable("profileAccount", Parcels.wrap(replyTo.account));
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
Nav.go(getActivity(), ProfileFragment.class, args);
});
((TextView) view.findViewById(R.id.name)).setText(status.account.displayName);
((TextView) view.findViewById(R.id.username)).setText(status.account.getDisplayUsername());
((TextView) view.findViewById(R.id.name)).setText(replyTo.account.displayName);
((TextView) view.findViewById(R.id.username)).setText(replyTo.account.getDisplayUsername());
view.findViewById(R.id.visibility).setVisibility(View.GONE);
Drawable visibilityIcon = getActivity().getDrawable(switch(status.visibility){
Drawable visibilityIcon = getActivity().getDrawable(switch(replyTo.visibility){
case PUBLIC -> R.drawable.ic_fluent_earth_20_regular;
case UNLISTED -> R.drawable.ic_fluent_lock_open_20_regular;
case PRIVATE -> R.drawable.ic_fluent_lock_closed_20_filled;
@@ -701,37 +686,40 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
moreBtn.setImageDrawable(visibilityIcon);
moreBtn.setBackground(null);
TextView timestamp = view.findViewById(R.id.timestamp);
if (status.editedAt!=null) timestamp.setText(getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(getContext(), status.editedAt)));
else if (status.createdAt!=null) timestamp.setText(UiUtils.formatRelativeTimestamp(getContext(), status.createdAt));
else timestamp.setText("");
if (status.spoilerText != null && !status.spoilerText.isBlank()) {
if (replyTo.editedAt==null) timestamp.setText(UiUtils.formatRelativeTimestamp(getContext(), replyTo.createdAt));
else timestamp.setText(getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(getContext(), replyTo.editedAt)));
if (replyTo.spoilerText != null && !replyTo.spoilerText.isBlank()) {
view.findViewById(R.id.spoiler_header).setVisibility(View.VISIBLE);
((TextView) view.findViewById(R.id.spoiler_title_inline)).setText(status.spoilerText);
((TextView) view.findViewById(R.id.spoiler_title_inline)).setText(replyTo.spoilerText);
}
SpannableStringBuilder content = HtmlParser.parse(status.content, status.emojis, status.mentions, status.tags, accountID);
SpannableStringBuilder content = HtmlParser.parse(replyTo.content, replyTo.emojis, replyTo.mentions, replyTo.tags, accountID);
LinkedTextView text = view.findViewById(R.id.text);
if (content.length() > 0) text.setText(content);
else view.findViewById(R.id.display_item_text).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));
int visibilityNameRes = switch (status.visibility) {
replyText.setText(getString(R.string.in_reply_to, replyTo.account.displayName));
int visibilityNameRes = switch (replyTo.visibility) {
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;
};
replyText.setContentDescription(getString(R.string.in_reply_to, status.account.displayName) + ". " + getString(R.string.post_visibility) + ": " + getString(visibilityNameRes));
replyText.setContentDescription(getString(R.string.in_reply_to, replyTo.account.displayName) + ". " + getString(R.string.post_visibility) + ": " + getString(visibilityNameRes));
replyText.setOnClickListener(v->{
scrollView.smoothScrollTo(0, 0);
});
replyText.setOnClickListener(v->{
scrollView.smoothScrollTo(0, 0);
});
ArrayList<String> mentions=new ArrayList<>();
String ownID=AccountSessionManager.getInstance().getAccount(accountID).self.id;
if(!status.account.id.equals(ownID))
mentions.add('@'+status.account.acct);
for(Mention mention:status.mentions){
if(!replyTo.account.id.equals(ownID))
mentions.add('@'+replyTo.account.acct);
for(Mention mention:replyTo.mentions){
if(mention.id.equals(ownID))
continue;
String m='@'+mention.acct;
@@ -744,19 +732,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
ignoreSelectionChanges=true;
mainEditText.setSelection(mainEditText.length());
ignoreSelectionChanges=false;
if(!TextUtils.isEmpty(status.spoilerText)){
if(!TextUtils.isEmpty(replyTo.spoilerText)){
hasSpoiler=true;
spoilerEdit.setVisibility(View.VISIBLE);
if ((GlobalUserPreferences.prefixReplies == ALWAYS
|| (GlobalUserPreferences.prefixReplies == TO_OTHERS && !ownID.equals(status.account.id)))
&& !status.spoilerText.startsWith("re: ")) {
spoilerEdit.setText("re: " + status.spoilerText);
} else {
spoilerEdit.setText(status.spoilerText);
}
spoilerEdit.setText(replyTo.spoilerText);
spoilerBtn.setSelected(true);
}
if (status.language != null && !status.language.isEmpty()) updateLanguage(status.language);
if (replyTo.language != null && !replyTo.language.isEmpty()) updateLanguage(replyTo.language);
}
}else if (editingStatus==null || editingStatus.inReplyToId==null){
// TODO: remove workaround after https://github.com/mastodon/mastodon-android/issues/341 gets fixed
@@ -823,7 +805,20 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
item.setActionView(wrap);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
draftsBtn = wrap.findViewById(R.id.drafts_btn);
if(!GlobalUserPreferences.relocatePublishButton){
publishButton = wrap.findViewById(R.id.publish_btn);
publishButton.setOnClickListener(this::onPublishClick);
publishButton.setVisibility(View.VISIBLE);
draftsBtn = wrap.findViewById(R.id.drafts_btn);
draftsBtn.setVisibility(View.VISIBLE);
}else{
charCounter = wrap.findViewById(R.id.char_counter);
charCounter.setVisibility(View.VISIBLE);
charCounter.setText(String.valueOf(charLimit));
}
// draftsBtn = wrap.findViewById(R.id.drafts_btn);
draftOptionsPopup = new PopupMenu(getContext(), draftsBtn);
draftOptionsPopup.inflate(R.menu.compose_more);
draftMenuItem = draftOptionsPopup.getMenu().findItem(R.id.draft);
@@ -840,29 +835,22 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
});
UiUtils.enablePopupMenuIcons(getContext(), draftOptionsPopup);
publishButton = wrap.findViewById(R.id.publish_btn);
languageButton = wrap.findViewById(R.id.language_btn);
sendProgress = wrap.findViewById(R.id.send_progress);
sendError = wrap.findViewById(R.id.send_error);
publishButton.setOnClickListener(this::onPublishClick);
draftsBtn.setOnClickListener(v-> draftOptionsPopup.show());
draftsBtn.setOnTouchListener(draftOptionsPopup.getDragToOpenListener());
updateScheduledAt(scheduledAt != null ? scheduledAt : scheduledStatus != null ? scheduledStatus.scheduledAt : null);
buildLanguageSelector(languageButton);
if (isInstancePixelfed()) spoilerBtn.setVisibility(View.GONE);
if (isInstancePixelfed() || (editingStatus != null && scheduledStatus == null)) {
if (editingStatus != null && scheduledStatus == null) {
// editing an already published post
draftsBtn.setVisibility(View.GONE);
}
}
@Override
public String getAccountID() {
return accountID;
}
private void navigateToUnsentPosts() {
Bundle args=new Bundle();
args.putString("account", accountID);
@@ -884,13 +872,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
private void updateLanguage(MastodonLanguage loc) {
updateLanguage(loc.getLanguage(), loc.getLanguageName(), loc.getDefaultName());
}
private void updateLanguage(String languageTag, String languageName, String defaultName) {
language = languageTag;
languageButton.setText(languageName);
languageButton.setContentDescription(getActivity().getString(R.string.sk_post_language, defaultName));
language = loc.getLanguage();
languageButton.setText(loc.getLanguageName());
languageButton.setContentDescription(getActivity().getString(R.string.sk_post_language, loc.getDefaultName()));
}
@SuppressLint("ClickableViewAccessibility")
@@ -907,12 +891,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
Menu languageMenu = languagePopup.getMenu();
for (String recentLanguage : Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages)) {
if (recentLanguage.equals("bottom")) {
addBottomLanguage(languageMenu);
} else {
MastodonLanguage l = languageResolver.from(recentLanguage);
languageMenu.add(0, allLanguages.indexOf(l), Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName()));
}
MastodonLanguage l = languageResolver.from(recentLanguage);
languageMenu.add(0, allLanguages.indexOf(l), Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName()));
}
SubMenu allLanguagesMenu = languageMenu.addSubMenu(R.string.sk_available_languages);
@@ -921,44 +901,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
allLanguagesMenu.add(0, i, Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName()));
}
if (GlobalUserPreferences.bottomEncoding) addBottomLanguage(allLanguagesMenu);
btn.setOnLongClickListener(v->{
btn.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
if (!GlobalUserPreferences.bottomEncoding) addBottomLanguage(allLanguagesMenu);
return false;
});
languagePopup.setOnMenuItemClickListener(i->{
if (i.hasSubMenu()) return false;
if (i.getItemId() == allLanguages.size()) {
updateLanguage(language, "\uD83E\uDD7A\uD83D\uDC49\uD83D\uDC48", "bottom");
encoding = "bottom";
} else {
updateLanguage(allLanguages.get(i.getItemId()));
encoding = null;
}
updateLanguage(allLanguages.get(i.getItemId()));
return true;
});
}
private int getContentTypeName(String id) {
return switch (id) {
case "text/plain" -> R.string.sk_content_type_plain;
case "text/html" -> R.string.sk_content_type_html;
case "text/markdown" -> R.string.sk_content_type_markdown;
case "text/bbcode" -> R.string.sk_content_type_bbcode;
case "text/x.misskeymarkdown" -> R.string.sk_content_type_mfm;
default -> throw new IllegalArgumentException("Invalid content type");
};
}
private void addBottomLanguage(Menu menu) {
if (menu.findItem(allLanguages.size()) == null) {
menu.add(0, allLanguages.size(), Menu.NONE, "bottom (\uD83E\uDD7A\uD83D\uDC49\uD83D\uDC48)");
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item){
return true;
@@ -998,6 +947,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private void resetPublishButtonText() {
int publishText = editingStatus==null || redraftStatus ? R.string.publish : R.string.save;
if(GlobalUserPreferences.relocatePublishButton){
return;
}
if (publishText == R.string.publish && !GlobalUserPreferences.publishButtonText.isEmpty()) {
publishButton.setText(GlobalUserPreferences.publishButtonText);
} else {
@@ -1019,16 +971,14 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
if(att.state!=AttachmentUploadState.DONE)
nonDoneAttachmentCount++;
}
publishButton.setEnabled((!isInstancePixelfed() || attachments.size() > 0) && (trimmedCharCount>0 || !attachments.isEmpty()) && charCount<=charLimit && nonDoneAttachmentCount==0 && (pollOptions.isEmpty() || nonEmptyPollOptionsCount>1));
sendError.setVisibility(View.GONE);
publishButton.setEnabled((trimmedCharCount>0 || !attachments.isEmpty()) && charCount<=charLimit && nonDoneAttachmentCount==0 && (pollOptions.isEmpty() || nonEmptyPollOptionsCount>1));
// sendError.setVisibility(View.GONE);
}
private void onCustomEmojiClick(Emoji emoji){
if(getActivity().getCurrentFocus() instanceof EditText edit){
int start=edit.getSelectionStart();
String prefix=start>0 && !Character.isWhitespace(edit.getText().charAt(start-1)) ? " :" : ":";
edit.getText().replace(start, edit.getSelectionEnd(), prefix+emoji.shortcode+':');
}
int start=mainEditText.getSelectionStart();
String prefix=start>0 && !Character.isWhitespace(mainEditText.getText().charAt(start-1)) ? " :" : ":";
mainEditText.getText().replace(start, mainEditText.getSelectionEnd(), prefix+emoji.shortcode+':');
}
@Override
@@ -1038,7 +988,18 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
private void onPublishClick(View v){
publish();
if (!attachments.isEmpty()
&& statusVisibility != StatusPrivacy.DIRECT
&& !attachments.stream().allMatch(attachment -> attachment.description != null && !attachment.description.isBlank())) {
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.mo_no_image_desc_title)
.setMessage(R.string.mo_no_image_desc)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.publish, (dialog, i)-> publish())
.show();
} else {
publish();
}
}
private void publishErrorCallback(ErrorResponse error) {
@@ -1085,10 +1046,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private void publish(boolean force){
String text=mainEditText.getText().toString();
CreateStatus.Request req=new CreateStatus.Request();
if ("bottom".equals(encoding)) {
text = new StatusTextEncoder(Bottom::encode).encode(text);
req.spoilerText = "bottom-encoded emoji spam";
}
if (localOnly &&
GlobalUserPreferences.accountsInGlitchMode.contains(accountID) &&
!GLITCH_LOCAL_ONLY_PATTERN.matcher(text).matches()) {
@@ -1096,10 +1053,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
req.status=text;
req.localOnly=localOnly;
req.visibility=localOnly && instance.isAkkoma() ? StatusPrivacy.LOCAL : statusVisibility;
req.visibility=localOnly && instance.pleroma != null ? StatusPrivacy.LOCAL : statusVisibility;
req.sensitive=sensitive;
req.language=language;
req.contentType=contentType;
req.scheduledAt = scheduledAt;
if(!attachments.isEmpty()){
req.mediaIds=attachments.stream().map(a->a.serverAttachment.id).collect(Collectors.toList());
@@ -1141,9 +1097,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
if(hasSpoiler && spoilerEdit.length()>0){
req.spoilerText=spoilerEdit.getText().toString();
}
if(quote != null){
req.quoteId=quote.id;
}
if(uuid==null)
uuid=UUID.randomUUID().toString();
@@ -1161,7 +1114,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
sendProgress.setVisibility(View.VISIBLE);
sendError.setVisibility(View.GONE);
Callback<Status> resCallback = new Callback<>(){
Callback<Status> resCallback=new Callback<>(){
@Override
public void onSuccess(Status result){
maybeDeleteScheduledPost(() -> {
@@ -1174,21 +1127,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
E.post(new StatusCountersUpdatedEvent(replyTo));
}
}else{
// pixelfed doesn't return the edited status :/
Status editedStatus = result == null ? editingStatus : result;
if (result == null) {
editedStatus.text = req.status;
editedStatus.spoilerText = req.spoilerText;
editedStatus.sensitive = req.sensitive;
editedStatus.language = req.language;
// user will have to reload to see html
editedStatus.content = req.status;
}
E.post(new StatusUpdatedEvent(editedStatus));
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || !isStateSaved()) {
Nav.finish(ComposeFragment.this);
E.post(new StatusUpdatedEvent(result));
}
Nav.finish(ComposeFragment.this);
if (getArguments().getBoolean("navigateToStatus", false)) {
Bundle args=new Bundle();
args.putString("account", accountID);
@@ -1205,6 +1146,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
};
if(editingStatus!=null && !redraftStatus){
new EditStatus(req, editingStatus.id)
.setCallback(resCallback)
@@ -1246,14 +1188,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
List<String> newRecentLanguages = new ArrayList<>(Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages));
newRecentLanguages.remove(language);
newRecentLanguages.add(0, language);
if (encoding != null) {
newRecentLanguages.remove(encoding);
newRecentLanguages.add(0, encoding);
}
if ("bottom".equals(encoding) && !GlobalUserPreferences.bottomEncoding) {
GlobalUserPreferences.bottomEncoding = true;
GlobalUserPreferences.save();
}
recentLanguages.put(accountID, newRecentLanguages.stream().limit(4).collect(Collectors.toList()));
GlobalUserPreferences.save();
}
@@ -1319,14 +1253,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
private void confirmDiscardDraftAndFinish(){
boolean attachmentsPending = attachments.stream().anyMatch(att -> att.state != AttachmentUploadState.DONE);
if (attachmentsPending) new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_unfinished_attachments)
.setMessage(R.string.sk_unfinished_attachments_message)
.setPositiveButton(R.string.edit, (d, w) -> {})
.setNegativeButton(R.string.discard, (d, w) -> Nav.finish(this))
.show();
else new M3AlertDialogBuilder(getActivity())
new M3AlertDialogBuilder(getActivity())
.setTitle(editingStatus != null ? R.string.sk_confirm_save_changes : R.string.sk_confirm_save_draft)
.setPositiveButton(R.string.save, (d, w) -> {
updateScheduledAt(scheduledAt == null ? getDraftInstant() : scheduledAt);
@@ -1336,6 +1263,18 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
.show();
}
/**
* Check to see if Android platform photopicker is available on the device\
* @return whether the device supports photopicker intents.
*/
private boolean isPhotoPickerAvailable() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
return true;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return getExtensionVersion(Build.VERSION_CODES.R) >= 2;
} else
return false;
}
/**
* Builds the correct intent for the device version to select media.
@@ -1347,24 +1286,24 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
*/
private void openFilePicker(boolean photoPicker){
Intent intent;
boolean usePhotoPicker=photoPicker && isPhotoPickerAvailable();
if(usePhotoPicker){
intent=new Intent(MediaStore.ACTION_PICK_IMAGES);
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MAX_ATTACHMENTS-getMediaAttachmentsCount());
}else{
intent=new Intent(Intent.ACTION_GET_CONTENT);
boolean usePhotoPicker = photoPicker && isPhotoPickerAvailable();
if (usePhotoPicker) {
intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
} else {
intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
}
if(!usePhotoPicker && instance.configuration!=null &&
instance.configuration.mediaAttachments!=null &&
instance.configuration.mediaAttachments.supportedMimeTypes!=null &&
!instance.configuration.mediaAttachments.supportedMimeTypes.isEmpty()){
if (!usePhotoPicker && instance.configuration != null &&
instance.configuration.mediaAttachments != null &&
instance.configuration.mediaAttachments.supportedMimeTypes != null &&
!instance.configuration.mediaAttachments.supportedMimeTypes.isEmpty()) {
intent.putExtra(Intent.EXTRA_MIME_TYPES,
instance.configuration.mediaAttachments.supportedMimeTypes.toArray(
new String[0]));
}else{
if(!usePhotoPicker){
} else {
if (!usePhotoPicker) {
// If photo picker is being used these are the default mimetypes.
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"image/*", "video/*"});
}
@@ -1511,7 +1450,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private void uploadMediaAttachment(DraftMediaAttachment attachment){
if(areThereAnyUploadingAttachments()){
throw new IllegalStateException("there is already an attachment being uploaded");
throw new IllegalStateException("there is already an attachment being uploaded");
}
attachment.state=AttachmentUploadState.UPLOADING;
attachment.progressBar.setVisibility(View.VISIBLE);
@@ -1604,8 +1543,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
if(att.isUploadingOrProcessing())
att.cancelUpload();
attachments.remove(att);
if(!areThereAnyUploadingAttachments())
uploadNextQueuedAttachment();
uploadNextQueuedAttachment();
attachmentsView.removeView(att.view);
if(getMediaAttachmentsCount()==0)
attachmentsView.setVisibility(View.GONE);
@@ -1710,10 +1648,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
DraftMediaAttachment att=(DraftMediaAttachment) v.getTag();
if(att.serverAttachment==null)
return;
editMediaDescription(att);
}
private void editMediaDescription(DraftMediaAttachment att) {
Bundle args=new Bundle();
args.putString("account", accountID);
args.putString("attachment", att.serverAttachment.id);
@@ -1762,24 +1696,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
pollChanged=true;
updatePublishButtonState();
}));
int maxCharactersPerOption = 50;
if(instance.configuration!=null && instance.configuration.polls!=null && instance.configuration.polls.maxCharactersPerOption>0)
maxCharactersPerOption = instance.configuration.polls.maxCharactersPerOption;
else if(instance.pollLimits!=null && instance.pollLimits.maxOptionChars>0)
maxCharactersPerOption = instance.pollLimits.maxOptionChars;
option.edit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxCharactersPerOption)});
option.edit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(instance.configuration!=null && instance.configuration.polls!=null && instance.configuration.polls.maxCharactersPerOption>0 ? instance.configuration.polls.maxCharactersPerOption : 50)});
pollOptionsView.addView(option.view);
pollOptions.add(option);
int maxPollOptions = 4;
if(instance.configuration!=null && instance.configuration.polls!=null && instance.configuration.polls.maxOptions>0)
maxPollOptions = instance.configuration.polls.maxOptions;
else if (instance.pollLimits!=null && instance.pollLimits.maxOptions>0)
maxPollOptions = instance.pollLimits.maxOptions;
if(pollOptions.size()==maxPollOptions)
if(pollOptions.size()==(instance.configuration!=null && instance.configuration.polls!=null && instance.configuration.polls.maxOptions>0 ? instance.configuration.polls.maxOptions : 4))
addPollOptionBtn.setVisibility(View.GONE);
return option;
}
@@ -1884,9 +1805,15 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
scheduleDraftText.setText(R.string.sk_compose_draft);
scheduleDraftText.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_fluent_drafts_20_regular, 0, 0, 0);
scheduleDraftDismiss.setContentDescription(getString(R.string.sk_compose_no_draft));
draftsBtn.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_fluent_drafts_20_filled, 0, 0, 0);
publishButton.setText(scheduledStatus != null && scheduledStatus.scheduledAt.isAfter(DRAFTS_AFTER_INSTANT)
? R.string.save : R.string.sk_draft);
draftsBtn.setCompoundDrawablesWithIntrinsicBounds(GlobalUserPreferences.relocatePublishButton ? R.drawable.ic_fluent_drafts_24_regular : R.drawable.ic_fluent_drafts_20_filled, 0, 0, 0);
if(GlobalUserPreferences.relocatePublishButton){
publishButton.setCompoundDrawablesWithIntrinsicBounds(scheduledStatus != null && scheduledStatus.scheduledAt.isAfter(DRAFTS_AFTER_INSTANT)
? R.drawable.ic_fluent_save_24_selector : R.drawable.ic_fluent_drafts_24_selector, 0, 0, 0);
}else{
publishButton.setText(scheduledStatus != null && scheduledStatus.scheduledAt.isAfter(DRAFTS_AFTER_INSTANT)
? R.string.save : R.string.sk_draft);
}
} else {
scheduleMenuItem.setVisible(false);
unscheduleMenuItem.setVisible(true);
@@ -1896,12 +1823,21 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
scheduleDraftText.setText(R.string.sk_compose_scheduled);
scheduleDraftText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
scheduleDraftDismiss.setContentDescription(getString(R.string.sk_compose_no_schedule));
draftsBtn.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_fluent_clock_20_filled, 0, 0, 0);
publishButton.setText(scheduledStatus != null && scheduledStatus.scheduledAt.equals(scheduledAt)
? R.string.save : R.string.sk_schedule);
draftsBtn.setCompoundDrawablesWithIntrinsicBounds(GlobalUserPreferences.relocatePublishButton ? R.drawable.ic_fluent_clock_24_filled : R.drawable.ic_fluent_clock_20_filled, 0, 0, 0);
if(GlobalUserPreferences.relocatePublishButton)
{
publishButton.setCompoundDrawablesWithIntrinsicBounds(scheduledStatus != null && scheduledStatus.scheduledAt.isAfter(DRAFTS_AFTER_INSTANT)
? R.drawable.ic_fluent_save_24_selector : R.drawable.ic_fluent_clock_24_selector, 0, 0, 0);
}else{
publishButton.setText(scheduledStatus != null && scheduledStatus.scheduledAt.equals(scheduledAt)
? R.string.save : R.string.sk_schedule);
}
}
} else {
draftsBtn.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_fluent_clock_20_regular, 0, 0, 0);
draftsBtn.setCompoundDrawablesWithIntrinsicBounds(GlobalUserPreferences.relocatePublishButton ? R.drawable.ic_fluent_clock_24_regular : R.drawable.ic_fluent_clock_20_regular, 0, 0, 0);
if(GlobalUserPreferences.relocatePublishButton){
publishButton.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_fluent_send_24_selector, 0, 0, 0);
}
resetPublishButtonText();
}
}
@@ -1919,12 +1855,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
visibilityPopup=new PopupMenu(getActivity(), v);
visibilityPopup.inflate(R.menu.compose_visibility);
Menu m=visibilityPopup.getMenu();
if (isInstancePixelfed()) {
m.findItem(R.id.vis_private).setVisible(false);
}
MenuItem localOnlyItem = visibilityPopup.getMenu().findItem(R.id.local_only);
boolean prefsSaysSupported = GlobalUserPreferences.accountsWithLocalOnlySupport.contains(accountID);
if (isInstanceAkkoma()) {
if (instance.pleroma != null) {
m.findItem(R.id.vis_local).setVisible(true);
} else if (localOnly || prefsSaysSupported) {
localOnlyItem.setVisible(true);
@@ -1968,36 +1901,14 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
});
}
@SuppressLint("ClickableViewAccessibility")
private void buildContentTypePopup(View btn) {
contentTypePopup=new PopupMenu(getActivity(), btn);
contentTypePopup.inflate(R.menu.compose_content_type);
Menu m = contentTypePopup.getMenu();
ContentType.adaptMenuToInstance(m, instance);
if (contentType != null) m.findItem(R.id.content_type_null).setVisible(false);
contentTypePopup.setOnMenuItemClickListener(i->{
int id=i.getItemId();
if (id == R.id.content_type_null) contentType = null;
else if (id == R.id.content_type_plain) contentType = ContentType.PLAIN;
else if (id == R.id.content_type_html) contentType = ContentType.HTML;
else if (id == R.id.content_type_markdown) contentType = ContentType.MARKDOWN;
else if (id == R.id.content_type_bbcode) contentType = ContentType.BBCODE;
else if (id == R.id.content_type_misskey_markdown) contentType = ContentType.MISSKEY_MARKDOWN;
else return false;
btn.setSelected(id != R.id.content_type_null && id != R.id.content_type_plain);
i.setChecked(true);
return true;
});
if (!GlobalUserPreferences.accountsWithContentTypesEnabled.contains(accountID)) {
btn.setVisibility(View.GONE);
}
}
private void loadDefaultStatusVisibility(Bundle savedInstanceState) {
if(replyTo != null) statusVisibility = replyTo.visibility;
// A saved privacy setting from a previous compose session wins over the reply visibility
if(savedInstanceState !=null){
statusVisibility = (StatusPrivacy) savedInstanceState.getSerializable("visibility");
}
AccountSessionManager asm = AccountSessionManager.getInstance();
Preferences prefs = asm.getAccount(accountID).preferences;
if (prefs != null) {
@@ -2146,6 +2057,14 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
});
}
private void editMediaDescription(DraftMediaAttachment att) {
Bundle args=new Bundle();
args.putString("account", accountID);
args.putString("attachment", att.serverAttachment.id);
args.putParcelable("uri", att.uri);
args.putString("existingDescription", att.description);
Nav.goForResult(getActivity(), ComposeImageDescriptionFragment.class, args, IMAGE_DESCRIPTION_RESULT, this);
}
@Override
public CharSequence getTitle(){

View File

@@ -30,11 +30,8 @@ import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.lists.GetLists;
import org.joinmastodon.android.api.requests.tags.GetFollowedHashtags;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Hashtag;
import org.joinmastodon.android.model.HeaderPaginationList;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.ListTimeline;
import org.joinmastodon.android.model.TimelineDefinition;
import org.joinmastodon.android.ui.DividerItemDecoration;
@@ -50,10 +47,11 @@ import java.util.Map;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.views.UsableRecyclerView;
public class EditTimelinesFragment extends RecyclerFragment<TimelineDefinition> implements ScrollableToTop {
public class EditTimelinesFragment extends BaseRecyclerFragment<TimelineDefinition> implements ScrollableToTop {
private String accountID;
private TimelinesAdapter adapter;
private final ItemTouchHelper itemTouchHelper;
@@ -167,7 +165,7 @@ public class EditTimelinesFragment extends RecyclerFragment<TimelineDefinition>
makeBackItem(listsMenu);
makeBackItem(hashtagsMenu);
TimelineDefinition.getAllTimelines(accountID).forEach(tl -> addTimelineToOptions(tl, timelinesMenu));
TimelineDefinition.ALL_TIMELINES.forEach(tl -> addTimelineToOptions(tl, timelinesMenu));
listTimelines.stream().map(TimelineDefinition::ofList).forEach(tl -> addTimelineToOptions(tl, listsMenu));
hashtags.stream().map(TimelineDefinition::ofHashtag).forEach(tl -> addTimelineToOptions(tl, hashtagsMenu));
@@ -193,7 +191,7 @@ public class EditTimelinesFragment extends RecyclerFragment<TimelineDefinition>
@Override
protected void doLoadData(int offset, int count){
onDataLoaded(GlobalUserPreferences.pinnedTimelines.getOrDefault(accountID, TimelineDefinition.getDefaultTimelines(accountID)), false);
onDataLoaded(GlobalUserPreferences.pinnedTimelines.getOrDefault(accountID, TimelineDefinition.DEFAULT_TIMELINES), false);
updateOptionsMenu();
}

View File

@@ -0,0 +1,37 @@
package org.joinmastodon.android.fragments;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;
import org.joinmastodon.android.R;
import org.joinmastodon.android.ui.utils.UiUtils;
import me.grishka.appkit.Nav;
public abstract class FabStatusListFragment extends StatusListFragment {
protected ImageButton fab;
public FabStatusListFragment() {
setListLayoutId(R.layout.recycler_fragment_with_fab);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
fab = view.findViewById(R.id.fab);
fab.setOnClickListener(this::onFabClick);
fab.setOnLongClickListener(this::onFabLongClick);
}
protected void onFabClick(View v){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), ComposeFragment.class, args);
}
protected boolean onFabLongClick(View v) {
return UiUtils.pickAccountForCompose(getActivity(), accountID);
}
}

View File

@@ -1,11 +1,9 @@
package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.net.Uri;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.statuses.GetFavoritedStatuses;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.HeaderPaginationList;
import org.joinmastodon.android.model.Status;
@@ -37,16 +35,4 @@ public class FavoritedStatusListFragment extends StatusListFragment{
})
.exec(accountID);
}
@Override
protected Filter.FilterContext getFilterContext() {
return Filter.FilterContext.ACCOUNT;
}
@Override
public Uri getWebUri(Uri.Builder base) {
return base.encodedPath(isInstanceAkkoma()
? '/' + getSession().self.username + "#favorites"
: "/favourites").build();
}
}

View File

@@ -4,7 +4,6 @@ import android.app.Activity;
import android.graphics.Rect;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
@@ -25,7 +24,6 @@ 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.ProgressBarButton;
import org.joinmastodon.android.utils.ProvidesAssistContent;
import org.parceler.Parcels;
import java.util.Collections;
@@ -40,6 +38,7 @@ 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.fragments.BaseRecyclerFragment;
import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
@@ -48,7 +47,7 @@ import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.UsableRecyclerView;
public class FollowRequestsListFragment extends RecyclerFragment<FollowRequestsListFragment.AccountWrapper> implements ScrollableToTop, ProvidesAssistContent.ProvidesWebUri {
public class FollowRequestsListFragment extends BaseRecyclerFragment<FollowRequestsListFragment.AccountWrapper> implements ScrollableToTop{
private String accountID;
private Map<String, Relationship> relationships=Collections.emptyMap();
private GetAccountRelationships relationshipsRequest;
@@ -150,16 +149,6 @@ public class FollowRequestsListFragment extends RecyclerFragment<FollowRequestsL
smoothScrollRecyclerViewToTop(list);
}
@Override
public String getAccountID() {
return accountID;
}
@Override
public Uri getWebUri(Uri.Builder base) {
return base.path(isInstanceAkkoma() ? "/friend-requests" : "/follow_requests").build();
}
private class AccountsAdapter extends UsableRecyclerView.Adapter<AccountViewHolder> implements ImageLoaderRecyclerAdapter{
public AccountsAdapter(){
@@ -255,10 +244,6 @@ public class FollowRequestsListFragment extends RecyclerFragment<FollowRequestsL
followersLabel.setText(getResources().getQuantityString(R.plurals.followers, (int)Math.min(999, item.account.followersCount)));
followingLabel.setText(getResources().getQuantityString(R.plurals.following, (int)Math.min(999, item.account.followingCount)));
postsLabel.setText(getResources().getQuantityString(R.plurals.posts, (int)Math.min(999, item.account.statusesCount)));
followersCount.setVisibility(item.account.followersCount < 0 ? View.GONE : View.VISIBLE);
followersLabel.setVisibility(item.account.followersCount < 0 ? View.GONE : View.VISIBLE);
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);
if(relationship == null || !relationship.followedBy){
actionWrap.setVisibility(View.GONE);

View File

@@ -1,6 +1,5 @@
package org.joinmastodon.android.fragments;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
@@ -15,15 +14,15 @@ import org.joinmastodon.android.model.Hashtag;
import org.joinmastodon.android.model.HeaderPaginationList;
import org.joinmastodon.android.ui.DividerItemDecoration;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.utils.ProvidesAssistContent;
import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.views.UsableRecyclerView;
public class FollowedHashtagsFragment extends RecyclerFragment<Hashtag> implements ScrollableToTop, ProvidesAssistContent.ProvidesWebUri {
public class FollowedHashtagsFragment extends BaseRecyclerFragment<Hashtag> implements ScrollableToTop {
private String nextMaxID;
private String accountID;
private String accountId;
public FollowedHashtagsFragment() {
super(20);
@@ -33,7 +32,7 @@ public class FollowedHashtagsFragment extends RecyclerFragment<Hashtag> implemen
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args=getArguments();
accountID=args.getString("account");
accountId=args.getString("account");
setTitle(R.string.sk_hashtags_you_follow);
}
@@ -64,7 +63,7 @@ public class FollowedHashtagsFragment extends RecyclerFragment<Hashtag> implemen
onDataLoaded(result, nextMaxID!=null);
}
})
.exec(accountID);
.exec(accountId);
}
@Override
@@ -77,16 +76,6 @@ public class FollowedHashtagsFragment extends RecyclerFragment<Hashtag> implemen
smoothScrollRecyclerViewToTop(list);
}
@Override
public String getAccountID() {
return accountID;
}
@Override
public Uri getWebUri(Uri.Builder base) {
return isInstanceAkkoma() ? null : base.path("/followed_tags").build();
}
private class HashtagsAdapter extends RecyclerView.Adapter<HashtagViewHolder>{
@NonNull
@Override
@@ -121,7 +110,7 @@ public class FollowedHashtagsFragment extends RecyclerFragment<Hashtag> implemen
@Override
public void onClick() {
UiUtils.openHashtagTimeline(getActivity(), accountID, item.name, item.following);
UiUtils.openHashtagTimeline(getActivity(), accountId, item.name, item.following);
}
}
}

View File

@@ -1,27 +0,0 @@
package org.joinmastodon.android.fragments;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Instance;
import java.util.Optional;
public interface HasAccountID {
String getAccountID();
default AccountSession getSession() {
return AccountSessionManager.getInstance().getAccount(getAccountID());
}
default boolean isInstanceAkkoma() {
return getInstance().map(Instance::isAkkoma).orElse(false);
}
default boolean isInstancePixelfed() {
return getInstance().map(Instance::isPixelfed).orElse(false);
}
default Optional<Instance> getInstance() {
return getSession().getInstance();
}
}

View File

@@ -1,10 +0,0 @@
package org.joinmastodon.android.fragments;
import android.view.View;
public interface HasFab {
View getFab();
void showFab();
void hideFab();
boolean isScrolling();
}

View File

@@ -1,7 +1,6 @@
package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.HapticFeedbackConstants;
import android.view.Menu;
@@ -9,6 +8,7 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.Toast;
import org.joinmastodon.android.E;
@@ -17,15 +17,12 @@ import org.joinmastodon.android.api.requests.tags.GetHashtag;
import org.joinmastodon.android.api.requests.tags.SetHashtagFollowed;
import org.joinmastodon.android.api.requests.timelines.GetHashtagTimeline;
import org.joinmastodon.android.events.HashtagUpdatedEvent;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Hashtag;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.TimelineDefinition;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.utils.StatusFilterPredicate;
import java.util.List;
import java.util.stream.Collectors;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
@@ -36,11 +33,11 @@ import me.grishka.appkit.utils.V;
public class HashtagTimelineFragment extends PinnableStatusListFragment {
private String hashtag;
private boolean following;
private ImageButton fab;
private MenuItem followButton;
@Override
protected boolean wantsComposeButton() {
return true;
public HashtagTimelineFragment(){
setListLayoutId(R.layout.recycler_fragment_with_fab);
}
@Override
@@ -123,7 +120,6 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment {
@Override
public void onSuccess(List<Status> result){
if (getActivity() == null) return;
result=result.stream().filter(new StatusFilterPredicate(accountID, getFilterContext())).collect(Collectors.toList());
onDataLoaded(result, !result.isEmpty());
}
})
@@ -138,12 +134,14 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment {
}
@Override
public boolean onFabLongClick(View v) {
return UiUtils.pickAccountForCompose(getActivity(), accountID, '#'+hashtag+' ');
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
fab=view.findViewById(R.id.fab);
fab.setOnClickListener(this::onFabClick);
fab.setOnLongClickListener(v -> UiUtils.pickAccountForCompose(getActivity(), accountID, '#'+hashtag+' '));
}
@Override
public void onFabClick(View v){
private void onFabClick(View v){
Bundle args=new Bundle();
args.putString("account", accountID);
args.putString("prefilledText", '#'+hashtag+' ');
@@ -154,14 +152,4 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment {
protected void onSetFabBottomInset(int inset){
((ViewGroup.MarginLayoutParams) fab.getLayoutParams()).bottomMargin=V.dp(24)+inset;
}
@Override
protected Filter.FilterContext getFilterContext() {
return Filter.FilterContext.PUBLIC;
}
@Override
public Uri getWebUri(Uri.Builder base) {
return base.path((isInstanceAkkoma() ? "/tag/" : "/tags") + hashtag).build();
}
}

View File

@@ -2,7 +2,6 @@ package org.joinmastodon.android.fragments;
import android.app.Fragment;
import android.app.NotificationManager;
import android.app.assist.AssistContent;
import android.graphics.Outline;
import android.os.Build;
import android.os.Bundle;
@@ -17,36 +16,21 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import androidx.annotation.IdRes;
import androidx.annotation.Nullable;
import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.notifications.GetNotifications;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.AllNotificationsSeenEvent;
import org.joinmastodon.android.events.NotificationReceivedEvent;
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.ui.AccountSwitcherSheet;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.TabBar;
import org.joinmastodon.android.utils.ProvidesAssistContent;
import org.parceler.Parcels;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import androidx.annotation.IdRes;
import androidx.annotation.Nullable;
import me.grishka.appkit.FragmentStackActivity;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.AppKitFragment;
import me.grishka.appkit.fragments.LoaderFragment;
import me.grishka.appkit.fragments.OnBackPressedListener;
@@ -55,43 +39,44 @@ import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
public class HomeFragment extends AppKitFragment implements OnBackPressedListener, ProvidesAssistContent, HasAccountID {
public class HomeFragment extends AppKitFragment implements OnBackPressedListener{
private FragmentRootLinearLayout content;
private HomeTabFragment homeTabFragment;
// private HomeTimelineFragment homeTimelineFragment;
private NotificationsFragment notificationsFragment;
private DiscoverFragment searchFragment;
private ProfileFragment profileFragment;
private TabBar tabBar;
private View tabBarWrap;
private ImageView tabBarAvatar;
private ImageView notificationTabIcon;
@IdRes
private int currentTab=R.id.tab_home;
private String accountID;
private boolean isPleroma;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
E.register(this);
accountID=getArguments().getString("account");
setTitle(R.string.sk_app_name);
isPleroma = AccountSessionManager.getInstance().getAccount(accountID).getInstance()
.map(Instance::isAkkoma)
.orElse(false);
setTitle(R.string.mo_app_name);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
setRetainInstance(true);
// TODO: clean up
if(savedInstanceState==null){
Bundle args=new Bundle();
args.putString("account", accountID);
homeTabFragment=new HomeTabFragment();
homeTabFragment.setArguments(args);
// homeTimelineFragment=new HomeTimelineFragment();
// homeTimelineFragment.setArguments(args);
args=new Bundle(args);
args.putBoolean("disableDiscover", isPleroma);
args.putBoolean("noAutoLoad", true);
searchFragment=new DiscoverFragment();
searchFragment.setArguments(args);
@@ -113,7 +98,7 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
content.setOrientation(LinearLayout.VERTICAL);
FrameLayout fragmentContainer=new FrameLayout(getActivity());
fragmentContainer.setId(me.grishka.appkit.R.id.fragment_wrap);
fragmentContainer.setId(R.id.fragment_wrap);
content.addView(fragmentContainer, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f));
inflater.inflate(R.layout.tab_bar, content);
@@ -132,17 +117,21 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
Account self=AccountSessionManager.getInstance().getAccount(accountID).self;
ViewImageLoader.load(tabBarAvatar, null, new UrlImageLoaderRequest(self.avatar, V.dp(28), V.dp(28)));
notificationTabIcon=content.findViewById(R.id.tab_notifications);
updateNotificationBadge();
if(savedInstanceState==null){
getChildFragmentManager().beginTransaction()
.add(me.grishka.appkit.R.id.fragment_wrap, homeTabFragment)
.add(me.grishka.appkit.R.id.fragment_wrap, searchFragment).hide(searchFragment)
.add(me.grishka.appkit.R.id.fragment_wrap, notificationsFragment).hide(notificationsFragment)
.add(me.grishka.appkit.R.id.fragment_wrap, profileFragment).hide(profileFragment)
.add(R.id.fragment_wrap, homeTabFragment)
.add(R.id.fragment_wrap, searchFragment).hide(searchFragment)
.add(R.id.fragment_wrap, notificationsFragment).hide(notificationsFragment)
.add(R.id.fragment_wrap, profileFragment).hide(profileFragment)
.commit();
// getChildFragmentManager().beginTransaction()
// .add(R.id.fragment_wrap, homeTimelineFragment)
// .add(R.id.fragment_wrap, searchFragment).hide(searchFragment)
// .add(R.id.fragment_wrap, notificationsFragment).hide(notificationsFragment)
// .add(R.id.fragment_wrap, profileFragment).hide(profileFragment)
// .commit();
String defaultTab=getArguments().getString("tab");
if("notifications".equals(defaultTab)){
tabBar.selectTab(R.id.tab_notifications);
@@ -163,14 +152,21 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
@Override
public void onViewStateRestored(Bundle savedInstanceState){
super.onViewStateRestored(savedInstanceState);
if(savedInstanceState==null) return;
// if(savedInstanceState==null || homeTimelineFragment!=null)
// return;
homeTabFragment=(HomeTabFragment) getChildFragmentManager().getFragment(savedInstanceState, "homeTabFragment");
// homeTimelineFragment=(HomeTimelineFragment) getChildFragmentManager().getFragment(savedInstanceState, "homeTimelineFragment");
searchFragment=(DiscoverFragment) getChildFragmentManager().getFragment(savedInstanceState, "searchFragment");
notificationsFragment=(NotificationsFragment) getChildFragmentManager().getFragment(savedInstanceState, "notificationsFragment");
profileFragment=(ProfileFragment) getChildFragmentManager().getFragment(savedInstanceState, "profileFragment");
currentTab=savedInstanceState.getInt("selectedTab");
tabBar.selectTab(currentTab);
Fragment current=fragmentForTab(currentTab);
getChildFragmentManager().beginTransaction()
.hide(homeTabFragment)
.hide(searchFragment)
@@ -178,6 +174,14 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
.hide(profileFragment)
.show(current)
.commit();
// getChildFragmentManager().beginTransaction()
// .hide(homeTimelineFragment)
// .hide(searchFragment)
// .hide(notificationsFragment)
// .hide(profileFragment)
// .show(current)
// .commit();
maybeTriggerLoading(current);
}
@@ -207,7 +211,11 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), 0, insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()));
}
WindowInsets topOnlyInsets=insets.replaceSystemWindowInsets(0, insets.getSystemWindowInsetTop(), 0, 0);
homeTabFragment.onApplyWindowInsets(topOnlyInsets);
// homeTimelineFragment.onApplyWindowInsets(topOnlyInsets);
searchFragment.onApplyWindowInsets(topOnlyInsets);
notificationsFragment.onApplyWindowInsets(topOnlyInsets);
profileFragment.onApplyWindowInsets(topOnlyInsets);
@@ -216,6 +224,9 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
private Fragment fragmentForTab(@IdRes int tab){
if(tab==R.id.tab_home){
return homeTabFragment;
// if(tab==R.id.tab_home){
// return homeTimelineFragment;
}else if(tab==R.id.tab_search){
return searchFragment;
}else if(tab==R.id.tab_notifications){
@@ -226,28 +237,28 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
throw new IllegalArgumentException();
}
public void setCurrentTab(@IdRes int tab){
if(tab==currentTab)
return;
tabBar.selectTab(tab);
onTabSelected(tab);
}
private void onTabSelected(@IdRes int tab){
Fragment newFragment=fragmentForTab(tab);
if(tab==currentTab){
if (tab == R.id.tab_search)
searchFragment.onSelect();
else if(newFragment instanceof ScrollableToTop scrollable)
if(tab == R.id.tab_search){
if(newFragment instanceof ScrollableToTop scrollable)
scrollable.scrollToTop();
searchFragment.selectSearch();
return;
}
if(newFragment instanceof ScrollableToTop scrollable)
scrollable.scrollToTop();
return;
}
if(tab==currentTab && tab == R.id.tab_search){
if(newFragment instanceof ScrollableToTop scrollable)
scrollable.scrollToTop();
return;
}
getChildFragmentManager().beginTransaction().hide(fragmentForTab(currentTab)).show(newFragment).commit();
maybeTriggerLoading(newFragment);
if (newFragment instanceof HasFab fabulous && !fabulous.isScrolling()) fabulous.showFab();
currentTab=tab;
((FragmentStackActivity)getActivity()).invalidateSystemBarColors(this);
if (tab == R.id.tab_search && isPleroma) searchFragment.selectSearch();
}
private void maybeTriggerLoading(Fragment newFragment){
@@ -274,7 +285,13 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
for(AccountSession session:AccountSessionManager.getInstance().getLoggedInAccounts()){
options.add(session.self.displayName+"\n("+session.self.username+"@"+session.domain+")");
}
new AccountSwitcherSheet(getActivity(), this).show();
new AccountSwitcherSheet(getActivity()).show();
return true;
}
if(tab==R.id.tab_search){
onTabSelected(R.id.tab_search);
tabBar.selectTab(R.id.tab_search);
searchFragment.selectSearch();
return true;
}
return false;
@@ -299,62 +316,15 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
outState.putInt("selectedTab", currentTab);
if (homeTabFragment.isAdded()) getChildFragmentManager().putFragment(outState, "homeTabFragment", homeTabFragment);
if (searchFragment.isAdded()) getChildFragmentManager().putFragment(outState, "searchFragment", searchFragment);
if (notificationsFragment.isAdded()) getChildFragmentManager().putFragment(outState, "notificationsFragment", notificationsFragment);
if (profileFragment.isAdded()) getChildFragmentManager().putFragment(outState, "profileFragment", profileFragment);
}
public void updateNotificationBadge() {
AccountSession session = AccountSessionManager.getInstance().getAccount(accountID);
Optional<Instance> instance = session.getInstance();
if (instance.isEmpty()) return; // avoiding incompatibility with akkoma
new GetNotifications(null, 1, EnumSet.allOf(Notification.Type.class), instance.get().isAkkoma())
.setCallback(new Callback<>() {
@Override
public void onSuccess(List<Notification> notifications) {
if (notifications.size() > 0) {
try {
long newestId = Long.parseLong(notifications.get(0).id);
long lastSeenId = Long.parseLong(session.markers.notifications.lastReadId);
setNotificationBadge(newestId > lastSeenId);
} catch (Exception ignored) {
setNotificationBadge(false);
}
}
}
@Override
public void onError(ErrorResponse error) {
setNotificationBadge(false);
}
}).exec(accountID);
}
public void setNotificationBadge(boolean badge) {
notificationTabIcon.setImageResource(badge
? R.drawable.ic_fluent_alert_28_selector_badged
: R.drawable.ic_fluent_alert_28_selector);
}
@Subscribe
public void onNotificationReceived(NotificationReceivedEvent notificationReceivedEvent) {
if (notificationReceivedEvent.account.equals(accountID)) setNotificationBadge(true);
}
@Subscribe
public void onAllNotificationsSeen(AllNotificationsSeenEvent allNotificationsSeenEvent) {
setNotificationBadge(false);
}
@Override
public String getAccountID() {
return accountID;
}
@Override
public void onProvideAssistContent(AssistContent assistContent) {
callFragmentToProvideAssistContent(fragmentForTab(currentTab), assistContent);
// getChildFragmentManager().putFragment(outState, "homeTimelineFragment", homeTimelineFragment);
// getChildFragmentManager().putFragment(outState, "searchFragment", searchFragment);
// getChildFragmentManager().putFragment(outState, "notificationsFragment", notificationsFragment);
// getChildFragmentManager().putFragment(outState, "profileFragment", profileFragment);
}
}

View File

@@ -10,7 +10,6 @@ import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.assist.AssistContent;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
@@ -25,7 +24,6 @@ import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
@@ -55,7 +53,6 @@ import org.joinmastodon.android.model.TimelineDefinition;
import org.joinmastodon.android.ui.SimpleViewHolder;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.updater.GithubSelfUpdater;
import org.joinmastodon.android.utils.ProvidesAssistContent;
import java.util.Collection;
import java.util.HashMap;
@@ -73,7 +70,7 @@ import me.grishka.appkit.fragments.OnBackPressedListener;
import me.grishka.appkit.utils.CubicBezierInterpolator;
import me.grishka.appkit.utils.V;
public class HomeTabFragment extends MastodonToolbarFragment implements ScrollableToTop, OnBackPressedListener, HasFab, ProvidesAssistContent {
public class HomeTabFragment extends MastodonToolbarFragment implements ScrollableToTop, OnBackPressedListener {
private static final int ANNOUNCEMENTS_RESULT = 654;
private String accountID;
@@ -101,14 +98,13 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
private PopupMenu overflowPopup;
private View overflowActionView = null;
private boolean announcementsBadged, settingsBadged;
private ImageButton fab;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
E.register(this);
accountID = getArguments().getString("account");
timelineDefinitions = GlobalUserPreferences.pinnedTimelines.getOrDefault(accountID, TimelineDefinition.getDefaultTimelines(accountID));
timelineDefinitions = GlobalUserPreferences.pinnedTimelines.getOrDefault(accountID, TimelineDefinition.DEFAULT_TIMELINES);
assert timelineDefinitions != null;
if (timelineDefinitions.size() == 0) timelineDefinitions = List.of(TimelineDefinition.HOME_TIMELINE);
count = timelineDefinitions.size();
@@ -126,10 +122,6 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
@Override
public View onCreateContentView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
FrameLayout view = new FrameLayout(getContext());
inflater.inflate(R.layout.compose_fab, view);
fab = view.findViewById(R.id.fab);
fab.setOnClickListener(this::onFabClick);
fab.setOnLongClickListener(this::onFabLongClick);
pager = new ViewPager2(getContext());
toolbarFrame = (FrameLayout) LayoutInflater.from(getContext()).inflate(R.layout.home_toolbar, getToolbar(), false);
@@ -137,7 +129,6 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
Bundle args = new Bundle();
args.putString("account", accountID);
args.putBoolean("__is_tab", true);
args.putBoolean("__disable_fab", true);
args.putBoolean("onlyPosts", true);
for (int i = 0; i < timelineDefinitions.size(); i++) {
@@ -289,20 +280,6 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
}).exec(accountID);
}
private void onFabClick(View v){
if (fragments[pager.getCurrentItem()] instanceof BaseStatusListFragment<?> l) {
l.onFabClick(v);
}
}
private boolean onFabLongClick(View v) {
if (fragments[pager.getCurrentItem()] instanceof BaseStatusListFragment<?> l) {
return l.onFabLongClick(v);
} else {
return false;
}
}
private void addListsToOverflowMenu() {
Context ctx = getContext();
listsMenu.clear();
@@ -381,7 +358,7 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
addListsToOverflowMenu();
addHashtagsToOverflowMenu();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !UiUtils.isEMUI()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
m.setGroupDividerEnabled(true);
}
}
@@ -398,7 +375,7 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
}
private <T> void updateList(List<T> addItems, Map<Integer, T> items) {
if (addItems.size() == 0 || getActivity() == null) return;
if (addItems.size() == 0) return;
for (int i = 0; i < addItems.size(); i++) items.put(View.generateViewId(), addItems.get(i));
updateOverflowMenu();
}
@@ -450,26 +427,9 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
updateSwitcherIcon(i);
}
@Override
public void showFab() {
if (fragments[pager.getCurrentItem()] instanceof BaseStatusListFragment<?> l) l.showFab();
}
@Override
public void hideFab() {
if (fragments[pager.getCurrentItem()] instanceof BaseStatusListFragment<?> l) l.hideFab();
}
@Override
public boolean isScrolling() {
return (fragments[pager.getCurrentItem()] instanceof HasFab fabulous)
&& fabulous.isScrolling();
}
private void updateSwitcherIcon(int i) {
timelineIcon.setImageResource(timelines[i].getIcon().iconRes);
timelineTitle.setText(timelines[i].getTitle(getContext()));
showFab();
}
@Override
@@ -697,22 +657,12 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
return hashtagsItems.values();
}
public ImageButton getFab() {
return fab;
}
@Override
public void onProvideAssistContent(AssistContent assistContent) {
callFragmentToProvideAssistContent(fragments[pager.getCurrentItem()], assistContent);
}
private class HomePagerAdapter extends RecyclerView.Adapter<SimpleViewHolder> {
@NonNull
@Override
public SimpleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
FrameLayout tabView = tabViews[viewType % getItemCount()];
ViewGroup tabParent = (ViewGroup) tabView.getParent();
if (tabParent != null) tabParent.removeView(tabView);
((ViewGroup)tabView.getParent()).removeView(tabView);
tabView.setVisibility(View.VISIBLE);
return new SimpleViewHolder(tabView);
}

View File

@@ -1,7 +1,6 @@
package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
@@ -9,6 +8,8 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.E;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.markers.SaveMarkers;
import org.joinmastodon.android.api.requests.timelines.GetHomeTimeline;
import org.joinmastodon.android.api.session.AccountSessionManager;
@@ -31,16 +32,11 @@ import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.utils.V;
public class HomeTimelineFragment extends StatusListFragment {
public class HomeTimelineFragment extends FabStatusListFragment {
private HomeTabFragment parent;
private String maxID;
private String lastSavedMarkerID;
@Override
protected boolean wantsComposeButton() {
return true;
}
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
@@ -48,13 +44,12 @@ public class HomeTimelineFragment extends StatusListFragment {
loadData();
}
private boolean typeFilterPredicate(Status s) {
return (GlobalUserPreferences.showReplies || s.inReplyToId == null) &&
(GlobalUserPreferences.showBoosts || s.reblog == null);
}
private List<Status> filterPosts(List<Status> items) {
return items.stream().filter(this::typeFilterPredicate).collect(Collectors.toList());
// This is the function I must use to solve the filters thing for real
return items.stream().filter(i ->
(GlobalUserPreferences.showReplies || i.inReplyToId == null) &&
(GlobalUserPreferences.showBoosts || i.reblog == null)
).collect(Collectors.toList());
}
@Override
@@ -103,24 +98,24 @@ public class HomeTimelineFragment extends StatusListFragment {
@Override
protected void onHidden(){
super.onHidden();
if(!data.isEmpty()){
String topPostID=displayItems.get(Math.max(0, list.getChildAdapterPosition(list.getChildAt(0))-getMainAdapterOffset())).parentID;
if(!topPostID.equals(lastSavedMarkerID)){
lastSavedMarkerID=topPostID;
new SaveMarkers(topPostID, null)
.setCallback(new Callback<>(){
@Override
public void onSuccess(SaveMarkers.Response result){
}
@Override
public void onError(ErrorResponse error){
lastSavedMarkerID=null;
}
})
.exec(accountID);
}
}
// if(!data.isEmpty()){
// String topPostID=displayItems.get(list.getChildAdapterPosition(list.getChildAt(0))-getMainAdapterOffset()).parentID;
// if(!topPostID.equals(lastSavedMarkerID)){
// lastSavedMarkerID=topPostID;
// new SaveMarkers(topPostID, null)
// .setCallback(new Callback<>(){
// @Override
// public void onSuccess(SaveMarkers.Response result){
// }
//
// @Override
// public void onError(ErrorResponse error){
// lastSavedMarkerID=null;
// }
// })
// .exec(accountID);
// }
// }
}
public void onStatusCreated(StatusCreatedEvent ev){
@@ -151,7 +146,7 @@ public class HomeTimelineFragment extends StatusListFragment {
result.get(result.size()-1).hasGapAfter=true;
toAdd=result;
}
StatusFilterPredicate filterPredicate=new StatusFilterPredicate(accountID, getFilterContext());
StatusFilterPredicate filterPredicate=new StatusFilterPredicate(accountID, Filter.FilterContext.HOME);
toAdd=toAdd.stream().filter(filterPredicate).collect(Collectors.toList());
if(!toAdd.isEmpty()){
prependItems(toAdd, true);
@@ -167,10 +162,6 @@ public class HomeTimelineFragment extends StatusListFragment {
}
})
.exec(accountID);
if (parent.getParentFragment() instanceof HomeFragment homeFragment) {
homeFragment.updateNotificationBadge();
}
}
@Override
@@ -230,11 +221,11 @@ public class HomeTimelineFragment extends StatusListFragment {
List<StatusDisplayItem> targetList=displayItems.subList(gapPos, gapPos+1);
targetList.clear();
List<Status> insertedPosts=data.subList(gapPostIndex+1, gapPostIndex+1);
StatusFilterPredicate filterPredicate=new StatusFilterPredicate(accountID, getFilterContext());
StatusFilterPredicate filterPredicate=new StatusFilterPredicate(accountID, Filter.FilterContext.HOME);
for(Status s:result){
if(idsBelowGap.contains(s.id))
break;
if(typeFilterPredicate(s) && filterPredicate.test(s)){
if(filterPredicate.test(s)){
targetList.addAll(buildDisplayItems(s));
insertedPosts.add(s);
}
@@ -283,14 +274,4 @@ public class HomeTimelineFragment extends StatusListFragment {
protected boolean shouldRemoveAccountPostsWhenUnfollowing(){
return true;
}
@Override
protected Filter.FilterContext getFilterContext() {
return Filter.FilterContext.HOME;
}
@Override
public Uri getWebUri(Uri.Builder base) {
return base.path("/").build();
}
}

View File

@@ -1,13 +1,13 @@
package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import androidx.annotation.Nullable;
@@ -18,17 +18,14 @@ import org.joinmastodon.android.api.requests.lists.UpdateList;
import org.joinmastodon.android.api.requests.timelines.GetListTimeline;
import org.joinmastodon.android.events.ListDeletedEvent;
import org.joinmastodon.android.events.ListUpdatedCreatedEvent;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.ListTimeline;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.TimelineDefinition;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ListTimelineEditor;
import org.joinmastodon.android.utils.StatusFilterPredicate;
import java.util.List;
import java.util.stream.Collectors;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
@@ -42,10 +39,10 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
private String listTitle;
@Nullable
private ListTimeline.RepliesPolicy repliesPolicy;
private ImageButton fab;
@Override
protected boolean wantsComposeButton() {
return true;
public ListTimelineFragment() {
setListLayoutId(R.layout.recycler_fragment_with_fab);
}
@Override
@@ -137,11 +134,10 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
@Override
public void onSuccess(List<Status> result) {
if (getActivity() == null) return;
result=result.stream().filter(new StatusFilterPredicate(accountID, getFilterContext())).collect(Collectors.toList());
onDataLoaded(result, !result.isEmpty());
}
})
.exec(accountID);
.exec(accountID);
}
@Override
@@ -152,7 +148,14 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
}
@Override
public void onFabClick(View v){
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
fab=view.findViewById(R.id.fab);
fab.setOnClickListener(this::onFabClick);
fab.setOnLongClickListener(v -> UiUtils.pickAccountForCompose(getActivity(), accountID));
}
private void onFabClick(View v){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), ComposeFragment.class, args);
@@ -162,15 +165,4 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
protected void onSetFabBottomInset(int inset) {
((ViewGroup.MarginLayoutParams) fab.getLayoutParams()).bottomMargin=V.dp(24)+inset;
}
@Override
protected Filter.FilterContext getFilterContext() {
return Filter.FilterContext.HOME;
}
@Override
public Uri getWebUri(Uri.Builder base) {
return base.path("/lists/" + listID).build();
}
}

View File

@@ -0,0 +1,260 @@
package org.joinmastodon.android.fragments;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.requests.lists.AddAccountsToList;
import org.joinmastodon.android.api.requests.lists.CreateList;
import org.joinmastodon.android.api.requests.lists.GetLists;
import org.joinmastodon.android.api.requests.lists.RemoveAccountsFromList;
import org.joinmastodon.android.events.ListDeletedEvent;
import org.joinmastodon.android.events.ListUpdatedCreatedEvent;
import org.joinmastodon.android.model.ListTimeline;
import org.joinmastodon.android.ui.DividerItemDecoration;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.views.ListTimelineEditor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
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.fragments.BaseRecyclerFragment;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.views.UsableRecyclerView;
public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> implements ScrollableToTop {
private String accountId;
private String profileAccountId;
private final HashMap<String, Boolean> userInListBefore = new HashMap<>();
private final HashMap<String, Boolean> userInList = new HashMap<>();
private ListsAdapter adapter;
public ListTimelinesFragment() {
super(10);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args=getArguments();
accountId=args.getString("account");
setHasOptionsMenu(true);
E.register(this);
if(args.containsKey("profileAccount")){
profileAccountId=args.getString("profileAccount");
String profileDisplayUsername = args.getString("profileDisplayUsername");
setTitle(getString(R.string.sk_lists_with_user, profileDisplayUsername));
} else {
setTitle(R.string.sk_your_lists);
}
}
@Override
protected void onShown(){
super.onShown();
if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading)
loadData();
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
list.addItemDecoration(new DividerItemDecoration(getActivity(), R.attr.colorPollVoted, 0.5f, 56, 16));
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_list, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create) {
ListTimelineEditor editor = new ListTimelineEditor(getContext());
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_create_list_title)
.setIcon(R.drawable.ic_fluent_people_add_28_regular)
.setView(editor)
.setPositiveButton(R.string.sk_create, (d, which) ->
new CreateList(editor.getTitle(), editor.getRepliesPolicy()).setCallback(new Callback<>() {
@Override
public void onSuccess(ListTimeline list) {
saveListMembership(list.id, true);
data.add(0, list);
adapter.notifyItemRangeInserted(0, 1);
E.post(new ListUpdatedCreatedEvent(list.id, list.title, list.repliesPolicy));
}
@Override
public void onError(ErrorResponse error) {
error.showToast(getContext());
}
}).exec(accountId)
)
.setNegativeButton(R.string.cancel, (d, which) -> {})
.show();
}
return true;
}
private void saveListMembership(String listId, boolean isMember) {
userInList.put(listId, isMember);
List<String> accountIdList = Collections.singletonList(profileAccountId);
MastodonAPIRequest<Object> req = isMember ? new AddAccountsToList(listId, accountIdList) : new RemoveAccountsFromList(listId, accountIdList);
req.setCallback(new Callback<>() {
@Override
public void onSuccess(Object o) {}
@Override
public void onError(ErrorResponse error) {
error.showToast(getContext());
}
}).exec(accountId);
}
@Override
protected void doLoadData(int offset, int count){
userInListBefore.clear();
userInList.clear();
currentRequest=(profileAccountId != null ? new GetLists(profileAccountId) : new GetLists())
.setCallback(new SimpleCallback<>(this) {
@Override
public void onSuccess(List<ListTimeline> lists) {
if (getActivity() == null) return;
for (ListTimeline l : lists) userInListBefore.put(l.id, true);
userInList.putAll(userInListBefore);
if (profileAccountId == null || !lists.isEmpty()) onDataLoaded(lists, false);
if (profileAccountId == null) return;
currentRequest=new GetLists().setCallback(new SimpleCallback<>(ListTimelinesFragment.this) {
@Override
public void onSuccess(List<ListTimeline> allLists) {
if (getActivity() == null) return;
List<ListTimeline> newLists = new ArrayList<>();
for (ListTimeline l : allLists) {
if (lists.stream().noneMatch(e -> e.id.equals(l.id))) newLists.add(l);
if (!userInListBefore.containsKey(l.id)) {
userInListBefore.put(l.id, false);
}
}
userInList.putAll(userInListBefore);
onDataLoaded(newLists, false);
}
}).exec(accountId);
}
})
.exec(accountId);
}
@Subscribe
public void onListDeletedEvent(ListDeletedEvent event) {
for (int i = 0; i < data.size(); i++) {
ListTimeline item = data.get(i);
if (item.id.equals(event.id)) {
data.remove(i);
adapter.notifyItemRemoved(i);
break;
}
}
}
@Subscribe
public void onListUpdatedCreatedEvent(ListUpdatedCreatedEvent event) {
for (int i = 0; i < data.size(); i++) {
ListTimeline item = data.get(i);
if (item.id.equals(event.id)) {
item.title = event.title;
item.repliesPolicy = event.repliesPolicy;
adapter.notifyItemChanged(i);
break;
}
}
}
@Override
protected RecyclerView.Adapter<ListViewHolder> getAdapter() {
return adapter = new ListsAdapter();
}
@Override
public void scrollToTop() {
smoothScrollRecyclerViewToTop(list);
}
private class ListsAdapter extends RecyclerView.Adapter<ListViewHolder>{
@NonNull
@Override
public ListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
return new ListViewHolder();
}
@Override
public void onBindViewHolder(@NonNull ListViewHolder holder, int position) {
holder.bind(data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
}
private class ListViewHolder extends BindableViewHolder<ListTimeline> implements UsableRecyclerView.Clickable{
private final TextView title;
private final CheckBox listToggle;
public ListViewHolder(){
super(getActivity(), R.layout.item_text, list);
title=findViewById(R.id.title);
listToggle=findViewById(R.id.list_toggle);
}
@Override
public void onBind(ListTimeline item) {
title.setText(item.title);
title.setCompoundDrawablesRelativeWithIntrinsicBounds(itemView.getContext().getDrawable(R.drawable.ic_fluent_people_24_regular), null, null, null);
if (profileAccountId != null) {
Boolean checked = userInList.get(item.id);
listToggle.setVisibility(View.VISIBLE);
listToggle.setChecked(userInList.containsKey(item.id) && checked != null && checked);
listToggle.setOnClickListener(this::onClickToggle);
} else {
listToggle.setVisibility(View.GONE);
}
}
private void onClickToggle(View view) {
saveListMembership(item.id, listToggle.isChecked());
}
@Override
public void onClick() {
Bundle args=new Bundle();
args.putString("account", accountId);
args.putString("listID", item.id);
args.putString("listTitle", item.title);
if (item.repliesPolicy != null) args.putInt("repliesPolicy", item.repliesPolicy.ordinal());
Nav.go(getActivity(), ListTimelineFragment.class, args);
}
}
}

View File

@@ -1,270 +0,0 @@
package org.joinmastodon.android.fragments;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.requests.lists.AddAccountsToList;
import org.joinmastodon.android.api.requests.lists.CreateList;
import org.joinmastodon.android.api.requests.lists.GetLists;
import org.joinmastodon.android.api.requests.lists.RemoveAccountsFromList;
import org.joinmastodon.android.events.ListDeletedEvent;
import org.joinmastodon.android.events.ListUpdatedCreatedEvent;
import org.joinmastodon.android.model.ListTimeline;
import org.joinmastodon.android.ui.DividerItemDecoration;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.views.ListTimelineEditor;
import org.joinmastodon.android.utils.ProvidesAssistContent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
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.BindableViewHolder;
import me.grishka.appkit.views.UsableRecyclerView;
public class ListsFragment extends RecyclerFragment<ListTimeline> implements ScrollableToTop, ProvidesAssistContent.ProvidesWebUri {
private String accountID;
private String profileAccountId;
private final HashMap<String, Boolean> userInListBefore = new HashMap<>();
private final HashMap<String, Boolean> userInList = new HashMap<>();
private ListsAdapter adapter;
public ListsFragment() {
super(10);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
accountID = args.getString("account");
setHasOptionsMenu(true);
E.register(this);
if(args.containsKey("profileAccount")){
profileAccountId=args.getString("profileAccount");
String profileDisplayUsername = args.getString("profileDisplayUsername");
setTitle(getString(R.string.sk_lists_with_user, profileDisplayUsername));
} else {
setTitle(R.string.sk_your_lists);
}
}
@Override
protected void onShown(){
super.onShown();
if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading)
loadData();
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
list.addItemDecoration(new DividerItemDecoration(getActivity(), R.attr.colorPollVoted, 0.5f, 56, 16));
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_list, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create) {
ListTimelineEditor editor = new ListTimelineEditor(getContext());
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_create_list_title)
.setIcon(R.drawable.ic_fluent_people_add_28_regular)
.setView(editor)
.setPositiveButton(R.string.sk_create, (d, which) ->
new CreateList(editor.getTitle(), editor.getRepliesPolicy()).setCallback(new Callback<>() {
@Override
public void onSuccess(ListTimeline list) {
data.add(0, list);
adapter.notifyItemRangeInserted(0, 1);
E.post(new ListUpdatedCreatedEvent(list.id, list.title, list.repliesPolicy));
}
@Override
public void onError(ErrorResponse error) {
error.showToast(getContext());
}
}).exec(accountID)
)
.setNegativeButton(R.string.cancel, (d, which) -> {})
.show();
}
return true;
}
private void saveListMembership(String listId, boolean isMember) {
userInList.put(listId, isMember);
List<String> accountIdList = Collections.singletonList(profileAccountId);
MastodonAPIRequest<Object> req = isMember ? new AddAccountsToList(listId, accountIdList) : new RemoveAccountsFromList(listId, accountIdList);
req.setCallback(new Callback<>() {
@Override
public void onSuccess(Object o) {}
@Override
public void onError(ErrorResponse error) {
error.showToast(getContext());
}
}).exec(accountID);
}
@Override
protected void doLoadData(int offset, int count){
userInListBefore.clear();
userInList.clear();
currentRequest=(profileAccountId != null ? new GetLists(profileAccountId) : new GetLists())
.setCallback(new SimpleCallback<>(this) {
@Override
public void onSuccess(List<ListTimeline> lists) {
if (getActivity() == null) return;
for (ListTimeline l : lists) userInListBefore.put(l.id, true);
userInList.putAll(userInListBefore);
if (profileAccountId == null || !lists.isEmpty()) onDataLoaded(lists, false);
if (profileAccountId == null) return;
currentRequest=new GetLists().setCallback(new SimpleCallback<>(ListsFragment.this) {
@Override
public void onSuccess(List<ListTimeline> allLists) {
if (getActivity() == null) return;
List<ListTimeline> newLists = new ArrayList<>();
for (ListTimeline l : allLists) {
if (lists.stream().noneMatch(e -> e.id.equals(l.id))) newLists.add(l);
if (!userInListBefore.containsKey(l.id)) {
userInListBefore.put(l.id, false);
}
}
userInList.putAll(userInListBefore);
onDataLoaded(newLists, false);
}
}).exec(accountID);
}
})
.exec(accountID);
}
@Subscribe
public void onListDeletedEvent(ListDeletedEvent event) {
for (int i = 0; i < data.size(); i++) {
ListTimeline item = data.get(i);
if (item.id.equals(event.id)) {
data.remove(i);
adapter.notifyItemRemoved(i);
break;
}
}
}
@Subscribe
public void onListUpdatedCreatedEvent(ListUpdatedCreatedEvent event) {
for (int i = 0; i < data.size(); i++) {
ListTimeline item = data.get(i);
if (item.id.equals(event.id)) {
item.title = event.title;
item.repliesPolicy = event.repliesPolicy;
adapter.notifyItemChanged(i);
break;
}
}
}
@Override
protected RecyclerView.Adapter<ListViewHolder> getAdapter() {
return adapter = new ListsAdapter();
}
@Override
public void scrollToTop() {
smoothScrollRecyclerViewToTop(list);
}
@Override
public String getAccountID() {
return accountID;
}
@Override
public Uri getWebUri(Uri.Builder base) {
return base.path("/lists").build();
}
private class ListsAdapter extends RecyclerView.Adapter<ListViewHolder>{
@NonNull
@Override
public ListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
return new ListViewHolder();
}
@Override
public void onBindViewHolder(@NonNull ListViewHolder holder, int position) {
holder.bind(data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
}
private class ListViewHolder extends BindableViewHolder<ListTimeline> implements UsableRecyclerView.Clickable{
private final TextView title;
private final CheckBox listToggle;
public ListViewHolder(){
super(getActivity(), R.layout.item_text, list);
title=findViewById(R.id.title);
listToggle=findViewById(R.id.list_toggle);
}
@Override
public void onBind(ListTimeline item) {
title.setText(item.title);
title.setCompoundDrawablesRelativeWithIntrinsicBounds(itemView.getContext().getDrawable(R.drawable.ic_fluent_people_24_regular), null, null, null);
if (profileAccountId != null) {
Boolean checked = userInList.get(item.id);
listToggle.setVisibility(View.VISIBLE);
listToggle.setChecked(userInList.containsKey(item.id) && checked != null && checked);
listToggle.setOnClickListener(this::onClickToggle);
} else {
listToggle.setVisibility(View.GONE);
}
}
private void onClickToggle(View view) {
saveListMembership(item.id, listToggle.isChecked());
}
@Override
public void onClick() {
Bundle args=new Bundle();
args.putString("account", accountID);
args.putString("listID", item.id);
args.putString("listTitle", item.title);
if (item.repliesPolicy != null) args.putInt("repliesPolicy", item.repliesPolicy.ordinal());
Nav.go(getActivity(), ListTimelineFragment.class, args);
}
}
}

View File

@@ -30,9 +30,4 @@ public abstract class MastodonToolbarFragment extends ToolbarFragment{
toolbar.setNavigationContentDescription(R.string.back);
}
}
@Override
protected boolean wantsToolbarMenuIconsTinted() {
return false; // else, badged icons don't work :(
}
}

View File

@@ -2,7 +2,6 @@ package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.app.Fragment;
import android.app.assist.AssistContent;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -14,12 +13,6 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
@@ -31,7 +24,12 @@ import org.joinmastodon.android.ui.SimpleViewHolder;
import org.joinmastodon.android.ui.tabs.TabLayout;
import org.joinmastodon.android.ui.tabs.TabLayoutMediator;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.utils.ProvidesAssistContent;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import com.squareup.otto.Subscribe;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
@@ -39,16 +37,17 @@ import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.utils.V;
public class NotificationsFragment extends MastodonToolbarFragment implements ScrollableToTop, ProvidesAssistContent {
public class NotificationsFragment extends MastodonToolbarFragment implements ScrollableToTop{
private TabLayout tabLayout;
private ViewPager2 pager;
private FrameLayout[] tabViews;
private TabLayoutMediator tabLayoutMediator;
private NotificationsListFragment allNotificationsFragment, mentionsFragment;
private NotificationsListFragment allNotificationsFragment, mentionsFragment, postsFragment;
private String accountID;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
@@ -105,12 +104,13 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
pager=view.findViewById(R.id.pager);
UiUtils.reduceSwipeSensitivity(pager);
tabViews=new FrameLayout[2];
tabViews=new FrameLayout[3];
for(int i=0;i<tabViews.length;i++){
FrameLayout tabView=new FrameLayout(getActivity());
tabView.setId(switch(i){
case 0 -> R.id.notifications_all;
case 1 -> R.id.notifications_mentions;
case 2 -> R.id.notifications_posts;
default -> throw new IllegalStateException("Unexpected value: "+i);
});
tabView.setVisibility(View.GONE);
@@ -162,9 +162,15 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
mentionsFragment=new NotificationsListFragment();
mentionsFragment.setArguments(args);
args=new Bundle(args);
args.putBoolean("onlyPosts", true);
postsFragment=new NotificationsListFragment();
postsFragment.setArguments(args);
getChildFragmentManager().beginTransaction()
.add(R.id.notifications_all, allNotificationsFragment)
.add(R.id.notifications_mentions, mentionsFragment)
.add(R.id.notifications_posts, postsFragment)
.commit();
}
@@ -174,6 +180,7 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
tab.setText(switch(position){
case 0 -> R.string.all_notifications;
case 1 -> R.string.mentions;
case 2 -> R.string.posts;
default -> throw new IllegalStateException("Unexpected value: "+position);
});
tab.view.textView.setAllCaps(true);
@@ -224,21 +231,17 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
return switch(page){
case 0 -> allNotificationsFragment;
case 1 -> mentionsFragment;
case 2 -> postsFragment;
default -> throw new IllegalStateException("Unexpected value: "+page);
};
}
@Override
public void onProvideAssistContent(AssistContent assistContent) {
callFragmentToProvideAssistContent(getFragmentForPage(pager.getCurrentItem()), assistContent);
}
private class DiscoverPagerAdapter extends RecyclerView.Adapter<SimpleViewHolder>{
@NonNull
@Override
public SimpleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
FrameLayout view=tabViews[viewType];
if (view.getParent() != null) ((ViewGroup)view.getParent()).removeView(view);
((ViewGroup)view.getParent()).removeView(view);
view.setVisibility(View.VISIBLE);
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return new SimpleViewHolder(view);
@@ -249,7 +252,7 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
@Override
public int getItemCount(){
return 2;
return 3;
}
@Override

View File

@@ -1,7 +1,6 @@
package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
@@ -11,27 +10,19 @@ import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.markers.SaveMarkers;
import org.joinmastodon.android.api.requests.notifications.PleromaMarkNotificationsRead;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.AllNotificationsSeenEvent;
import org.joinmastodon.android.events.PollUpdatedEvent;
import org.joinmastodon.android.events.RemoveAccountPostsEvent;
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.CacheablePaginatedResponse;
import org.joinmastodon.android.model.Emoji;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Markers;
import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.model.PaginatedResponse;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.displayitems.AccountCardStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ImageStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.DiscoverInfoBannerHelper;
import org.joinmastodon.android.ui.utils.InsetStatusItemDecoration;
import org.joinmastodon.android.ui.utils.UiUtils;
@@ -48,6 +39,7 @@ import java.util.stream.Stream;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.utils.V;
public class NotificationsListFragment extends BaseStatusListFragment<Notification>{
private boolean onlyMentions;
@@ -55,11 +47,6 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
private String maxID;
private final DiscoverInfoBannerHelper bannerHelper = new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.POST_NOTIFICATIONS);
@Override
protected boolean wantsComposeButton() {
return false;
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
@@ -91,13 +78,6 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
protected List<StatusDisplayItem> buildDisplayItems(Notification n){
Account reportTarget = n.report == null ? null : n.report.targetAccount == null ? null :
n.report.targetAccount;
Emoji emoji = new Emoji();
if(n.emojiUrl!=null){
emoji.shortcode=n.emoji.substring(1,n.emoji.length()-1);
emoji.url=n.emojiUrl;
emoji.staticUrl=n.emojiUrl;
emoji.visibleInPicker=false;
}
String extraText=switch(n.type){
case FOLLOW -> getString(R.string.user_followed_you);
case FOLLOW_REQUEST -> getString(R.string.user_sent_follow_request);
@@ -108,12 +88,17 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
case UPDATE -> getString(R.string.sk_post_edited);
case SIGN_UP -> getString(R.string.sk_signed_up);
case REPORT -> getString(R.string.sk_reported);
case REACTION, PLEROMA_EMOJI_REACTION ->
n.emoji != null ? getString(R.string.sk_reacted_with, n.emoji) : getString(R.string.sk_reacted);
};
HeaderStatusDisplayItem titleItem=extraText!=null ? new HeaderStatusDisplayItem(n.id, n.account, n.createdAt, this, accountID, n.status, n.emojiUrl!=null ? HtmlParser.parseCustomEmoji(extraText, Collections.singletonList(emoji)) : extraText, n, null) : null;
HeaderStatusDisplayItem titleItem=extraText!=null ? new HeaderStatusDisplayItem(n.id, n.account, n.createdAt, this, accountID, n.status, extraText, n, null) : null;
if(n.status!=null){
ArrayList<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, n.status, accountID, n, knownAccounts, titleItem!=null, titleItem==null, n, false, Filter.FilterContext.NOTIFICATIONS);
ArrayList<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, n.status, accountID, n, knownAccounts, titleItem!=null, titleItem==null, n);
if(titleItem!=null){
for(StatusDisplayItem item:items){
if(item instanceof ImageStatusDisplayItem imgItem){
imgItem.horizontalInset=V.dp(32);
}
}
}
if(titleItem!=null)
items.add(0, titleItem);
return items;
@@ -136,8 +121,6 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
knownAccounts.put(s.account.id, s.account);
if(s.status!=null && !knownAccounts.containsKey(s.status.account.id))
knownAccounts.put(s.status.account.id, s.status.account);
if(s.status!=null && s.status.reblog!=null && !knownAccounts.containsKey(s.status.reblog.account.id))
knownAccounts.put(s.status.reblog.account.id, s.status.reblog.account);
}
@Override
@@ -146,7 +129,7 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
.getAccount(accountID).getCacheController()
.getNotifications(offset>0 ? maxID : null, count, onlyMentions, onlyPosts, refreshing, new SimpleCallback<>(this){
@Override
public void onSuccess(CacheablePaginatedResponse<List<Notification>> result){
public void onSuccess(PaginatedResponse<List<Notification>> result){
if (getActivity() == null) return;
if(refreshing)
relationships.clear();
@@ -158,17 +141,8 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
loadRelationships(needRelationships);
maxID=result.maxID;
Markers markers = AccountSessionManager.getInstance().getAccount(accountID).markers;
if(offset==0 && !result.items.isEmpty() && !result.isFromCache() && markers != null && markers.notifications != null){
E.post(new AllNotificationsSeenEvent());
if(offset==0 && !result.items.isEmpty()){
new SaveMarkers(null, result.items.get(0).id).exec(accountID);
AccountSessionManager.getInstance().getAccount(accountID).markers
.notifications.lastReadId = result.items.get(0).id;
AccountSessionManager.getInstance().writeAccountsFile();
if (isInstanceAkkoma()) {
new PleromaMarkNotificationsRead(result.items.get(0).id).exec(accountID);
}
}
}
});
@@ -195,10 +169,23 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
@Override
public void onItemClick(String id){
Notification n=getNotificationByID(id);
Bundle args = new Bundle();
if(n.status != null && n.status.inReplyToAccountId != null && knownAccounts.containsKey(n.status.inReplyToAccountId))
args.putParcelable("inReplyToAccount", Parcels.wrap(knownAccounts.get(n.status.inReplyToAccountId)));
UiUtils.showFragmentForNotification(getContext(), n, accountID, args);
if(n.status!=null){
Status status=n.status;
Bundle args=new Bundle();
args.putString("account", accountID);
args.putParcelable("status", Parcels.wrap(status));
if(status.inReplyToAccountId!=null && knownAccounts.containsKey(status.inReplyToAccountId))
args.putParcelable("inReplyToAccount", Parcels.wrap(knownAccounts.get(status.inReplyToAccountId)));
Nav.go(getActivity(), ThreadFragment.class, args);
}else if(n.report != null){
String domain = AccountSessionManager.getInstance().getAccount(accountID).domain;
UiUtils.launchWebBrowser(getActivity(), "https://"+domain+"/admin/reports/"+n.report.id);
}else{
Bundle args=new Bundle();
args.putString("account", accountID);
args.putParcelable("profileAccount", Parcels.wrap(n.account));
Nav.go(getActivity(), ProfileFragment.class, args);
}
}
@Override
@@ -230,32 +217,6 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
}
}
// copied from StatusListFragment.EventListener (just like the method above)
// (which assumes this.data to be a list of statuses...)
@Subscribe
public void onStatusCountersUpdated(StatusCountersUpdatedEvent ev){
for(Notification n:data){
if (n.status == null) continue;
if(n.status.getContentStatus().id.equals(ev.id)){
n.status.getContentStatus().update(ev);
for(int i=0;i<list.getChildCount();i++){
RecyclerView.ViewHolder holder=list.getChildViewHolder(list.getChildAt(i));
if(holder instanceof FooterStatusDisplayItem.Holder footer && footer.getItem().status==n.status.getContentStatus()){
footer.rebind();
}else if(holder instanceof ExtendedFooterStatusDisplayItem.Holder footer && footer.getItem().status==n.status.getContentStatus()){
footer.rebind();
}
}
}
}
for(Notification n:preloadedData){
if (n.status == null) continue;
if(n.status.getContentStatus().id.equals(ev.id)){
n.status.getContentStatus().update(ev);
}
}
}
@Subscribe
public void onRemoveAccountPostsEvent(RemoveAccountPostsEvent ev){
if(!ev.accountID.equals(accountID) || ev.isUnfollow)
@@ -288,11 +249,4 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
displayItems.subList(index, lastIndex).clear();
adapter.notifyItemRangeRemoved(index, lastIndex-index);
}
@Override
public Uri getWebUri(Uri.Builder base) {
return base.path(isInstanceAkkoma()
? "/users/" + getSession().self.username + "/interactions"
: "/notifications").build();
}
}
}

View File

@@ -15,12 +15,13 @@ import java.util.ArrayList;
import java.util.List;
public abstract class PinnableStatusListFragment extends StatusListFragment {
protected boolean pinnedUpdated;
protected List<TimelineDefinition> pinnedTimelines;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pinnedTimelines = new ArrayList<>(GlobalUserPreferences.pinnedTimelines.getOrDefault(accountID, TimelineDefinition.getDefaultTimelines(accountID)));
pinnedTimelines = new ArrayList<>(GlobalUserPreferences.pinnedTimelines.getOrDefault(accountID, TimelineDefinition.DEFAULT_TIMELINES));
}
@Override
@@ -53,7 +54,7 @@ public abstract class PinnableStatusListFragment extends StatusListFragment {
}
protected void togglePin(MenuItem pin) {
onPinnedUpdated(true);
pinnedUpdated = true;
getToolbar().performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
TimelineDefinition def = makeTimelineDefinition();
boolean pinned = isPinned();
@@ -65,5 +66,17 @@ public abstract class PinnableStatusListFragment extends StatusListFragment {
updatePinButton(pin);
}
public void onPinnedUpdated(boolean pinned) {}
protected Bundle getResultArgs() {
return new Bundle();
}
@Override
public void onDestroy() {
super.onDestroy();
Bundle resultArgs = getResultArgs();
if (pinnedUpdated) {
resultArgs.putBoolean("pinnedUpdated", true);
setResult(true, resultArgs);
}
}
}

View File

@@ -1,52 +0,0 @@
package org.joinmastodon.android.fragments;
import android.net.Uri;
import android.os.Bundle;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status;
import org.parceler.Parcels;
import java.util.List;
import me.grishka.appkit.api.SimpleCallback;
public class PinnedPostsListFragment extends StatusListFragment{
private Account account;
public PinnedPostsListFragment() {
setListLayoutId(R.layout.recycler_fragment_no_refresh);
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
account=Parcels.unwrap(getArguments().getParcelable("profileAccount"));
setTitle(R.string.posts);
loadData();
}
@Override
protected void doLoadData(int offset, int count){
new GetAccountStatuses(account.id, null, null, 100, GetAccountStatuses.Filter.PINNED)
.setCallback(new SimpleCallback<>(this){
@Override
public void onSuccess(List<Status> result){
onDataLoaded(result, false);
}
}).exec(accountID);
}
@Override
protected Filter.FilterContext getFilterContext() {
return Filter.FilterContext.ACCOUNT;
}
@Override
public Uri getWebUri(Uri.Builder base) {
return Uri.parse(account.url);
}
}

View File

@@ -1,5 +1,6 @@
package org.joinmastodon.android.fragments;
import android.app.Activity;
import android.app.Fragment;
import android.graphics.Canvas;
import android.graphics.Paint;
@@ -12,11 +13,23 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.SetPrivateNote;
import org.joinmastodon.android.model.AccountField;
import org.joinmastodon.android.model.Relationship;
import org.joinmastodon.android.ui.BetterItemAnimator;
import org.joinmastodon.android.ui.text.CustomEmojiSpan;
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
@@ -26,11 +39,8 @@ import org.joinmastodon.android.ui.views.LinkedTextView;
import java.util.Collections;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.WindowInsetsAwareFragment;
import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
@@ -46,6 +56,11 @@ public class ProfileAboutFragment extends Fragment implements WindowInsetsAwareF
private static final int MAX_FIELDS=4;
public UsableRecyclerView list;
public FrameLayout noteWrap;
public EditText noteEdit;
private String accountID;
private String profileAccountID;
private String note;
private List<AccountField> fields=Collections.emptyList();
private AboutAdapter adapter;
private Paint dividerPaint=new Paint();
@@ -64,11 +79,49 @@ public class ProfileAboutFragment extends Fragment implements WindowInsetsAwareF
adapter.notifyDataSetChanged();
}
public void setNote(String note, String accountID, String profileAccountID){
this.note=note;
this.accountID=accountID;
this.profileAccountID=profileAccountID;
// noteWrap.setVisibility(View.VISIBLE);
// noteEdit.setVisibility(View.VISIBLE);
// noteEdit.setText(note);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState){
list=new UsableRecyclerView(getActivity());
list.setId(R.id.list);
View view = inflater.inflate(R.layout.fragment_profile_about, null);
noteEdit = view.findViewById(R.id.note_edit);
noteWrap = view.findViewById(R.id.note_edit_wrap);
ImageButton noteEditConfirm = view.findViewById(R.id.note_edit_confirm);
noteEdit.setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
noteEditConfirm.setVisibility(View.VISIBLE);
noteEditConfirm.animate()
.alpha(1.0f)
.setDuration(700);
} else {
noteEditConfirm.animate()
.alpha(0.0f)
.setDuration(700);
noteEditConfirm.setVisibility(View.INVISIBLE);
}
});
noteEditConfirm.setOnClickListener((v -> {
if (!noteEdit.getText().toString().trim().equals(note)) {
savePrivateNote();
}
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(this.getView().getRootView().getWindowToken(), 0);
noteEdit.clearFocus();
}));
list = view.findViewById(R.id.list);
list.setItemAnimator(new BetterItemAnimator());
list.setDrawSelectorOnTop(true);
list.setLayoutManager(new LinearLayoutManager(getActivity()));
@@ -95,8 +148,20 @@ public class ProfileAboutFragment extends Fragment implements WindowInsetsAwareF
}
}
});
return list;
return view;
}
private void savePrivateNote(){
new SetPrivateNote(profileAccountID, noteEdit.getText().toString()).setCallback(new Callback<>() {
@Override
public void onSuccess(Relationship result) {}
@Override
public void onError(ErrorResponse result) {
Toast.makeText(getActivity(), getString(R.string.mo_personal_note_update_failed), Toast.LENGTH_LONG).show();
}
}).exec(accountID);
}
public void enterEditMode(List<AccountField> editableFields){
isInEditMode=true;
@@ -337,7 +402,7 @@ public class ProfileAboutFragment extends Fragment implements WindowInsetsAwareF
public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState){
super.onSelectedChanged(viewHolder, actionState);
if(actionState==ItemTouchHelper.ACTION_STATE_DRAG){
viewHolder.itemView.setTag(me.grishka.appkit.R.id.item_touch_helper_previous_elevation, viewHolder.itemView.getElevation()); // prevents the default behavior of changing elevation in onDraw()
viewHolder.itemView.setTag(R.id.item_touch_helper_previous_elevation, viewHolder.itemView.getElevation()); // prevents the default behavior of changing elevation in onDraw()
viewHolder.itemView.animate().translationZ(V.dp(1)).setDuration(200).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
draggedViewHolder=viewHolder;
}

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