Compare commits

..

885 Commits

Author SHA1 Message Date
Espasant3
7a71aad676 Translated using Weblate (Galician)
Currently translated at 37.5% (6 of 16 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/gl/
2023-02-07 23:08:41 +00:00
Espasant3
e34d4cf04c Translated using Weblate (Galician)
Currently translated at 100.0% (23 of 23 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/gl/
2023-02-07 23:08:41 +00:00
poesty
55b32111da Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (23 of 23 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/zh_Hans/
2023-02-07 23:08:41 +00:00
Andrewblasco
00b081b20b Translated using Weblate (Spanish)
Currently translated at 100.0% (23 of 23 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-02-07 23:08:41 +00:00
dontobi
8d08ff397a Translated using Weblate (German)
Currently translated at 100.0% (23 of 23 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/de/
2023-02-07 23:08:41 +00:00
LucasGGamerM
57a1c1b198 92 changelog 2023-02-07 20:03:23 -03:00
LucasGGamerM
6be2978857 Bump thy version number 2023-02-07 19:04:36 -03:00
LucasGGamerM
facde9ea15 Readding the posts notifications tab 2023-02-07 18:41:30 -03:00
LucasGGamerM
02e9c5f577 Fixing thy profile page 2023-02-07 18:32:46 -03:00
LucasGGamerM
d04b09f75f Making thy necessary adjustments for the thing to compile 2023-02-07 18:25:46 -03:00
LucasGGamerM
ec0f6edc41 Merge branch 'main'
# Conflicts:
#	mastodon/build.gradle
#	mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/SettingsFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/discover/LocalTimelineFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/onboarding/SignupFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/model/Status.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/PhotoStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/WarningFilteredStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java
#	mastodon/src/main/res/layout/display_item_footer.xml
#	mastodon/src/main/res/layout/fragment_profile.xml
#	mastodon/src/main/res/layout/recycler_fragment_with_fab.xml
#	mastodon/src/main/res/values/strings.xml
2023-02-07 18:09:13 -03:00
McKris
a900c79e2c Fixing duplicate stuff after merging 2023-02-07 16:11:51 -03:00
LucasGGamerM
97dbd3499f Merge branch 'master' of https://github.com/LucasGGamerM/moshidon 2023-02-07 16:05:09 -03:00
LucasGGamerM
f07e0906dd Merge branch 'main'
# Conflicts:
#	README.md
#	mastodon/build.gradle
#	mastodon/src/github/java/org/joinmastodon/android/updater/GithubSelfUpdaterImpl.java
#	mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java
#	mastodon/src/main/java/org/joinmastodon/android/MainActivity.java
#	mastodon/src/main/java/org/joinmastodon/android/PushNotificationReceiver.java
#	mastodon/src/main/java/org/joinmastodon/android/api/requests/notifications/DismissNotification.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/ComposeFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/HomeFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/PinnableStatusListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/ScheduledStatusListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/SettingsFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/StatusEditHistoryFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/StatusListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/discover/DiscoverFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/discover/LocalTimelineFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/discover/SearchFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/onboarding/AccountActivationFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/onboarding/CustomWelcomeFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/onboarding/InstanceRulesFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/onboarding/SignupFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/report/ReportAddPostsChoiceFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/model/TranslatedStatus.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/AccountSwitcherSheet.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/M3AlertDialogBuilder.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/LinkCardStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/PhotoStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/text/ClickableLinksDelegate.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/text/LinkSpan.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/utils/ColorPalette.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java
#	mastodon/src/main/java/org/joinmastodon/android/utils/StatusFilterPredicate.java
#	mastodon/src/main/res/color/button_bg_secondary_dark_on_light.xml
#	mastodon/src/main/res/color/button_text_primary_light_on_dark.xml
#	mastodon/src/main/res/drawable/ic_fluent_arrow_forward_24_regular.xml
#	mastodon/src/main/res/drawable/ic_fluent_arrow_repeat_all_24_very_filled.xml
#	mastodon/src/main/res/drawable/ic_fluent_chat_24_filled.xml
#	mastodon/src/main/res/drawable/ic_fluent_chat_multiple_24_regular_text.xml
#	mastodon/src/main/res/drawable/ic_fluent_eye_24_regular.xml
#	mastodon/src/main/res/drawable/ic_fluent_send_24_regular.xml
#	mastodon/src/main/res/drawable/ic_fluent_translate_24_regular.xml
#	mastodon/src/main/res/layout/compose_action.xml
#	mastodon/src/main/res/layout/display_item_footer.xml
#	mastodon/src/main/res/layout/fragment_compose.xml
#	mastodon/src/main/res/layout/fragment_profile.xml
#	mastodon/src/main/res/layout/header_welcome_custom.xml
#	mastodon/src/main/res/layout/item_list_header_simple.xml
#	mastodon/src/main/res/layout/item_settings_text.xml
#	mastodon/src/main/res/layout/item_settings_update.xml
#	mastodon/src/main/res/layout/item_text.xml
#	mastodon/src/main/res/layout/recycler_fragment_with_fab.xml
#	mastodon/src/main/res/menu/color_palettes.xml
#	mastodon/src/main/res/menu/post.xml
#	mastodon/src/main/res/menu/profile.xml
#	mastodon/src/main/res/menu/profile_own.xml
#	mastodon/src/main/res/values-fr-rFR/strings_sk.xml
#	mastodon/src/main/res/values-in-rID/strings_sk.xml
#	mastodon/src/main/res/values-pl-rPL/strings_sk.xml
#	mastodon/src/main/res/values-ru-rRU/strings_sk.xml
#	mastodon/src/main/res/values-uk-rUA/strings_sk.xml
#	mastodon/src/main/res/values-v31/colors.xml
#	mastodon/src/main/res/values/attrs.xml
#	mastodon/src/main/res/values/colors.xml
#	mastodon/src/main/res/values/ids.xml
#	mastodon/src/main/res/values/palettes.xml
#	mastodon/src/main/res/values/strings.xml
#	mastodon/src/main/res/values/strings_sk.xml
#	mastodon/src/main/res/values/styles.xml
#	metadata/ca/changelogs/50.txt
#	metadata/ca/changelogs/51.txt
#	metadata/ca/full_description.txt
#	metadata/de-DE/full_description.txt
#	metadata/en-US/changelogs/50.txt
#	metadata/en-US/changelogs/51.txt
#	metadata/en-US/changelogs/56.txt
#	metadata/en-US/full_description.txt
#	metadata/en-US/images/phoneScreenshots/1.jpg
#	metadata/en-US/images/phoneScreenshots/2.jpg
#	metadata/en-US/images/phoneScreenshots/3.jpg
#	metadata/en-US/images/phoneScreenshots/4.jpg
#	metadata/en-US/images/phoneScreenshots/5.jpg
#	metadata/en-US/images/phoneScreenshots/6.jpg
#	metadata/en-US/short_description.txt
#	metadata/en-US/title.txt
#	metadata/es/changelogs/50.txt
#	metadata/es/changelogs/51.txt
#	metadata/es/full_description.txt
#	metadata/fr-FR/full_description.txt
#	metadata/gl-ES/short_description.txt
#	metadata/gl-ES/title.txt
#	metadata/id/full_description.txt
#	metadata/nl-NL/short_description.txt
#	metadata/nl-NL/title.txt
#	metadata/pt-BR/full_description.txt
#	metadata/sl/short_description.txt
#	metadata/sl/title.txt
#	metadata/sv/full_description.txt
2023-02-07 16:04:28 -03:00
sk
8933c0647e bump version 2023-02-07 16:03:18 +01:00
sk
333c38c64d add alt badge to video/gifs
closes sk22#409
2023-02-07 15:44:40 +01:00
sk
ca5827e3f8 add null check
closes sk22#414
2023-02-07 15:29:56 +01:00
sk
4884667484 generify fab button
closes sk22#380
2023-02-07 14:10:31 +01:00
sk
a2f687898c fix wrong time in edited notifications
closes sk22#387
2023-02-07 13:34:52 +01:00
sk
defd038064 display roles in profile 2023-02-06 19:41:36 +01:00
sk
f88b65f479 add spectator mode
closes sk22#264
2023-02-06 18:16:41 +01:00
sk
f65d56361f support account filter context 2023-02-06 17:59:06 +01:00
sk
255155b55a fix filters not working in lists
closes sk22#379
2023-02-06 17:52:05 +01:00
sk
ee2e39462a remove broken auto-add user to created list 2023-02-06 17:24:05 +01:00
sk
32b459ae77 hide expand/collapse to screen reader 2023-02-06 16:54:54 +01:00
sk
c1b79da4a7 tweak profile fragment 2023-02-06 15:25:12 +01:00
sk
65dfd8667d realign post header buttons 2023-02-06 15:17:05 +01:00
sk
12558c3c18 handle saving draft when attachment not uploaded
closes sk22#402
2023-02-06 14:31:53 +01:00
sk
dae347a29f fix filtered crash in scheduled posts
closes sk22#408
2023-02-06 14:00:52 +01:00
sk
c51be5f199 add missing margin
closes sk22#407
2023-02-06 13:53:28 +01:00
sk
fc1bd14f70 tweak collapse button 2023-02-06 13:44:57 +01:00
sk
bd39ed3754 fix notifications crashing with collapse button
closes sk22#410
2023-02-06 13:26:56 +01:00
sk
50029c7f73 avoid null pointer when switching tabs
closes sk22#412
2023-02-06 13:16:17 +01:00
sk
e2c907eb10 don't hide collapse button 2023-02-06 11:04:38 +01:00
sk
937747e11b add collapse button to header 2023-02-06 10:42:27 +01:00
LucasGGamerM
e5ad2db1ad Merge pull request #79 from FineFindus/fix/compose-ui
fix(compose): remove marginEnd
2023-02-05 17:43:18 -03:00
FineFindus
3520ebafc9 fix(compose): remove marginEnd 2023-02-05 19:56:31 +01:00
LucasGGamerM
f7c85d7d53 Update README.md 2023-02-05 10:12:34 -03:00
LucasGGamerM
fb812d5d88 Update README.md 2023-02-05 10:11:40 -03:00
LucasGGamerM
fde44e61bc Revert "Now the filter context finally makes sense!"
This reverts commit 0ee99fa709.
2023-02-04 15:35:14 -03:00
LucasGGamerM
34e072a1b5 Revert "Fixing the last commit"
This reverts commit 0b9b51294e.
2023-02-04 15:35:14 -03:00
LucasGGamerM
fe244112d4 Revert "Now the filter context things are fixed."
This reverts commit 3fcf8818c0.
2023-02-04 15:35:13 -03:00
LucasGGamerM
3fcf8818c0 Now the filter context things are fixed. 2023-02-04 14:52:41 -03:00
LucasGGamerM
0b9b51294e Fixing the last commit 2023-02-04 14:50:30 -03:00
sk
85b6bc79a3 increase max text height 2023-02-04 14:21:14 +01:00
sk
ec9d41fbbd collapse long posts 2023-02-03 23:40:20 +01:00
sk
847d966daa only display warning when not already revealed 2023-02-03 23:08:04 +01:00
LucasGGamerM
2783806f97 Merge branch 'master' of https://github.com/LucasGGamerM/moshidon 2023-02-03 15:29:12 -03:00
LucasGGamerM
0ee99fa709 Now the filter context finally makes sense! 2023-02-03 15:24:36 -03:00
sk22
618840c76a Display filtered posts with a warning (#406)
* copy changes from @LucasGGamerM
* simplify building filter item
* fix adapter ranges
* change filter item styling

closes sk22#209 

Co-authored-by: LucasGGamerM <71328265+LucasGGamerM@users.noreply.github.com>
2023-02-03 18:33:15 +01:00
sk
33d856562d hide compose fab when editing 2023-02-03 16:54:51 +01:00
sk
9873e9ede5 fix text scaling height and margin issues 2023-02-03 16:24:30 +01:00
sk
63dad42bf3 auto-orientation counters alignment
closes sk22#381
2023-02-03 15:35:36 +01:00
sk
dad58f8245 hide tab bar when editing profile 2023-02-03 15:30:10 +01:00
sk
647a7d70cd rearrange profile items 2023-02-03 15:24:21 +01:00
sk
f49c7dff00 remove about tab 2023-02-03 15:07:15 +01:00
sk
72f638c96c move metadata to profile 2023-02-03 14:50:06 +01:00
LucasGGamerM
e223bdd2bd Merge remote-tracking branch 'weblate/master' 2023-02-02 16:26:54 -03:00
LucasGGamerM
c28a7d6029 Update README.md 2023-02-02 16:23:11 -03:00
LucasGGamerM
b814c7eab9 91 changelog 2023-02-02 16:08:56 -03:00
LucasGGamerM
ecfa255d75 Bump version number 2023-02-02 16:07:27 -03:00
LucasGGamerM
979977aec6 Removing som unused functions 2023-02-02 16:07:15 -03:00
LucasGGamerM
a487a45828 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (23 of 23 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/pt_BR/
(cherry picked from commit 43c82ed99b)
2023-02-02 16:05:38 -03:00
Andrewblasco
0afcf10c74 Translated using Weblate (Spanish)
Currently translated at 100.0% (16 of 16 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/es/
(cherry picked from commit 28302f3a4b)
2023-02-02 16:05:38 -03:00
LucasGGamerM
43c82ed99b Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (23 of 23 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/pt_BR/
2023-02-02 18:58:28 +00:00
Andrewblasco
28302f3a4b Translated using Weblate (Spanish)
Currently translated at 100.0% (16 of 16 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/es/
2023-02-02 18:54:05 +00:00
LucasGGamerM
d6ad1cbfbf Maybe adding filter contexts. Needs testing 2023-02-02 15:51:00 -03:00
LucasGGamerM
fd08a1f845 The auto updater is not brokey anymore :) 2023-02-02 15:40:32 -03:00
LucasGGamerM
67b2a82058 Maybe works? 2023-02-02 15:36:14 -03:00
LucasGGamerM
f7ab8bd27e Pulling better button from megalodon, thanks @sk22! 2023-02-02 15:20:34 -03:00
LucasGGamerM
5df8318200 Unbreak weird switch items thing 2023-02-02 15:13:20 -03:00
LucasGGamerM
0fcaa08ed0 Readding the pre-releases toggle, not in the self updater yet though 2023-02-02 15:11:25 -03:00
LucasGGamerM
2ce3167db0 Revert "implement pre-release toggle"
This reverts commit 430dd616
2023-02-02 15:05:18 -03:00
LucasGGamerM
2c8ecbd996 Reverting broken images 2023-02-02 15:01:39 -03:00
LucasGGamerM
90aa8c5762 Clicking on filtered items will show them like expected (It previously showed another warning when you clicked it) 2023-02-02 13:35:44 -03:00
LucasGGamerM
bb0ca63a03 Revert "Its now a much cleaner transition"
This reverts commit 562a5aae7d.
2023-02-02 13:18:14 -03:00
sk
35e0897869 move profile counters down 2023-02-02 15:46:26 +01:00
sk
e22cb07d63 Revert "enable selecting text via alt badge"
This reverts commit 14e639aa8a.
2023-02-02 13:41:49 +01:00
sk
c2df989217 fix width misalignment in header 2023-02-01 11:05:50 +01:00
sk
31d0bfb434 fix footer item hitbox sizes
closes sk22#389
2023-02-01 10:59:55 +01:00
sk
14e639aa8a enable selecting text via alt badge
re: sk22#400
2023-02-01 10:36:14 +01:00
sk
6c24e06157 change string 2023-02-01 10:30:31 +01:00
sk
53ce4276f6 Merge remote-tracking branch 'origin/main' 2023-02-01 10:25:43 +01:00
sk
423e919e16 fix crash 2023-02-01 10:25:24 +01:00
aetsucore
c6cd424f30 Prefix replies with "re:" (#385)
* Prefix replies with "re:"
* Use correct quotation marks
* Avoid repeating "re: " prefix when replying to a post that already has it
2023-01-31 10:30:36 +01:00
sk
e282d54f99 Merge remote-tracking branch 'upstream/master' 2023-01-31 00:00:56 +01:00
sk
29ad08f2ea fix crashes
closes sk22#393
closes sk22#394
2023-01-30 23:46:32 +01:00
Gregory K
5c2f72a706 Merge pull request #521 from FineFindus/fix/typos
fix: typos
2023-01-30 01:54:30 +03:00
Grishka
b153a64373 Signup flow redesign WIP 2023-01-30 01:54:13 +03:00
FineFindus
1124486f1f fix(Instance): typo langauges => languages 2023-01-26 20:56:15 +01:00
sk22
c757b1ffea Translated using Weblate (German)
Currently translated at 100.0% (14 of 14 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/de/
2023-01-26 15:52:46 +00:00
sk22
932655eeb6 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-26 15:52:46 +00:00
sk
21d57b25c9 bump version and update strings 2023-01-26 16:48:36 +01:00
sk
bed572f343 Merge remote-tracking branch 'weblate/main' 2023-01-26 16:43:13 +01:00
sk
c7483a6b20 update screenshots 2023-01-26 16:42:17 +01:00
sk
cdb1e26a4d move some settings around 2023-01-26 16:38:04 +01:00
Oliebol
ce1a450ccb 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-26 15:21:28 +00:00
gallegonovato
dfc244ff41 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-26 15:21:28 +00:00
gallegonovato
9c3e2f5deb 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-26 15:21:28 +00:00
gallegonovato
452b286352 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-26 15:21:28 +00:00
McKris
6deca645de 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-26 15:21:28 +00:00
ihor_ck
49fd1aba76 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-26 15:21:28 +00:00
tygyh
7bc951ba67 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-26 15:21:28 +00:00
Choukajohn
a70e73a8cb 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-26 15:21:28 +00:00
ihor_ck
cf345356a5 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-26 15:21:28 +00:00
tygyh
3da3967afa 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-26 15:21:28 +00:00
McKris
a12f09a38a 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-26 15:21:27 +00:00
rex07
a7302cc3e1 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-26 15:21:27 +00:00
rex07
9aed2a96dc Added translation using Weblate (Arabic) 2023-01-26 15:21:27 +00:00
Linerly
dbe49134e1 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-26 15:21:27 +00:00
Linerly
089d176704 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-26 15:21:27 +00:00
Espasant3
4e482ef6fa 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-26 15:21:27 +00:00
Espasant3
c64397a613 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-26 15:21:27 +00:00
sk
6c0d4778b7 separate notification toggle for polls 2023-01-26 16:18:19 +01:00
sk
b94c1f4a82 Merge branch 'fix-notify-policy-none' 2023-01-26 16:03:54 +01:00
sk
a29a072e53 unsubscribe from notifications when policy is none
re: mastodon#520
2023-01-26 15:48:10 +01:00
sk
4f435c6957 set disabled state if policy is none
re: mastodon#520
2023-01-26 15:47:30 +01:00
sk
2a6115f6d9 add server version to settings
closes sk22#376
2023-01-26 15:01:41 +01:00
sk
4cbc1e3664 use regular lock in boost menu
closes sk22#375
2023-01-26 14:58:01 +01:00
Choukajohn
1053d2ac0c 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-26 00:31:07 +00:00
sk22
0123b17602 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-26 00:31:06 +00:00
sk22
1dace6ead9 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-26 00:31:06 +00:00
sk22
3287cf69c1 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-26 00:31:06 +00:00
sk
a2854524a9 rename string 2023-01-26 01:13:01 +01:00
sk
71c06c0762 Merge remote-tracking branch 'weblate/main' 2023-01-26 01:09:43 +01:00
ihor_ck
e30df6067d 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-26 00:09:37 +00:00
edxkl
912a354b1c 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-26 00:09:36 +00:00
McKris
71f830ea82 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-26 00:09:36 +00:00
Linerly
bd109a9139 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-26 00:09:36 +00:00
Choukajohn
c82b4445ff 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-26 00:09:36 +00:00
irure
9a7d149dae 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-26 00:09:36 +00:00
sk
c66e576461 adapt upstream changes 2023-01-26 01:09:08 +01:00
sk
2a47d2fe77 update comment 2023-01-26 00:58:21 +01:00
sk
331d490f4f Merge remote-tracking branch 'upstream/master' 2023-01-26 00:56:48 +01:00
sk
8d722a2130 bump version, update changelog 2023-01-26 00:54:13 +01:00
sk
6863363452 change local-only string 2023-01-26 00:40:10 +01:00
sk
10e66a58eb fix visibility radio button 2023-01-26 00:39:02 +01:00
sk
3a5c27eadc change missing icons 2023-01-26 00:28:14 +01:00
sk
8c6bce4f73 enable boosting local posts 2023-01-26 00:07:50 +01:00
sk
17e1cd1fe9 replace visibility icons 2023-01-25 23:51:42 +01:00
sk
d7aceffc8f change list icon 2023-01-25 23:41:07 +01:00
Grishka
bcb3e217cd More onboarding updates 2023-01-26 01:38:29 +03:00
sk
229c19664c hopefully prevent some crashes 2023-01-25 23:23:43 +01:00
sk
8bdbb2adef dividers and alignments
nobody knows the trouble i've seen
2023-01-25 22:55:14 +01:00
HudobniVolk
907c5a2ca1 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-25 17:32:56 +00:00
HudobniVolk
2a2bfebf48 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-25 17:32:56 +00:00
edxkl
eba59549ec 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-25 17:32:56 +00:00
HudobniVolk
9478a71693 Translated using Weblate (Slovenian)
Currently translated at 15.3% (2 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/sl/
2023-01-25 17:32:56 +00:00
ghose
b01d7a417a 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-25 17:32:56 +00:00
ihor_ck
80c77292ed 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-25 17:32:56 +00:00
HudobniVolk
488e6dda04 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-25 17:32:56 +00:00
edxkl
689f676668 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-25 17:32:56 +00:00
gicorada
a06db9a3ab 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-25 17:32:56 +00:00
irure
a7283cbed8 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-25 17:32:56 +00:00
gallegonovato
bc70d5e212 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-25 17:32:56 +00:00
AiOO
441686740a 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-25 17:32:56 +00:00
LucasGGamerM
ac0df083f2 Added translation using Weblate (Portuguese) 2023-01-25 17:32:56 +00:00
Espasant3
e10762d5fa 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-25 17:32:56 +00:00
McKris
0ca4663c29 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-25 17:32:56 +00:00
edxkl
7efd9341b1 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-25 17:32:56 +00:00
McKris
3d8693b2bd 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-25 17:32:56 +00:00
Oliebol
a3b5f3c926 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-25 17:32:56 +00:00
gicorada
f9f4a1d1ef 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-25 17:32:56 +00:00
Linerly
dd536002d0 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-25 17:32:56 +00:00
ghose
4f8e381c84 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-25 17:32:56 +00:00
Choukajohn
3b6b212c9e 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-25 17:32:56 +00:00
gallegonovato
bf429ee263 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-25 17:32:55 +00:00
Espasant3
e7b1301b71 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-25 17:32:55 +00:00
ling0412
6726e9523c 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-25 17:32:55 +00:00
sk22
3ffcc7cef2 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-25 17:32:55 +00:00
edxkl
e6232f6d3b 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-25 17:32:55 +00:00
ihor_ck
5efc431192 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-25 17:32:55 +00:00
HudobniVolk
c3b75782b1 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-25 17:32:55 +00:00
edxkl
ec6f3f0cc3 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-25 17:32:55 +00:00
Linerly
136c3cfb4a 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-25 17:32:55 +00:00
Choukajohn
79d1dbd3b7 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-25 17:32:55 +00:00
ling0412
f2e1663c41 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-25 17:32:55 +00:00
Oliebol
5c73f37599 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-25 17:32:55 +00:00
sheepnik
7f239abf2f 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-25 17:32:55 +00:00
sheepnik
a07f7c232a 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-25 17:32:55 +00:00
McKris
4a60a5190f 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-25 17:32:55 +00:00
ling0412
69986fd869 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-25 17:32:55 +00:00
ihor_ck
e2ca572d45 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-25 17:32:55 +00:00
HudobniVolk
746e41fdbc 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-25 17:32:55 +00:00
McKris
091f1f1e8c 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-25 17:32:55 +00:00
Oliebol
844ec185a6 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-25 17:32:55 +00:00
Linerly
5622eaed83 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-25 17:32:55 +00:00
ghose
dbf25da1db 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-25 17:32:54 +00:00
Choukajohn
d35a416084 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-25 17:32:54 +00:00
ling0412
098acb85e4 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-25 17:32:54 +00:00
AiOO
9d67337913 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-25 17:32:54 +00:00
sk22
914861775a 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-25 17:32:54 +00:00
sk
c12a6eaee6 support admin notifications 2023-01-25 18:32:07 +01:00
sk
5de23581fe improve local visibility compatibility 2023-01-25 16:49:15 +01:00
sk
413141df1e fix null pointer exception 2023-01-25 16:24:54 +01:00
sk
5f48870a90 re-arrange settings 2023-01-25 15:52:41 +01:00
sk
86e781cdea tweak no alt indicator 2023-01-25 15:32:51 +01:00
sk
34ebd9219f fix alt indicator setting not saving 2023-01-25 15:19:30 +01:00
sk
41688c4670 update string 2023-01-25 12:54:50 +01:00
sk
0d30cd973e support akkoma local visibility 2023-01-25 12:54:35 +01:00
sk
5ed80ca40a Merge remote-tracking branch 'upstream/master' 2023-01-25 10:44:10 +01:00
sk
78958085c3 fix non-local-only posting (which i broke) 2023-01-25 10:33:04 +01:00
Grishka
a1798b6666 Update onboarding 2023-01-24 23:43:56 +03:00
sk
baa7dd6302 add missing import 2023-01-24 16:05:59 +01:00
sk
ba93e5bac3 bump version 2023-01-24 16:04:30 +01:00
sk
2358d3c602 implement local-only posting 2023-01-24 16:04:17 +01:00
sk
cf61626901 use notification icon 2023-01-24 12:41:23 +01:00
sk
349a1115a6 add indicator for direct and local-only posts 2023-01-24 12:40:23 +01:00
sk
8fa4980ba5 don't apply title for hashtags/lists
closes sk22#343
2023-01-24 11:20:14 +01:00
sk
099d0ccf94 no hashtag header in list timeline
closes sk22#366
2023-01-24 11:06:35 +01:00
sk
35a1de7888 add option to disable show new posts button 2023-01-24 10:53:11 +01:00
sk
6fc850b5ba tweak no alt indicator background 2023-01-24 10:08:03 +01:00
sk
96f13defd4 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-24 09:46:22 +01:00
sk
36dd07aa38 fix loading default visibility 2023-01-24 09:31:49 +01:00
sk
6a831539ad bump version, again 2023-01-24 09:31:16 +01:00
sk
c679f5529e add null check 2023-01-24 02:17:15 +01:00
sk
9c8096274a bump version 2023-01-24 01:28:49 +01:00
sk
7291b2da5a implement pre-release toggle 2023-01-24 01:27:17 +01:00
sk
4ff98140cb fix navigation bumpiness
closes sk22#347
2023-01-24 01:09:41 +01:00
sk
c2a993c5c1 don't override visibility when replying to self
closes sk22#348
2023-01-23 22:00:23 +01:00
sk
1b04440546 bigger hitbox for alt indicator
closes sk22#353
2023-01-23 20:13:01 +01:00
sk
c0c276f03e add indicator for missing alt texts
closes sk22#355
2023-01-23 19:21:21 +01:00
sk
d30b1f7bbd hide scheduling options when editing
closes sk22#364
2023-01-23 17:11:10 +01:00
sk
c0ee16cf08 fix current language getting overwritten 2023-01-23 16:57:56 +01:00
sk
a37fb33a68 prompt when saving edited draft
closes sk22#319
2023-01-23 16:11:09 +01:00
sk
59095e4ffe Merge remote-tracking branch 'upstream/master' 2023-01-23 15:32:32 +01:00
sk
626614c03d Merge branch 'improve-compose-toolbar-hitbox' 2023-01-23 15:32:02 +01:00
Gregory K
58ab0c0fc1 Merge pull request #516 from sk22/improve-compose-toolbar-hitbox
Bigger hitbox for items in compose toolbar
2023-01-23 17:17:20 +03:00
sk
32a8d38edf bigger hitbox for items in compose toolbar 2023-01-23 14:54:39 +01:00
sk
82534f7c4a change add media icon
closes sk22#351
2023-01-23 14:42:05 +01:00
sk
c6d7242043 display header for followed hashtags
closes sk22#323
2023-01-23 14:31:09 +01:00
sk
c4e23b0fe6 update hashtags/lists in home
closes sk22#312
2023-01-23 13:57:17 +01:00
Gregory K
a5c753a9f8 Merge pull request #515 from sk22/allow-notifications-toolbar-tab
Enable scrolling to top by tapping Notifications toolbar
2023-01-23 15:38:07 +03:00
sk
e3520df57e Merge branch 'allow-notifications-toolbar-tab' 2023-01-23 12:50:05 +01:00
sk
66cede567e enable scrolling to top via toolbar 2023-01-23 12:49:55 +01:00
sk
6916f435b3 improve search empty text 2023-01-23 12:41:10 +01:00
sk
dab0c560e9 fix crash when recycler view is null 2023-01-23 12:23:15 +01:00
sk
1b23ef31d5 improve header icons
* align more button to action overflow button
* use different background to better reflect hitbox
2023-01-23 12:14:05 +01:00
sk
dd7af8b5d3 use fluent more icon, correct padding
closes sk22#350
2023-01-23 11:43:19 +01:00
sk
5914ef8fad fix akkoma crash on list edit
closes sk22#352
2023-01-23 10:51:24 +01:00
sk
a26ddfe70f move edit timelines option 2023-01-23 10:25:44 +01:00
sk
cb067ca4fa clean up code 2023-01-23 10:21:19 +01:00
sk
3df9a3eecc probably fix options menu issue
closes sk22#360
2023-01-23 10:20:06 +01:00
sk
987cbc86ec fix wrong status bar color
closes sk22#363
2023-01-23 10:13:23 +01:00
sk
66dcaa9169 Merge remote-tracking branch 'origin/main' 2023-01-23 10:07:55 +01:00
sk
7162feea31 fix double-click icon button 2023-01-23 10:07:43 +01:00
sk22
1a51744807 Update blocks.tsv 2023-01-22 17:36:04 +01:00
sk22
f83a28a1b3 Adding a 12 hour option for polls (#346)
Co-authored-by: Pleclown <pleclown+github@gmail.com>

closes #346
2023-01-22 13:38:29 +01:00
sk
f5d4e2a0b5 Merge remote-tracking branch 'upstream/master' 2023-01-22 03:44:30 +01:00
sk
4aaf0c4fa4 Merge remote-tracking branch 'weblate/main' 2023-01-22 03:27:55 +01:00
sk22
38e133bee4 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-22 02:26:28 +00:00
sk
87bc01d985 remove add media string 2023-01-22 03:26:18 +01:00
sk
d5561674cd add a few icons 2023-01-22 03:15:07 +01:00
ihor_ck
48ec9e9fc6 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-22 02:11:57 +00:00
Linerly
63775c6eb9 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-22 02:11:57 +00:00
Choukajohn
79a61f6865 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-22 02:11:57 +00:00
florian-obernberger
5f7e03a562 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-22 02:11:57 +00:00
sheepnik
c93c4efe1d 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-22 02:11:57 +00:00
sheepnik
69771269fc 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-22 02:11:57 +00:00
gicorada
e7a28696c6 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-22 02:11:57 +00:00
sk
124ad1df06 add a few icons 2023-01-22 03:11:41 +01:00
sk
3a6ace53d5 add back file opener
closes sk22#328
2023-01-22 01:06:49 +01:00
sk
1e825c979c rearrange home menus 2023-01-22 00:43:17 +01:00
Grishka
c67b2b35f3 Fix #509 2023-01-22 02:08:55 +03:00
Grishka
8588ca8ae3 Fix #510 2023-01-22 02:05:36 +03:00
Grishka
7bb280e8b8 Fix #69 (nice) 2023-01-22 02:04:12 +03:00
sk
ad1e1b112b Merge remote-tracking branch 'upstream/master' 2023-01-21 23:14:35 +01:00
sk
29139a8f4d Revert "work around crash onHidden"
This reverts commit 763c5fe2a7.
2023-01-21 23:14:24 +01:00
Grishka
ddfeaabd44 Fix #512 2023-01-22 01:12:39 +03:00
Gregory K
51219bf98a Merge pull request #513 from sk22/fix-has-spoiler-restore
Fix wrong "hasSpoiler" value on restore
2023-01-22 01:11:42 +03:00
sk
335f734698 Merge branch 'fix-has-spoiler-restore' 2023-01-21 23:09:12 +01:00
sk
512cb70347 fix wrong "hasSpoiler" value on restore
closes sk22#324
2023-01-21 23:06:31 +01:00
sk
c7e0adfbd4 Merge remote-tracking branch 'weblate/main' 2023-01-21 22:50:26 +01:00
sk
ad7a9626a4 fix typo in string 2023-01-21 22:50:11 +01:00
sk
92f37fdf16 scroll image in alt text editor
closes sk22#315
2023-01-21 22:48:00 +01:00
sk
900e8fb2e9 notifications for edited posts
closes sk22#331
2023-01-21 22:06:00 +01:00
sk
be4b032527 fix redrafting empty posts
closes sk22#325
2023-01-21 21:48:33 +01:00
sk
95cb04530f add lists to status header 2023-01-21 21:39:11 +01:00
sk
4b6a0b71a0 restart app when pinned changes 2023-01-21 19:55:51 +01:00
sk
187190c07e update bug report template 2023-01-21 19:29:48 +01:00
sk
5142851f57 remove pivot for timeline title 2023-01-21 19:24:55 +01:00
sk
763c5fe2a7 work around crash onHidden
re: mastodon#512
2023-01-21 19:24:33 +01:00
sk
7f0265fe24 work around black screen opening notifs
closes sk22#342
2023-01-21 19:22:23 +01:00
sk
f87827700b different icon for post notifs 2023-01-21 16:17:53 +01:00
sk
fb2c0c0ec2 tweak alt button 2023-01-21 02:35:46 +01:00
sk
ec40488ed1 Merge remote-tracking branch 'upstream/master' 2023-01-21 02:25:44 +01:00
sk22
88851a085e 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-21 02:17:47 +01:00
Espasant3
87c743886e 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-19 12:53:13 +00:00
McKris
f3cde5441b 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-19 12:53:13 +00:00
ghose
7a9534772d 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-19 12:53:13 +00:00
Jippang
42faa62a5f 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-19 12:53:13 +00:00
Grishka
6e718d6765 Save last seen home timeline post via markers API 2023-01-18 20:29:49 +03:00
Grishka
b26d491eda remove log 2023-01-18 20:10:03 +03:00
Grishka
abdbab9d7b Allow viewing alt text on images
closes #100
2023-01-18 20:09:27 +03:00
Grishka
af1c7194e6 Workaround to fix #497 2023-01-18 18:41:48 +03:00
sk
8e507e7970 move post notifications into home
closes sk22#314
2023-01-18 12:29:33 +01:00
sk
3b542730b1 fix update item margin
closes sk22#308
2023-01-18 12:10:35 +01:00
sk
b038f81718 add alt text reminder
closes sk22#103
2023-01-18 12:08:40 +01:00
sk
e1206703cf disable translating scheduled posts
closes sk22#318
2023-01-18 11:39:49 +01:00
Espasant3
924affee14 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-18 08:32:08 +00:00
sheepnik
0c5da34cd6 Translated using Weblate (Welsh)
Currently translated at 62.4% (93 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/cy/
2023-01-18 08:32:08 +00:00
AiOO
b44e6b9f0a Translated using Weblate (Korean)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ko/
2023-01-18 08:32:08 +00:00
gallegonovato
9d3369f601 Translated using Weblate (Spanish)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/es/
2023-01-18 08:32:07 +00:00
edxkl
f607ed314d Translated using Weblate (Portuguese (Brazil))
Currently translated at 95.9% (143 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_BR/
2023-01-18 08:32:07 +00:00
McKris
2cdf642ca3 Translated using Weblate (Polish)
Currently translated at 95.9% (143 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2023-01-18 08:32:07 +00:00
Oliebol
5d278eb5aa Translated using Weblate (Dutch)
Currently translated at 97.9% (146 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/nl/
2023-01-18 08:32:07 +00:00
Espasant3
860c2826e3 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-18 08:32:07 +00:00
ghose
3060c36cca 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-18 08:32:07 +00:00
gallegonovato
a1b0632c75 Translated using Weblate (Spanish)
Currently translated at 100.0% (149 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-01-18 08:32:07 +00:00
ling0412
14cbb1107f Translated using Weblate (Chinese (Simplified))
Currently translated at 99.3% (148 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-01-18 08:32:07 +00:00
AiOO
dd5f352f5e 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-18 08:32:07 +00:00
ihor_ck
d148883ab2 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/uk/
2023-01-17 11:26:44 +00:00
Linerly
cfa93424cc Translated using Weblate (Indonesian)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/id/
2023-01-17 11:26:43 +00:00
ihor_ck
ff575f75c7 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (149 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-01-17 11:26:43 +00:00
itslameni
6fec7a5205 Translated using Weblate (Russian)
Currently translated at 81.2% (121 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2023-01-17 11:26:43 +00:00
Oliebol
0693495e12 Translated using Weblate (Dutch)
Currently translated at 97.9% (146 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/nl/
2023-01-17 11:26:43 +00:00
Linerly
04381d57f2 Translated using Weblate (Indonesian)
Currently translated at 100.0% (149 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-01-17 11:26:43 +00:00
ghose
9f4adcab23 Translated using Weblate (Galician)
Currently translated at 46.9% (70 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-01-17 11:26:43 +00:00
Choukajohn
00dba5981c Translated using Weblate (French)
Currently translated at 100.0% (149 of 149 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-01-17 11:26:43 +00:00
AiOO
ae838fe4d7 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-17 11:26:43 +00:00
sk
2110861f1b bump version 2023-01-17 02:20:27 +01:00
sk
4f6476c807 fix "0" reply to ID 2023-01-17 02:17:40 +01:00
sk22
eccfa27128 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-17 00:58:32 +00:00
sk22
460bce6174 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-17 00:57:46 +00:00
ling0412
d40790a85a 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-17 00:57:46 +00:00
sk22
75dc6fd019 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-17 00:57:46 +00:00
sk22
581e2056f7 Translated using Weblate (English)
Currently translated at 100.0% (13 of 13 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/en/
2023-01-17 00:57:46 +00:00
ihor_ck
70d5100419 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-17 00:57:46 +00:00
Linerly
0285d9620e 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-17 00:57:46 +00:00
Choukajohn
f6411052dd 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-17 00:57:46 +00:00
ling0412
ff21c0c103 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-17 00:57:46 +00:00
gicorada
443c18ce13 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-17 00:57:46 +00:00
ihor_ck
7380da88f9 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-17 00:57:46 +00:00
Oliebol
a7551ce9d9 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-17 00:57:46 +00:00
gicorada
dbb2c62702 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-17 00:57:46 +00:00
Choukajohn
eb2385afe4 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-17 00:57:46 +00:00
Nicolas_Horvath
6c63e7b833 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-17 00:57:46 +00:00
ca
d8eb1f280b 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-17 00:57:46 +00:00
ca
82a90d5486 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-17 00:57:46 +00:00
ca
78a3c43b06 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-17 00:57:46 +00:00
EifionLlwyd
54c23b2d05 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-17 00:57:46 +00:00
McKris
3fb350abe4 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-17 00:57:46 +00:00
gallegonovato
2e4bb98bb0 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/
2023-01-17 00:57:46 +00:00
ihor_ck
0d2d4dd1b2 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-17 00:57:46 +00:00
HudobniVolk
f8b1695c61 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-17 00:57:46 +00:00
edxkl
b456973c6a 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-17 00:57:46 +00:00
McKris
7c4616568b 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-17 00:57:46 +00:00
Linerly
1e93360778 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-17 00:57:46 +00:00
ghose
e7db1fcfc1 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-17 00:57:46 +00:00
Choukajohn
8be50e126b 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-17 00:57:46 +00:00
gallegonovato
a75611e707 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-17 00:57:45 +00:00
ling0412
1df643fc9a 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-17 00:57:45 +00:00
AiOO
1e730df767 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-17 00:57:45 +00:00
maxocito
f4c097704e 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-17 00:57:45 +00:00
ca
a86035a4ed 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-17 00:57:45 +00:00
Anonymous
5b57b4ca79 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-17 00:57:45 +00:00
Linerly
5e9dda72b5 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-17 00:57:45 +00:00
ghose
4121346794 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-17 00:57:45 +00:00
mondstern
3ce24f72d8 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-17 00:57:45 +00:00
NovaQ64
5ee81a6416 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-17 00:57:45 +00:00
EifionLlwyd
0fb7402094 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-17 00:57:45 +00:00
ihor_ck
4de4617cf5 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/
2023-01-17 00:57:45 +00:00
ihor_ck
bc3ace42f4 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-17 00:57:45 +00:00
brenno
7c9437b5d2 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-17 00:57:45 +00:00
Linerly
7d4b82f4ca 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-17 00:57:45 +00:00
Choukajohn
f7ea6fb0dd 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-17 00:57:45 +00:00
gallegonovato
afff61fe8c 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-17 00:57:45 +00:00
ling0412
d60c82b21c 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-17 00:57:45 +00:00
sk22
7c9107f229 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-17 00:57:45 +00:00
EifionLlwyd
40eb686418 Added translation using Weblate (Welsh) 2023-01-17 00:57:45 +00:00
irure
bf9f859827 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-17 00:57:45 +00:00
Hiajen
cd51bca670 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-17 00:57:45 +00:00
AiOO
2048a49f9b 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-17 00:57:45 +00:00
irure
ea00117844 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-17 00:57:45 +00:00
mondstern
f8df86ae6b 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-17 00:57:45 +00:00
edxkl
924f792f8b 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-17 00:57:45 +00:00
khant
02c9928a1f 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-17 00:57:45 +00:00
AiOO
0fec486ce0 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-17 00:57:45 +00:00
gallegonovato
c6c90d61b5 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/
2023-01-17 00:57:45 +00:00
HitaloM
9147b3b495 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-17 00:57:45 +00:00
ling0412
a9cca7f8db 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-17 00:57:45 +00:00
Choukajohn
e8e8eef42d 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/
2023-01-17 00:57:45 +00:00
khant
c1f31f3983 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-17 00:57:45 +00:00
ihor_ck
3df7123599 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-17 00:57:45 +00:00
edxkl
6dd4b202d9 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-17 00:57:45 +00:00
Linerly
71432fb87d 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-17 00:57:44 +00:00
Choukajohn
1a0a09ddae 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-17 00:57:44 +00:00
gallegonovato
94b0c8be08 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-17 00:57:44 +00:00
ling0412
5cb5f426d8 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-17 00:57:44 +00:00
AiOO
2b0b612191 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-17 00:57:44 +00:00
AiOO
6c4424bca4 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-17 00:57:44 +00:00
Linerly
b9e46339cd 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-17 00:57:44 +00:00
Choukajohn
ded00f84f1 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-17 00:57:44 +00:00
AiOO
79b74a1960 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-17 00:57:44 +00:00
itslameni
25e8febc44 Translated using Weblate (Russian)
Currently translated at 91.6% (11 of 12 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ru/
2023-01-17 00:57:44 +00:00
sk
6cc2885050 update changelog 2023-01-17 01:57:11 +01:00
sk
a68053f3a5 update readme and changelog 2023-01-17 01:47:10 +01:00
sk
deca8df309 bump version 2023-01-17 01:43:50 +01:00
sk
60edcfee1f add changelog to updater
thanks, @LucasGGamerM!
2023-01-17 01:26:08 +01:00
sk
eb1ab99262 fix null-pointer when switching themes 2023-01-17 00:44:55 +01:00
sk
e75d350b7a implement soft-blocking
sk22#297
2023-01-16 23:56:32 +01:00
sk
e9cfe3dee0 change search placeholder string 2023-01-16 22:09:10 +01:00
sk
753914ca5a fix akkoma link previews not showing
closes sk22#183
2023-01-16 22:06:20 +01:00
sk
93e3097993 fix images not loading on akkoma
closes sk22#25
2023-01-16 21:38:47 +01:00
sk
0916eddbb7 hide recent searches header
closes sk22#188
2023-01-16 21:20:31 +01:00
sk
a4848f001b double-tab search to open keyboard
closes sk22#119
2023-01-16 21:09:32 +01:00
sk
8952cd6f97 make announcements selectable
closes sk22#275
2023-01-16 20:23:38 +01:00
sk
4a3e6888d6 display unread announcements first
closes sk22#274
2023-01-16 19:46:44 +01:00
sk
b9bcb62cda tweak timeline title animation 2023-01-16 19:38:00 +01:00
sk
d3491b5753 include list title in delete prompt
closes sk22#304
2023-01-16 19:12:37 +01:00
sk
9e9f9357fd display image cache size
closes sk22#301
2023-01-16 19:06:40 +01:00
sk
ec525bde6d fix clearing notifications
closes sk22#292
2023-01-16 18:32:42 +01:00
sk
ee19410cc6 add missing draft params
closes sk22#302
2023-01-16 18:12:21 +01:00
sk
0468ae246e only show new posts button at home 2023-01-16 18:02:35 +01:00
sk
9722cd9e12 set pivot of timeline title
closes sk22#296
2023-01-16 18:00:43 +01:00
sk
85799a7d93 fix cut off text
closes sk22#295
2023-01-16 17:55:44 +01:00
sk
e222559bde remove debug statements 2023-01-16 17:29:27 +01:00
sk
2f3c7dc8f1 improve multi-line style 2023-01-16 17:28:33 +01:00
sk
d86588bbe2 don't cut off multi-line strings 2023-01-16 16:51:38 +01:00
sk
2bf787c8f2 fix new posts centered layout 2023-01-16 16:46:09 +01:00
sk
82ab8bef56 fix centering button in rtl 2023-01-16 16:15:35 +01:00
sk
cf024dc85f fix rtl direction 2023-01-16 15:50:17 +01:00
sk
ddebe1b3c0 restore current tab 2023-01-16 14:46:12 +01:00
sk
070e5637cc don't use old fragments 2023-01-16 14:46:03 +01:00
sk
bdd3c849e7 simplify method 2023-01-16 10:08:06 +01:00
sk
21073b11d0 don't require unused fields 2023-01-16 09:48:29 +01:00
sk
b4fa74b78f Merge remote-tracking branch 'upstream/master' 2023-01-16 09:39:29 +01:00
Gregory K
ab3a98fd60 Merge pull request #439 from Poussinou/patch-1
Update README.md
2023-01-15 22:15:30 +03:00
Grishka
6e6fdbccd5 Fix #484 2023-01-15 11:40:06 +03:00
Grishka
1764e5f3d1 Paginate trending posts 2023-01-15 11:09:53 +03:00
sk
1cc6bf4971 change crash workaround 2023-01-13 18:24:23 +01:00
sk
54200991cb Revert "work around crash theme switch"
This reverts commit 58fd0c444f30aa5352486b97cab34b2aca6ce8ab.
2023-01-13 18:18:39 +01:00
sk
6bea10bdac add pager title transition 2023-01-13 05:46:43 +01:00
sk
6c615a4893 don't use person icon for unblock
close #245
2023-01-13 04:52:35 +01:00
sk
3dc338b3a5 fix multiple notifications
close sk22#219
2023-01-13 04:50:51 +01:00
sk22
37278ff52b 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-13 04:35:48 +01:00
sk
17262ebdac Merge remote-tracking branch 'upstream/master' 2023-01-11 22:49:50 +01:00
Grishka
836c493951 Fix #499 2023-01-12 00:40:50 +03:00
sk
eb45874546 tweak list decoration
closes sk22#273
2023-01-11 14:46:09 +01:00
sk
f75520a1d8 fix edit user lists always visible
closes sk22#272
2023-01-11 14:44:26 +01:00
sk
b5392f0c2b Merge remote-tracking branch 'upstream/master' 2023-01-11 14:37:58 +01:00
Grishka
d667b8fa98 Fix #498 2023-01-11 13:06:40 +03:00
Gregory K
6a1032cd61 Merge pull request #492 from tylersaunders/mastodon-photopicker
Update ComposeFragment to use the photopicker.
2023-01-11 12:49:19 +03:00
sk
d72f8d3f9c disable more button when read
closes #262
2023-01-10 16:09:55 +01:00
sk
cd95a75f8f fix editing sensitive option
closes sk22#260
2023-01-10 15:54:08 +01:00
sk
e7bb393cee add more domains 2023-01-10 15:41:52 +01:00
sk
9b74373c22 improve domain check logic 2023-01-10 15:41:46 +01:00
LucasGGamerM
de0afdfa16 improve fab background color
thanks, @LucasGGamerM!
2023-01-10 15:26:19 +01:00
sk
480b3f1902 add missing icons to popup 2023-01-10 15:25:06 +01:00
sk
be73ca188d add dividers to lists 2023-01-10 15:05:06 +01:00
sk
d0ad55611d move lists and change icons 2023-01-10 14:26:46 +01:00
sk
d47797bf7a implement editing lists
re: sk22#30
2023-01-10 13:56:37 +01:00
sk
54c29fd787 implement deleting lists
re: sk22#30
2023-01-10 13:27:28 +01:00
sk
294595513a implement creating lists
re: sk22#30
2023-01-10 11:33:04 +01:00
sk
b8f101ead7 change lists string 2023-01-10 09:39:25 +01:00
sk
2614118d7d don't overwrite notifications
re: sk22#219
2023-01-10 09:38:28 +01:00
sk
cbcbaaa9fa add missing margin 2023-01-10 09:13:15 +01:00
FineFindus
7c6f6816b3 feat(settings): add about instance link (#263) 2023-01-10 09:13:02 +01:00
sk
3e3ed050ba bump version 2023-01-09 17:18:43 +01:00
sk
84179bc207 implement announcements
closes #127
2023-01-09 17:16:55 +01:00
sk
9dc795ded7 don't connect to fascists 2023-01-09 12:25:48 +01:00
sk
9c733d65b2 tweak header text margin 2023-01-09 11:24:02 +01:00
sk
4d49890b1e hide keyboard when navigating
closes #227
2023-01-09 11:15:14 +01:00
sk
f78c6978cf scale text according to system
closes #244
2023-01-09 11:11:00 +01:00
sk
b58a3d89e8 fix wrong pin icon
closes #230
2023-01-09 10:47:12 +01:00
sk
cd0cfba7c0 click "replying to" to scroll up
closes #241
2023-01-09 10:44:51 +01:00
sk
713c95d597 tweak reply animation
closes #237
2023-01-09 10:38:30 +01:00
sk
15534ad42e don't add subject if blank
closes #240
2023-01-09 10:30:49 +01:00
Thiago 'Jedi' Abreu
32bb3fac69 Filter all status, even if filters are empty (#255) 2023-01-09 10:23:14 +01:00
sk
e604da4ff4 Merge remote-tracking branch 'upstream/master' 2023-01-09 10:22:25 +01:00
Tyler Saunders
557d535e5a 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-03 17:21:22 +00:00
Gregory K
60517b00f3 Merge pull request #491 from mishnz/master
Second fix for MIME64 inconsistency in serverKey.
2023-01-02 14:23:23 +03:00
mishnz
faf5e8e82b Merge branch 'master' of https://github.com/mishnz/mastodon-android 2023-01-03 00:16:12 +13:00
mishnz
7264982761 serverKey assignment was missing, corrected. 2023-01-03 00:15:45 +13:00
mishnz
fedf74258f Merge branch 'mastodon:master' into master 2023-01-03 00:06:53 +13:00
mishnz
def4960be6 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-02 23:56:52 +13:00
Eugen Rochko
525cc69c70 Merge pull request #486 from mishnz/master
The Mastodon server does not currently use URL_SAFE encoding on its s…
2023-01-01 10:01:17 +01:00
mishnz
7ed1b164b5 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-01 18:50:09 +13:00
sk
0a9c31fb09 update changelog 2022-12-31 03:13:06 +01:00
sk
5ed6f97846 update changelog 2022-12-31 03:08:08 +01:00
sk
7dc195606c fix empty space when no text 2022-12-31 03:07:14 +01:00
sk
b2377a3353 tweak scroll height/timing 2022-12-31 02:54:33 +01:00
sk
0fdae0c775 Revert "match navigation bar color with toolbar"
This reverts commit 43d334259b.
2022-12-31 02:50:18 +01:00
sk
113bbd960f move settings items 2022-12-31 02:40:49 +01:00
sk
a48e09e77b bump version 2022-12-31 02:02:38 +01:00
sk
3c3f759d9a update readme 2022-12-31 02:02:00 +01:00
sk
5f0986d03b add option to reduce motion 2022-12-31 02:00:40 +01:00
sk
579794d7e0 peek original post before scrolling 2022-12-31 01:52:07 +01:00
sk
4956543eac update changelog 2022-12-31 01:37:39 +01:00
sk
87043f19bc Merge remote-tracking branch 'weblate/main' 2022-12-31 01:35:07 +01:00
sk
375f8ceb27 display original post when replying
closes sk22#193
2022-12-31 01:33:37 +01:00
sk
496ad6a442 change interact with strings 2022-12-30 23:08:04 +01:00
ihor_ck
83a09c4af2 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-30 21:54:40 +00:00
gallegonovato
fac6985d01 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-30 21:54:40 +00:00
Linerly
43670ba62b 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-30 21:54:40 +00:00
Choukajohn
ef511349f8 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-30 21:54:40 +00:00
ihor_ck
eea0199a21 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-30 21:54:40 +00:00
Linerly
7e0f02ecc7 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-30 21:54:40 +00:00
Choukajohn
7b26a65ea0 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-30 21:54:40 +00:00
gallegonovato
c5b92d7162 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-30 21:54:40 +00:00
bubblineyuri
f8387f0a81 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-30 21:54:40 +00:00
bubblineyuri
8486326b00 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-30 21:54:40 +00:00
edxkl
8f64747e75 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-30 21:54:40 +00:00
ihor_ck
f75efdaa03 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-30 21:54:40 +00:00
Linerly
ee8d9d0c07 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-30 21:54:40 +00:00
ling0412
6791adef46 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-30 21:54:40 +00:00
irure
80bcb84acf 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-30 21:54:40 +00:00
AiOO
7d6b0f9ca8 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-30 21:54:39 +00:00
nkufideal
594f6d4fc5 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-30 21:54:39 +00:00
nkufideal
e40acb9bf6 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-30 21:54:39 +00:00
itslameni
e372871108 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-30 21:54:39 +00:00
edxkl
1c01469a3e 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-30 21:54:39 +00:00
irure
90c2e45be2 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-30 21:54:39 +00:00
AiOO
1a783d4faf 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-30 21:54:39 +00:00
edxkl
d2944983a4 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-30 21:54:39 +00:00
ihor_ck
26459eecb0 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-30 21:54:39 +00:00
Linerly
90dea16222 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-30 21:54:39 +00:00
Choukajohn
8897a326b3 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-30 21:54:39 +00:00
gallegonovato
f3e69ddef1 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-30 21:54:39 +00:00
ling0412
8ecaa2c4d1 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-30 21:54:39 +00:00
sk
3a607a81f6 add compose fab to drafts list 2022-12-30 22:54:07 +01:00
sk
4b113e4a82 handle recursive compose/drafts list 2022-12-30 22:34:41 +01:00
sk
3e0e0c1484 move and refine scheduling and drafting 2022-12-30 21:48:59 +01:00
sk
676e166459 move compose action to layout file 2022-12-30 19:24:30 +01:00
sk
f0a704b93b schedule/draft in overflow menu 2022-12-29 20:24:37 +01:00
sk
cfc528df9a Merge remote-tracking branch 'origin/main' 2022-12-29 20:12:31 +01:00
sk
9231ea1446 offer to save when scheduledAt changed
closes sk22#218
2022-12-29 20:12:08 +01:00
sk22
f2f9138435 Update README.md 2022-12-29 18:39:32 +01:00
sk
624700497b update changelog 2022-12-29 18:28:24 +01:00
sk
5794a64da6 use rules fragment in settings 2022-12-29 18:27:37 +01:00
sk
7e6e9d3dcd move translation availability
closes sk22#213
2022-12-29 18:14:26 +01:00
sk
07634edfa3 don't finish compose fragment 2022-12-29 18:14:00 +01:00
sk
4a03fbfbf0 update changelog, bump version 2022-12-29 18:01:50 +01:00
sk
000cdb08ec change fab styles
closes sk22#211
2022-12-29 18:01:22 +01:00
sk
e0521b3c95 add mention with quasi-quoting 2022-12-29 17:14:38 +01:00
sk22
9547be89e1 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-29 16:53:18 +01:00
sk
40d44269fc Merge branch 'main' of github.com:sk22/megalodon 2022-12-29 16:46:14 +01:00
sk
3bf0903453 fix toolbar inset not applying in true black 2022-12-29 16:46:10 +01:00
Thiago 'Jedi' Abreu
c3abf8c05c Better handling of filter expiration date (#212)
* Better handling of filter expiration date
* Simplify Thread and Home Timeline filtering
2022-12-29 13:32:22 +01:00
Thiago 'Jedi' Abreu
6220ce6780 Implement 4.0 filters with hide action (#202)
* adding new "filtered" field for status
* respect "hide" filter action on status
* handling expire date for filter

closes #161
2022-12-28 14:49:45 +01:00
sk
6107698a76 optionally forward report
closes #205
2022-12-28 14:45:20 +01:00
sk
a3c3fec9b4 add icon indicating the existence of replies
closes #207
2022-12-28 14:13:49 +01:00
sk
f3a9b19104 replace mute icon 2022-12-28 01:58:44 +01:00
sk
d9ed6f600b change animation duration 2022-12-28 01:39:06 +01:00
sk
8a6d86727c remove unused menu item 2022-12-28 01:35:53 +01:00
sk
d9abf82918 fix null pointer on loading profile 2022-12-28 01:35:04 +01:00
sk
3cd9020ee0 use short usernames in popup menus
improves upon mastodon#148
2022-12-28 00:58:57 +01:00
sk
6d22a4d014 icons. icons everywhere 2022-12-28 00:53:06 +01:00
sk
ccad5d40ec fix akkoma crash on edit 2022-12-27 22:00:19 +01:00
ihor_ck
5b7b022d9f 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-27 20:46:35 +00:00
Andrewblasco
387139b5d3 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-27 20:46:35 +00:00
edxkl
0ae10d5fbe 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-27 20:46:35 +00:00
ihor_ck
d53397d8f8 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-27 20:46:35 +00:00
sk
b1006d2a14 rename string 2022-12-27 21:46:21 +01:00
sk
c5cf318cdd Merge remote-tracking branch 'weblate/main' 2022-12-27 21:45:01 +01:00
sk
671338c16a different icon for delete notifs setting 2022-12-27 21:41:08 +01:00
sk
bbaa70e396 add option to use uniform notif icon 2022-12-27 21:39:41 +01:00
sk
536d6cf63e revert broken color attribute for notif icon
closes #190
2022-12-27 21:30:35 +01:00
sk
b564a297ab fix #200 2022-12-27 21:20:20 +01:00
sk
6d34ae1a50 long-click to compose from other account 2022-12-27 21:02:05 +01:00
sk
0d2457f39e restore accidentally deleted functionality 2022-12-27 20:43:29 +01:00
sk
420505328c fix default visibility crashing akkoma session
closes #196
2022-12-27 20:36:06 +01:00
sk
0e60d71006 refine long-clicks
and disable long-click for multiple accounts when logged in to single account
2022-12-27 20:30:58 +01:00
sk
0f1456819b interact as other accounts
closes #199
2022-12-27 19:53:01 +01:00
sk
3af89a6175 update readme 2022-12-27 13:32:23 +01:00
gallegonovato
2fac871493 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-26 09:34:47 +00:00
Pointifurry
0166133b61 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-26 09:34:46 +00:00
Linerly
a9e0911796 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-26 09:34:46 +00:00
ling0412
213f341257 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-26 09:34:46 +00:00
Choukajohn
01cc2a2c67 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-26 09:34:46 +00:00
nitrogenez
6c7a040c02 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-26 09:34:46 +00:00
itslameni
4e40944b26 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-26 09:34:46 +00:00
goliv
af859438b4 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-26 09:34:46 +00:00
Linerly
7ef80e87b8 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-26 09:34:45 +00:00
Choukajohn
f8e873cd78 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-26 09:34:45 +00:00
Pointifurry
5cc97f7cf1 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-26 09:34:45 +00:00
ling0412
44c56331fd 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-26 09:34:45 +00:00
sk22
1272c3962e 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-26 09:34:45 +00:00
sk
e2799fcdff fix metadata markdown 2022-12-23 23:58:59 +01:00
sk
8e4f402e21 update changelogs 2022-12-23 23:48:21 +01:00
sk
10d2949647 remove unused method 2022-12-23 23:43:19 +01:00
sk
30ef23308b bump version 2022-12-23 23:41:46 +01:00
sk
564132ee82 update changelog 2022-12-23 23:40:50 +01:00
sk
1e527e87df fix default reblog visibility 2022-12-23 23:39:51 +01:00
sk
9692a04275 Merge remote-tracking branch 'weblate/main' 2022-12-23 23:36:48 +01:00
Linerly
6ece8eb0c1 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-23 22:18:14 +00:00
Choukajohn
1f33237e8a 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-23 22:18:14 +00:00
Linerly
9209508aac 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-23 22:18:14 +00:00
Choukajohn
f750e6ff7e 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-23 22:18:14 +00:00
sk
f2eecf774b disable block domain from post 2022-12-23 22:59:06 +01:00
sk
98de4e75e0 implement open with other account as submenu 2022-12-23 22:56:18 +01:00
sk
459e32caf8 fix instance info v2 never getting saved 2022-12-23 21:49:21 +01:00
sk
c4ad325e5c improve settings items 2022-12-23 21:35:16 +01:00
sk
f55bd6d6cd truncate publish button 2022-12-23 21:16:36 +01:00
sk
f1ce700c93 add option to open post with other account
closes #182
2022-12-23 21:11:22 +01:00
nitrogenez
c18e1e8456 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-23 19:22:28 +00:00
ling0412
1fcd1924c3 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-23 19:22:28 +00:00
Choukajohn
a1767f0425 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-23 19:22:28 +00:00
nitrogenez
44d95ca25f 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-23 19:22:28 +00:00
Linerly
7432540c29 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-23 19:22:28 +00:00
Choukajohn
c289f58351 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-23 19:22:28 +00:00
gallegonovato
711e041ff5 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-23 19:22:28 +00:00
ling0412
0ac3534585 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-23 19:22:27 +00:00
benjaminwolkchen
57821e0860 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-23 19:22:27 +00:00
sk
0dae798c9a add option to open post with other account
closes #182
2022-12-23 20:17:54 +01:00
sk
732e780fd9 Merge remote-tracking branch 'weblate/main' 2022-12-23 18:54:20 +01:00
sk
5577124b7a use popup background color for dialogs 2022-12-23 18:38:16 +01:00
sk
81b82c75a2 add copy link item and change copyText
use haptic feedback instead of vibrator
2022-12-23 18:10:08 +01:00
sk
b32e322749 implement long-click to copy links
closes sk22#84
2022-12-23 17:51:06 +01:00
sk
3031cc4561 remove selectable background for username
closes sk22#187
2022-12-23 17:22:17 +01:00
sk
d60abc648c only show boost visibility for own posts 2022-12-23 17:11:29 +01:00
sk
a9a0233bb3 Merge branch 'clickable-boost-reply-line' 2022-12-23 16:52:04 +01:00
sk
f6fa9e5122 remove selectable background 2022-12-23 16:51:13 +01:00
sk
29b4f7c91a update changelog 2022-12-22 16:51:50 +01:00
sk
0a9ee57233 implement followed hashtags list
closes sk22/megalodon#162
2022-12-22 16:51:43 +01:00
AiOO
94b69a9c1c 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-22 14:59:36 +00:00
gallegonovato
f0209dd1cc 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-22 14:59:36 +00:00
Linerly
366e432c18 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-22 14:59:36 +00:00
Christian Elbrianno
0075c0e779 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-22 14:59:36 +00:00
Linerly
d99dfd4185 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-22 14:59:36 +00:00
Choukajohn
0309b3ad25 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-22 14:59:36 +00:00
gallegonovato
7a85532b73 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-22 14:59:36 +00:00
AiOO
7299d947f7 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-22 14:59:35 +00:00
braydofficial
adec7b28f1 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-22 14:59:35 +00:00
sk
c2563da056 Merge branch 'feature/open-urls-in-app' 2022-12-22 15:35:53 +01:00
sk
64b9e53916 add missing fedi url format 2022-12-22 15:35:26 +01:00
sk
86ab6f7b3d implement setting boost visibility 2022-12-22 15:03:42 +01:00
sk
ed02733524 disable boost button if disabled
closes #180
2022-12-22 11:27:24 +01:00
sk
a99af63f34 Merge branch 'feature/open-urls-in-app' 2022-12-22 11:14:03 +01:00
sk
1d900a66fe try to open link previews in app 2022-12-22 11:13:50 +01:00
sk
f29acc217d update changelog 2022-12-22 01:37:52 +01:00
sk
f60164f5c5 bump version 2022-12-22 01:30:41 +01:00
sk
578cf1f00d update readme 2022-12-22 01:29:28 +01:00
sk
bca3bc6b4a Merge branch 'feature/more-html-tags' 2022-12-22 01:28:21 +01:00
sk
352c813544 smaller space between paragraphs 2022-12-22 01:27:55 +01:00
sk
7d876bddc7 preserve whitespaces in html 2022-12-22 01:25:43 +01:00
sk
43d334259b match navigation bar color with toolbar 2022-12-22 01:09:46 +01:00
sk
750579b1c2 use color attributes instead of fixed colors 2022-12-22 00:57:12 +01:00
sk
d69221d85b fix media upload colors 2022-12-22 00:50:23 +01:00
sk
a1c80e92cd reset state on boost long click 2022-12-22 00:47:44 +01:00
sk
ce1a0d66f1 update changelog 2022-12-22 00:14:59 +01:00
sk
f28057d620 update changelog 2022-12-22 00:08:37 +01:00
sk
8f6dc7e6d2 update changelog 2022-12-22 00:05:19 +01:00
sk
b25a237c20 add long-click to "quote" 2022-12-22 00:01:51 +01:00
sk
ccb0b59e17 Merge branch 'feature/open-urls-in-app' 2022-12-21 23:50:14 +01:00
sk
14658a2d70 only perform fedi lookup if looks like fedi url 2022-12-21 23:45:27 +01:00
sk
5f26878c06 resolve fediverse links in app
closes sk22#177
closes sk22#96
2022-12-21 23:29:16 +01:00
sk
df78ae59fe Merge remote-tracking branch 'weblate/main' 2022-12-21 22:39:19 +01:00
Choukajohn
47924dfb61 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-21 21:37:59 +00:00
Choukajohn
3eb442e0f6 Translated using Weblate (French)
Currently translated at 100.0% (82 of 82 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-21 21:37:59 +00:00
sk
b309fc09f6 tweak item header and notification deletion 2022-12-21 22:37:30 +01:00
gallegonovato
a00fe0485b 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-21 19:21:44 +00:00
sk22
a60f65857b Translated using Weblate (Spanish)
Currently translated at 98.7% (81 of 82 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-21 19:21:44 +00:00
gallegonovato
fe584b58b0 Translated using Weblate (Spanish)
Currently translated at 98.7% (81 of 82 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-21 19:21:44 +00:00
sk22
91ad2bf66b Translated using Weblate (German)
Currently translated at 100.0% (82 of 82 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-21 19:21:44 +00:00
sk22
01988a9435 Translated using Weblate (English)
Currently translated at 100.0% (82 of 82 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/en/
2022-12-21 19:21:44 +00:00
sk
51bc8e1b2c use instance domain if title blank 2022-12-21 19:57:31 +01:00
sk
b28c684bd3 fix missing text in notification 2022-12-21 19:54:15 +01:00
sk
42b2cde1e2 use UiUtils.getThemeColor 2022-12-21 19:48:44 +01:00
sk
199a7b816c Merge remote-tracking branch 'weblate/main' 2022-12-21 18:20:08 +01:00
sk22
2b8fc6764e Translated using Weblate (German)
Currently translated at 100.0% (80 of 80 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-21 17:18:57 +00:00
sk22
37f93cda4d Translated using Weblate (English)
Currently translated at 100.0% (80 of 80 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/en/
2022-12-21 17:18:57 +00:00
sk
4114f5b3c2 update changelog 2022-12-21 18:18:03 +01:00
Florian Obernberger
14d45eb759 Custom icons for different types of notifications (#178)
* Add filled variant of the person_add icon
* Add mention icon
* Add custom icons for different notification types

Co-authored-by: sk22 <sk22@mailbox.org>
2022-12-21 18:13:08 +01:00
sk
0dfa9d2c2c Merge branch 'use-fluent-mention-icon' 2022-12-21 18:09:41 +01:00
sk
6fce18ffe8 replace custom symbol with fluent mention symbol 2022-12-21 17:59:38 +01:00
sk
956c56c494 add translation availability info text 2022-12-21 17:54:28 +01:00
gallegonovato
75e7c6a9eb 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-21 16:18:19 +00:00
Choukajohn
a7fb66d269 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-21 16:18:19 +00:00
Choukajohn
5f48802357 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-21 16:18:19 +00:00
gallegonovato
a27488c8da 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-21 16:18:19 +00:00
sk
b6dbd7512c no ellipsis for settings items 2022-12-21 16:37:40 +01:00
sk
e41386082c add toggle for hiding translate button 2022-12-21 16:35:47 +01:00
sk
ae385c139b animate translate button opacity 2022-12-21 16:23:09 +01:00
LucasGGamerM
dd2f213a4f lower opacity of button while translating 2022-12-21 16:18:28 +01:00
sk
35f92a6e91 fix icons not showing in RTL layout 2022-12-21 16:12:03 +01:00
sk
ab5648a5d6 make toot button customizable 2022-12-21 16:07:47 +01:00
sk
8a9b59c66a generalize color picker settings item 2022-12-21 14:49:38 +01:00
sk
a6e0c877b5 use heart for donation link 2022-12-21 14:36:23 +01:00
sk
de5a623a00 update changelog 2022-12-21 14:34:27 +01:00
sk
b0f9ce081f implement deleting notifications 2022-12-21 14:25:19 +01:00
sk
e17b6e83a4 new light grays 2022-12-21 11:40:07 +01:00
sk
96f4322f74 reuse old brownish gray and move colors 2022-12-21 10:45:40 +01:00
sk
780f59d666 new grays 2022-12-21 10:19:59 +01:00
sk
8c5db2eef5 Merge remote-tracking branch 'upstream/master' 2022-12-21 09:41:29 +01:00
sk
5ab004b87e fix wrong default visibility in popup
closes sk22#174
2022-12-21 09:41:03 +01:00
sk
1b001bdd4f Merge branch 'fix-wrong-visibility-on-edit' 2022-12-21 09:29:57 +01:00
Gregory K
a5fa44213d Merge pull request #474 from sk22/fix-wrong-visibility-on-edit
Only load default status visibility if not editing
2022-12-21 11:25:14 +03:00
sk
68e9d9d91c only load default visibility if not editing
fix mastodon#306
2022-12-21 09:24:09 +01:00
sk
a14783a275 fix action bar buttons color
closes sk22#175
2022-12-21 09:14:36 +01:00
sk
3ce58d2edf move button text/background to styles 2022-12-20 16:06:28 +01:00
sk
523efac4fb make separator color brighter
closes #159
2022-12-20 15:51:00 +01:00
sk
d352aca9cc add toolbar background color 2022-12-20 15:44:37 +01:00
sk
ae6afab01b Merge branch 'feature/animate-buttons' 2022-12-20 15:19:02 +01:00
sk
efea405b83 fire counter updated event for content status
see mastodon#467
closes sk22#173
2022-12-20 15:17:43 +01:00
sk
ad9262cf0f fix counter updates for preloaded data
re: mastodon#467
see fb5289372d
2022-12-20 14:58:27 +01:00
sk
636c268e46 add drag to open to visibility button 2022-12-20 12:58:18 +01:00
sk
06a61f0374 update fastlane descriptions 2022-12-20 12:50:47 +01:00
sk
4ba7763de5 fix fastlane configs 2022-12-20 12:49:01 +01:00
sk
b486542e7b update strings 2022-12-20 12:43:56 +01:00
sk22
f53ce6cbf0 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 11:34:43 +00:00
AiOO
b10ff655f1 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 11:34:43 +00:00
jonta
bbc27dbeea 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 11:34:43 +00:00
jonta
dadb929afd 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 11:34:43 +00:00
gallegonovato
c0f397cdd5 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 11:34:43 +00:00
itslameni
b597cf6e18 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 11:34:43 +00:00
Linerly
e3bbeb2022 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 11:34:43 +00:00
Radiquum
cad9fc8977 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 11:34:43 +00:00
Linerly
2f191c1f71 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 11:34:43 +00:00
Choukajohn
dc0debce1a 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 11:34:43 +00:00
AiOO
d96b6f0100 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 11:34:42 +00:00
sk
16f1901976 update strings 2022-12-20 12:34:32 +01:00
sk
61d9e4d531 update german 2022-12-20 12:25:59 +01:00
sk
aec4479e19 rename color theme to color palette 2022-12-20 12:23:59 +01:00
sk
ec7235c03a add settings links
closes #163
2022-12-20 12:12:45 +01:00
sk
f3db153ea9 check if server supports translation earlier
closes #172
2022-12-20 11:19:50 +01:00
sk
e1c258478f fix italian 2022-12-20 10:38:54 +01:00
sk
1f2e691eb1 Merge remote-tracking branch 'upstream/master' 2022-12-20 10:27:54 +01:00
sk
be9a3a9975 fix error in readme 2022-12-20 10:27:11 +01:00
sk
8d17ac6f28 simplify themes 2022-12-20 10:26:03 +01:00
Grishka
d9df150cf8 Fix #472 2022-12-20 12:14:56 +03:00
sk
667a4aab1a Merge branch 'main' of github.com:sk22/megalodon 2022-12-19 19:06:04 +01:00
sk
862ffd8172 Merge remote-tracking branch 'upstream/master' 2022-12-19 19:05:36 +01:00
sk
eb1dd954ee merge miui fix for copying text 2022-12-19 19:03:11 +01:00
Grishka
6f2e5a63d7 This is officially the first Xiaomi workaround in this app 🎉
#469
2022-12-19 20:27:56 +03:00
sk
5bf78c5cd2 use primary color for update notification
closes #169
2022-12-19 18:27:03 +01:00
LucasGGamerM
277361a562 merge moshidon's red theme
closes sk22#160
2022-12-19 17:58:16 +01:00
sk
6697d3d0d5 update changelog 2022-12-19 16:38:00 +01:00
sk
7202aae712 Merge branch 'feature/animate-buttons' 2022-12-19 16:34:25 +01:00
sk
6d2c6748f7 set pivot point once 2022-12-19 16:34:16 +01:00
sk
6c98c9ccf2 fix broken long click 2022-12-19 16:33:30 +01:00
sk
afc25ec8b3 Merge branch 'feature/animate-buttons' 2022-12-19 16:06:24 +01:00
sk
6c9553ba65 tweak animations 2022-12-19 16:05:30 +01:00
sk
0fd5ea4689 fix counter updates for preloaded data
re: mastodon#467
see fb5289372d
2022-12-19 16:00:46 +01:00
sk
8441208058 fix bug in bookmark button
closes #167
2022-12-19 15:59:15 +01:00
sk
aa34298771 Merge branch 'feature/animate-buttons' 2022-12-19 15:43:18 +01:00
sk
ccacd88f80 tweak animations 2022-12-19 15:42:32 +01:00
sk
1f20b21fc8 add option to disable swiping
closes sk22#165
2022-12-19 15:31:38 +01:00
sk
ae7152aca7 Merge branch 'feature/long-press-copy-url' 2022-12-19 15:15:03 +01:00
sk
ba36347f03 copy post URL on long click 2022-12-19 15:14:54 +01:00
sk
c0c5e83f31 move copy text to UiUtils 2022-12-19 15:12:37 +01:00
sk
9c05ff2f7c restore toast message for android 13+ 2022-12-19 15:08:13 +01:00
sk
0ada05bf3a add vibration when copying username 2022-12-19 15:06:17 +01:00
sk
c77b5dfac2 bump version 2022-12-17 23:28:56 +01:00
sk
673ea40238 hide material you theme for older versions 2022-12-17 23:22:51 +01:00
sk
f7ced7f253 Merge branch 'feature/animate-buttons' 2022-12-17 23:19:42 +01:00
sk
6152ec9d0d tweak scaling while animating buttons 2022-12-17 23:19:36 +01:00
sk
7ed8bb259d Merge branch 'feature/animate-buttons' 2022-12-17 23:12:16 +01:00
sk
06882d5bea change button animations 2022-12-17 23:07:36 +01:00
sk
f460456502 add missing night variant for red 2022-12-17 22:30:15 +01:00
sk
6ef9f2ff15 update changelog 2022-12-17 22:08:39 +01:00
sk
062af9937f update changelog 2022-12-17 21:59:22 +01:00
sk
452ee8e1a5 update readme, bump version 2022-12-17 21:49:23 +01:00
sk
88c62427aa Merge remote-tracking branch 'weblate/main' 2022-12-17 21:46:52 +01:00
gallegonovato
09458c5ecb 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-17 20:46:15 +00:00
Choukajohn
4171a5d210 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-17 20:46:15 +00:00
tippete
1362a03877 Translated using Weblate (Italian)
Currently translated at 100.0% (60 of 60 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/it/
2022-12-17 20:46:15 +00:00
Choukajohn
34ae099b89 Translated using Weblate (French)
Currently translated at 100.0% (60 of 60 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-17 20:46:14 +00:00
gallegonovato
679bd4588f Translated using Weblate (Spanish)
Currently translated at 100.0% (60 of 60 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-17 20:46:14 +00:00
sk
7d4c69bc82 tweak gray colors 2022-12-17 21:36:19 +01:00
sk
1749fcacb1 fix text view cutting off text
closes #157
2022-12-17 21:16:35 +01:00
sk
683f87cc19 Merge branch 'feature/lists' 2022-12-17 21:13:23 +01:00
sk
2ef19be3c7 add missing lists with handling
fix #158
2022-12-17 21:11:48 +01:00
sk
fb5289372d fix updating wrong status when interacting with reblog
see mastodon#467
2022-12-17 21:01:10 +01:00
sk
f8d9d00dac Merge branch 'feature/animate-buttons' 2022-12-17 19:56:24 +01:00
sk
a7c707f62e animate footer icons
closes sk22#154
2022-12-17 19:48:20 +01:00
sk
336ebb71cf Merge branch 'feature/follow-requests' 2022-12-17 16:35:53 +01:00
sk
a5f98f5c50 fix follow request list issues
closes #153
2022-12-17 16:35:41 +01:00
sk
9d5d4b7957 make red theme less orange 2022-12-17 15:47:04 +01:00
LucasGGamerM
3626da7362 custom, darker grays for everyone 2022-12-17 15:41:42 +01:00
sk
400e340859 Merge branch 'fix-toolbar-styles-api-24' 2022-12-17 14:58:09 +01:00
sk
31cad1efbe move api 24 styles into extra styles.xml 2022-12-17 14:56:26 +01:00
sk
e5da24a44d add red theme 2022-12-16 14:41:53 +01:00
sk
d63e5af8d0 use custom instead of app name 2022-12-16 14:21:54 +01:00
sk
abdce64b99 for pink shall remain the default
also, save color name as a string
2022-12-16 14:00:43 +01:00
kaea
d5696684fa 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-16 12:39:36 +00:00
itslameni
d168794d4e 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-16 12:39:36 +00:00
itslameni
52c5057e85 Translated using Weblate (Russian)
Currently translated at 89.8% (53 of 59 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2022-12-16 12:39:36 +00:00
tippete
21167f64c9 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-16 12:39:36 +00:00
AiOO
26343ce10b 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-16 12:39:36 +00:00
nitrogenez
238d930c48 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-16 12:39:36 +00:00
jonta
87ade4a020 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-16 12:39:36 +00:00
kaea
db9bb58b3c 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-16 12:39:36 +00:00
Choukajohn
99cbc8f071 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-16 12:39:36 +00:00
AiOO
d2a4ae8f59 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-16 12:39:36 +00:00
sk
9a47530ab8 Merge remote-tracking branch 'upstream/master' 2022-12-16 02:52:55 +01:00
sk
ed1d9165e1 use default posting language from server 2022-12-16 02:14:06 +01:00
sk
ef421dd5dd set material3 theme as default 2022-12-16 02:02:48 +01:00
sk
acbf27f025 add button styles for each theme 2022-12-16 01:33:28 +01:00
sk
f54e2375be material you and true black improvements 2022-12-16 01:20:39 +01:00
sk
1a66db065f fix wrong button colors 2022-12-16 01:16:45 +01:00
sk
c51b2bb2e7 add m3 colors to colors.xml for compatibility 2022-12-16 00:24:04 +01:00
sk
4de3da09b3 introduce dedicated button colors 2022-12-16 00:13:01 +01:00
Grishka
e0febda372 Minor fixes 2022-12-15 20:16:32 +03:00
sk
516f97e679 improve material you colors 2022-12-15 18:03:06 +01:00
Grishka
069d141451 Fix crash in ComposeFragment::onSaveInstanceState in release builds
fixes #452, fixes #453, fixes #457
2022-12-15 20:02:26 +03:00
Grishka
166401ea18 Signup flow redesign 2022-12-15 19:41:38 +03:00
sk
55e5c03b5f add missing string 2022-12-15 17:03:24 +01:00
sk
c950b6e6c1 simplify code 2022-12-15 17:03:17 +01:00
LucasGGamerM
2dc884b1bb Making material you setting work fine. Its ready for release 2022-12-15 16:44:16 +01:00
LucasGGamerM
c49660950d Adding the color things 2022-12-15 16:37:31 +01:00
sk
9162908173 Merge branch 'more-distinct-filled-boost-icon' 2022-12-15 16:18:42 +01:00
sk
2789169dd7 slightly more padding for fill 2022-12-15 16:18:21 +01:00
sk
0728b00381 Merge branch 'more-distinct-filled-boost-icon' 2022-12-13 15:45:30 +01:00
sk
34b82337b1 add distinct filled boost icon 2022-12-13 15:45:19 +01:00
sk
f25d4e4d44 update screenshots 2022-12-13 12:04:34 +01:00
sk
ac3176c0d8 Merge branch 'external-share-include-subject' 2022-12-13 09:18:42 +01:00
sk
021fc9e5a0 add empty line after subject
closes #149
2022-12-13 09:18:18 +01:00
sk
a48c11332c Merge branch 'feature/translate-button' 2022-12-13 09:15:34 +01:00
sk
93bccc02bf add missing language null check
fix #143
2022-12-13 09:15:15 +01:00
sk
7a594be3f2 update metadata 2022-12-13 00:03:37 +01:00
sk
c9f4df3d4e bump version, update changelog 2022-12-12 23:35:54 +01:00
sk22
9078667d51 Translated using Weblate (German)
Currently translated at 100.0% (59 of 59 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-12 22:29:04 +00:00
sk
7569e1aef6 add strings back 2022-12-12 23:26:52 +01:00
nitrogenez
723983dadf Translated using Weblate (Ukrainian)
Currently translated at 100.0% (8 of 8 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/uk/
2022-12-12 22:25:44 +00:00
lunarna
f87e020abd 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-12 22:25:44 +00:00
AiOO
fb5729d5cc 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-12 22:25:44 +00:00
Adolfo Jayme Barrientos
2ff6c53d6d 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-12 22:25:44 +00:00
edxkl
cfc6895711 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-12 22:25:44 +00:00
Choukajohn
1c27fc68ee 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-12 22:25:44 +00:00
nitrogenez
df0d578573 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-12 22:25:44 +00:00
edxkl
2fa3c69af1 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-12 22:25:44 +00:00
lunarna
095bf92fed 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-12 22:25:44 +00:00
Choukajohn
debe017f12 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-12 22:25:44 +00:00
Adolfo Jayme Barrientos
f956e12167 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-12 22:25:44 +00:00
AiOO
2c50c38d82 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-12 22:25:44 +00:00
sk22
b4980101ad 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-12 22:25:44 +00:00
sk22
8395fca60f 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-12 22:25:44 +00:00
AiOO
b22e7d277f 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-12 22:25:44 +00:00
edxkl
c0e67593ee 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-12 22:25:44 +00:00
edxkl
5dc4235724 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-12 22:25:43 +00:00
kaea
f77caeefae 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-12 22:25:43 +00:00
Adolfo Jayme Barrientos
c1ef23bbe8 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-12 22:25:43 +00:00
plutonemhikari
e7e80bcf7d 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-12 22:25:43 +00:00
AiOO
c27f5aaf30 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-12 22:25:43 +00:00
gallegonovato
d52728f22e 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-12 22:25:43 +00:00
Christian Elbrianno
3c7c962320 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-12 22:25:43 +00:00
Choukajohn
abf570d177 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-12 22:25:43 +00:00
edxkl
46422cd62d 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-12 22:25:43 +00:00
tippete
f1ffa2629e 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-12 22:25:43 +00:00
Christian Elbrianno
2074f3c33b 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-12 22:25:43 +00:00
Choukajohn
7c51803674 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-12 22:25:43 +00:00
Adolfo Jayme Barrientos
6d80c62f30 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-12 22:25:43 +00:00
gallegonovato
64907a7e1c 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-12 22:25:43 +00:00
ca
17922ca1d5 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-12 22:25:43 +00:00
sk
01ac219854 remove strings 2022-12-12 23:25:31 +01:00
sk
9bbf8c4618 add custom login fragment 2022-12-12 23:18:01 +01:00
sk
978beaec77 use system default language for translation
fix #144
2022-12-12 09:09:45 +01:00
sk
0950e2eb7f Merge branch 'better-poll-voting' 2022-12-10 22:40:46 +01:00
sk
116328adb9 hide icons in own polls
closes #137
2022-12-10 22:40:35 +01:00
sk
32a2c66c34 Merge branch 'feature/language-selector' 2022-12-10 22:30:25 +01:00
sk
661f545e35 Merge branch 'feature/language-selector' 2022-12-10 22:24:05 +01:00
sk
d1e0cd3c20 Merge branch 'feature/display-reply-visibility' 2022-12-10 17:55:41 +01:00
sk
db16dde073 fix wrong visibility in reply
fix #140
2022-12-10 17:55:29 +01:00
sk
b3fe44bc08 update push settings on app start
fix #138, hopefully
2022-12-10 17:37:09 +01:00
sk
e5fab4a555 update changelog, bump version 2022-12-09 21:25:24 +01:00
sk
abe28179ec use saved default status visibility 2022-12-09 21:23:20 +01:00
sk
60d4e4d396 use default posting language 2022-12-09 21:15:11 +01:00
sk
435e73d718 Merge branch 'feature/language-selector' 2022-12-09 20:56:09 +01:00
sk
8714b24388 bump version 2022-12-09 03:15:01 +01:00
sk
495db142d7 update readme 2022-12-09 03:14:11 +01:00
sk
ac5d11159f Merge branch 'feature/translate-button' 2022-12-09 03:05:59 +01:00
sk
d1479f142b add progress spinner 2022-12-09 03:05:17 +01:00
sk
ee6ec631e8 Merge branch 'feature/translate-button' 2022-12-09 02:46:55 +01:00
sk
dee21222a7 implement translate feature 2022-12-09 02:37:38 +01:00
sk
cd8123ca34 Merge remote-tracking branch 'upstream/master' 2022-12-08 21:41:38 +01:00
sk
ceb08ea78d fix get started button color 2022-12-08 21:36:50 +01:00
sk
cac5b554e2 Merge remote-tracking branch 'upstream/master' 2022-12-08 21:02:45 +01:00
sk
c4adbc8e45 update changelog/readme 2022-12-08 21:02:06 +01:00
sk
bb01077c3b Merge branch 'feature/mark-media-as-sensitive' 2022-12-08 21:00:43 +01:00
sk
b370fcda6d add bottom margin to sensitive toggle 2022-12-08 21:00:30 +01:00
sk
d364ebbb2f Merge branch 'better-poll-voting' 2022-12-08 20:56:19 +01:00
sk
5b28468efd add option to allow multiple poll choices 2022-12-08 20:53:34 +01:00
sk
6fd58c9682 improve semantics for poll options 2022-12-08 19:56:04 +01:00
sk
b580743619 fix poll option displaying wrong own vote
fixes #132
2022-12-08 16:03:46 +01:00
sk
4a9cb9f2dc fix poll option displaying wrong own vote
fixes #132
2022-12-08 15:53:35 +01:00
Poussinou
0dcdda75be fix typo in README 2022-12-08 12:45:28 +09:30
sk22
145f55817f 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-07 18:20:46 +00:00
sk
79025c2f36 update description 2022-12-07 19:19:05 +01:00
sk
2515a8d381 add missing item to changelog 2022-12-07 19:16:14 +01:00
sk22
ede7ece25a 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-07 18:11:14 +00:00
sk22
2db39f8c66 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-07 18:11:13 +00:00
sk
5f0382456f remove upstream fastlane changes 2022-12-07 19:09:13 +01:00
sk
63b1b58c4e use dashes instead of asterisks 2022-12-07 19:05:38 +01:00
Poussinou
e9fe4a82df Update README.md 2022-12-04 05:26:19 +09:30
283 changed files with 3998 additions and 843 deletions

View File

@@ -8,25 +8,35 @@ assignees: ''
--- ---
**Describe the bug** **Describe the bug**
A clear and concise description of what the bug is. A clear and concise description of what the bug is.
**To Reproduce** **To reproduce**
Steps to reproduce the behavior: Steps to reproduce the behavior:
1. Go to '...' 1. Go to '...'
2. Click on '....' 2. Click on '....'
3. Scroll down to '....' 3. Scroll down to '....'
4. See error 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** **Screenshots and screen recordings**
If applicable, add screenshots (and screen recordings, if possible) to help explain your problem. If applicable, add screenshots (and screen recordings, if possible) to help explain your problem.
**Version** **Version**
Megalodon version: [e.g. v1.1.4+fork.#] Megalodon version: [e.g. v1.1.4+fork.#]
**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** **Crash log**
If you know your way around Android development tools, please consider attaching a crash log, if possible. If you know your way around Android development tools, please consider attaching a crash log, if possible.

View File

@@ -14,6 +14,15 @@
### **Material you theme support on Android 12+ devices!** ### **Material you theme support on Android 12+ devices!**
### **Show posts filtered with a warning!**
**Allows you to have filtered posts collapsed with a warning! As shown in the screenshots:**
Before | After
:-------------------------:|:-------------------------:
![Screenshot_20230205-100200edited](https://user-images.githubusercontent.com/71328265/216820539-20802dc5-e433-4511-b2d9-291d810e4ef2.png) | ![Screenshot_20230205-100203edited](https://user-images.githubusercontent.com/71328265/216820544-231b2966-f38f-4ec6-b555-d39c62433839.png)
### **Color themes** ### **Color themes**
**Allows you to change theme within the app. Supports Purple, pink, green, blue, orange and yellow!** **Allows you to change theme within the app. Supports Purple, pink, green, blue, orange and yellow!**
@@ -77,11 +86,13 @@ Variant with an integrated updater. If you download Moshidon from here (and not
### Features ### Features
* [Adding the ability to have filtered posts show with a warning](https://github.com/LucasGGamerM/moshidon/tree/feature/filters_again)
* [Add “Unlisted” as a post visibility option](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/enable-unlisted) * [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)) ([Pull request](https://github.com/mastodon/mastodon-android/pull/103))
* Adding a useful private profile note box!* * Adding a useful private profile note box!*
* Auto hiding the compose button on scroll!* * Auto hiding the compose button on scroll!*
* Adding the hability to remind yourself to add alt text to images!* * Adding the hability to remind yourself to add alt text to images!*
* An indicator for if an image has alt text or not*
* Adding the ability to have drafts!* * Adding the ability to have drafts!*
* Also adding the ability to view announcements from your instance!* * 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!)* * Adding the ability to post for local timeline only (Only on instances that support it!)*
@@ -106,7 +117,7 @@ Variant with an integrated updater. If you download Moshidon from here (and not
### Behavior ### Behavior
* Adding a bottom option for the publish button, allowing for easier user on larger screens! * Adding a bottom option for the publish button, allowing for easier use 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)) * [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)) * [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)) * [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))

3
fix-metadata-markdown-lists.sh Executable file
View File

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

View File

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

BIN
img/izzy-badge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -9,8 +9,8 @@ android {
applicationId "org.joinmastodon.android.moshinda" applicationId "org.joinmastodon.android.moshinda"
minSdk 23 minSdk 23
targetSdk 33 targetSdk 33
versionCode 90 versionCode 92
versionName "1.1.4+fork.90.moshinda" versionName "1.1.4+fork.92.moshinda"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
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" 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"
} }
@@ -70,6 +70,7 @@ dependencies {
implementation 'com.squareup:otto:1.3.8' implementation 'com.squareup:otto:1.3.8'
implementation 'de.psdev:async-otto:1.0.3' implementation 'de.psdev:async-otto:1.0.3'
implementation 'org.parceler:parceler-api:1.1.12' 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' annotationProcessor 'org.parceler:parceler:1.1.12'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'

View File

@@ -115,7 +115,7 @@ public class GithubSelfUpdaterImpl extends GithubSelfUpdater{
private void actuallyCheckForUpdates(){ private void actuallyCheckForUpdates(){
Request req=new Request.Builder() Request req=new Request.Builder()
.url("https://api.github.com/repos/LucasGGamerM/moshidon/releases/latest") .url("https://api.github.com/repos/LucasGGamerM/moshidon/releases")
.build(); .build();
Call call=MastodonAPIController.getHttpClient().newCall(req); Call call=MastodonAPIController.getHttpClient().newCall(req);
try(Response resp=call.execute()){ try(Response resp=call.execute()){

View File

@@ -12,7 +12,6 @@ import android.widget.Toast;
import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.ComposeFragment; import org.joinmastodon.android.fragments.ComposeFragment;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import java.util.ArrayList; import java.util.ArrayList;
@@ -36,13 +35,10 @@ public class ExternalShareActivity extends FragmentStackActivity{
openComposeFragment(sessions.get(0).getID()); openComposeFragment(sessions.get(0).getID());
}else{ }else{
getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000)); getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000));
new M3AlertDialogBuilder(this) UiUtils.pickAccount(this, null, R.string.choose_account, 0,
.setItems(sessions.stream().map(as->"@"+as.self.username+"@"+as.domain).toArray(String[]::new), (dialog, which)->{ session -> openComposeFragment(session.getID()),
openComposeFragment(sessions.get(which).getID()); b -> b.setOnCancelListener(d -> finish())
}) );
.setTitle(R.string.choose_account)
.setOnCancelListener(dialog -> finish())
.show();
} }
} }
} }

View File

@@ -42,6 +42,10 @@ public class GlobalUserPreferences{
public static boolean showAltIndicator; public static boolean showAltIndicator;
public static boolean showNoAltIndicator; public static boolean showNoAltIndicator;
public static boolean enablePreReleases; public static boolean enablePreReleases;
public static boolean prefixRepliesWithRe;
public static boolean bottomEncoding;
public static boolean collapseLongPosts;
public static boolean spectatorMode;
public static String publishButtonText; public static String publishButtonText;
public static ThemePreference theme; public static ThemePreference theme;
public static ColorPreference color; public static ColorPreference color;
@@ -91,6 +95,10 @@ public class GlobalUserPreferences{
showAltIndicator=prefs.getBoolean("showAltIndicator", true); showAltIndicator=prefs.getBoolean("showAltIndicator", true);
showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true); showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true);
enablePreReleases=prefs.getBoolean("enablePreReleases", false); enablePreReleases=prefs.getBoolean("enablePreReleases", false);
prefixRepliesWithRe=prefs.getBoolean("prefixRepliesWithRe", false);
bottomEncoding=prefs.getBoolean("bottomEncoding", false);
collapseLongPosts=prefs.getBoolean("collapseLongPosts", true);
spectatorMode=prefs.getBoolean("spectatorMode", false);
publishButtonText=prefs.getString("publishButtonText", ""); publishButtonText=prefs.getString("publishButtonText", "");
theme=ThemePreference.values()[prefs.getInt("theme", 0)]; theme=ThemePreference.values()[prefs.getInt("theme", 0)];
recentLanguages=fromJson(prefs.getString("recentLanguages", "{}"), recentLanguagesType, new HashMap<>()); recentLanguages=fromJson(prefs.getString("recentLanguages", "{}"), recentLanguagesType, new HashMap<>());
@@ -136,7 +144,11 @@ public class GlobalUserPreferences{
.putBoolean("showAltIndicator", showAltIndicator) .putBoolean("showAltIndicator", showAltIndicator)
.putBoolean("showNoAltIndicator", showNoAltIndicator) .putBoolean("showNoAltIndicator", showNoAltIndicator)
.putBoolean("enablePreReleases", enablePreReleases) .putBoolean("enablePreReleases", enablePreReleases)
.putBoolean("prefixRepliesWithRe", prefixRepliesWithRe)
.putBoolean("collapseLongPosts", collapseLongPosts)
.putBoolean("spectatorMode", spectatorMode)
.putString("publishButtonText", publishButtonText) .putString("publishButtonText", publishButtonText)
.putBoolean("bottomEncoding", bottomEncoding)
.putInt("theme", theme.ordinal()) .putInt("theme", theme.ordinal())
.putString("color", color.name()) .putString("color", color.name())
.putString("recentLanguages", gson.toJson(recentLanguages)) .putString("recentLanguages", gson.toJson(recentLanguages))

View File

@@ -155,6 +155,7 @@ public class MainActivity extends FragmentStackActivity{
); );
Bundle currentArgs = currentFragment.getArguments(); Bundle currentArgs = currentFragment.getArguments();
if (this.fragmentContainers.size() == 1 if (this.fragmentContainers.size() == 1
&& currentArgs != null
&& currentArgs.getBoolean("_can_go_back", false) && currentArgs.getBoolean("_can_go_back", false)
&& currentArgs.containsKey("account")) { && currentArgs.containsKey("account")) {
Bundle args = new Bundle(); Bundle args = new Bundle();

View File

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

View File

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

View File

@@ -15,12 +15,15 @@ import org.joinmastodon.android.events.RemoveAccountPostsEvent;
import org.joinmastodon.android.events.StatusCreatedEvent; import org.joinmastodon.android.events.StatusCreatedEvent;
import org.joinmastodon.android.events.StatusUnpinnedEvent; import org.joinmastodon.android.events.StatusUnpinnedEvent;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem;
import org.joinmastodon.android.utils.StatusFilterPredicate;
import org.parceler.Parcels; import org.parceler.Parcels;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import me.grishka.appkit.api.SimpleCallback; import me.grishka.appkit.api.SimpleCallback;
@@ -61,6 +64,7 @@ public class AccountTimelineFragment extends StatusListFragment{
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
if(getActivity()==null) return; if(getActivity()==null) return;
result=result.stream().filter(new StatusFilterPredicate(accountID, Filter.FilterContext.ACCOUNT)).collect(Collectors.toList());
onDataLoaded(result, !result.isEmpty()); onDataLoaded(result, !result.isEmpty());
} }
}) })

View File

@@ -59,6 +59,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse; import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.BaseRecyclerFragment; import me.grishka.appkit.fragments.BaseRecyclerFragment;
@@ -82,6 +84,11 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
public BaseStatusListFragment(){ public BaseStatusListFragment(){
super(20); super(20);
if (withComposeButton()) setListLayoutId(R.layout.recycler_fragment_with_fab);
}
protected boolean withComposeButton() {
return false;
} }
@Override @Override
@@ -95,6 +102,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
setRetainInstance(true); setRetainInstance(true);
} }
@Override @Override
protected RecyclerView.Adapter getAdapter(){ protected RecyclerView.Adapter getAdapter(){
return adapter=new DisplayItemsAdapter(); return adapter=new DisplayItemsAdapter();
@@ -353,6 +362,13 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
list.setItemAnimator(new BetterItemAnimator()); list.setItemAnimator(new BetterItemAnimator());
((UsableRecyclerView) list).setIncludeMarginsInItemHitbox(true); ((UsableRecyclerView) list).setIncludeMarginsInItemHitbox(true);
updateToolbar(); updateToolbar();
if (withComposeButton()) {
fab = view.findViewById(R.id.fab);
fab.setVisibility(View.VISIBLE);
fab.setOnClickListener(this::onFabClick);
fab.setOnLongClickListener(this::onFabLongClick);
}
} }
@Override @Override
@@ -514,31 +530,11 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
updateImagesSpoilerState(status, itemID); 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){ public void onVisibilityIconClick(HeaderStatusDisplayItem.Holder holder){
Status status=holder.getItem().status; Status status=holder.getItem().status;
status.spoilerRevealed=!status.spoilerRevealed; status.spoilerRevealed=!status.spoilerRevealed;
if(!TextUtils.isEmpty(status.spoilerText)){ 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){ if(text!=null){
adapter.notifyItemChanged(text.getAbsoluteAdapterPosition()); adapter.notifyItemChanged(text.getAbsoluteAdapterPosition());
} }
@@ -547,6 +543,23 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
updateImagesSpoilerState(status, holder.getItemID()); 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();
holder.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){ protected void updateImagesSpoilerState(Status status, String itemID){
ArrayList<Integer> updatedPositions=new ArrayList<>(); ArrayList<Integer> updatedPositions=new ArrayList<>();
for(ImageStatusDisplayItem.Holder photo:(List<ImageStatusDisplayItem.Holder>)findAllHoldersOfType(itemID, ImageStatusDisplayItem.Holder.class)){ for(ImageStatusDisplayItem.Holder photo:(List<ImageStatusDisplayItem.Holder>)findAllHoldersOfType(itemID, ImageStatusDisplayItem.Holder.class)){
@@ -564,14 +577,13 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
public void onGapClick(GapStatusDisplayItem.Holder item){} public void onGapClick(GapStatusDisplayItem.Holder item){}
public void onWarningClick(WarningFilteredStatusDisplayItem.Holder warningItem){ public void onWarningClick(WarningFilteredStatusDisplayItem.Holder warning){
int i = warningItem.getAbsoluteAdapterPosition(); int startPos = warning.getAbsoluteAdapterPosition();
displayItems.remove(warningItem.getAbsoluteAdapterPosition()); displayItems.remove(startPos);
for(StatusDisplayItem item:warningItem.filteredItems){ displayItems.addAll(startPos, warning.filteredItems);
displayItems.add(i, item); adapter.notifyItemRangeInserted(startPos, warning.filteredItems.size() - 1);
i++; if (startPos == 0) scrollToTop();
} warning.getItem().status.filterRevealed = true;
adapter.notifyItemChanged(warningItem.getAbsoluteAdapterPosition());
} }
public String getAccountID(){ public String getAccountID(){
@@ -689,6 +701,16 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
currentPhotoViewer.onPause(); currentPhotoViewer.onPause();
} }
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);
}
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{ protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
public DisplayItemsAdapter(){ public DisplayItemsAdapter(){

View File

@@ -5,6 +5,7 @@ import static android.os.ext.SdkExtensions.getExtensionVersion;
import static org.joinmastodon.android.GlobalUserPreferences.recentLanguages; 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.DRAFTS_AFTER_INSTANT;
import static org.joinmastodon.android.api.requests.statuses.CreateStatus.getDraftInstant; 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.allLanguages;
import static org.joinmastodon.android.utils.MastodonLanguage.defaultRecentLanguages; import static org.joinmastodon.android.utils.MastodonLanguage.defaultRecentLanguages;
@@ -43,6 +44,7 @@ import android.text.TextWatcher;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.util.Log; import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@@ -67,6 +69,7 @@ import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.github.bottomSoftwareFoundation.bottom.Bottom;
import com.twitter.twittertext.TwitterTextEmojiRegex; import com.twitter.twittertext.TwitterTextEmojiRegex;
import org.joinmastodon.android.E; import org.joinmastodon.android.E;
@@ -116,6 +119,7 @@ import org.joinmastodon.android.ui.views.LinkedTextView;
import org.joinmastodon.android.ui.views.ReorderableLinearLayout; import org.joinmastodon.android.ui.views.ReorderableLinearLayout;
import org.joinmastodon.android.ui.views.SizeListenerLinearLayout; import org.joinmastodon.android.ui.views.SizeListenerLinearLayout;
import org.joinmastodon.android.utils.MastodonLanguage; import org.joinmastodon.android.utils.MastodonLanguage;
import org.joinmastodon.android.utils.StatusTextEncoder;
import org.parceler.Parcel; import org.parceler.Parcel;
import org.parceler.Parcels; import org.parceler.Parcels;
@@ -156,11 +160,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 Pattern GLITCH_LOCAL_ONLY_PATTERN = Pattern.compile("[\\s\\S]*" + GLITCH_LOCAL_ONLY_SUFFIX + "[\uFE00-\uFE0F]*");
private static final String TAG="ComposeFragment"; private static final String TAG="ComposeFragment";
private static final Pattern MENTION_PATTERN=Pattern.compile("(^|[^\\/\\w])@(([a-z0-9_]+)@[a-z0-9\\.\\-]+[a-z0-9]+)", Pattern.CASE_INSENSITIVE); public 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 // from https://github.com/mastodon/mastodon-ios/blob/main/Mastodon/Helper/MastodonRegex.swift
private 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 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.]+))"); public 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 @SuppressLint("NewApi") // this class actually exists on 6.0
private final BreakIterator breakIterator=BreakIterator.getCharacterInstance(); private final BreakIterator breakIterator=BreakIterator.getCharacterInstance();
@@ -230,7 +234,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private boolean ignoreSelectionChanges=false; private boolean ignoreSelectionChanges=false;
private Runnable updateUploadEtaRunnable; private Runnable updateUploadEtaRunnable;
private String language; private String language, encoding;
private MastodonLanguage.LanguageResolver languageResolver; private MastodonLanguage.LanguageResolver languageResolver;
private int navigationBarColorBefore; private int navigationBarColorBefore;
@@ -735,7 +739,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
if(!TextUtils.isEmpty(replyTo.spoilerText)){ if(!TextUtils.isEmpty(replyTo.spoilerText)){
hasSpoiler=true; hasSpoiler=true;
spoilerEdit.setVisibility(View.VISIBLE); spoilerEdit.setVisibility(View.VISIBLE);
if(GlobalUserPreferences.prefixRepliesWithRe && !replyTo.spoilerText.startsWith("re: ")){
spoilerEdit.setText("re: " + replyTo.spoilerText);
}else{
spoilerEdit.setText(replyTo.spoilerText); spoilerEdit.setText(replyTo.spoilerText);
}
spoilerBtn.setSelected(true); spoilerBtn.setSelected(true);
} }
if (replyTo.language != null && !replyTo.language.isEmpty()) updateLanguage(replyTo.language); if (replyTo.language != null && !replyTo.language.isEmpty()) updateLanguage(replyTo.language);
@@ -872,9 +880,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
} }
private void updateLanguage(MastodonLanguage loc) { private void updateLanguage(MastodonLanguage loc) {
language = loc.getLanguage(); updateLanguage(loc.getLanguage(), loc.getLanguageName(), loc.getDefaultName());
languageButton.setText(loc.getLanguageName()); }
languageButton.setContentDescription(getActivity().getString(R.string.sk_post_language, 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));
} }
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@@ -891,9 +903,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
Menu languageMenu = languagePopup.getMenu(); Menu languageMenu = languagePopup.getMenu();
for (String recentLanguage : Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages)) { for (String recentLanguage : Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages)) {
if (recentLanguage.equals("bottom")) {
addBottomLanguage(languageMenu);
} else {
MastodonLanguage l = languageResolver.from(recentLanguage); MastodonLanguage l = languageResolver.from(recentLanguage);
languageMenu.add(0, allLanguages.indexOf(l), Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName())); 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); SubMenu allLanguagesMenu = languageMenu.addSubMenu(R.string.sk_available_languages);
for (int i = 0; i < allLanguages.size(); i++) { for (int i = 0; i < allLanguages.size(); i++) {
@@ -901,13 +917,33 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
allLanguagesMenu.add(0, i, Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName())); 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->{ languagePopup.setOnMenuItemClickListener(i->{
if (i.hasSubMenu()) return false; 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())); updateLanguage(allLanguages.get(i.getItemId()));
encoding = null;
}
return true; return true;
}); });
} }
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 @Override
public boolean onOptionsItemSelected(MenuItem item){ public boolean onOptionsItemSelected(MenuItem item){
return true; return true;
@@ -1046,6 +1082,10 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private void publish(boolean force){ private void publish(boolean force){
String text=mainEditText.getText().toString(); String text=mainEditText.getText().toString();
CreateStatus.Request req=new CreateStatus.Request(); 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 && if (localOnly &&
GlobalUserPreferences.accountsInGlitchMode.contains(accountID) && GlobalUserPreferences.accountsInGlitchMode.contains(accountID) &&
!GLITCH_LOCAL_ONLY_PATTERN.matcher(text).matches()) { !GLITCH_LOCAL_ONLY_PATTERN.matcher(text).matches()) {
@@ -1188,6 +1228,14 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
List<String> newRecentLanguages = new ArrayList<>(Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages)); List<String> newRecentLanguages = new ArrayList<>(Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages));
newRecentLanguages.remove(language); newRecentLanguages.remove(language);
newRecentLanguages.add(0, 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())); recentLanguages.put(accountID, newRecentLanguages.stream().limit(4).collect(Collectors.toList()));
GlobalUserPreferences.save(); GlobalUserPreferences.save();
} }
@@ -1253,7 +1301,14 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
} }
private void confirmDiscardDraftAndFinish(){ private void confirmDiscardDraftAndFinish(){
new M3AlertDialogBuilder(getActivity()) 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())
.setTitle(editingStatus != null ? R.string.sk_confirm_save_changes : R.string.sk_confirm_save_draft) .setTitle(editingStatus != null ? R.string.sk_confirm_save_changes : R.string.sk_confirm_save_draft)
.setPositiveButton(R.string.save, (d, w) -> { .setPositiveButton(R.string.save, (d, w) -> {
updateScheduledAt(scheduledAt == null ? getDraftInstant() : scheduledAt); updateScheduledAt(scheduledAt == null ? getDraftInstant() : scheduledAt);
@@ -1263,18 +1318,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
.show(); .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. * Builds the correct intent for the device version to select media.
@@ -1286,24 +1329,24 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
*/ */
private void openFilePicker(boolean photoPicker){ private void openFilePicker(boolean photoPicker){
Intent intent; Intent intent;
boolean usePhotoPicker = photoPicker && isPhotoPickerAvailable(); boolean usePhotoPicker=photoPicker && isPhotoPickerAvailable();
if (usePhotoPicker) { if(usePhotoPicker){
intent = new Intent(MediaStore.ACTION_PICK_IMAGES); intent=new Intent(MediaStore.ACTION_PICK_IMAGES);
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit()); intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MAX_ATTACHMENTS-getMediaAttachmentsCount());
} else { }else{
intent = new Intent(Intent.ACTION_GET_CONTENT); intent=new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE); intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*"); intent.setType("*/*");
} }
if (!usePhotoPicker && instance.configuration != null && if(!usePhotoPicker && instance.configuration!=null &&
instance.configuration.mediaAttachments != null && instance.configuration.mediaAttachments!=null &&
instance.configuration.mediaAttachments.supportedMimeTypes != null && instance.configuration.mediaAttachments.supportedMimeTypes!=null &&
!instance.configuration.mediaAttachments.supportedMimeTypes.isEmpty()) { !instance.configuration.mediaAttachments.supportedMimeTypes.isEmpty()){
intent.putExtra(Intent.EXTRA_MIME_TYPES, intent.putExtra(Intent.EXTRA_MIME_TYPES,
instance.configuration.mediaAttachments.supportedMimeTypes.toArray( instance.configuration.mediaAttachments.supportedMimeTypes.toArray(
new String[0])); new String[0]));
} else { }else{
if (!usePhotoPicker) { if(!usePhotoPicker){
// If photo picker is being used these are the default mimetypes. // If photo picker is being used these are the default mimetypes.
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"image/*", "video/*"}); intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"image/*", "video/*"});
} }

View File

@@ -1,37 +0,0 @@
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

@@ -17,12 +17,15 @@ import org.joinmastodon.android.api.requests.tags.GetHashtag;
import org.joinmastodon.android.api.requests.tags.SetHashtagFollowed; import org.joinmastodon.android.api.requests.tags.SetHashtagFollowed;
import org.joinmastodon.android.api.requests.timelines.GetHashtagTimeline; import org.joinmastodon.android.api.requests.timelines.GetHashtagTimeline;
import org.joinmastodon.android.events.HashtagUpdatedEvent; import org.joinmastodon.android.events.HashtagUpdatedEvent;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Hashtag; import org.joinmastodon.android.model.Hashtag;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.TimelineDefinition; import org.joinmastodon.android.model.TimelineDefinition;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.utils.StatusFilterPredicate;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import me.grishka.appkit.Nav; import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
@@ -33,11 +36,11 @@ import me.grishka.appkit.utils.V;
public class HashtagTimelineFragment extends PinnableStatusListFragment { public class HashtagTimelineFragment extends PinnableStatusListFragment {
private String hashtag; private String hashtag;
private boolean following; private boolean following;
private ImageButton fab;
private MenuItem followButton; private MenuItem followButton;
public HashtagTimelineFragment(){ @Override
setListLayoutId(R.layout.recycler_fragment_with_fab); protected boolean withComposeButton() {
return true;
} }
@Override @Override
@@ -120,6 +123,7 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment {
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
if (getActivity() == null) return; if (getActivity() == null) return;
result=result.stream().filter(new StatusFilterPredicate(accountID, Filter.FilterContext.PUBLIC)).collect(Collectors.toList());
onDataLoaded(result, !result.isEmpty()); onDataLoaded(result, !result.isEmpty());
} }
}) })
@@ -134,14 +138,12 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment {
} }
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState){ protected boolean onFabLongClick(View v) {
super.onViewCreated(view, savedInstanceState); return UiUtils.pickAccountForCompose(getActivity(), accountID, '#'+hashtag+' ');
fab=view.findViewById(R.id.fab);
fab.setOnClickListener(this::onFabClick);
fab.setOnLongClickListener(v -> UiUtils.pickAccountForCompose(getActivity(), accountID, '#'+hashtag+' '));
} }
private void onFabClick(View v){ @Override
protected void onFabClick(View v){
Bundle args=new Bundle(); Bundle args=new Bundle();
args.putString("account", accountID); args.putString("account", accountID);
args.putString("prefilledText", '#'+hashtag+' '); args.putString("prefilledText", '#'+hashtag+' ');

View File

@@ -375,7 +375,7 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
} }
private <T> void updateList(List<T> addItems, Map<Integer, T> items) { private <T> void updateList(List<T> addItems, Map<Integer, T> items) {
if (addItems.size() == 0) return; if (addItems.size() == 0 || getActivity() == null) return;
for (int i = 0; i < addItems.size(); i++) items.put(View.generateViewId(), addItems.get(i)); for (int i = 0; i < addItems.size(); i++) items.put(View.generateViewId(), addItems.get(i));
updateOverflowMenu(); updateOverflowMenu();
} }
@@ -662,7 +662,8 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
@Override @Override
public SimpleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public SimpleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
FrameLayout tabView = tabViews[viewType % getItemCount()]; FrameLayout tabView = tabViews[viewType % getItemCount()];
((ViewGroup)tabView.getParent()).removeView(tabView); ViewGroup tabParent = (ViewGroup) tabView.getParent();
if (tabParent != null) tabParent.removeView(tabView);
tabView.setVisibility(View.VISIBLE); tabView.setVisibility(View.VISIBLE);
return new SimpleViewHolder(tabView); return new SimpleViewHolder(tabView);
} }

View File

@@ -32,11 +32,16 @@ import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.api.SimpleCallback; import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.utils.V; import me.grishka.appkit.utils.V;
public class HomeTimelineFragment extends FabStatusListFragment { public class HomeTimelineFragment extends StatusListFragment {
private HomeTabFragment parent; private HomeTabFragment parent;
private String maxID; private String maxID;
private String lastSavedMarkerID; private String lastSavedMarkerID;
@Override
protected boolean withComposeButton() {
return true;
}
@Override @Override
public void onAttach(Activity activity){ public void onAttach(Activity activity){
super.onAttach(activity); super.onAttach(activity);

View File

@@ -18,14 +18,17 @@ import org.joinmastodon.android.api.requests.lists.UpdateList;
import org.joinmastodon.android.api.requests.timelines.GetListTimeline; import org.joinmastodon.android.api.requests.timelines.GetListTimeline;
import org.joinmastodon.android.events.ListDeletedEvent; import org.joinmastodon.android.events.ListDeletedEvent;
import org.joinmastodon.android.events.ListUpdatedCreatedEvent; import org.joinmastodon.android.events.ListUpdatedCreatedEvent;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.ListTimeline; import org.joinmastodon.android.model.ListTimeline;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.TimelineDefinition; import org.joinmastodon.android.model.TimelineDefinition;
import org.joinmastodon.android.ui.M3AlertDialogBuilder; import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ListTimelineEditor; import org.joinmastodon.android.ui.views.ListTimelineEditor;
import org.joinmastodon.android.utils.StatusFilterPredicate;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import me.grishka.appkit.Nav; import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
@@ -39,10 +42,10 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
private String listTitle; private String listTitle;
@Nullable @Nullable
private ListTimeline.RepliesPolicy repliesPolicy; private ListTimeline.RepliesPolicy repliesPolicy;
private ImageButton fab;
public ListTimelineFragment() { @Override
setListLayoutId(R.layout.recycler_fragment_with_fab); protected boolean withComposeButton() {
return true;
} }
@Override @Override
@@ -134,6 +137,7 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
@Override @Override
public void onSuccess(List<Status> result) { public void onSuccess(List<Status> result) {
if (getActivity() == null) return; if (getActivity() == null) return;
result=result.stream().filter(new StatusFilterPredicate(accountID, Filter.FilterContext.HOME)).collect(Collectors.toList());
onDataLoaded(result, !result.isEmpty()); onDataLoaded(result, !result.isEmpty());
} }
}) })
@@ -148,14 +152,7 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
} }
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { protected void onFabClick(View v){
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(); Bundle args=new Bundle();
args.putString("account", accountID); args.putString("account", accountID);
Nav.go(getActivity(), ComposeFragment.class, args); Nav.go(getActivity(), ComposeFragment.class, args);

View File

@@ -99,7 +99,6 @@ public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> im
new CreateList(editor.getTitle(), editor.getRepliesPolicy()).setCallback(new Callback<>() { new CreateList(editor.getTitle(), editor.getRepliesPolicy()).setCallback(new Callback<>() {
@Override @Override
public void onSuccess(ListTimeline list) { public void onSuccess(ListTimeline list) {
saveListMembership(list.id, true);
data.add(0, list); data.add(0, list);
adapter.notifyItemRangeInserted(0, 1); adapter.notifyItemRangeInserted(0, 1);
E.post(new ListUpdatedCreatedEvent(list.id, list.title, list.repliesPolicy)); E.post(new ListUpdatedCreatedEvent(list.id, list.title, list.repliesPolicy));

View File

@@ -102,7 +102,6 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
tabLayout=view.findViewById(R.id.tabbar); tabLayout=view.findViewById(R.id.tabbar);
pager=view.findViewById(R.id.pager); pager=view.findViewById(R.id.pager);
UiUtils.reduceSwipeSensitivity(pager);
tabViews=new FrameLayout[3]; tabViews=new FrameLayout[3];
for(int i=0;i<tabViews.length;i++){ for(int i=0;i<tabViews.length;i++){
@@ -120,18 +119,6 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
tabLayout.setTabTextSize(V.dp(16)); tabLayout.setTabTextSize(V.dp(16));
tabLayout.setTabTextColors(UiUtils.getThemeColor(getActivity(), R.attr.colorTabInactive), UiUtils.getThemeColor(getActivity(), android.R.attr.textColorPrimary)); tabLayout.setTabTextColors(UiUtils.getThemeColor(getActivity(), R.attr.colorTabInactive), UiUtils.getThemeColor(getActivity(), android.R.attr.textColorPrimary));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {}
@Override
public void onTabUnselected(TabLayout.Tab tab) {}
@Override
public void onTabReselected(TabLayout.Tab tab) {
scrollToTop();
}
});
pager.setOffscreenPageLimit(4); pager.setOffscreenPageLimit(4);
pager.setUserInputEnabled(!GlobalUserPreferences.disableSwipe); pager.setUserInputEnabled(!GlobalUserPreferences.disableSwipe);
@@ -195,7 +182,6 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
new GetFollowRequests(null, 1).setCallback(new Callback<>() { new GetFollowRequests(null, 1).setCallback(new Callback<>() {
@Override @Override
public void onSuccess(HeaderPaginationList<Account> accounts) { public void onSuccess(HeaderPaginationList<Account> accounts) {
if (getActivity() == null) return;
getToolbar().getMenu().findItem(R.id.follow_requests).setVisible(!accounts.isEmpty()); getToolbar().getMenu().findItem(R.id.follow_requests).setVisible(!accounts.isEmpty());
} }
@@ -224,7 +210,6 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
protected void updateToolbar(){ protected void updateToolbar(){
super.updateToolbar(); super.updateToolbar();
getToolbar().setOutlineProvider(null); getToolbar().setOutlineProvider(null);
getToolbar().setOnClickListener(v->scrollToTop());
} }
private NotificationsListFragment getFragmentForPage(int page){ private NotificationsListFragment getFragmentForPage(int page){

View File

@@ -14,6 +14,7 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.PollUpdatedEvent; import org.joinmastodon.android.events.PollUpdatedEvent;
import org.joinmastodon.android.events.RemoveAccountPostsEvent; import org.joinmastodon.android.events.RemoveAccountPostsEvent;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Notification; import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.model.PaginatedResponse; import org.joinmastodon.android.model.PaginatedResponse;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
@@ -47,6 +48,11 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
private String maxID; private String maxID;
private final DiscoverInfoBannerHelper bannerHelper = new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.POST_NOTIFICATIONS); private final DiscoverInfoBannerHelper bannerHelper = new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.POST_NOTIFICATIONS);
@Override
protected boolean withComposeButton() {
return true;
}
@Override @Override
public void onCreate(Bundle savedInstanceState){ public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -91,7 +97,7 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
}; };
HeaderStatusDisplayItem titleItem=extraText!=null ? new HeaderStatusDisplayItem(n.id, n.account, n.createdAt, this, accountID, n.status, 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){ if(n.status!=null){
ArrayList<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, n.status, accountID, n, knownAccounts, titleItem!=null, titleItem==null, n); ArrayList<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, n.status, accountID, n, knownAccounts, titleItem!=null, titleItem==null, n, false, Filter.FilterContext.NOTIFICATIONS);
if(titleItem!=null){ if(titleItem!=null){
for(StatusDisplayItem item:items){ for(StatusDisplayItem item:items){
if(item instanceof ImageStatusDisplayItem imgItem){ if(item instanceof ImageStatusDisplayItem imgItem){
@@ -192,6 +198,7 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
public void onViewCreated(View view, Bundle savedInstanceState){ public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
list.addItemDecoration(new InsetStatusItemDecoration(this)); list.addItemDecoration(new InsetStatusItemDecoration(this));
if (getParentFragment() instanceof NotificationsFragment) fab.setVisibility(View.GONE);
if (onlyPosts) bannerHelper.maybeAddBanner(contentWrap); if (onlyPosts) bannerHelper.maybeAddBanner(contentWrap);
} }

View File

@@ -8,9 +8,11 @@ import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.Outline; import android.graphics.Outline;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@@ -62,6 +64,7 @@ import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.AccountField; import org.joinmastodon.android.model.AccountField;
import org.joinmastodon.android.model.Attachment; import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.Relationship; import org.joinmastodon.android.model.Relationship;
import org.joinmastodon.android.ui.BetterItemAnimator;
import org.joinmastodon.android.ui.SimpleViewHolder; import org.joinmastodon.android.ui.SimpleViewHolder;
import org.joinmastodon.android.ui.SingleImagePhotoViewerListener; import org.joinmastodon.android.ui.SingleImagePhotoViewerListener;
import org.joinmastodon.android.ui.drawables.CoverOverlayGradientDrawable; import org.joinmastodon.android.ui.drawables.CoverOverlayGradientDrawable;
@@ -70,8 +73,10 @@ import org.joinmastodon.android.ui.tabs.TabLayout;
import org.joinmastodon.android.ui.tabs.TabLayoutMediator; import org.joinmastodon.android.ui.tabs.TabLayoutMediator;
import org.joinmastodon.android.ui.text.CustomEmojiSpan; import org.joinmastodon.android.ui.text.CustomEmojiSpan;
import org.joinmastodon.android.ui.text.HtmlParser; import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.CoverImageView; import org.joinmastodon.android.ui.views.CoverImageView;
import org.joinmastodon.android.ui.views.LinkedTextView;
import org.joinmastodon.android.ui.views.NestedRecyclerScrollView; import org.joinmastodon.android.ui.views.NestedRecyclerScrollView;
import org.joinmastodon.android.ui.views.ProgressBarButton; import org.joinmastodon.android.ui.views.ProgressBarButton;
import org.parceler.Parcels; import org.parceler.Parcels;
@@ -84,6 +89,13 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; 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 androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.viewpager2.widget.ViewPager2;
import me.grishka.appkit.Nav; import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse; import me.grishka.appkit.api.ErrorResponse;
@@ -91,10 +103,17 @@ import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.fragments.BaseRecyclerFragment; import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.fragments.LoaderFragment; import me.grishka.appkit.fragments.LoaderFragment;
import me.grishka.appkit.fragments.OnBackPressedListener; import me.grishka.appkit.fragments.OnBackPressedListener;
import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.ListImageLoaderWrapper;
import me.grishka.appkit.imageloader.RecyclerViewDelegate;
import me.grishka.appkit.imageloader.ViewImageLoader; import me.grishka.appkit.imageloader.ViewImageLoader;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest; import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.CubicBezierInterpolator; import me.grishka.appkit.utils.CubicBezierInterpolator;
import me.grishka.appkit.utils.V; import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.UsableRecyclerView;
public class ProfileFragment extends LoaderFragment implements OnBackPressedListener, ScrollableToTop{ public class ProfileFragment extends LoaderFragment implements OnBackPressedListener, ScrollableToTop{
private static final int AVATAR_RESULT=722; private static final int AVATAR_RESULT=722;
@@ -102,23 +121,24 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
private ImageView avatar; private ImageView avatar;
private CoverImageView cover; private CoverImageView cover;
private View avatarBorder; private View avatarBorder, nameWrap;
private TextView name, username, bio, followersCount, followersLabel, followingCount, followingLabel, postsCount, postsLabel; private TextView name, username, bio, followersCount, followersLabel, followingCount, followingLabel, postsCount, postsLabel;
private ProgressBarButton actionButton, notifyButton; private ProgressBarButton actionButton, notifyButton;
private ViewPager2 pager; private ViewPager2 pager;
private NestedRecyclerScrollView scrollView; private NestedRecyclerScrollView scrollView;
private AccountTimelineFragment postsFragment, postsWithRepliesFragment, pinnedPostsFragment, mediaFragment; private AccountTimelineFragment postsFragment, postsWithRepliesFragment, pinnedPostsFragment, mediaFragment;
private ProfileAboutFragment aboutFragment; // private ProfileAboutFragment aboutFragment;
private TabLayout tabbar; private TabLayout tabbar;
private SwipeRefreshLayout refreshLayout; private SwipeRefreshLayout refreshLayout;
private CoverOverlayGradientDrawable coverGradient=new CoverOverlayGradientDrawable(); private CoverOverlayGradientDrawable coverGradient=new CoverOverlayGradientDrawable();
private float titleTransY; private float titleTransY;
private View postsBtn, followersBtn, followingBtn; private View postsBtn, followersBtn, followingBtn, profileCounters;
private EditText nameEdit, bioEdit; private EditText nameEdit, bioEdit;
private ProgressBar actionProgress, notifyProgress; private ProgressBar actionProgress, notifyProgress;
private FrameLayout[] tabViews; private FrameLayout[] tabViews;
private TabLayoutMediator tabLayoutMediator; private TabLayoutMediator tabLayoutMediator;
private TextView followsYouView; private TextView followsYouView;
private ViewGroup rolesView;
public FrameLayout noteWrap; public FrameLayout noteWrap;
public EditText noteEdit; public EditText noteEdit;
@@ -140,6 +160,16 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
private boolean editModeLoading; private boolean editModeLoading;
private boolean isScrollingUp = false; private boolean isScrollingUp = false;
private static final int MAX_FIELDS=4;
// from ProfileAboutFragment
public UsableRecyclerView list;
private List<AccountField> metadataListData=Collections.emptyList();
private MetadataAdapter adapter;
private ItemTouchHelper dragHelper=new ItemTouchHelper(new ReorderCallback());
private RecyclerView.ViewHolder draggedViewHolder;
private ListImageLoaderWrapper imgLoader;
public ProfileFragment(){ public ProfileFragment(){
super(R.layout.loader_fragment_overlay_toolbar); super(R.layout.loader_fragment_overlay_toolbar);
} }
@@ -184,8 +214,10 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
cover=content.findViewById(R.id.cover); cover=content.findViewById(R.id.cover);
avatarBorder=content.findViewById(R.id.avatar_border); avatarBorder=content.findViewById(R.id.avatar_border);
name=content.findViewById(R.id.name); name=content.findViewById(R.id.name);
nameWrap=content.findViewById(R.id.name_wrap);
username=content.findViewById(R.id.username); username=content.findViewById(R.id.username);
bio=content.findViewById(R.id.bio); bio=content.findViewById(R.id.bio);
profileCounters=content.findViewById(R.id.profile_counters);
followersCount=content.findViewById(R.id.followers_count); followersCount=content.findViewById(R.id.followers_count);
followersLabel=content.findViewById(R.id.followers_label); followersLabel=content.findViewById(R.id.followers_label);
followersBtn=content.findViewById(R.id.followers_btn); followersBtn=content.findViewById(R.id.followers_btn);
@@ -208,6 +240,8 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
notifyProgress=content.findViewById(R.id.notify_progress); notifyProgress=content.findViewById(R.id.notify_progress);
fab=content.findViewById(R.id.fab); fab=content.findViewById(R.id.fab);
followsYouView=content.findViewById(R.id.follows_you); followsYouView=content.findViewById(R.id.follows_you);
list=content.findViewById(R.id.metadata);
rolesView=content.findViewById(R.id.roles);
noteEdit = content.findViewById(R.id.note_edit); noteEdit = content.findViewById(R.id.note_edit);
noteWrap = content.findViewById(R.id.note_edit_wrap); noteWrap = content.findViewById(R.id.note_edit_wrap);
@@ -274,7 +308,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
} }
}; };
tabViews=new FrameLayout[5]; tabViews=new FrameLayout[4];
for(int i=0;i<tabViews.length;i++){ for(int i=0;i<tabViews.length;i++){
FrameLayout tabView=new FrameLayout(getActivity()); FrameLayout tabView=new FrameLayout(getActivity());
tabView.setId(switch(i){ tabView.setId(switch(i){
@@ -291,7 +325,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
} }
UiUtils.reduceSwipeSensitivity(pager); UiUtils.reduceSwipeSensitivity(pager);
pager.setOffscreenPageLimit(5); pager.setOffscreenPageLimit(4);
pager.setUserInputEnabled(!GlobalUserPreferences.disableSwipe); pager.setUserInputEnabled(!GlobalUserPreferences.disableSwipe);
pager.setAdapter(new ProfilePagerAdapter()); pager.setAdapter(new ProfilePagerAdapter());
pager.getLayoutParams().height=getResources().getDisplayMetrics().heightPixels; pager.getLayoutParams().height=getResources().getDisplayMetrics().heightPixels;
@@ -352,6 +386,14 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
return true; return true;
}); });
// from ProfileAboutFragment
list.setItemAnimator(new BetterItemAnimator());
list.setDrawSelectorOnTop(true);
list.setLayoutManager(new LinearLayoutManager(getActivity()));
imgLoader=new ListImageLoaderWrapper(getActivity(), list, new RecyclerViewDelegate(list), null);
list.setAdapter(adapter=new MetadataAdapter());
list.setClipToPadding(false);
return sizeWrapper; return sizeWrapper;
} }
@@ -426,8 +468,8 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
postsWithRepliesFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.INCLUDE_REPLIES, false); postsWithRepliesFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.INCLUDE_REPLIES, false);
pinnedPostsFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.PINNED, false); pinnedPostsFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.PINNED, false);
mediaFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.MEDIA, false); mediaFragment=AccountTimelineFragment.newInstance(accountID, account, GetAccountStatuses.Filter.MEDIA, false);
aboutFragment=new ProfileAboutFragment(); // aboutFragment=new ProfileAboutFragment();
aboutFragment.setFields(fields); setFields(fields);
} }
pager.getAdapter().notifyDataSetChanged(); pager.getAdapter().notifyDataSetChanged();
super.dataLoaded(); super.dataLoaded();
@@ -520,6 +562,19 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
name.setText(ssb); name.setText(ssb);
setTitle(ssb); setTitle(ssb);
if (account.roles != null && !account.roles.isEmpty()) {
rolesView.setVisibility(View.VISIBLE);
rolesView.removeAllViews();
name.setPadding(0, 0, V.dp(12), 0);
for (Account.Role role : account.roles) {
TextView roleText = new TextView(getActivity(), null, 0, R.style.role_label);
roleText.setText(role.name);
GradientDrawable bg = (GradientDrawable) roleText.getBackground().mutate();
bg.setStroke(V.dp(2), Color.parseColor(role.color));
rolesView.addView(roleText);
}
}
boolean isSelf=AccountSessionManager.getInstance().isSelf(accountID, account); boolean isSelf=AccountSessionManager.getInstance().isSelf(accountID, account);
@@ -603,9 +658,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
fields.add(field); fields.add(field);
} }
if(aboutFragment!=null){ setFields(fields);
aboutFragment.setFields(fields);
}
} }
private void updateToolbar(){ private void updateToolbar(){
@@ -780,7 +833,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
notifyButton.setSelected(relationship.notifying); notifyButton.setSelected(relationship.notifying);
if (!isOwnProfile) { if (!isOwnProfile) {
setNote(relationship.note); setNote(relationship.note);
aboutFragment.setNote(relationship.note, accountID, profileAccountID); // aboutFragment.setNote(relationship.note, accountID, profileAccountID);
} }
notifyButton.setContentDescription(getString(relationship.notifying ? R.string.sk_user_post_notifications_on : R.string.sk_user_post_notifications_off, '@'+account.username)); notifyButton.setContentDescription(getString(relationship.notifying ? R.string.sk_user_post_notifications_on : R.string.sk_user_post_notifications_off, '@'+account.username));
} }
@@ -809,8 +862,8 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
coverGradient.setTopOffset(scrollY); coverGradient.setTopOffset(scrollY);
cover.invalidate(); cover.invalidate();
titleTransY=getToolbar().getHeight(); titleTransY=getToolbar().getHeight();
if(scrollY>name.getTop()-topBarsH){ if(scrollY>nameWrap.getTop()-topBarsH){
titleTransY=Math.max(0f, titleTransY-(scrollY-(name.getTop()-topBarsH))); titleTransY=Math.max(0f, titleTransY-(scrollY-(nameWrap.getTop()-topBarsH)));
} }
if(toolbarTitleView!=null){ if(toolbarTitleView!=null){
toolbarTitleView.setTranslationY(titleTransY); toolbarTitleView.setTranslationY(titleTransY);
@@ -827,7 +880,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
case 1 -> postsWithRepliesFragment; case 1 -> postsWithRepliesFragment;
case 2 -> pinnedPostsFragment; case 2 -> pinnedPostsFragment;
case 3 -> mediaFragment; case 3 -> mediaFragment;
case 4 -> aboutFragment; // case 4 -> aboutFragment;
default -> throw new IllegalStateException(); default -> throw new IllegalStateException();
}; };
} }
@@ -892,16 +945,12 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
invalidateOptionsMenu(); invalidateOptionsMenu();
pager.setUserInputEnabled(false); pager.setUserInputEnabled(false);
actionButton.setText(R.string.done); actionButton.setText(R.string.done);
pager.setCurrentItem(4);
ArrayList<Animator> animators=new ArrayList<>(); ArrayList<Animator> animators=new ArrayList<>();
for(int i=0;i<tabViews.length-1;i++){
animators.add(ObjectAnimator.ofFloat(tabbar.getTabAt(i).view, View.ALPHA, .3f));
tabbar.getTabAt(i).view.setEnabled(false);
}
Drawable overlay=getResources().getDrawable(R.drawable.edit_avatar_overlay).mutate(); Drawable overlay=getResources().getDrawable(R.drawable.edit_avatar_overlay).mutate();
avatar.setForeground(overlay); avatar.setForeground(overlay);
animators.add(ObjectAnimator.ofInt(overlay, "alpha", 0, 255)); animators.add(ObjectAnimator.ofInt(overlay, "alpha", 0, 255));
nameWrap.setVisibility(View.GONE);
nameEdit.setVisibility(View.VISIBLE); nameEdit.setVisibility(View.VISIBLE);
nameEdit.setText(account.displayName); nameEdit.setText(account.displayName);
RelativeLayout.LayoutParams lp=(RelativeLayout.LayoutParams) username.getLayoutParams(); RelativeLayout.LayoutParams lp=(RelativeLayout.LayoutParams) username.getLayoutParams();
@@ -913,10 +962,9 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
bioEdit.setText(account.source.note); bioEdit.setText(account.source.note);
animators.add(ObjectAnimator.ofFloat(bioEdit, View.ALPHA, 0f, 1f)); animators.add(ObjectAnimator.ofFloat(bioEdit, View.ALPHA, 0f, 1f));
animators.add(ObjectAnimator.ofFloat(bio, View.ALPHA, 0f)); animators.add(ObjectAnimator.ofFloat(bio, View.ALPHA, 0f));
profileCounters.setVisibility(View.GONE);
animators.add(ObjectAnimator.ofFloat(postsBtn, View.ALPHA, .3f)); pager.setVisibility(View.GONE);
animators.add(ObjectAnimator.ofFloat(followersBtn, View.ALPHA, .3f)); tabbar.setVisibility(View.GONE);
animators.add(ObjectAnimator.ofFloat(followingBtn, View.ALPHA, .3f));
AnimatorSet set=new AnimatorSet(); AnimatorSet set=new AnimatorSet();
set.playTogether(animators); set.playTogether(animators);
@@ -924,7 +972,12 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
set.setInterpolator(CubicBezierInterpolator.DEFAULT); set.setInterpolator(CubicBezierInterpolator.DEFAULT);
set.start(); set.start();
aboutFragment.enterEditMode(account.source.fields); // aboutFragment.enterEditMode(account.source.fields);
V.setVisibilityAnimated(fab, View.GONE);
metadataListData=account.source.fields;
adapter.notifyDataSetChanged();
dragHelper.attachToRecyclerView(list);
} }
private void exitEditMode(){ private void exitEditMode(){
@@ -935,16 +988,14 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
invalidateOptionsMenu(); invalidateOptionsMenu();
ArrayList<Animator> animators=new ArrayList<>(); ArrayList<Animator> animators=new ArrayList<>();
actionButton.setText(R.string.edit_profile); actionButton.setText(R.string.edit_profile);
for(int i=0;i<tabViews.length-1;i++){
animators.add(ObjectAnimator.ofFloat(tabbar.getTabAt(i).view, View.ALPHA, 1f));
}
animators.add(ObjectAnimator.ofInt(avatar.getForeground(), "alpha", 0)); animators.add(ObjectAnimator.ofInt(avatar.getForeground(), "alpha", 0));
animators.add(ObjectAnimator.ofFloat(nameEdit, View.ALPHA, 0f)); animators.add(ObjectAnimator.ofFloat(nameEdit, View.ALPHA, 0f));
animators.add(ObjectAnimator.ofFloat(bioEdit, View.ALPHA, 0f)); animators.add(ObjectAnimator.ofFloat(bioEdit, View.ALPHA, 0f));
animators.add(ObjectAnimator.ofFloat(bio, View.ALPHA, 1f)); animators.add(ObjectAnimator.ofFloat(bio, View.ALPHA, 1f));
animators.add(ObjectAnimator.ofFloat(postsBtn, View.ALPHA, 1f)); profileCounters.setVisibility(View.VISIBLE);
animators.add(ObjectAnimator.ofFloat(followersBtn, View.ALPHA, 1f)); pager.setVisibility(View.VISIBLE);
animators.add(ObjectAnimator.ofFloat(followingBtn, View.ALPHA, 1f)); tabbar.setVisibility(View.VISIBLE);
V.setVisibilityAnimated(nameWrap, View.VISIBLE);
AnimatorSet set=new AnimatorSet(); AnimatorSet set=new AnimatorSet();
set.playTogether(animators); set.playTogether(animators);
@@ -953,20 +1004,21 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
set.addListener(new AnimatorListenerAdapter(){ set.addListener(new AnimatorListenerAdapter(){
@Override @Override
public void onAnimationEnd(Animator animation){ public void onAnimationEnd(Animator animation){
for(int i=0;i<tabViews.length-1;i++){
tabbar.getTabAt(i).view.setEnabled(true);
}
pager.setUserInputEnabled(true); pager.setUserInputEnabled(true);
nameEdit.setVisibility(View.GONE); nameEdit.setVisibility(View.GONE);
bioEdit.setVisibility(View.GONE); bioEdit.setVisibility(View.GONE);
RelativeLayout.LayoutParams lp=(RelativeLayout.LayoutParams) username.getLayoutParams(); RelativeLayout.LayoutParams lp=(RelativeLayout.LayoutParams) username.getLayoutParams();
lp.addRule(RelativeLayout.BELOW, R.id.name); lp.addRule(RelativeLayout.BELOW, R.id.name_wrap);
username.getParent().requestLayout(); username.getParent().requestLayout();
avatar.setForeground(null); avatar.setForeground(null);
scrollToTop();
} }
}); });
set.start(); set.start();
InputMethodManager imm=getActivity().getSystemService(InputMethodManager.class);
imm.hideSoftInputFromWindow(content.getWindowToken(), 0);
V.setVisibilityAnimated(fab, View.VISIBLE);
bindHeaderView(); bindHeaderView();
} }
@@ -974,7 +1026,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
if(!isInEditMode) if(!isInEditMode)
throw new IllegalStateException(); throw new IllegalStateException();
setActionProgressVisible(true); setActionProgressVisible(true);
new UpdateAccountCredentials(nameEdit.getText().toString(), bioEdit.getText().toString(), editNewAvatar, editNewCover, aboutFragment.getFields()) new UpdateAccountCredentials(nameEdit.getText().toString(), bioEdit.getText().toString(), editNewAvatar, editNewCover, metadataListData)
.setCallback(new Callback<>(){ .setCallback(new Callback<>(){
@Override @Override
public void onSuccess(Account result){ public void onSuccess(Account result){
@@ -1148,4 +1200,227 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
return position; return position;
} }
} }
// from ProfileAboutFragment
public void setFields(ArrayList<AccountField> fields){
metadataListData=fields;
if (isInEditMode) {
isInEditMode=false;
dragHelper.attachToRecyclerView(null);
}
if (adapter != null) adapter.notifyDataSetChanged();
}
private class MetadataAdapter extends UsableRecyclerView.Adapter<BaseViewHolder> implements ImageLoaderRecyclerAdapter {
public MetadataAdapter(){
super(imgLoader);
}
@NonNull
@Override
public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
return switch(viewType){
case 0 -> new AboutViewHolder();
case 1 -> new EditableAboutViewHolder();
case 2 -> new AddRowViewHolder();
default -> throw new IllegalStateException("Unexpected value: "+viewType);
};
}
@Override
public void onBindViewHolder(BaseViewHolder holder, int position){
if(position<metadataListData.size()){
holder.bind(metadataListData.get(position));
}else{
holder.bind(null);
}
super.onBindViewHolder(holder, position);
}
@Override
public int getItemCount(){
if(isInEditMode){
int size=metadataListData.size();
if(size<MAX_FIELDS)
size++;
return size;
}
return metadataListData.size();
}
@Override
public int getItemViewType(int position){
if(isInEditMode){
return position==metadataListData.size() ? 2 : 1;
}
return 0;
}
@Override
public int getImageCountForItem(int position){
return isInEditMode || metadataListData.get(position).emojiRequests==null
? 0 : metadataListData.get(position).emojiRequests.size();
}
@Override
public ImageLoaderRequest getImageRequest(int position, int image){
return metadataListData.get(position).emojiRequests.get(image);
}
}
private abstract class BaseViewHolder extends BindableViewHolder<AccountField> {
public BaseViewHolder(int layout){
super(getActivity(), layout, list);
}
}
private class AboutViewHolder extends BaseViewHolder implements ImageLoaderViewHolder {
private TextView title;
private LinkedTextView value;
public AboutViewHolder(){
super(R.layout.item_profile_about);
title=findViewById(R.id.title);
value=findViewById(R.id.value);
}
@Override
public void onBind(AccountField item){
title.setText(item.parsedName);
value.setText(item.parsedValue);
if(item.verifiedAt!=null){
int textColor=UiUtils.isDarkTheme() ? 0xFF89bb9c : 0xFF5b8e63;
value.setTextColor(textColor);
value.setLinkTextColor(textColor);
Drawable check=getResources().getDrawable(R.drawable.ic_fluent_checkmark_24_regular, getActivity().getTheme()).mutate();
check.setTint(textColor);
value.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, check, null);
}else{
value.setTextColor(UiUtils.getThemeColor(getActivity(), android.R.attr.textColorPrimary));
value.setLinkTextColor(UiUtils.getThemeColor(getActivity(), android.R.attr.colorAccent));
value.setCompoundDrawables(null, null, null, null);
}
}
@Override
public void setImage(int index, Drawable image){
CustomEmojiSpan span=index>=item.nameEmojis.length ? item.valueEmojis[index-item.nameEmojis.length] : item.nameEmojis[index];
span.setDrawable(image);
title.invalidate();
value.invalidate();
}
@Override
public void clearImage(int index){
setImage(index, null);
}
}
private class EditableAboutViewHolder extends BaseViewHolder {
private EditText title;
private EditText value;
public EditableAboutViewHolder(){
super(R.layout.item_profile_about_editable);
title=findViewById(R.id.title);
value=findViewById(R.id.value);
findViewById(R.id.dragger_thingy).setOnLongClickListener(v->{
dragHelper.startDrag(this);
return true;
});
title.addTextChangedListener(new SimpleTextWatcher(e->item.name=e.toString()));
value.addTextChangedListener(new SimpleTextWatcher(e->item.value=e.toString()));
findViewById(R.id.remove_row_btn).setOnClickListener(this::onRemoveRowClick);
}
@Override
public void onBind(AccountField item){
title.setText(item.name);
value.setText(item.value);
}
private void onRemoveRowClick(View v){
int pos=getAbsoluteAdapterPosition();
metadataListData.remove(pos);
adapter.notifyItemRemoved(pos);
for(int i=0;i<list.getChildCount();i++){
BaseViewHolder vh=(BaseViewHolder) list.getChildViewHolder(list.getChildAt(i));
vh.rebind();
}
}
}
private class AddRowViewHolder extends BaseViewHolder implements UsableRecyclerView.Clickable{
public AddRowViewHolder(){
super(R.layout.item_profile_about_add_row);
}
@Override
public void onClick(){
metadataListData.add(new AccountField());
if(metadataListData.size()==MAX_FIELDS){ // replace this row with new row
adapter.notifyItemChanged(metadataListData.size()-1);
}else{
adapter.notifyItemInserted(metadataListData.size()-1);
rebind();
}
}
@Override
public void onBind(AccountField item) {}
}
private class ReorderCallback extends ItemTouchHelper.SimpleCallback{
public ReorderCallback(){
super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0);
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target){
if(target instanceof AddRowViewHolder)
return false;
int fromPosition=viewHolder.getAbsoluteAdapterPosition();
int toPosition=target.getAbsoluteAdapterPosition();
if (fromPosition<toPosition) {
for (int i=fromPosition;i<toPosition;i++) {
Collections.swap(metadataListData, i, i+1);
}
} else {
for (int i=fromPosition;i>toPosition;i--) {
Collections.swap(metadataListData, i, i-1);
}
}
adapter.notifyItemMoved(fromPosition, toPosition);
((BindableViewHolder)viewHolder).rebind();
((BindableViewHolder)target).rebind();
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction){
}
@Override
public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState){
super.onSelectedChanged(viewHolder, actionState);
if(actionState==ItemTouchHelper.ACTION_STATE_DRAG){
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;
}
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder){
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.animate().translationZ(0).setDuration(100).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
draggedViewHolder=null;
}
@Override
public boolean isLongPressDragEnabled(){
return false;
}
}
} }

View File

@@ -13,6 +13,7 @@ import org.joinmastodon.android.api.requests.statuses.CreateStatus;
import org.joinmastodon.android.api.requests.statuses.GetScheduledStatuses; import org.joinmastodon.android.api.requests.statuses.GetScheduledStatuses;
import org.joinmastodon.android.events.ScheduledStatusCreatedEvent; import org.joinmastodon.android.events.ScheduledStatusCreatedEvent;
import org.joinmastodon.android.events.ScheduledStatusDeletedEvent; import org.joinmastodon.android.events.ScheduledStatusDeletedEvent;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.HeaderPaginationList; import org.joinmastodon.android.model.HeaderPaginationList;
import org.joinmastodon.android.model.ScheduledStatus; import org.joinmastodon.android.model.ScheduledStatus;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
@@ -28,11 +29,11 @@ import me.grishka.appkit.api.SimpleCallback;
public class ScheduledStatusListFragment extends BaseStatusListFragment<ScheduledStatus> { public class ScheduledStatusListFragment extends BaseStatusListFragment<ScheduledStatus> {
private String nextMaxID; private String nextMaxID;
private ImageButton fab;
private static final int SCHEDULED_STATUS_LIST_OPENED = 161; private static final int SCHEDULED_STATUS_LIST_OPENED = 161;
public ScheduledStatusListFragment() { @Override
setListLayoutId(R.layout.recycler_fragment_with_fab); protected boolean withComposeButton() {
return true;
} }
@Override @Override
@@ -56,20 +57,30 @@ public class ScheduledStatusListFragment extends BaseStatusListFragment<Schedule
} }
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { protected void onFabClick(View v) {
super.onViewCreated(view, savedInstanceState);
fab=view.findViewById(R.id.fab);
Bundle args=new Bundle(); Bundle args=new Bundle();
args.putString("account", accountID); args.putString("account", accountID);
args.putSerializable("scheduledAt", CreateStatus.getDraftInstant()); args.putSerializable("scheduledAt", CreateStatus.getDraftInstant());
fab.setOnClickListener(v -> Nav.go(getActivity(), ComposeFragment.class, args)); Nav.go(getActivity(), ComposeFragment.class, args);
fab.setOnLongClickListener(v -> UiUtils.pickAccountForCompose(getActivity(), accountID, args)); }
@Override
protected boolean onFabLongClick(View v) {
Bundle args=new Bundle();
args.putString("account", accountID);
args.putSerializable("scheduledAt", CreateStatus.getDraftInstant());
return UiUtils.pickAccountForCompose(getActivity(), accountID, args);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (getArguments().getBoolean("hide_fab", false)) fab.setVisibility(View.GONE); if (getArguments().getBoolean("hide_fab", false)) fab.setVisibility(View.GONE);
} }
@Override @Override
protected List<StatusDisplayItem> buildDisplayItems(ScheduledStatus s) { protected List<StatusDisplayItem> buildDisplayItems(ScheduledStatus s) {
return StatusDisplayItem.buildItems(this, s.toStatus(), accountID, s, knownAccounts, false, false, null, true); return StatusDisplayItem.buildItems(this, s.toStatus(), accountID, s, knownAccounts, false, false, null, true, Filter.FilterContext.HOME);
} }
@Override @Override

View File

@@ -45,11 +45,13 @@ import org.joinmastodon.android.R;
import org.joinmastodon.android.api.MastodonAPIController; import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.PushSubscriptionManager; import org.joinmastodon.android.api.PushSubscriptionManager;
import org.joinmastodon.android.api.requests.oauth.RevokeOauthToken; import org.joinmastodon.android.api.requests.oauth.RevokeOauthToken;
import org.joinmastodon.android.api.session.AccountActivationInfo;
import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent; import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
import org.joinmastodon.android.fragments.onboarding.InstanceRulesFragment; import org.joinmastodon.android.fragments.onboarding.InstanceRulesFragment;
import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.fragments.onboarding.AccountActivationFragment;
import org.joinmastodon.android.model.PushNotification; import org.joinmastodon.android.model.PushNotification;
import org.joinmastodon.android.model.PushSubscription; import org.joinmastodon.android.model.PushSubscription;
import org.joinmastodon.android.ui.M3AlertDialogBuilder; import org.joinmastodon.android.ui.M3AlertDialogBuilder;
@@ -66,7 +68,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.Nav; import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse; import me.grishka.appkit.api.ErrorResponse;
@@ -222,15 +223,10 @@ public class SettingsFragment extends MastodonToolbarFragment{
GlobalUserPreferences.keepOnlyLatestNotification=i.checked; GlobalUserPreferences.keepOnlyLatestNotification=i.checked;
GlobalUserPreferences.save(); GlobalUserPreferences.save();
})); }));
// items.add(new SwitchItem(R.string.sk_settings_translate_only_opened, R.drawable.ic_fluent_translate_24_regular, GlobalUserPreferences.translateButtonOpenedOnly, i->{ items.add(new SwitchItem(R.string.sk_settings_prefix_reply_cw_with_re, R.drawable.ic_fluent_arrow_reply_24_regular, GlobalUserPreferences.prefixRepliesWithRe, i->{
// GlobalUserPreferences.translateButtonOpenedOnly=i.checked; GlobalUserPreferences.prefixRepliesWithRe=i.checked;
// GlobalUserPreferences.save(); GlobalUserPreferences.save();
// })); }));
// items.add(new SwitchItem(R.string.sk_settings_hide_translate_in_timeline, R.drawable.ic_fluent_translate_24_regular, GlobalUserPreferences.translateButtonOpenedOnly, i->{
// GlobalUserPreferences.translateButtonOpenedOnly=i.checked;
// GlobalUserPreferences.save();
// needAppRestart=true;
// }));
items.add(new HeaderItem(R.string.sk_timelines)); items.add(new HeaderItem(R.string.sk_timelines));
items.add(new SwitchItem(R.string.sk_settings_show_replies, R.drawable.ic_fluent_chat_multiple_24_regular, GlobalUserPreferences.showReplies, i->{ items.add(new SwitchItem(R.string.sk_settings_show_replies, R.drawable.ic_fluent_chat_multiple_24_regular, GlobalUserPreferences.showReplies, i->{
@@ -264,8 +260,21 @@ public class SettingsFragment extends MastodonToolbarFragment{
items.add(new SwitchItem(R.string.sk_settings_show_no_alt_indicator, R.drawable.ic_fluent_important_24_regular, GlobalUserPreferences.showNoAltIndicator, i->{ items.add(new SwitchItem(R.string.sk_settings_show_no_alt_indicator, R.drawable.ic_fluent_important_24_regular, GlobalUserPreferences.showNoAltIndicator, i->{
GlobalUserPreferences.showNoAltIndicator=i.checked; GlobalUserPreferences.showNoAltIndicator=i.checked;
GlobalUserPreferences.save(); GlobalUserPreferences.save();
}));
items.add(new SwitchItem(R.string.sk_settings_collapse_long_posts, R.drawable.ic_fluent_chevron_down_24_filled, GlobalUserPreferences.collapseLongPosts, i->{
GlobalUserPreferences.collapseLongPosts=i.checked;
GlobalUserPreferences.save();
}));
items.add(new SwitchItem(R.string.sk_spectator_mode, R.drawable.ic_fluent_eye_24_regular, GlobalUserPreferences.spectatorMode, i->{
GlobalUserPreferences.spectatorMode=i.checked;
GlobalUserPreferences.save();
needAppRestart=true; needAppRestart=true;
})); }));
// items.add(new SwitchItem(R.string.sk_settings_translate_only_opened, R.drawable.ic_fluent_translate_24_regular, GlobalUserPreferences.translateButtonOpenedOnly, i->{
// GlobalUserPreferences.translateButtonOpenedOnly=i.checked;
// GlobalUserPreferences.save();
// needAppRestart=true;
// }));
items.add(new HeaderItem(R.string.settings_notifications)); items.add(new HeaderItem(R.string.settings_notifications));
@@ -360,7 +369,20 @@ public class SettingsFragment extends MastodonToolbarFragment{
})); }));
// items.add(new TextItem(R.string.log_out, this::confirmLogOut)); // items.add(new TextItem(R.string.log_out, this::confirmLogOut));
items.add(new FooterItem(getString(R.string.mo_settings_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE))); if(BuildConfig.DEBUG){
items.add(new RedHeaderItem("Debug options"));
items.add(new TextItem("Test e-mail confirmation flow", ()->{
AccountSession sess=AccountSessionManager.getInstance().getAccount(accountID);
sess.activated=false;
sess.activationInfo=new AccountActivationInfo("test@email", System.currentTimeMillis());
Bundle args=new Bundle();
args.putString("account", accountID);
args.putBoolean("debug", true);
Nav.goClearingStack(getActivity(), AccountActivationFragment.class, args);
}));
}
items.add(new FooterItem(getString(R.string.sk_settings_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)));
} }
private void updatePublishText(Button btn) { private void updatePublishText(Button btn) {
@@ -645,7 +667,7 @@ public class SettingsFragment extends MastodonToolbarFragment{
this.text=getString(text); this.text=getString(text);
} }
public HeaderItem(String text) { public HeaderItem(String text){
this.text=text; this.text=text;
} }
@@ -763,6 +785,11 @@ public class SettingsFragment extends MastodonToolbarFragment{
this.secondaryText = secondaryText; this.secondaryText = secondaryText;
} }
public TextItem(String text, Runnable onClick){
this.text=text;
this.onClick=onClick;
}
@Override @Override
public int getViewType(){ public int getViewType(){
return 4; return 4;
@@ -775,6 +802,10 @@ public class SettingsFragment extends MastodonToolbarFragment{
super(text); super(text);
} }
public RedHeaderItem(String text){
super(text);
}
@Override @Override
public int getViewType(){ public int getViewType(){
return 5; return 5;

View File

@@ -6,6 +6,7 @@ import android.view.View;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.statuses.GetStatusEditHistory; import org.joinmastodon.android.api.requests.statuses.GetStatusEditHistory;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.displayitems.ReblogOrReplyLineStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.ReblogOrReplyLineStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem; import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
@@ -55,7 +56,7 @@ public class StatusEditHistoryFragment extends StatusListFragment{
@Override @Override
protected List<StatusDisplayItem> buildDisplayItems(Status s){ protected List<StatusDisplayItem> buildDisplayItems(Status s){
List<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, true, false, null); List<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, true, false, null, Filter.FilterContext.HOME);
int idx=data.indexOf(s); int idx=data.indexOf(s);
if(idx>=0){ if(idx>=0){
String date=UiUtils.DATE_TIME_FORMATTER.format(s.createdAt.atZone(ZoneId.systemDefault())); String date=UiUtils.DATE_TIME_FORMATTER.format(s.createdAt.atZone(ZoneId.systemDefault()));

View File

@@ -6,12 +6,14 @@ import android.os.Bundle;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E; import org.joinmastodon.android.E;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.events.PollUpdatedEvent; import org.joinmastodon.android.events.PollUpdatedEvent;
import org.joinmastodon.android.events.RemoveAccountPostsEvent; import org.joinmastodon.android.events.RemoveAccountPostsEvent;
import org.joinmastodon.android.events.StatusCountersUpdatedEvent; import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.events.StatusCreatedEvent; import org.joinmastodon.android.events.StatusCreatedEvent;
import org.joinmastodon.android.events.StatusDeletedEvent; import org.joinmastodon.android.events.StatusDeletedEvent;
import org.joinmastodon.android.events.StatusUpdatedEvent; import org.joinmastodon.android.events.StatusUpdatedEvent;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
@@ -30,7 +32,9 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>{
protected EventListener eventListener=new EventListener(); protected EventListener eventListener=new EventListener();
protected List<StatusDisplayItem> buildDisplayItems(Status s){ protected List<StatusDisplayItem> buildDisplayItems(Status s){
return StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, false, true, null); boolean addFooter = !GlobalUserPreferences.spectatorMode ||
(this instanceof ThreadFragment t && s.id.equals(t.mainStatus.id));
return StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, false, addFooter, null, Filter.FilterContext.HOME);
} }
@Override @Override
@@ -56,6 +60,7 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>{
Status status=getContentStatusByID(id); Status status=getContentStatusByID(id);
if(status==null) if(status==null)
return; return;
status.filterRevealed = true;
Bundle args=new Bundle(); Bundle args=new Bundle();
args.putString("account", accountID); args.putString("account", accountID);
args.putParcelable("status", Parcels.wrap(status)); args.putParcelable("status", Parcels.wrap(status));

View File

@@ -26,7 +26,7 @@ import java.util.stream.Collectors;
import me.grishka.appkit.api.SimpleCallback; import me.grishka.appkit.api.SimpleCallback;
public class ThreadFragment extends StatusListFragment{ public class ThreadFragment extends StatusListFragment{
private Status mainStatus; protected Status mainStatus;
@Override @Override
public void onCreate(Bundle savedInstanceState){ public void onCreate(Bundle savedInstanceState){

View File

@@ -129,7 +129,8 @@ public abstract class BaseAccountListFragment extends BaseRecyclerFragment<BaseA
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
// list.setPadding(0, V.dp(16), 0, V.dp(16)); // list.setPadding(0, V.dp(16), 0, V.dp(16));
list.setClipToPadding(false); list.setClipToPadding(false);
list.addItemDecoration(new DividerItemDecoration(getActivity(), R.attr.colorPollVoted, 1, 72, 16)); list.addItemDecoration(new DividerItemDecoration(getActivity(), R.attr.colorPollVoted, 1,
Math.round(16f + 56f * getResources().getConfiguration().fontScale), 16));
updateToolbar(); updateToolbar();
} }

View File

@@ -15,6 +15,7 @@ import android.widget.TextView;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships; import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
import org.joinmastodon.android.api.requests.accounts.GetFollowSuggestions; import org.joinmastodon.android.api.requests.accounts.GetFollowSuggestions;
import org.joinmastodon.android.fragments.IsOnTop;
import org.joinmastodon.android.fragments.ProfileFragment; import org.joinmastodon.android.fragments.ProfileFragment;
import org.joinmastodon.android.fragments.ScrollableToTop; import org.joinmastodon.android.fragments.ScrollableToTop;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
@@ -48,7 +49,7 @@ import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.V; import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.UsableRecyclerView; import me.grishka.appkit.views.UsableRecyclerView;
public class DiscoverAccountsFragment extends BaseRecyclerFragment<DiscoverAccountsFragment.AccountWrapper> implements ScrollableToTop{ public class DiscoverAccountsFragment extends BaseRecyclerFragment<DiscoverAccountsFragment.AccountWrapper> implements ScrollableToTop, IsOnTop {
private String accountID; private String accountID;
private Map<String, Relationship> relationships=Collections.emptyMap(); private Map<String, Relationship> relationships=Collections.emptyMap();
private GetAccountRelationships relationshipsRequest; private GetAccountRelationships relationshipsRequest;
@@ -139,6 +140,11 @@ public class DiscoverAccountsFragment extends BaseRecyclerFragment<DiscoverAccou
smoothScrollRecyclerViewToTop(list); smoothScrollRecyclerViewToTop(list);
} }
@Override
public boolean isOnTop() {
return isRecyclerViewOnTop(list);
}
private class AccountsAdapter extends UsableRecyclerView.Adapter<AccountViewHolder> implements ImageLoaderRecyclerAdapter{ private class AccountsAdapter extends UsableRecyclerView.Adapter<AccountViewHolder> implements ImageLoaderRecyclerAdapter{
public AccountsAdapter(){ public AccountsAdapter(){

View File

@@ -10,6 +10,7 @@ import android.widget.TextView;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.trends.GetTrendingLinks; import org.joinmastodon.android.api.requests.trends.GetTrendingLinks;
import org.joinmastodon.android.fragments.IsOnTop;
import org.joinmastodon.android.fragments.ScrollableToTop; import org.joinmastodon.android.fragments.ScrollableToTop;
import org.joinmastodon.android.model.Card; import org.joinmastodon.android.model.Card;
import org.joinmastodon.android.ui.DividerItemDecoration; import org.joinmastodon.android.ui.DividerItemDecoration;
@@ -34,7 +35,7 @@ import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.V; import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.UsableRecyclerView; import me.grishka.appkit.views.UsableRecyclerView;
public class DiscoverNewsFragment extends BaseRecyclerFragment<Card> implements ScrollableToTop{ public class DiscoverNewsFragment extends BaseRecyclerFragment<Card> implements ScrollableToTop, IsOnTop {
private String accountID; private String accountID;
private List<ImageLoaderRequest> imageRequests=Collections.emptyList(); private List<ImageLoaderRequest> imageRequests=Collections.emptyList();
private DiscoverInfoBannerHelper bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.TRENDING_LINKS); private DiscoverInfoBannerHelper bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.TRENDING_LINKS);
@@ -82,6 +83,11 @@ public class DiscoverNewsFragment extends BaseRecyclerFragment<Card> implements
smoothScrollRecyclerViewToTop(list); smoothScrollRecyclerViewToTop(list);
} }
@Override
public boolean isOnTop() {
return isRecyclerViewOnTop(list);
}
private class LinksAdapter extends UsableRecyclerView.Adapter<LinkViewHolder> implements ImageLoaderRecyclerAdapter{ private class LinksAdapter extends UsableRecyclerView.Adapter<LinkViewHolder> implements ImageLoaderRecyclerAdapter{
public LinksAdapter(){ public LinksAdapter(){
super(imgLoader); super(imgLoader);

View File

@@ -4,15 +4,19 @@ import android.os.Bundle;
import android.view.View; import android.view.View;
import org.joinmastodon.android.api.requests.trends.GetTrendingStatuses; import org.joinmastodon.android.api.requests.trends.GetTrendingStatuses;
import org.joinmastodon.android.fragments.IsOnTop;
import org.joinmastodon.android.fragments.StatusListFragment; import org.joinmastodon.android.fragments.StatusListFragment;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.utils.DiscoverInfoBannerHelper; import org.joinmastodon.android.ui.utils.DiscoverInfoBannerHelper;
import org.joinmastodon.android.utils.StatusFilterPredicate;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import me.grishka.appkit.api.SimpleCallback; import me.grishka.appkit.api.SimpleCallback;
public class DiscoverPostsFragment extends StatusListFragment{ public class DiscoverPostsFragment extends StatusListFragment implements IsOnTop {
private DiscoverInfoBannerHelper bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.TRENDING_POSTS); private DiscoverInfoBannerHelper bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.TRENDING_POSTS);
@Override @Override
@@ -22,6 +26,7 @@ public class DiscoverPostsFragment extends StatusListFragment{
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
if (getActivity() == null) return; if (getActivity() == null) return;
result=result.stream().filter(new StatusFilterPredicate(accountID, Filter.FilterContext.PUBLIC)).collect(Collectors.toList());
onDataLoaded(result, !result.isEmpty()); onDataLoaded(result, !result.isEmpty());
} }
}).exec(accountID); }).exec(accountID);
@@ -32,4 +37,9 @@ public class DiscoverPostsFragment extends StatusListFragment{
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
bannerHelper.maybeAddBanner(contentWrap); bannerHelper.maybeAddBanner(contentWrap);
} }
@Override
public boolean isOnTop() {
return isRecyclerViewOnTop(list);
}
} }

View File

@@ -5,7 +5,6 @@ import android.view.View;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.timelines.GetPublicTimeline; import org.joinmastodon.android.api.requests.timelines.GetPublicTimeline;
import org.joinmastodon.android.fragments.FabStatusListFragment;
import org.joinmastodon.android.fragments.StatusListFragment; import org.joinmastodon.android.fragments.StatusListFragment;
import org.joinmastodon.android.model.Filter; import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
@@ -17,10 +16,16 @@ import java.util.stream.Collectors;
import me.grishka.appkit.api.SimpleCallback; import me.grishka.appkit.api.SimpleCallback;
public class FederatedTimelineFragment extends FabStatusListFragment { public class FederatedTimelineFragment extends StatusListFragment {
private DiscoverInfoBannerHelper bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.FEDERATED_TIMELINE); private DiscoverInfoBannerHelper bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.FEDERATED_TIMELINE);
private String maxID; private String maxID;
@Override
protected boolean withComposeButton() {
return true;
}
@Override @Override
protected void doLoadData(int offset, int count){ protected void doLoadData(int offset, int count){
currentRequest=new GetPublicTimeline(false, false, refreshing ? null : maxID, count) currentRequest=new GetPublicTimeline(false, false, refreshing ? null : maxID, count)
@@ -30,7 +35,8 @@ public class FederatedTimelineFragment extends FabStatusListFragment {
if(!result.isEmpty()) if(!result.isEmpty())
maxID=result.get(result.size()-1).id; maxID=result.get(result.size()-1).id;
if (getActivity() == null) return; if (getActivity() == null) return;
onDataLoaded(result.stream().filter(new StatusFilterPredicate(accountID, Filter.FilterContext.PUBLIC)).collect(Collectors.toList()), !result.isEmpty()); result=result.stream().filter(new StatusFilterPredicate(accountID, Filter.FilterContext.PUBLIC)).collect(Collectors.toList());
onDataLoaded(result, !result.isEmpty());
} }
}) })
.exec(accountID); .exec(accountID);

View File

@@ -3,9 +3,7 @@ package org.joinmastodon.android.fragments.discover;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.timelines.GetPublicTimeline; import org.joinmastodon.android.api.requests.timelines.GetPublicTimeline;
import org.joinmastodon.android.fragments.FabStatusListFragment;
import org.joinmastodon.android.fragments.StatusListFragment; import org.joinmastodon.android.fragments.StatusListFragment;
import org.joinmastodon.android.model.Filter; import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
@@ -17,10 +15,16 @@ import java.util.stream.Collectors;
import me.grishka.appkit.api.SimpleCallback; import me.grishka.appkit.api.SimpleCallback;
public class LocalTimelineFragment extends FabStatusListFragment { public class LocalTimelineFragment extends StatusListFragment {
// private DiscoverInfoBannerHelper bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.LOCAL_TIMELINE); private DiscoverInfoBannerHelper bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.LOCAL_TIMELINE);
private String maxID; private String maxID;
@Override
protected boolean withComposeButton() {
return true;
}
@Override @Override
protected void doLoadData(int offset, int count){ protected void doLoadData(int offset, int count){
currentRequest=new GetPublicTimeline(true, false, refreshing ? null : maxID, count) currentRequest=new GetPublicTimeline(true, false, refreshing ? null : maxID, count)
@@ -30,7 +34,8 @@ public class LocalTimelineFragment extends FabStatusListFragment {
if(!result.isEmpty()) if(!result.isEmpty())
maxID=result.get(result.size()-1).id; maxID=result.get(result.size()-1).id;
if (getActivity() == null) return; if (getActivity() == null) return;
onDataLoaded(result.stream().filter(new StatusFilterPredicate(accountID, Filter.FilterContext.PUBLIC)).collect(Collectors.toList()), !result.isEmpty()); result=result.stream().filter(new StatusFilterPredicate(accountID, Filter.FilterContext.PUBLIC)).collect(Collectors.toList());
onDataLoaded(result, !result.isEmpty());
} }
}) })
.exec(accountID); .exec(accountID);
@@ -39,6 +44,6 @@ public class LocalTimelineFragment extends FabStatusListFragment {
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState){ public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
// bannerHelper.maybeAddBanner(contentWrap); bannerHelper.maybeAddBanner(contentWrap);
} }
} }

View File

@@ -14,6 +14,7 @@ import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.fragments.ProfileFragment; import org.joinmastodon.android.fragments.ProfileFragment;
import org.joinmastodon.android.fragments.ThreadFragment; import org.joinmastodon.android.fragments.ThreadFragment;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Hashtag; import org.joinmastodon.android.model.Hashtag;
import org.joinmastodon.android.model.SearchResult; import org.joinmastodon.android.model.SearchResult;
import org.joinmastodon.android.model.SearchResults; import org.joinmastodon.android.model.SearchResults;
@@ -80,7 +81,7 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
return switch(s.type){ return switch(s.type){
case ACCOUNT -> Collections.singletonList(new AccountStatusDisplayItem(s.id, this, s.account)); case ACCOUNT -> Collections.singletonList(new AccountStatusDisplayItem(s.id, this, s.account));
case HASHTAG -> Collections.singletonList(new HashtagStatusDisplayItem(s.id, this, s.hashtag)); case HASHTAG -> Collections.singletonList(new HashtagStatusDisplayItem(s.id, this, s.hashtag));
case STATUS -> StatusDisplayItem.buildItems(this, s.status, accountID, s, knownAccounts, false, true, null); case STATUS -> StatusDisplayItem.buildItems(this, s.status, accountID, s, knownAccounts, false, true, null, Filter.FilterContext.PUBLIC);
}; };
} }

View File

@@ -7,6 +7,7 @@ import android.widget.TextView;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.trends.GetTrendingHashtags; import org.joinmastodon.android.api.requests.trends.GetTrendingHashtags;
import org.joinmastodon.android.fragments.IsOnTop;
import org.joinmastodon.android.fragments.ScrollableToTop; import org.joinmastodon.android.fragments.ScrollableToTop;
import org.joinmastodon.android.model.Hashtag; import org.joinmastodon.android.model.Hashtag;
import org.joinmastodon.android.ui.DividerItemDecoration; import org.joinmastodon.android.ui.DividerItemDecoration;
@@ -23,7 +24,7 @@ import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.utils.BindableViewHolder; import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.views.UsableRecyclerView; import me.grishka.appkit.views.UsableRecyclerView;
public class TrendingHashtagsFragment extends BaseRecyclerFragment<Hashtag> implements ScrollableToTop{ public class TrendingHashtagsFragment extends BaseRecyclerFragment<Hashtag> implements ScrollableToTop, IsOnTop {
private String accountID; private String accountID;
private DiscoverInfoBannerHelper bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.TRENDING_HASHTAGS); private DiscoverInfoBannerHelper bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.TRENDING_HASHTAGS);
@@ -67,6 +68,11 @@ public class TrendingHashtagsFragment extends BaseRecyclerFragment<Hashtag> impl
smoothScrollRecyclerViewToTop(list); smoothScrollRecyclerViewToTop(list);
} }
@Override
public boolean isOnTop() {
return isRecyclerViewOnTop(list);
}
private class HashtagsAdapter extends RecyclerView.Adapter<HashtagViewHolder>{ private class HashtagsAdapter extends RecyclerView.Adapter<HashtagViewHolder>{
@NonNull @NonNull
@Override @Override

View File

@@ -193,30 +193,24 @@ public class AccountActivationFragment extends ToolbarFragment{
mgr.removeAccount(accountID); mgr.removeAccount(accountID);
mgr.addAccount(mgr.getInstanceInfo(session.domain), session.token, result, session.app, null); mgr.addAccount(mgr.getInstanceInfo(session.domain), session.token, result, session.app, null);
String newID=mgr.getLastActiveAccountID(); String newID=mgr.getLastActiveAccountID();
Bundle args=new Bundle(); accountID=newID;
args.putString("account", newID); if((session.self.avatar!=null || session.self.displayName!=null) && !getArguments().getBoolean("debug")){
if(session.self.avatar!=null || session.self.displayName!=null){ new UpdateAccountCredentials(session.self.displayName, "", (File)null, null, Collections.emptyList())
File avaFile=session.self.avatar!=null ? new File(session.self.avatar) : null;
new UpdateAccountCredentials(session.self.displayName, "", avaFile, null, Collections.emptyList())
.setCallback(new Callback<>(){ .setCallback(new Callback<>(){
@Override @Override
public void onSuccess(Account result){ public void onSuccess(Account result){
if(avaFile!=null)
avaFile.delete();
mgr.updateAccountInfo(newID, result); mgr.updateAccountInfo(newID, result);
Nav.goClearingStack(getActivity(), HomeFragment.class, args); proceed();
} }
@Override @Override
public void onError(ErrorResponse error){ public void onError(ErrorResponse error){
if(avaFile!=null) proceed();
avaFile.delete();
Nav.goClearingStack(getActivity(), HomeFragment.class, args);
} }
}) })
.exec(newID); .exec(newID);
}else{ }else{
Nav.goClearingStack(getActivity(), HomeFragment.class, args); proceed();
} }
} }
@@ -249,4 +243,11 @@ public class AccountActivationFragment extends ToolbarFragment{
super.onDestroyView(); super.onDestroyView();
resendBtn.removeCallbacks(resendTimer); resendBtn.removeCallbacks(resendTimer);
} }
private void proceed(){
Bundle args=new Bundle();
args.putString("account", accountID);
// Nav.goClearingStack(getActivity(), HomeFragment.class, args);
Nav.goClearingStack(getActivity(), OnboardingProfileSetupFragment.class, args);
}
} }

View File

@@ -63,6 +63,8 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
private ItemsAdapter itemsAdapter; private ItemsAdapter itemsAdapter;
private ElevationOnScrollListener onScrollListener; private ElevationOnScrollListener onScrollListener;
private static final int SIGNUP_REQUEST=722;
@Override @Override
public void onCreate(Bundle savedInstanceState){ public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -139,7 +141,16 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
protected void onButtonClick(){ protected void onButtonClick(){
Bundle args=new Bundle(); Bundle args=new Bundle();
args.putParcelable("instance", Parcels.wrap(instance)); args.putParcelable("instance", Parcels.wrap(instance));
Nav.go(getActivity(), SignupFragment.class, args); Nav.goForResult(getActivity(), SignupFragment.class, args, SIGNUP_REQUEST, this);
}
@Override
public void onFragmentResult(int reqCode, boolean success, Bundle result){
super.onFragmentResult(reqCode, success, result);
if(reqCode==SIGNUP_REQUEST && !success){
setResult(false, null);
Nav.finish(this);
}
} }
@Override @Override

View File

@@ -92,7 +92,7 @@ abstract class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInsta
protected boolean onSearchEnterPressed(TextView v, int actionId, KeyEvent event){ protected boolean onSearchEnterPressed(TextView v, int actionId, KeyEvent event){
if(event!=null && event.getAction()!=KeyEvent.ACTION_DOWN) if(event!=null && event.getAction()!=KeyEvent.ACTION_DOWN)
return true; return true;
currentSearchQuery=searchEdit.getText().toString().toLowerCase(); currentSearchQuery=searchEdit.getText().toString().toLowerCase().trim();
updateFilteredList(); updateFilteredList();
searchEdit.removeCallbacks(searchDebouncer); searchEdit.removeCallbacks(searchDebouncer);
Instance instance=instancesCache.get(normalizeInstanceDomain(currentSearchQuery)); Instance instance=instancesCache.get(normalizeInstanceDomain(currentSearchQuery));
@@ -106,7 +106,7 @@ abstract class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInsta
} }
protected void onSearchChangedDebounced(){ protected void onSearchChangedDebounced(){
currentSearchQuery=searchEdit.getText().toString().toLowerCase(); currentSearchQuery=searchEdit.getText().toString().toLowerCase().trim();
updateFilteredList(); updateFilteredList();
loadInstanceInfo(currentSearchQuery, false); loadInstanceInfo(currentSearchQuery, false);
} }

View File

@@ -527,6 +527,15 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
updateFilteredList(); updateFilteredList();
} }
@Override
protected void onShown(){
super.onShown();
if(!searchQueryMode){
// Prevent search view automatically getting focused when the user returns to this fragment
focusThing.requestFocus();
}
}
private class InstancesAdapter extends UsableRecyclerView.Adapter<InstanceCatalogSignupFragment.InstanceViewHolder>{ private class InstancesAdapter extends UsableRecyclerView.Adapter<InstanceCatalogSignupFragment.InstanceViewHolder>{
public InstancesAdapter(){ public InstancesAdapter(){
super(imgLoader); super(imgLoader);

View File

@@ -0,0 +1,350 @@
package org.joinmastodon.android.fragments.onboarding;
import android.app.ProgressDialog;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
import org.joinmastodon.android.api.requests.accounts.GetFollowSuggestions;
import org.joinmastodon.android.api.requests.accounts.SetAccountFollowed;
import org.joinmastodon.android.fragments.HomeFragment;
import org.joinmastodon.android.fragments.ProfileFragment;
import org.joinmastodon.android.model.FollowSuggestion;
import org.joinmastodon.android.model.ParsedAccount;
import org.joinmastodon.android.model.Relationship;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ProgressBarButton;
import org.joinmastodon.android.utils.ElevationOnScrollListener;
import org.parceler.Parcels;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import androidx.annotation.NonNull;
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.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;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
import me.grishka.appkit.views.UsableRecyclerView;
public class OnboardingFollowSuggestionsFragment extends BaseRecyclerFragment<ParsedAccount>{
private String accountID;
private Map<String, Relationship> relationships=Collections.emptyMap();
private GetAccountRelationships relationshipsRequest;
private View buttonBar;
private ElevationOnScrollListener onScrollListener;
private int numRunningFollowRequests=0;
public OnboardingFollowSuggestionsFragment(){
super(R.layout.fragment_onboarding_follow_suggestions, 40);
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setRetainInstance(true);
setTitle(R.string.popular_on_mastodon);
accountID=getArguments().getString("account");
loadData();
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
buttonBar=view.findViewById(R.id.button_bar);
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
list.addOnScrollListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
view.findViewById(R.id.btn_next).setOnClickListener(UiUtils.rateLimitedClickListener(this::onFollowAllClick));
view.findViewById(R.id.btn_skip).setOnClickListener(UiUtils.rateLimitedClickListener(v->proceed()));
}
@Override
protected void onUpdateToolbar(){
super.onUpdateToolbar();
getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
getToolbar().setElevation(0);
if(onScrollListener!=null){
onScrollListener.setViews(buttonBar, getToolbar());
}
}
@Override
protected void doLoadData(int offset, int count){
new GetFollowSuggestions(40)
.setCallback(new SimpleCallback<>(this){
@Override
public void onSuccess(List<FollowSuggestion> result){
onDataLoaded(result.stream().map(fs->new ParsedAccount(fs.account, accountID)).collect(Collectors.toList()), false);
loadRelationships();
}
})
.exec(accountID);
}
private void loadRelationships(){
relationships=Collections.emptyMap();
relationshipsRequest=new GetAccountRelationships(data.stream().map(fs->fs.account.id).collect(Collectors.toList()));
relationshipsRequest.setCallback(new Callback<>(){
@Override
public void onSuccess(List<Relationship> result){
relationshipsRequest=null;
relationships=result.stream().collect(Collectors.toMap(rel->rel.id, Function.identity()));
if(list==null)
return;
for(int i=0;i<list.getChildCount();i++){
RecyclerView.ViewHolder holder=list.getChildViewHolder(list.getChildAt(i));
if(holder instanceof SuggestionViewHolder svh)
svh.rebind();
}
}
@Override
public void onError(ErrorResponse error){
relationshipsRequest=null;
}
}).exec(accountID);
}
@Override
public void onApplyWindowInsets(WindowInsets insets){
if(Build.VERSION.SDK_INT>=27){
int inset=insets.getSystemWindowInsetBottom();
buttonBar.setPadding(0, 0, 0, inset>0 ? Math.max(inset, V.dp(36)) : 0);
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), 0));
}else{
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()));
}
}
@Override
protected RecyclerView.Adapter getAdapter(){
return new SuggestionsAdapter();
}
private void onFollowAllClick(View v){
if(!loaded || relationships.isEmpty())
return;
if(data.isEmpty()){
proceed();
return;
}
ArrayList<String> accountIdsToFollow=new ArrayList<>();
for(ParsedAccount acc:data){
Relationship rel=relationships.get(acc.account.id);
if(rel==null)
continue;
if(rel.canFollow())
accountIdsToFollow.add(acc.account.id);
}
final ProgressDialog progress=new ProgressDialog(getActivity());
progress.setIndeterminate(false);
progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progress.setMax(accountIdsToFollow.size());
progress.setCancelable(false);
progress.setMessage(getString(R.string.sending_follows));
progress.show();
for(int i=0;i<Math.min(accountIdsToFollow.size(), 5);i++){ // Send up to 5 requests in parallel
followNextAccount(accountIdsToFollow, progress);
}
}
private void followNextAccount(ArrayList<String> accountIdsToFollow, ProgressDialog progress){
if(accountIdsToFollow.isEmpty()){
if(numRunningFollowRequests==0){
progress.dismiss();
proceed();
}
return;
}
numRunningFollowRequests++;
String id=accountIdsToFollow.remove(0);
new SetAccountFollowed(id, true, true)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Relationship result){
numRunningFollowRequests--;
progress.setProgress(progress.getMax()-accountIdsToFollow.size()-numRunningFollowRequests);
followNextAccount(accountIdsToFollow, progress);
}
@Override
public void onError(ErrorResponse error){
numRunningFollowRequests--;
progress.setProgress(progress.getMax()-accountIdsToFollow.size()-numRunningFollowRequests);
followNextAccount(accountIdsToFollow, progress);
}
})
.exec(accountID);
}
private void proceed(){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), HomeFragment.class, args);
getActivity().getWindow().getDecorView().postDelayed(()->Nav.finish(this), 500);
}
@Override
protected boolean canGoBack(){
return true;
}
@Override
public void onToolbarNavigationClick(){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.goClearingStack(getActivity(), HomeFragment.class, args);
}
private class SuggestionsAdapter extends UsableRecyclerView.Adapter<SuggestionViewHolder> implements ImageLoaderRecyclerAdapter{
public SuggestionsAdapter(){
super(imgLoader);
}
@NonNull
@Override
public SuggestionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
return new SuggestionViewHolder();
}
@Override
public int getItemCount(){
return data.size();
}
@Override
public void onBindViewHolder(SuggestionViewHolder holder, int position){
holder.bind(data.get(position));
super.onBindViewHolder(holder, position);
}
@Override
public int getImageCountForItem(int position){
return data.get(position).emojiHelper.getImageCount()+1;
}
@Override
public ImageLoaderRequest getImageRequest(int position, int image){
ParsedAccount account=data.get(position);
if(image==0)
return account.avatarRequest;
return account.emojiHelper.getImageRequest(image-1);
}
}
private class SuggestionViewHolder extends BindableViewHolder<ParsedAccount> implements ImageLoaderViewHolder, UsableRecyclerView.Clickable{
private final TextView name, username, bio;
private final ImageView avatar;
private final ProgressBarButton actionButton;
private final ProgressBar actionProgress;
private final View actionWrap;
private Relationship relationship;
public SuggestionViewHolder(){
super(getActivity(), R.layout.item_user_row_m3, list);
name=findViewById(R.id.name);
username=findViewById(R.id.username);
bio=findViewById(R.id.bio);
avatar=findViewById(R.id.avatar);
actionButton=findViewById(R.id.action_btn);
actionProgress=findViewById(R.id.action_progress);
actionWrap=findViewById(R.id.action_btn_wrap);
avatar.setOutlineProvider(OutlineProviders.roundedRect(10));
avatar.setClipToOutline(true);
actionButton.setOnClickListener(UiUtils.rateLimitedClickListener(this::onActionButtonClick));
}
@Override
public void onBind(ParsedAccount item){
name.setText(item.parsedName);
username.setText(item.account.getDisplayUsername());
if(TextUtils.isEmpty(item.parsedBio)){
bio.setVisibility(View.GONE);
}else{
bio.setVisibility(View.VISIBLE);
bio.setText(item.parsedBio);
}
relationship=relationships.get(item.account.id);
if(relationship==null){
actionWrap.setVisibility(View.GONE);
}else{
actionWrap.setVisibility(View.VISIBLE);
UiUtils.setRelationshipToActionButtonM3(relationship, actionButton);
}
}
@Override
public void setImage(int index, Drawable image){
if(index==0){
avatar.setImageDrawable(image);
}else{
item.emojiHelper.setImageDrawable(index-1, image);
name.invalidate();
bio.invalidate();
}
if(image instanceof Animatable a && !a.isRunning())
a.start();
}
@Override
public void clearImage(int index){
setImage(index, null);
}
@Override
public void onClick(){
Bundle args=new Bundle();
args.putString("account", accountID);
args.putParcelable("profileAccount", Parcels.wrap(item.account));
Nav.go(getActivity(), ProfileFragment.class, args);
}
private void onActionButtonClick(View v){
itemView.setHasTransientState(true);
UiUtils.performAccountAction(getActivity(), item.account, accountID, relationship, actionButton, this::setActionProgressVisible, rel->{
itemView.setHasTransientState(false);
relationships.put(item.account.id, rel);
rebind();
});
}
private void setActionProgressVisible(boolean visible){
actionButton.setTextVisible(!visible);
actionProgress.setVisibility(visible ? View.VISIBLE : View.GONE);
actionButton.setClickable(!visible);
}
}
}

View File

@@ -0,0 +1,237 @@
package org.joinmastodon.android.fragments.onboarding;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ScrollView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.UpdateAccountCredentials;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.HomeFragment;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.AccountField;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ReorderableLinearLayout;
import org.joinmastodon.android.utils.ElevationOnScrollListener;
import java.util.ArrayList;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.ToolbarFragment;
import me.grishka.appkit.imageloader.ViewImageLoader;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
public class OnboardingProfileSetupFragment extends ToolbarFragment implements ReorderableLinearLayout.OnDragListener{
private Button btn;
private View buttonBar;
private String accountID;
private ElevationOnScrollListener onScrollListener;
private ScrollView scroller;
private EditText nameEdit, bioEdit;
private ImageView avaImage, coverImage;
private Button addRow;
private ReorderableLinearLayout profileFieldsLayout;
private Uri avatarUri, coverUri;
private static final int AVATAR_RESULT=348;
private static final int COVER_RESULT=183;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
setNavigationBarColor(UiUtils.getThemeColor(activity, R.attr.colorWindowBackground));
accountID=getArguments().getString("account");
setTitle(R.string.profile_setup);
}
@Override
public View onCreateContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view=inflater.inflate(R.layout.fragment_onboarding_profile_setup, container, false);
scroller=view.findViewById(R.id.scroller);
nameEdit=view.findViewById(R.id.display_name);
bioEdit=view.findViewById(R.id.bio);
avaImage=view.findViewById(R.id.avatar);
coverImage=view.findViewById(R.id.header);
addRow=view.findViewById(R.id.add_row);
profileFieldsLayout=view.findViewById(R.id.profile_fields);
btn=view.findViewById(R.id.btn_next);
btn.setOnClickListener(v->onButtonClick());
buttonBar=view.findViewById(R.id.button_bar);
avaImage.setOutlineProvider(OutlineProviders.roundedRect(24));
avaImage.setClipToOutline(true);
Account account=AccountSessionManager.getInstance().getAccount(accountID).self;
if(savedInstanceState==null){
nameEdit.setText(account.displayName);
makeFieldsRow();
}else{
ArrayList<String> fieldTitles=savedInstanceState.getStringArrayList("fieldTitles");
ArrayList<String> fieldValues=savedInstanceState.getStringArrayList("fieldValues");
for(int i=0;i<fieldTitles.size();i++){
View row=makeFieldsRow();
EditText title=row.findViewById(R.id.title);
EditText content=row.findViewById(R.id.content);
title.setText(fieldTitles.get(i));
content.setText(fieldValues.get(i));
}
if(fieldTitles.size()==4)
addRow.setVisibility(View.GONE);
}
addRow.setOnClickListener(v->{
makeFieldsRow();
if(profileFieldsLayout.getChildCount()==4){
addRow.setVisibility(View.GONE);
}
});
profileFieldsLayout.setDragListener(this);
avaImage.setOnClickListener(v->startActivityForResult(UiUtils.getMediaPickerIntent(new String[]{"image/*"}, 1), AVATAR_RESULT));
coverImage.setOnClickListener(v->startActivityForResult(UiUtils.getMediaPickerIntent(new String[]{"image/*"}, 1), COVER_RESULT));
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
scroller.setOnScrollChangeListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
}
@Override
protected void onUpdateToolbar(){
super.onUpdateToolbar();
getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
getToolbar().setElevation(0);
if(onScrollListener!=null){
onScrollListener.setViews(buttonBar, getToolbar());
}
}
protected void onButtonClick(){
ArrayList<AccountField> fields=new ArrayList<>();
for(int i=0;i<profileFieldsLayout.getChildCount();i++){
View row=profileFieldsLayout.getChildAt(i);
EditText title=row.findViewById(R.id.title);
EditText content=row.findViewById(R.id.content);
AccountField fld=new AccountField();
fld.name=title.getText().toString();
fld.value=content.getText().toString();
fields.add(fld);
}
new UpdateAccountCredentials(nameEdit.getText().toString(), bioEdit.getText().toString(), avatarUri, coverUri, fields)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Account result){
AccountSessionManager.getInstance().updateAccountInfo(accountID, result);
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), OnboardingFollowSuggestionsFragment.class, args);
getActivity().getWindow().getDecorView().postDelayed(()->Nav.finish(OnboardingProfileSetupFragment.this), 500);
}
@Override
public void onError(ErrorResponse error){
error.showToast(getActivity());
}
})
.wrapProgress(getActivity(), R.string.saving, true)
.exec(accountID);
}
@Override
public void onApplyWindowInsets(WindowInsets insets){
if(Build.VERSION.SDK_INT>=27){
int inset=insets.getSystemWindowInsetBottom();
buttonBar.setPadding(0, 0, 0, inset>0 ? Math.max(inset, V.dp(36)) : 0);
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), 0));
}else{
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()));
}
}
private View makeFieldsRow(){
View view=LayoutInflater.from(getActivity()).inflate(R.layout.onboarding_profile_field, profileFieldsLayout, false);
profileFieldsLayout.addView(view);
view.findViewById(R.id.dragger_thingy).setOnLongClickListener(v->{
profileFieldsLayout.startDragging(view);
return true;
});
return view;
}
@Override
public void onSwapItems(int oldIndex, int newIndex){}
@Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
ArrayList<String> fieldTitles=new ArrayList<>(), fieldValues=new ArrayList<>();
for(int i=0;i<profileFieldsLayout.getChildCount();i++){
View row=profileFieldsLayout.getChildAt(i);
EditText title=row.findViewById(R.id.title);
EditText content=row.findViewById(R.id.content);
fieldTitles.add(title.getText().toString());
fieldValues.add(content.getText().toString());
}
outState.putStringArrayList("fieldTitles", fieldTitles);
outState.putStringArrayList("fieldValues", fieldValues);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(resultCode!=Activity.RESULT_OK)
return;
ImageView img;
Uri uri=data.getData();
int size;
if(requestCode==AVATAR_RESULT){
img=avaImage;
avatarUri=uri;
size=V.dp(100);
}else{
img=coverImage;
coverUri=uri;
size=V.dp(1000);
}
img.setForeground(null);
ViewImageLoader.load(img, null, new UrlImageLoaderRequest(uri, size, size));
}
@Override
protected boolean canGoBack(){
return true;
}
@Override
public void onToolbarNavigationClick(){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.goClearingStack(getActivity(), HomeFragment.class, args);
}
}

View File

@@ -1,14 +1,18 @@
package org.joinmastodon.android.fragments.onboarding; package org.joinmastodon.android.fragments.onboarding;
import android.app.Activity;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Intent; import android.graphics.Typeface;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable; import android.text.Editable;
import android.text.Html;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.Log; import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -16,11 +20,9 @@ import android.view.ViewTreeObserver;
import android.view.WindowInsets; import android.view.WindowInsets;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.MastodonDetailedErrorResponse; import org.joinmastodon.android.api.MastodonDetailedErrorResponse;
import org.joinmastodon.android.api.requests.accounts.RegisterAccount; import org.joinmastodon.android.api.requests.accounts.RegisterAccount;
import org.joinmastodon.android.api.requests.oauth.CreateOAuthApp; import org.joinmastodon.android.api.requests.oauth.CreateOAuthApp;
@@ -31,18 +33,22 @@ import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Application; import org.joinmastodon.android.model.Application;
import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Token; import org.joinmastodon.android.model.Token;
import org.joinmastodon.android.ui.text.LinkSpan;
import org.joinmastodon.android.ui.utils.SimpleTextWatcher; import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.FloatingHintEditTextLayout; import org.joinmastodon.android.ui.views.FloatingHintEditTextLayout;
import org.joinmastodon.android.utils.ElevationOnScrollListener;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.NodeVisitor;
import org.parceler.Parcels; import org.parceler.Parcels;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -51,12 +57,10 @@ import me.grishka.appkit.api.APIRequest;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse; import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.ToolbarFragment; import me.grishka.appkit.fragments.ToolbarFragment;
import me.grishka.appkit.imageloader.ViewImageLoader;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.V; import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
public class SignupFragment extends ToolbarFragment{ public class SignupFragment extends ToolbarFragment{
private static final int AVATAR_RESULT=198;
private static final String TAG="SignupFragment"; private static final String TAG="SignupFragment";
private Instance instance; private Instance instance;
@@ -73,6 +77,7 @@ public class SignupFragment extends ToolbarFragment{
private boolean submitAfterGettingToken; private boolean submitAfterGettingToken;
private ProgressDialog progressDialog; private ProgressDialog progressDialog;
private HashSet<EditText> errorFields=new HashSet<>(); private HashSet<EditText> errorFields=new HashSet<>();
private ElevationOnScrollListener onScrollListener;
@Override @Override
public void onCreate(Bundle savedInstanceState){ public void onCreate(Bundle savedInstanceState){
@@ -145,19 +150,22 @@ public class SignupFragment extends ToolbarFragment{
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background)); setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background)); view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
view.findViewById(R.id.scroller).setOnScrollChangeListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
} }
// @Override @Override
protected void onUpdateToolbar(){ protected void onUpdateToolbar(){
// super.onUpdateToolbar(); super.onUpdateToolbar();
getToolbar().setBackground(null); getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
getToolbar().setElevation(0); getToolbar().setElevation(0);
if(onScrollListener!=null){
onScrollListener.setViews(buttonBar, getToolbar());
}
} }
private void onButtonClick(){ private void onButtonClick(){
if(!password.getText().toString().equals(passwordConfirm.getText().toString())){ if(!password.getText().toString().equals(passwordConfirm.getText().toString())){
passwordConfirm.setError(getString(R.string.signup_passwords_dont_match)); passwordConfirmWrap.setErrorState(getString(R.string.signup_passwords_dont_match));
passwordConfirmWrap.setErrorState();
return; return;
} }
showProgressDialog(); showProgressDialog();
@@ -212,8 +220,22 @@ public class SignupFragment extends ToolbarFragment{
anyFieldsSkipped=true; anyFieldsSkipped=true;
continue; continue;
} }
field.setError(fieldErrors.get(fieldName).stream().map(err->err.description).collect(Collectors.joining("\n"))); List<MastodonDetailedErrorResponse.FieldError> errors=Objects.requireNonNull(fieldErrors.get(fieldName));
getFieldWrapByName(fieldName).setErrorState(); if(errors.size()==1){
getFieldWrapByName(fieldName).setErrorState(getErrorDescription(errors.get(0), fieldName));
}else{
SpannableStringBuilder ssb=new SpannableStringBuilder();
boolean firstErr=true;
for(MastodonDetailedErrorResponse.FieldError err:errors){
if(firstErr){
firstErr=false;
}else{
ssb.append('\n');
}
ssb.append(getErrorDescription(err, fieldName));
}
getFieldWrapByName(fieldName).setErrorState(getErrorDescription(errors.get(0), fieldName));
}
errorFields.add(field); errorFields.add(field);
if(first){ if(first){
first=false; first=false;
@@ -231,6 +253,40 @@ public class SignupFragment extends ToolbarFragment{
.exec(instance.uri, apiToken); .exec(instance.uri, apiToken);
} }
private CharSequence getErrorDescription(MastodonDetailedErrorResponse.FieldError error, String fieldName){
return switch(fieldName){
case "email" -> switch(error.error){
case "ERR_BLOCKED" -> {
String emailAddr=email.getText().toString();
String s=getResources().getString(R.string.signup_email_domain_blocked, TextUtils.htmlEncode(instance.uri), TextUtils.htmlEncode(emailAddr.substring(emailAddr.lastIndexOf('@')+1)));
SpannableStringBuilder ssb=new SpannableStringBuilder();
Jsoup.parseBodyFragment(s).body().traverse(new NodeVisitor(){
private int spanStart;
@Override
public void head(Node node, int depth){
if(node instanceof TextNode tn){
ssb.append(tn.text());
}else if(node instanceof Element){
spanStart=ssb.length();
}
}
@Override
public void tail(Node node, int depth){
if(node instanceof Element){
ssb.setSpan(new LinkSpan("", SignupFragment.this::onGoBackLinkClick, LinkSpan.Type.CUSTOM, null), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new TypefaceSpan("sans-serif-medium"), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
});
yield ssb;
}
default -> error.description;
};
default -> error.description;
};
}
private EditText getFieldByName(String name){ private EditText getFieldByName(String name){
return switch(name){ return switch(name){
case "email" -> email; case "email" -> email;
@@ -323,6 +379,11 @@ public class SignupFragment extends ToolbarFragment{
} }
} }
private void onGoBackLinkClick(LinkSpan span){
setResult(false, null);
Nav.finish(this);
}
private class ErrorClearingListener implements TextWatcher{ private class ErrorClearingListener implements TextWatcher{
public final EditText editText; public final EditText editText;

View File

@@ -21,6 +21,7 @@ import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses;
import org.joinmastodon.android.events.FinishReportFragmentsEvent; import org.joinmastodon.android.events.FinishReportFragmentsEvent;
import org.joinmastodon.android.fragments.StatusListFragment; import org.joinmastodon.android.fragments.StatusListFragment;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.PhotoLayoutHelper; import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.displayitems.AudioStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.AudioStatusDisplayItem;
@@ -238,7 +239,7 @@ public class ReportAddPostsChoiceFragment extends StatusListFragment{
@Override @Override
protected List<StatusDisplayItem> buildDisplayItems(Status s){ protected List<StatusDisplayItem> buildDisplayItems(Status s){
List<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, true, false, null); List<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, true, false, null, Filter.FilterContext.HOME);
for(StatusDisplayItem item:items){ for(StatusDisplayItem item:items){
if(item instanceof ImageStatusDisplayItem isdi){ if(item instanceof ImageStatusDisplayItem isdi){
isdi.horizontalInset=V.dp(40+32); isdi.horizontalInset=V.dp(40+32);

View File

@@ -9,6 +9,7 @@ import android.view.ViewGroup;
import android.view.WindowInsets; import android.view.WindowInsets;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView; import android.widget.TextView;
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
@@ -28,15 +29,17 @@ import java.util.ArrayList;
import me.grishka.appkit.Nav; import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse; import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.ToolbarFragment;
import me.grishka.appkit.utils.V; import me.grishka.appkit.utils.V;
public class ReportCommentFragment extends MastodonToolbarFragment{ public class ReportCommentFragment extends MastodonToolbarFragment{
private String accountID; private String accountID;
private Account reportAccount; private Account reportAccount;
private Button btn; private Button btn;
private View buttonBar; private View buttonBar, forwardReportItem;
private TextView forwardReportText;
private Switch forwardReportSwitch;
private EditText commentEdit; private EditText commentEdit;
private boolean forwardReport;
@Override @Override
public void onCreate(Bundle savedInstanceState){ public void onCreate(Bundle savedInstanceState){
@@ -77,7 +80,17 @@ public class ReportCommentFragment extends MastodonToolbarFragment{
view.findViewById(R.id.btn_back).setOnClickListener(this::onButtonClick); view.findViewById(R.id.btn_back).setOnClickListener(this::onButtonClick);
buttonBar=view.findViewById(R.id.button_bar); buttonBar=view.findViewById(R.id.button_bar);
commentEdit=view.findViewById(R.id.text); commentEdit=view.findViewById(R.id.text);
forwardReportSwitch = view.findViewById(R.id.forward_report_switch);
forwardReportItem = view.findViewById(R.id.forward_report);
forwardReportText = view.findViewById(R.id.forward_report_text);
String domain = reportAccount.getDomain();
if (domain == null) {
forwardReportItem.setVisibility(View.GONE);
} else {
forwardReportItem.setOnClickListener(this::onForwardReportClick);
forwardReportText.setText(getActivity().getString(R.string.sk_forward_report_to, domain));
forwardReportSwitch.setChecked(forwardReport = true);
}
return view; return view;
} }
@@ -102,7 +115,7 @@ public class ReportCommentFragment extends MastodonToolbarFragment{
ReportReason reason=ReportReason.valueOf(getArguments().getString("reason")); ReportReason reason=ReportReason.valueOf(getArguments().getString("reason"));
ArrayList<String> statusIDs=getArguments().getStringArrayList("statusIDs"); ArrayList<String> statusIDs=getArguments().getStringArrayList("statusIDs");
ArrayList<String> ruleIDs=getArguments().getStringArrayList("ruleIDs"); ArrayList<String> ruleIDs=getArguments().getStringArrayList("ruleIDs");
new SendReport(reportAccount.id, reason, statusIDs, ruleIDs, v.getId()==R.id.btn_back ? null : commentEdit.getText().toString(), true) new SendReport(reportAccount.id, reason, statusIDs, ruleIDs, v.getId()==R.id.btn_back ? null : commentEdit.getText().toString(), forwardReport)
.setCallback(new Callback<>(){ .setCallback(new Callback<>(){
@Override @Override
public void onSuccess(Object result){ public void onSuccess(Object result){
@@ -123,6 +136,11 @@ public class ReportCommentFragment extends MastodonToolbarFragment{
.exec(accountID); .exec(accountID);
} }
private void onForwardReportClick(View v) {
forwardReport = !forwardReport;
forwardReportSwitch.setChecked(forwardReport);
}
@Subscribe @Subscribe
public void onFinishReportFragments(FinishReportFragmentsEvent ev){ public void onFinishReportFragments(FinishReportFragmentsEvent ev){
if(ev.reportAccountID.equals(reportAccount.id)) if(ev.reportAccountID.equals(reportAccount.id))

View File

@@ -133,6 +133,14 @@ public class Account extends BaseModel{
*/ */
public Instant muteExpiresAt; public Instant muteExpiresAt;
public List<Role> roles;
@Parcel
public static class Role {
public String name;
/** #rrggbb */
public String color;
}
@Override @Override
public void postprocess() throws ObjectValidationException{ public void postprocess() throws ObjectValidationException{

View File

@@ -52,6 +52,7 @@ public class Filter extends BaseModel{
else else
pattern=Pattern.compile(Pattern.quote(phrase), Pattern.CASE_INSENSITIVE); pattern=Pattern.compile(Pattern.quote(phrase), Pattern.CASE_INSENSITIVE);
} }
if (title == null) title = phrase;
return pattern.matcher(text).find(); return pattern.matcher(text).find();
} }
@@ -80,7 +81,9 @@ public class Filter extends BaseModel{
@SerializedName("public") @SerializedName("public")
PUBLIC, PUBLIC,
@SerializedName("thread") @SerializedName("thread")
THREAD THREAD,
@SerializedName("account")
ACCOUNT
} }
public enum FilterAction{ public enum FilterAction{

View File

@@ -45,7 +45,7 @@ public class Instance extends BaseModel{
@RequiredField @RequiredField
public String version; public String version;
/** /**
* Primary langauges of the website and its staff. * Primary languages of the website and its staff.
*/ */
// @RequiredField // @RequiredField
public List<String> languages; public List<String> languages;

View File

@@ -0,0 +1,33 @@
package org.joinmastodon.android.model;
import android.text.SpannableStringBuilder;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
import java.util.Collections;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.V;
public class ParsedAccount{
public Account account;
public CharSequence parsedName, parsedBio;
public CustomEmojiHelper emojiHelper;
public ImageLoaderRequest avatarRequest;
public ParsedAccount(Account account, String accountID){
this.account=account;
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
emojiHelper=new CustomEmojiHelper();
SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName);
ssb.append(parsedBio);
emojiHelper.setText(ssb);
avatarRequest=new UrlImageLoaderRequest(GlobalUserPreferences.playGifs ? account.avatar : account.avatarStatic, V.dp(40), V.dp(40));
}
}

View File

@@ -18,6 +18,10 @@ public class Relationship extends BaseModel{
public boolean blockedBy; public boolean blockedBy;
public String note; public String note;
public boolean canFollow(){
return !(following || blocking || blockedBy || domainBlocking);
}
@Override @Override
public String toString(){ public String toString(){
return "Relationship{"+ return "Relationship{"+

View File

@@ -62,19 +62,13 @@ public class ScheduledStatus extends BaseModel implements DisplayItemsParent{
} }
public Status toStatus() { public Status toStatus() {
Status s = new Status(); Status s = Status.ofFake(id, params.text, scheduledAt);
s.id = id;
s.mediaAttachments = mediaAttachments; s.mediaAttachments = mediaAttachments;
s.createdAt = scheduledAt;
s.inReplyToId = params.inReplyToId > 0 ? "" + params.inReplyToId : null; s.inReplyToId = params.inReplyToId > 0 ? "" + params.inReplyToId : null;
s.content = s.text = params.text;
s.spoilerText = params.spoilerText; s.spoilerText = params.spoilerText;
s.visibility = params.visibility; s.visibility = params.visibility;
s.language = params.language; s.language = params.language;
s.sensitive = params.sensitive; s.sensitive = params.sensitive;
s.mentions = List.of();
s.tags = List.of();
s.emojis = List.of();
if (params.poll != null) s.poll = params.poll.toPoll(); if (params.poll != null) s.poll = params.poll.toPoll();
return s; return s;
} }

View File

@@ -58,9 +58,9 @@ public class Status extends BaseModel implements DisplayItemsParent{
public boolean bookmarked; public boolean bookmarked;
public boolean pinned; public boolean pinned;
public boolean filterRevealed; public transient boolean filterRevealed;
public transient boolean spoilerRevealed; public transient boolean spoilerRevealed;
public transient boolean textExpanded, textExpandable;
public transient boolean hasGapAfter; public transient boolean hasGapAfter;
private transient String strippedText; private transient String strippedText;
@@ -160,6 +160,7 @@ public class Status extends BaseModel implements DisplayItemsParent{
s.mentions = List.of(); s.mentions = List.of();
s.tags = List.of(); s.tags = List.of();
s.emojis = List.of(); s.emojis = List.of();
s.filtered = List.of();
return s; return s;
} }
} }

View File

@@ -23,6 +23,8 @@ import android.widget.PopupMenu;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.StringRes;
import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships; import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
@@ -140,7 +142,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
public static class Holder extends StatusDisplayItem.Holder<HeaderStatusDisplayItem> implements ImageLoaderViewHolder{ public static class Holder extends StatusDisplayItem.Holder<HeaderStatusDisplayItem> implements ImageLoaderViewHolder{
private final TextView name, username, timestamp, extraText, separator; private final TextView name, username, timestamp, extraText, separator;
private final ImageView avatar, more, visibility, deleteNotification, unreadIndicator, botIcon; private final View collapseBtn;
private final ImageView avatar, more, visibility, deleteNotification, unreadIndicator, collapseBtnIcon,botIcon;
private final PopupMenu optionsMenu; private final PopupMenu optionsMenu;
private Relationship relationship; private Relationship relationship;
private APIRequest<?> currentRelationshipRequest; private APIRequest<?> currentRelationshipRequest;
@@ -163,6 +166,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
visibility=findViewById(R.id.visibility); visibility=findViewById(R.id.visibility);
deleteNotification=findViewById(R.id.delete_notification); deleteNotification=findViewById(R.id.delete_notification);
unreadIndicator=findViewById(R.id.unread_indicator); unreadIndicator=findViewById(R.id.unread_indicator);
collapseBtn=findViewById(R.id.collapse_btn);
collapseBtnIcon=findViewById(R.id.collapse_btn_icon);
botIcon=findViewById(R.id.bot_icon); botIcon=findViewById(R.id.bot_icon);
extraText=findViewById(R.id.extra_text); extraText=findViewById(R.id.extra_text);
avatar.setOnClickListener(this::onAvaClick); avatar.setOnClickListener(this::onAvaClick);
@@ -175,6 +180,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
fragment.removeNotification(item.notification); fragment.removeNotification(item.notification);
} }
})); }));
collapseBtn.setOnClickListener(l -> item.parentFragment.onToggleExpanded(item.status, getItemID()));
optionsMenu=new PopupMenu(activity, more); optionsMenu=new PopupMenu(activity, more);
@@ -326,7 +332,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.getDefault()); DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.getDefault());
timestamp.setText(item.scheduledStatus.scheduledAt.atZone(ZoneId.systemDefault()).format(formatter)); timestamp.setText(item.scheduledStatus.scheduledAt.atZone(ZoneId.systemDefault()).format(formatter));
} }
else if ((item.status==null || item.status.editedAt==null) && item.createdAt != null) else if ((!item.inset || item.status==null || item.status.editedAt==null) && item.createdAt != null)
timestamp.setText(UiUtils.formatRelativeTimestamp(itemView.getContext(), item.createdAt)); timestamp.setText(UiUtils.formatRelativeTimestamp(itemView.getContext(), item.createdAt));
else if (item.status != null && item.status.editedAt != null) else if (item.status != null && item.status.editedAt != null)
timestamp.setText(item.parentFragment.getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(itemView.getContext(), item.status.editedAt))); timestamp.setText(item.parentFragment.getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(itemView.getContext(), item.status.editedAt)));
@@ -400,6 +406,16 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
more.setContentDescription(desc); more.setContentDescription(desc);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) more.setTooltipText(desc); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) more.setTooltipText(desc);
if (item.status == null || !item.status.textExpandable) {
collapseBtn.setVisibility(View.GONE);
} else {
String collapseText = item.parentFragment.getString(item.status.textExpanded ? R.string.sk_collapse : R.string.sk_expand);
collapseBtn.setVisibility(item.status.textExpandable ? View.VISIBLE : View.GONE);
collapseBtn.setContentDescription(collapseText);
if (GlobalUserPreferences.reduceMotion) collapseBtnIcon.setScaleY(item.status.textExpanded ? -1 : 1);
else collapseBtnIcon.animate().scaleY(item.status.textExpanded ? -1 : 1).start();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) collapseBtn.setTooltipText(collapseText);
}
} }
@Override @Override

View File

@@ -1,12 +1,21 @@
package org.joinmastodon.android.ui.displayitems; package org.joinmastodon.android.ui.displayitems;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity; import android.app.Activity;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Attachment; import org.joinmastodon.android.model.Attachment;
@@ -19,6 +28,7 @@ import org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout;
import androidx.annotation.LayoutRes; import androidx.annotation.LayoutRes;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder; import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest; import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
import me.grishka.appkit.utils.CubicBezierInterpolator;
public abstract class ImageStatusDisplayItem extends StatusDisplayItem{ public abstract class ImageStatusDisplayItem extends StatusDisplayItem{
public final int index; public final int index;
@@ -56,11 +66,35 @@ public abstract class ImageStatusDisplayItem extends StatusDisplayItem{
private BlurhashCrossfadeDrawable crossfadeDrawable=new BlurhashCrossfadeDrawable(); private BlurhashCrossfadeDrawable crossfadeDrawable=new BlurhashCrossfadeDrawable();
private boolean didClear; private boolean didClear;
private AnimatorSet currentAnim;
private final FrameLayout altTextWrapper;
private final TextView altTextButton;
private final ImageView noAltTextButton;
private final View altTextScroller;
private final ImageButton altTextClose;
private final TextView altText, noAltText;
private View altOrNoAltButton;
private boolean altTextShown;
public Holder(Activity activity, @LayoutRes int layout, ViewGroup parent){ public Holder(Activity activity, @LayoutRes int layout, ViewGroup parent){
super(activity, layout, parent); super(activity, layout, parent);
photo=findViewById(R.id.photo); photo=findViewById(R.id.photo);
photo.setOnClickListener(this::onViewClick); photo.setOnClickListener(this::onViewClick);
this.layout=(ImageAttachmentFrameLayout)itemView; this.layout=(ImageAttachmentFrameLayout)itemView;
altTextWrapper=findViewById(R.id.alt_text_wrapper);
altTextButton=findViewById(R.id.alt_button);
noAltTextButton=findViewById(R.id.no_alt_button);
altTextScroller=findViewById(R.id.alt_text_scroller);
altTextClose=findViewById(R.id.alt_text_close);
altText=findViewById(R.id.alt_text);
noAltText=findViewById(R.id.no_alt_text);
altTextButton.setOnClickListener(this::onShowHideClick);
noAltTextButton.setOnClickListener(this::onShowHideClick);
altTextClose.setOnClickListener(this::onShowHideClick);
// altTextScroller.setNestedScrollingEnabled(true);
} }
@Override @Override
@@ -74,6 +108,110 @@ public abstract class ImageStatusDisplayItem extends StatusDisplayItem{
photo.setContentDescription(TextUtils.isEmpty(item.attachment.description) ? item.parentFragment.getString(R.string.media_no_description) : item.attachment.description); photo.setContentDescription(TextUtils.isEmpty(item.attachment.description) ? item.parentFragment.getString(R.string.media_no_description) : item.attachment.description);
didClear=false; didClear=false;
if (currentAnim != null) currentAnim.cancel();
boolean altTextMissing = TextUtils.isEmpty(item.attachment.description);
altOrNoAltButton = altTextMissing ? noAltTextButton : altTextButton;
altTextShown=false;
altTextScroller.setVisibility(View.GONE);
altTextClose.setVisibility(View.GONE);
altTextButton.setVisibility(View.VISIBLE);
noAltTextButton.setVisibility(View.VISIBLE);
altTextButton.setAlpha(1f);
noAltTextButton.setAlpha(1f);
altTextWrapper.setVisibility(View.VISIBLE);
if (altTextMissing){
if (GlobalUserPreferences.showNoAltIndicator) {
noAltTextButton.setVisibility(View.VISIBLE);
noAltText.setVisibility(View.VISIBLE);
altTextWrapper.setBackgroundResource(R.drawable.bg_image_no_alt_overlay);
altTextButton.setVisibility(View.GONE);
altText.setVisibility(View.GONE);
} else {
altTextWrapper.setVisibility(View.GONE);
}
}else{
if (GlobalUserPreferences.showAltIndicator) {
noAltTextButton.setVisibility(View.GONE);
noAltText.setVisibility(View.GONE);
altTextWrapper.setBackgroundResource(R.drawable.bg_image_alt_overlay);
altTextButton.setVisibility(View.VISIBLE);
altTextButton.setText(R.string.sk_alt_button);
altText.setVisibility(View.VISIBLE);
altText.setText(item.attachment.description);
altText.setPadding(0, 0, 0, 0);
} else {
altTextWrapper.setVisibility(View.GONE);
}
}
}
private void onShowHideClick(View v){
boolean show=v.getId()==R.id.alt_button || v.getId()==R.id.no_alt_button;
if(altTextShown==show)
return;
if(currentAnim!=null)
currentAnim.cancel();
altTextShown=show;
if(show){
altTextScroller.setVisibility(View.VISIBLE);
altTextClose.setVisibility(View.VISIBLE);
}else{
altOrNoAltButton.setVisibility(View.VISIBLE);
// Hide these views temporarily so FrameLayout measures correctly
altTextScroller.setVisibility(View.GONE);
altTextClose.setVisibility(View.GONE);
}
// This is the current size...
int prevLeft=altTextWrapper.getLeft();
int prevRight=altTextWrapper.getRight();
int prevTop=altTextWrapper.getTop();
altTextWrapper.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
@Override
public boolean onPreDraw(){
altTextWrapper.getViewTreeObserver().removeOnPreDrawListener(this);
// ...and this is after the layout pass, right now the FrameLayout has its final size, but we animate that change
if(!show){
// Show these views again so they're visible for the duration of the animation.
// No one would notice they were missing during measure/layout.
altTextScroller.setVisibility(View.VISIBLE);
altTextClose.setVisibility(View.VISIBLE);
}
AnimatorSet set=new AnimatorSet();
set.playTogether(
ObjectAnimator.ofInt(altTextWrapper, "left", prevLeft, altTextWrapper.getLeft()),
ObjectAnimator.ofInt(altTextWrapper, "right", prevRight, altTextWrapper.getRight()),
ObjectAnimator.ofInt(altTextWrapper, "top", prevTop, altTextWrapper.getTop()),
ObjectAnimator.ofFloat(altOrNoAltButton, View.ALPHA, show ? 1f : 0f, show ? 0f : 1f),
ObjectAnimator.ofFloat(altTextScroller, View.ALPHA, show ? 0f : 1f, show ? 1f : 0f),
ObjectAnimator.ofFloat(altTextClose, View.ALPHA, show ? 0f : 1f, show ? 1f : 0f)
);
set.setDuration(300);
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
set.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
if(show){
altOrNoAltButton.setVisibility(View.GONE);
}else{
altTextScroller.setVisibility(View.GONE);
altTextClose.setVisibility(View.GONE);
}
currentAnim=null;
}
});
set.start();
currentAnim=set;
return true;
}
});
} }
@Override @Override

View File

@@ -73,6 +73,7 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
photo.setImageDrawable(null); photo.setImageDrawable(null);
if(item.imgRequest!=null){ if(item.imgRequest!=null){
crossfadeDrawable.setSize(card.width, card.height);
if (card.width > 0) { if (card.width > 0) {
// akkoma servers don't provide width and height // akkoma servers don't provide width and height
crossfadeDrawable.setSize(card.width, card.height); crossfadeDrawable.setSize(card.width, card.height);
@@ -84,7 +85,6 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
photo.setImageDrawable(crossfadeDrawable); photo.setImageDrawable(crossfadeDrawable);
didClear=false; didClear=false;
} }
} }
@Override @Override
@@ -105,3 +105,4 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
} }
} }
} }

View File

@@ -37,150 +37,9 @@ public class PhotoStatusDisplayItem extends ImageStatusDisplayItem{
return Type.PHOTO; return Type.PHOTO;
} }
public static class Holder extends ImageStatusDisplayItem.Holder<PhotoStatusDisplayItem>{ public static class Holder extends ImageStatusDisplayItem.Holder<PhotoStatusDisplayItem> {
private final FrameLayout altTextWrapper; public Holder(Activity activity, ViewGroup parent) {
private final TextView altTextButton;
private final ImageView noAltTextButton;
private final View altTextScroller;
private final ImageButton altTextClose;
private final TextView altText, noAltText;
private View altOrNoAltButton;
private boolean altTextShown;
private AnimatorSet currentAnim;
public Holder(Activity activity, ViewGroup parent){
super(activity, R.layout.display_item_photo, parent); super(activity, R.layout.display_item_photo, parent);
altTextWrapper=findViewById(R.id.alt_text_wrapper);
altTextButton=findViewById(R.id.alt_button);
noAltTextButton=findViewById(R.id.no_alt_button);
altTextScroller=findViewById(R.id.alt_text_scroller);
altTextClose=findViewById(R.id.alt_text_close);
altText=findViewById(R.id.alt_text);
noAltText=findViewById(R.id.no_alt_text);
altTextButton.setOnClickListener(this::onShowHideClick);
noAltTextButton.setOnClickListener(this::onShowHideClick);
altTextClose.setOnClickListener(this::onShowHideClick);
// altTextScroller.setNestedScrollingEnabled(true);
}
@Override
public void onBind(ImageStatusDisplayItem item){
super.onBind(item);
boolean altTextMissing = TextUtils.isEmpty(item.attachment.description);
altOrNoAltButton = altTextMissing ? noAltTextButton : altTextButton;
altTextShown=false;
if(currentAnim!=null)
currentAnim.cancel();
altTextScroller.setVisibility(View.GONE);
altTextClose.setVisibility(View.GONE);
altTextButton.setVisibility(View.VISIBLE);
noAltTextButton.setVisibility(View.VISIBLE);
altTextButton.setAlpha(1f);
noAltTextButton.setAlpha(1f);
altTextWrapper.setVisibility(View.VISIBLE);
if (altTextMissing){
if (GlobalUserPreferences.showNoAltIndicator) {
noAltTextButton.setVisibility(View.VISIBLE);
noAltText.setVisibility(View.VISIBLE);
altTextWrapper.setBackgroundResource(R.drawable.bg_image_no_alt_overlay);
altTextButton.setVisibility(View.GONE);
altText.setVisibility(View.GONE);
} else {
altTextWrapper.setVisibility(View.GONE);
}
}else{
if (GlobalUserPreferences.showAltIndicator) {
noAltTextButton.setVisibility(View.GONE);
noAltText.setVisibility(View.GONE);
altTextWrapper.setBackgroundResource(R.drawable.bg_image_alt_overlay);
altTextButton.setVisibility(View.VISIBLE);
altTextButton.setText(R.string.sk_alt_button);
altText.setVisibility(View.VISIBLE);
altText.setText(item.attachment.description);
altText.setPadding(0, 0, 0, 0);
} else {
altTextWrapper.setVisibility(View.GONE);
}
}
if(!item.status.filterRevealed){
this.itemView.setVisibility(View.GONE);
ViewGroup.LayoutParams params = this.itemView.getLayoutParams();
params.height = 0;
params.width = 0;
this.itemView.setLayoutParams(params);
// item.parentFragment.notifyItemsChanged(this.getAbsoluteAdapterPosition());
}
}
private void onShowHideClick(View v){
boolean show=v.getId()==R.id.alt_button || v.getId()==R.id.no_alt_button;
if(altTextShown==show)
return;
if(currentAnim!=null)
currentAnim.cancel();
altTextShown=show;
if(show){
altTextScroller.setVisibility(View.VISIBLE);
altTextClose.setVisibility(View.VISIBLE);
}else{
altOrNoAltButton.setVisibility(View.VISIBLE);
// Hide these views temporarily so FrameLayout measures correctly
altTextScroller.setVisibility(View.GONE);
altTextClose.setVisibility(View.GONE);
}
// This is the current size...
int prevLeft=altTextWrapper.getLeft();
int prevRight=altTextWrapper.getRight();
int prevTop=altTextWrapper.getTop();
altTextWrapper.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
@Override
public boolean onPreDraw(){
altTextWrapper.getViewTreeObserver().removeOnPreDrawListener(this);
// ...and this is after the layout pass, right now the FrameLayout has its final size, but we animate that change
if(!show){
// Show these views again so they're visible for the duration of the animation.
// No one would notice they were missing during measure/layout.
altTextScroller.setVisibility(View.VISIBLE);
altTextClose.setVisibility(View.VISIBLE);
}
AnimatorSet set=new AnimatorSet();
set.playTogether(
ObjectAnimator.ofInt(altTextWrapper, "left", prevLeft, altTextWrapper.getLeft()),
ObjectAnimator.ofInt(altTextWrapper, "right", prevRight, altTextWrapper.getRight()),
ObjectAnimator.ofInt(altTextWrapper, "top", prevTop, altTextWrapper.getTop()),
ObjectAnimator.ofFloat(altOrNoAltButton, View.ALPHA, show ? 1f : 0f, show ? 0f : 1f),
ObjectAnimator.ofFloat(altTextScroller, View.ALPHA, show ? 0f : 1f, show ? 1f : 0f),
ObjectAnimator.ofFloat(altTextClose, View.ALPHA, show ? 0f : 1f, show ? 1f : 0f)
);
set.setDuration(300);
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
set.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
if(show){
altOrNoAltButton.setVisibility(View.GONE);
}else{
altTextScroller.setVisibility(View.GONE);
altTextClose.setVisibility(View.GONE);
}
currentAnim=null;
}
});
set.start();
currentAnim=set;
return true;
}
});
} }
} }
} }

View File

@@ -81,30 +81,39 @@ public abstract class StatusDisplayItem{
case ACCOUNT -> new AccountStatusDisplayItem.Holder(activity, parent); case ACCOUNT -> new AccountStatusDisplayItem.Holder(activity, parent);
case HASHTAG -> new HashtagStatusDisplayItem.Holder(activity, parent); case HASHTAG -> new HashtagStatusDisplayItem.Holder(activity, parent);
case GAP -> new GapStatusDisplayItem.Holder(activity, parent); case GAP -> new GapStatusDisplayItem.Holder(activity, parent);
case WARNING -> new WarningFilteredStatusDisplayItem.Holder(activity, parent);
case EXTENDED_FOOTER -> new ExtendedFooterStatusDisplayItem.Holder(activity, parent); case EXTENDED_FOOTER -> new ExtendedFooterStatusDisplayItem.Holder(activity, parent);
case WARNING -> new WarningFilteredStatusDisplayItem.Holder(activity, parent);
}; };
} }
public static ArrayList<StatusDisplayItem> buildItems(BaseStatusListFragment fragment, Status status, String accountID, DisplayItemsParent parentObject, Map<String, Account> knownAccounts, boolean inset, boolean addFooter, Notification notification){ public static ArrayList<StatusDisplayItem> buildItems(BaseStatusListFragment<?> fragment, Status status, String accountID, DisplayItemsParent parentObject, Map<String, Account> knownAccounts, boolean inset, boolean addFooter, Notification notification){
return buildItems(fragment, status, accountID, parentObject, knownAccounts, inset, addFooter, notification, false); return buildItems(fragment, status, accountID, parentObject, knownAccounts, inset, addFooter, notification, false, Filter.FilterContext.HOME);
} }
public static ArrayList<StatusDisplayItem> buildItems(BaseStatusListFragment fragment, Status status, String accountID, DisplayItemsParent parentObject, Map<String, Account> knownAccounts, boolean inset, boolean addFooter, Notification notification, boolean disableTranslate){ public static ArrayList<StatusDisplayItem> buildItems(BaseStatusListFragment<?> fragment, Status status, String accountID, DisplayItemsParent parentObject, Map<String, Account> knownAccounts, boolean inset, boolean addFooter, Notification notification, Filter.FilterContext filterContext){
return buildItems(fragment, status, accountID, parentObject, knownAccounts, inset, addFooter, notification, false, filterContext);
}
public static ArrayList<StatusDisplayItem> buildItems(BaseStatusListFragment<?> fragment, Status status, String accountID, DisplayItemsParent parentObject, Map<String, Account> knownAccounts, boolean inset, boolean addFooter, Notification notification, boolean disableTranslate){
return buildItems(fragment, status, accountID, parentObject, knownAccounts, inset, addFooter, notification, disableTranslate, Filter.FilterContext.HOME);
}
public static ArrayList<StatusDisplayItem> buildItems(BaseStatusListFragment<?> fragment, Status status, String accountID, DisplayItemsParent parentObject, Map<String, Account> knownAccounts, boolean inset, boolean addFooter, Notification notification, boolean disableTranslate, Filter.FilterContext filterContext){
String parentID=parentObject.getID(); String parentID=parentObject.getID();
ArrayList<StatusDisplayItem> items=new ArrayList<>(); ArrayList<StatusDisplayItem> items=new ArrayList<>();
ArrayList<StatusDisplayItem> filtered=new ArrayList<>();
Status statusForContent=status.getContentStatus(); Status statusForContent=status.getContentStatus();
Bundle args=new Bundle(); Bundle args=new Bundle();
args.putString("account", accountID); args.putString("account", accountID);
ScheduledStatus scheduledStatus = parentObject instanceof ScheduledStatus ? (ScheduledStatus) parentObject : null; ScheduledStatus scheduledStatus = parentObject instanceof ScheduledStatus ? (ScheduledStatus) parentObject : null;
List<Filter> filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(Filter.FilterContext.HOME)).collect(Collectors.toList()); List<Filter> filters = AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream()
.filter(f -> f.context.contains(filterContext)).collect(Collectors.toList());
StatusFilterPredicate filterPredicate = new StatusFilterPredicate(filters); StatusFilterPredicate filterPredicate = new StatusFilterPredicate(filters);
if(!statusForContent.filterRevealed){
statusForContent.filterRevealed = filterPredicate.testWithWarning(status); statusForContent.filterRevealed = filterPredicate.testWithWarning(status);
}
if(status.reblog!=null){ if(status.reblog!=null){
boolean isOwnPost = AccountSessionManager.getInstance().isSelf(fragment.getAccountID(), status.account); boolean isOwnPost = AccountSessionManager.getInstance().isSelf(fragment.getAccountID(), status.account);
@@ -186,9 +195,10 @@ public abstract class StatusDisplayItem{
item.index=i++; item.index=i++;
} }
if(!statusForContent.filterRevealed){ if (!statusForContent.filterRevealed) {
filtered.add(new WarningFilteredStatusDisplayItem(parentID, fragment, statusForContent, items)); return new ArrayList<>(List.of(
return filtered; new WarningFilteredStatusDisplayItem(parentID, fragment, statusForContent, items)
));
} }
return items; return items;

View File

@@ -3,15 +3,19 @@ package org.joinmastodon.android.ui.displayitems;
import android.app.Activity; import android.app.Activity;
import android.graphics.drawable.Animatable; import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.TypedValue;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.Button; import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import com.github.bottomSoftwareFoundation.bottom.Bottom;
import com.github.bottomSoftwareFoundation.bottom.TranslationError;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.statuses.TranslateStatus; import org.joinmastodon.android.api.requests.statuses.TranslateStatus;
import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
@@ -19,12 +23,15 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.drawables.SpoilerStripesDrawable;
import org.joinmastodon.android.model.StatusPrivacy; import org.joinmastodon.android.model.StatusPrivacy;
import org.joinmastodon.android.model.TranslatedStatus; import org.joinmastodon.android.model.TranslatedStatus;
import org.joinmastodon.android.ui.text.HtmlParser; import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.CustomEmojiHelper; import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.LinkedTextView; import org.joinmastodon.android.ui.views.LinkedTextView;
import org.joinmastodon.android.utils.StatusTextEncoder;
import java.util.regex.Pattern;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse; import me.grishka.appkit.api.ErrorResponse;
@@ -44,6 +51,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
public boolean translated = false; public boolean translated = false;
public TranslatedStatus translation = null; public TranslatedStatus translation = null;
private AccountSession session; private AccountSession session;
public static final Pattern BOTTOM_TEXT_PATTERN = Pattern.compile("(?:[\uD83E\uDEC2\uD83D\uDC96✨\uD83E\uDD7A,]+|❤️)(?:\uD83D\uDC49\uD83D\uDC48(?:[\uD83E\uDEC2\uD83D\uDC96✨\uD83E\uDD7A,]+|❤️))*\uD83D\uDC49\uD83D\uDC48");
public TextStatusDisplayItem(String parentID, CharSequence text, BaseStatusListFragment parentFragment, Status status, boolean disableTranslate){ public TextStatusDisplayItem(String parentID, CharSequence text, BaseStatusListFragment parentFragment, Status status, boolean disableTranslate){
super(parentID, parentFragment); super(parentID, parentFragment);
@@ -81,10 +89,14 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
public static class Holder extends StatusDisplayItem.Holder<TextStatusDisplayItem> implements ImageLoaderViewHolder{ public static class Holder extends StatusDisplayItem.Holder<TextStatusDisplayItem> implements ImageLoaderViewHolder{
private final LinkedTextView text; private final LinkedTextView text;
private final LinearLayout spoilerHeader; private final LinearLayout spoilerHeader;
private final TextView spoilerTitle, spoilerTitleInline, translateInfo; private final TextView spoilerTitle, spoilerTitleInline, translateInfo, readMore;
private final View spoilerOverlay, borderTop, borderBottom, textWrap, translateWrap, translateProgress; private final View spoilerOverlay, borderTop, borderBottom, textWrap, translateWrap, translateProgress, spaceBelowText;
private final Drawable backgroundColor, borderColor; private final int backgroundColor, borderColor;
private final Button translateButton; private final Button translateButton;
private final ScrollView textScrollView;
private final float textMaxHeight, textCollapsedHeight;
private final LinearLayout.LayoutParams collapseParams, wrapParams;
public Holder(Activity activity, ViewGroup parent){ public Holder(Activity activity, ViewGroup parent){
super(activity, R.layout.display_item_text, parent); super(activity, R.layout.display_item_text, parent);
@@ -101,14 +113,16 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
translateInfo=findViewById(R.id.translate_info); translateInfo=findViewById(R.id.translate_info);
translateProgress=findViewById(R.id.translate_progress); translateProgress=findViewById(R.id.translate_progress);
itemView.setOnClickListener(v->item.parentFragment.onRevealSpoilerClick(this)); itemView.setOnClickListener(v->item.parentFragment.onRevealSpoilerClick(this));
backgroundColor=UiUtils.getThemeColor(activity, R.attr.colorBackgroundLight);
TypedValue outValue=new TypedValue(); borderColor=UiUtils.getThemeColor(activity, R.attr.colorPollVoted);
activity.getTheme().resolveAttribute(R.attr.colorBackgroundLight, outValue, true); textScrollView=findViewById(R.id.text_scroll_view);
backgroundColor=activity.getDrawable(outValue.resourceId); readMore=findViewById(R.id.read_more);
// activity.getTheme().resolveAttribute(R.attr.colorBackgroundLightest, outValue, true); spaceBelowText=findViewById(R.id.space_below_text);
// backgroundColorInset=activity.getDrawable(outValue.resourceId); textMaxHeight=activity.getResources().getDimension(R.dimen.text_max_height);
activity.getTheme().resolveAttribute(R.attr.colorPollVoted, outValue, true); textCollapsedHeight=activity.getResources().getDimension(R.dimen.text_collapsed_height);
borderColor=activity.getDrawable(outValue.resourceId); collapseParams=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) textCollapsedHeight);
wrapParams=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
readMore.setOnClickListener(v -> item.parentFragment.onToggleExpanded(item.status, getItemID()));
} }
@Override @Override
@@ -117,12 +131,15 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
? HtmlParser.parse(item.translation.content, item.status.emojis, item.status.mentions, item.status.tags, item.parentFragment.getAccountID()) ? HtmlParser.parse(item.translation.content, item.status.emojis, item.status.mentions, item.status.tags, item.parentFragment.getAccountID())
: item.text); : item.text);
text.setTextIsSelectable(item.textSelectable); text.setTextIsSelectable(item.textSelectable);
if (item.textSelectable) {
textScrollView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
}
spoilerTitleInline.setTextIsSelectable(item.textSelectable); spoilerTitleInline.setTextIsSelectable(item.textSelectable);
text.setInvalidateOnEveryFrame(false); text.setInvalidateOnEveryFrame(false);
spoilerTitleInline.setBackground(item.inset ? null : backgroundColor); spoilerTitleInline.setBackgroundColor(item.inset ? 0 : backgroundColor);
spoilerTitleInline.setPadding(spoilerTitleInline.getPaddingLeft(), item.inset ? 0 : V.dp(14), spoilerTitleInline.getPaddingRight(), item.inset ? 0 : V.dp(14)); spoilerTitleInline.setPadding(spoilerTitleInline.getPaddingLeft(), item.inset ? 0 : V.dp(14), spoilerTitleInline.getPaddingRight(), item.inset ? 0 : V.dp(14));
borderTop.setBackground(item.inset ? null : borderColor); borderTop.setBackgroundColor(item.inset ? 0 : borderColor);
borderBottom.setBackground(item.inset ? null : borderColor); borderBottom.setBackgroundColor(item.inset ? 0 : borderColor);
if(!TextUtils.isEmpty(item.status.spoilerText)){ if(!TextUtils.isEmpty(item.status.spoilerText)){
spoilerTitle.setText(item.parsedSpoilerText); spoilerTitle.setText(item.parsedSpoilerText);
spoilerTitleInline.setText(item.parsedSpoilerText); spoilerTitleInline.setText(item.parsedSpoilerText);
@@ -149,18 +166,30 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
instanceInfo.v2 != null && instanceInfo.v2.configuration.translation != null && instanceInfo.v2 != null && instanceInfo.v2.configuration.translation != null &&
instanceInfo.v2.configuration.translation.enabled; instanceInfo.v2.configuration.translation.enabled;
translateWrap.setVisibility(translateEnabled && boolean isBottomText = BOTTOM_TEXT_PATTERN.matcher(item.status.getStrippedText()).find();
boolean translateVisible = (isBottomText || (
translateEnabled &&
!item.status.visibility.isLessVisibleThan(StatusPrivacy.UNLISTED) && !item.status.visibility.isLessVisibleThan(StatusPrivacy.UNLISTED) &&
item.status.language != null && item.status.language != null &&
(item.session.preferences == null || !item.status.language.equalsIgnoreCase(item.session.preferences.postingDefaultLanguage)) (item.session.preferences == null || !item.status.language.equalsIgnoreCase(item.session.preferences.postingDefaultLanguage))));
? View.VISIBLE : View.GONE); // && (!GlobalUserPreferences.translateButtonOpenedOnly || item.textSelectable);
translateWrap.setVisibility(translateVisible ? View.VISIBLE : View.GONE);
translateButton.setText(item.translated ? R.string.sk_translate_show_original : R.string.sk_translate_post); translateButton.setText(item.translated ? R.string.sk_translate_show_original : R.string.sk_translate_post);
translateInfo.setText(item.translated ? itemView.getResources().getString(R.string.sk_translated_using, item.translation.provider) : ""); translateInfo.setText(item.translated ? itemView.getResources().getString(R.string.sk_translated_using, isBottomText ? "bottom-java" : item.translation.provider) : "");
translateButton.setOnClickListener(v->{ translateButton.setOnClickListener(v->{
if (item.translation == null) { if (item.translation == null) {
if (isBottomText) {
try {
item.translation = new TranslatedStatus();
item.translation.content = new StatusTextEncoder(Bottom::decode).decode(item.status.getStrippedText(), BOTTOM_TEXT_PATTERN);
item.translated = true;
} catch (TranslationError err) {
item.translation = null;
Toast.makeText(itemView.getContext(), err.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
rebind();
return;
}
translateProgress.setVisibility(View.VISIBLE); translateProgress.setVisibility(View.VISIBLE);
translateButton.setClickable(false); translateButton.setClickable(false);
translateButton.animate().alpha(0.5f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(150).start(); translateButton.animate().alpha(0.5f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(150).start();
@@ -190,6 +219,25 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
} }
}); });
readMore.setText(item.status.textExpanded ? R.string.sk_collapse : R.string.sk_expand);
spaceBelowText.setVisibility(translateVisible ? View.VISIBLE : View.GONE);
if (!GlobalUserPreferences.collapseLongPosts) {
textScrollView.setLayoutParams(wrapParams);
readMore.setVisibility(View.GONE);
}
if (GlobalUserPreferences.collapseLongPosts) text.post(() -> {
boolean tooBig = text.getMeasuredHeight() > textMaxHeight;
boolean inTimeline = !item.textSelectable;
boolean hasSpoiler = !TextUtils.isEmpty(item.status.spoilerText);
boolean expandable = inTimeline && tooBig && !hasSpoiler;
item.parentFragment.onEnableExpandable(this, expandable);
});
readMore.setVisibility(item.status.textExpandable && !item.status.textExpanded ? View.VISIBLE : View.GONE);
textScrollView.setLayoutParams(item.status.textExpandable && !item.status.textExpanded ? collapseParams : wrapParams);
if (item.status.textExpandable && !translateVisible) spaceBelowText.setVisibility(View.VISIBLE);
} }
@Override @Override

View File

@@ -602,7 +602,7 @@ public class TabLayout extends HorizontalScrollView {
* <p>If the tab indicator color is not {@code Color.TRANSPARENT}, the indicator will be wrapped * <p>If the tab indicator color is not {@code Color.TRANSPARENT}, the indicator will be wrapped
* and tinted right before it is drawn by {@link SlidingTabIndicator#draw(Canvas)}. If you'd like * and tinted right before it is drawn by {@link SlidingTabIndicator#draw(Canvas)}. If you'd like
* the inherent color or the tinted color of a custom drawable to be used, make sure this color is * the inherent color or the tinted color of a custom drawable to be used, make sure this color is
* set to {@code Color.TRANSPARENT} to avoid your color/tint being overriden. * set to {@code Color.TRANSPARENT} to avoid your color/tint being overridden.
* *
* @param color color to use for the indicator * @param color color to use for the indicator
* @attr ref com.google.android.material.R.styleable#TabLayout_tabIndicatorColor * @attr ref com.google.android.material.R.styleable#TabLayout_tabIndicatorColor

View File

@@ -111,7 +111,7 @@ public class HtmlParser{
@Override @Override
public void head(@NonNull Node node, int depth){ public void head(@NonNull Node node, int depth){
if(node instanceof TextNode textNode){ if(node instanceof TextNode textNode){
ssb.append(textNode.text()); ssb.append(textNode.getWholeText());
}else if(node instanceof Element el){ }else if(node instanceof Element el){
switch(el.nodeName()){ switch(el.nodeName()){
case "a" -> { case "a" -> {

View File

@@ -18,6 +18,10 @@ public class LinkSpan extends CharacterStyle {
private String accountID; private String accountID;
private String text; private String text;
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID){
this(link, listener, type, accountID, null);
}
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, String text){ public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, String text){
this.listener=listener; this.listener=listener;
this.link=link; this.link=link;
@@ -40,6 +44,7 @@ public class LinkSpan extends CharacterStyle {
case URL -> UiUtils.openURL(context, accountID, link); case URL -> UiUtils.openURL(context, accountID, link);
case MENTION -> UiUtils.openProfileByID(context, accountID, link); case MENTION -> UiUtils.openProfileByID(context, accountID, link);
case HASHTAG -> UiUtils.openHashtagTimeline(context, accountID, link, null); case HASHTAG -> UiUtils.openHashtagTimeline(context, accountID, link, null);
case CUSTOM -> listener.onLinkClick(this);
} }
} }
@@ -73,6 +78,7 @@ public class LinkSpan extends CharacterStyle {
public enum Type{ public enum Type{
URL, URL,
MENTION, MENTION,
HASHTAG HASHTAG,
CUSTOM
} }
} }

View File

@@ -28,6 +28,9 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.SystemClock;
import android.os.ext.SdkExtensions;
import android.provider.MediaStore;
import android.provider.OpenableColumns; import android.provider.OpenableColumns;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.Spanned; import android.text.Spanned;
@@ -175,6 +178,14 @@ public class UiUtils{
} }
} }
public static int alphaBlendColors(int color1, int color2, float alpha) {
float alpha0 = 1f - alpha;
int r = Math.round(((color1 >> 16) & 0xFF) * alpha0 + ((color2 >> 16) & 0xFF) * alpha);
int g = Math.round(((color1 >> 8) & 0xFF) * alpha0 + ((color2 >> 8) & 0xFF) * alpha);
int b = Math.round((color1 & 0xFF) * alpha0 + (color2 & 0xFF) * alpha);
return 0xFF000000 | (r << 16) | (g << 8) | b;
}
public static String formatRelativeTimestampAsMinutesAgo(Context context, Instant instant){ public static String formatRelativeTimestampAsMinutesAgo(Context context, Instant instant){
long t=instant.toEpochMilli(); long t=instant.toEpochMilli();
long now=System.currentTimeMillis(); long now=System.currentTimeMillis();
@@ -658,8 +669,40 @@ public class UiUtils{
}).exec(accountID); }).exec(accountID);
} }
public static void performAccountAction(Activity activity, Account account, String accountID, Relationship relationship, Button button, Consumer<Boolean> progressCallback, Consumer<Relationship> resultCallback){ public static void setRelationshipToActionButtonM3(Relationship relationship, Button button){
boolean secondaryStyle;
if(relationship.blocking){ if(relationship.blocking){
button.setText(R.string.button_blocked);
secondaryStyle=true;
}else if(relationship.blockedBy){
button.setText(R.string.button_follow);
secondaryStyle=false;
}else if(relationship.requested){
button.setText(R.string.button_follow_pending);
secondaryStyle=true;
}else if(!relationship.following){
button.setText(relationship.followedBy ? R.string.follow_back : R.string.button_follow);
secondaryStyle=false;
}else{
button.setText(R.string.button_following);
secondaryStyle=true;
}
button.setEnabled(!relationship.blockedBy);
int styleRes=secondaryStyle ? R.style.Widget_Mastodon_M3_Button_Tonal : R.style.Widget_Mastodon_M3_Button_Filled;
TypedArray ta=button.getContext().obtainStyledAttributes(styleRes, new int[]{android.R.attr.background});
button.setBackground(ta.getDrawable(0));
ta.recycle();
ta=button.getContext().obtainStyledAttributes(styleRes, new int[]{android.R.attr.textColor});
if(relationship.blocking)
button.setTextColor(button.getResources().getColorStateList(R.color.error_600));
else
button.setTextColor(ta.getColorStateList(0));
ta.recycle();
}
public static void performAccountAction(Activity activity, Account account, String accountID, Relationship relationship, Button button, Consumer<Boolean> progressCallback, Consumer<Relationship> resultCallback) {
if (relationship.blocking) {
confirmToggleBlockUser(activity, accountID, account, true, resultCallback); confirmToggleBlockUser(activity, accountID, account, true, resultCallback);
}else if(relationship.muting){ }else if(relationship.muting){
confirmToggleMuteUser(activity, accountID, account, true, resultCallback); confirmToggleMuteUser(activity, accountID, account, true, resultCallback);
@@ -1163,11 +1206,62 @@ public class UiUtils{
return container; return container;
} }
public static int alphaBlendColors(int color1, int color2, float alpha){ /**
float alpha0=1f-alpha; * Check to see if Android platform photopicker is available on the device\
int r=Math.round(((color1 >> 16) & 0xFF)*alpha0+((color2 >> 16) & 0xFF)*alpha); *
int g=Math.round(((color1 >> 8) & 0xFF)*alpha0+((color2 >> 8) & 0xFF)*alpha); * @return whether the device supports photopicker intents.
int b=Math.round((color1 & 0xFF)*alpha0+(color2 & 0xFF)*alpha); */
return 0xFF000000 | (r << 16) | (g << 8) | b; @SuppressLint("NewApi")
public static boolean isPhotoPickerAvailable(){
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.TIRAMISU){
return true;
}else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.R){
return SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R)>=2;
}else
return false;
}
@SuppressLint("InlinedApi")
public static Intent getMediaPickerIntent(String[] mimeTypes, int maxCount){
Intent intent;
if(isPhotoPickerAvailable()){
intent=new Intent(MediaStore.ACTION_PICK_IMAGES);
if(maxCount>1)
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxCount);
}else{
intent=new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
}
if(mimeTypes.length>1){
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
}else if(mimeTypes.length==1){
intent.setType(mimeTypes[0]);
}else{
intent.setType("*/*");
}
if(maxCount>1)
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
return intent;
}
/**
* Wraps a View.OnClickListener to filter multiple clicks in succession.
* Useful for buttons that perform some action that changes their state asynchronously.
* @param l
* @return
*/
public static View.OnClickListener rateLimitedClickListener(View.OnClickListener l){
return new View.OnClickListener(){
private long lastClickTime;
@Override
public void onClick(View v){
if(SystemClock.uptimeMillis()-lastClickTime>500L){
lastClickTime=SystemClock.uptimeMillis();
l.onClick(v);
}
}
};
} }
} }

View File

@@ -20,6 +20,7 @@ import android.text.Editable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.Gravity; import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.widget.EditText; import android.widget.EditText;
@@ -47,6 +48,7 @@ public class FloatingHintEditTextLayout extends FrameLayout{
private RectF tmpRect=new RectF(); private RectF tmpRect=new RectF();
private ColorStateList labelColors, origHintColors; private ColorStateList labelColors, origHintColors;
private boolean errorState; private boolean errorState;
private TextView errorView;
public FloatingHintEditTextLayout(Context context){ public FloatingHintEditTextLayout(Context context){
this(context, null); this(context, null);
@@ -95,12 +97,22 @@ public class FloatingHintEditTextLayout extends FrameLayout{
label.setAlpha(0f); label.setAlpha(0f);
edit.addTextChangedListener(new SimpleTextWatcher(this::onTextChanged)); edit.addTextChangedListener(new SimpleTextWatcher(this::onTextChanged));
errorView=new LinkedTextView(getContext());
errorView.setTextAppearance(R.style.m3_body_small);
errorView.setTextColor(UiUtils.getThemeColor(getContext(), R.attr.colorM3OnSurfaceVariant));
errorView.setLinkTextColor(UiUtils.getThemeColor(getContext(), R.attr.colorM3Primary));
errorView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
errorView.setPadding(V.dp(16), V.dp(4), V.dp(16), 0);
errorView.setVisibility(View.GONE);
addView(errorView);
} }
private void onTextChanged(Editable text){ private void onTextChanged(Editable text){
if(errorState){ if(errorState){
errorView.setVisibility(View.GONE);
errorState=false; errorState=false;
setForeground(getResources().getDrawable(R.drawable.bg_m3_outlined_text_field)); setForeground(getResources().getDrawable(R.drawable.bg_m3_outlined_text_field, getContext().getTheme()));
refreshDrawableState(); refreshDrawableState();
} }
boolean newHintVisible=text.length()==0; boolean newHintVisible=text.length()==0;
@@ -211,12 +223,34 @@ public class FloatingHintEditTextLayout extends FrameLayout{
label.setTextColor(color.getColorForState(getDrawableState(), 0xff00ff00)); label.setTextColor(color.getColorForState(getDrawableState(), 0xff00ff00));
} }
public void setErrorState(){ public void setErrorState(CharSequence error){
if(errorState) if(errorState)
return; return;
errorState=true; errorState=true;
setForeground(getResources().getDrawable(R.drawable.bg_m3_outlined_text_field_error, getContext().getTheme())); setForeground(getResources().getDrawable(R.drawable.bg_m3_outlined_text_field_error, getContext().getTheme()));
label.setTextColor(UiUtils.getThemeColor(getContext(), R.attr.colorM3Error)); label.setTextColor(UiUtils.getThemeColor(getContext(), R.attr.colorM3Error));
errorView.setVisibility(VISIBLE);
errorView.setText(error);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
if(errorView.getVisibility()!=GONE){
int width=MeasureSpec.getSize(widthMeasureSpec)-getPaddingLeft()-getPaddingRight();
LayoutParams editLP=(LayoutParams) edit.getLayoutParams();
width-=editLP.leftMargin+editLP.rightMargin;
errorView.measure(width | MeasureSpec.EXACTLY, MeasureSpec.UNSPECIFIED);
LayoutParams lp=(LayoutParams) errorView.getLayoutParams();
lp.width=width;
lp.height=errorView.getMeasuredHeight();
lp.gravity=Gravity.LEFT | Gravity.BOTTOM;
lp.leftMargin=editLP.leftMargin;
editLP.bottomMargin=errorView.getMeasuredHeight();
}else{
LayoutParams editLP=(LayoutParams) edit.getLayoutParams();
editLP.bottomMargin=0;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} }
private class PaddedForegroundDrawable extends Drawable{ private class PaddedForegroundDrawable extends Drawable{
@@ -313,8 +347,8 @@ public class FloatingHintEditTextLayout extends FrameLayout{
@Override @Override
protected void onBoundsChange(@NonNull Rect bounds){ protected void onBoundsChange(@NonNull Rect bounds){
super.onBoundsChange(bounds); super.onBoundsChange(bounds);
LayoutParams lp=(LayoutParams) edit.getLayoutParams(); int offset=V.dp(12);
wrapped.setBounds(bounds.left+lp.leftMargin-V.dp(12), bounds.top, bounds.right-lp.rightMargin+V.dp(12), bounds.bottom); wrapped.setBounds(edit.getLeft()-offset, edit.getTop()-offset, edit.getRight()+offset, edit.getBottom()+offset);
} }
} }
} }

View File

@@ -0,0 +1,30 @@
package org.joinmastodon.android.ui.views;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ScrollView;
public class UntouchableScrollView extends ScrollView {
public UntouchableScrollView(Context context) {
super(context);
}
public UntouchableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public UntouchableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public UntouchableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
return false;
}
}

View File

@@ -71,7 +71,7 @@ public class ElevationOnScrollListener extends RecyclerView.OnScrollListener imp
@Override @Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY){ public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY){
handleScroll(v.getContext(), scrollY==0); handleScroll(v.getContext(), scrollY<=0);
} }
private void handleScroll(Context context, boolean newAtTop){ private void handleScroll(Context context, boolean newAtTop){

View File

@@ -0,0 +1,58 @@
package org.joinmastodon.android.utils;
import android.text.TextUtils;
import org.joinmastodon.android.fragments.ComposeFragment;
import java.util.function.Function;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
// not a good class
public class StatusTextEncoder {
private final Function<String, String> fn;
// see ComposeFragment.HIGHLIGHT_PATTERN
private final static Pattern EXCLUDE_PATTERN = Pattern.compile("\\s*(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+))\\s*");
public StatusTextEncoder(Function<String, String> fn) {
this.fn = fn;
}
// prettiest method award winner 2023 [citation needed]
public String encode(String content) {
StringBuilder encodedString = new StringBuilder();
// matches mentions and hashtags
Matcher m = EXCLUDE_PATTERN.matcher(content);
int previousEnd = 0;
while (m.find()) {
MatchResult res = m.toMatchResult();
// everything before the match - do encode
encodedString.append(fn.apply(content.substring(previousEnd, res.start())));
previousEnd = res.end();
// the match - do not encode
encodedString.append(res.group());
}
// everything after the last match - do encode
encodedString.append(fn.apply(content.substring(previousEnd)));
return encodedString.toString();
}
// prettiest almost-exact replica of a pretty function
public String decode(String content, Pattern regex) {
Matcher m = regex.matcher(content);
StringBuilder decodedString = new StringBuilder();
int previousEnd = 0;
while (m.find()) {
MatchResult res = m.toMatchResult();
// everything before the match - do not decode
decodedString.append(content.substring(previousEnd, res.start()));
previousEnd = res.end();
// the match - do decode
decodedString.append(fn.apply(res.group()));
}
decodedString.append(content.substring(previousEnd));
return decodedString.toString();
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?android:colorPrimary" android:state_enabled="true"/> <item android:color="?attr/colorButtonBackgroundPrimaryDarkOnLight" android:state_enabled="true"/>
<item android:color="?colorPollVoted"/> <item android:color="?colorButtonBackgroundPrimaryDarkOnLightDisabled"/>
</selector> </selector>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?colorSecondary" android:state_enabled="true"/> <item android:color="?colorButtonBackgroundPrimaryLightOnDark" android:state_enabled="true"/>
<item android:color="?colorPollVoted"/> <item android:color="?colorButtonBackgroundPrimaryLightOnDarkDisabled"/>
</selector> </selector>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?colorPollVoted" android:state_enabled="true"/> <item android:color="?colorButtonBackgroundSecondaryLightOnDark" android:state_enabled="true"/>
<item android:color="?colorSearchHint"/> <item android:color="?colorButtonBackgroundSecondaryLightOnDarkDisabled"/>
</selector> </selector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?colorM3OnSecondaryContainer" android:state_enabled="true"/>
<item android:color="?colorM3OnSurface" android:alpha="0.38"/>
</selector>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?colorSecondary" android:state_enabled="true"/> <item android:color="?colorButtonTextPrimaryDarkOnLight" android:state_enabled="true"/>
<item android:color="?colorTabInactive"/> <item android:color="?colorButtonTextPrimaryDarkOnLightDisabled"/>
</selector> </selector>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?android:colorPrimary" android:state_enabled="true"/> <item android:color="?colorButtonTextSecondaryDarkOnLight" android:state_enabled="true"/>
<item android:color="?colorTabInactive"/> <item android:color="?colorButtonTextSecondaryDarkOnLightDisabled"/>
</selector> </selector>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<ripple android:color="@color/m3_on_secondary_container_overlay">
<item>
<shape>
<solid android:color="?colorM3SecondaryContainer"/>
<corners android:radius="20dp"/>
</shape>
</item>
</ripple>
</item>
<item>
<shape>
<solid android:color="?colorM3DisabledBackground"/>
<corners android:radius="20dp"/>
</shape>
</item>
</selector>

View File

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

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:dither="true"
android:shape="rectangle">
<corners android:radius="4sp" />
<solid android:color="?colorBackgroundLight" />
<stroke android:width="2dp" android:color="#00ff00" />
</shape>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M11,19V13H5V11H11V5H13V11H19V13H13V19Z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="@android:color/white"
android:pathData="M29.45,6V9H9Q9,9 9,9Q9,9 9,9V39Q9,39 9,39Q9,39 9,39H39Q39,39 39,39Q39,39 39,39V18.6H42V39Q42,40.2 41.1,41.1Q40.2,42 39,42H9Q7.8,42 6.9,41.1Q6,40.2 6,39V9Q6,7.8 6.9,6.9Q7.8,6 9,6ZM38,6V10.05H42.05V13.05H38V17.1H35V13.05H30.95V10.05H35V6ZM12,33.9H36L28.8,24.3L22.45,32.65L17.75,26.45ZM9,9V14.55V18.6V39Q9,39 9,39Q9,39 9,39Q9,39 9,39Q9,39 9,39V9Q9,9 9,9Q9,9 9,9Z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M4,15V13H20V15ZM4,11V9H20V11Z"/>
</vector>

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="M15.794 7.733c0.286 0.3 0.274 0.774-0.026 1.06l-5.25 5.001c-0.29 0.276-0.745 0.276-1.035 0l-5.25-5c-0.3-0.287-0.312-0.761-0.026-1.061 0.286-0.3 0.76-0.312 1.06-0.026l4.734 4.509 4.733-4.51c0.3-0.285 0.774-0.273 1.06 0.027z" 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="M4.293 8.293c0.39-0.39 1.024-0.39 1.414 0L12 14.586l6.293-6.293c0.39-0.39 1.024-0.39 1.414 0 0.39 0.39 0.39 1.024 0 1.414l-7 7c-0.39 0.39-1.024 0.39-1.414 0l-7-7c-0.39-0.39-0.39-1.024 0-1.414z" 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="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20">
<path android:pathData="M8.5 4h3c0-0.828-0.672-1.5-1.5-1.5S8.5 3.172 8.5 4zm-1 0c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5h5C17.776 4 18 4.224 18 4.5S17.776 5 17.5 5h-1.054l-1.194 10.344C15.077 16.858 13.796 18 12.272 18H7.728c-1.524 0-2.805-1.142-2.98-2.656L3.554 5H2.5C2.224 5 2 4.776 2 4.5S2.224 4 2.5 4h5zM9 8c0-0.276-0.224-0.5-0.5-0.5S8 7.724 8 8v6c0 0.276 0.224 0.5 0.5 0.5S9 14.276 9 14V8zm2.5-0.5C11.224 7.5 11 7.724 11 8v6c0 0.276 0.224 0.5 0.5 0.5S12 14.276 12 14V8c0-0.276-0.224-0.5-0.5-0.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="M25.256 16h0.006-0.01 0.005zm-0.704-0.52c0.1 0.318 0.387 0.518 0.704 0.52 0.07 0 0.148-0.02 0.226-0.04 0.39-0.12 0.61-0.55 0.48-0.94C25.932 14.93 22.932 6 14 6S2.067 14.93 2.037 15.02c-0.13 0.39 0.09 0.81 0.48 0.94 0.4 0.13 0.82-0.09 0.95-0.48l0.003-0.005C3.603 15.085 6.207 7.5 14.01 7.5c7.842 0 10.432 7.65 10.542 7.98zM10.5 16c0-1.933 1.567-3.5 3.5-3.5s3.5 1.567 3.5 3.5-1.567 3.5-3.5 3.5-3.5-1.567-3.5-3.5zm3.5-5c-2.761 0-5 2.239-5 5s2.239 5 5 5 5-2.239 5-5-2.239-5-5-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="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:pathData="M2.22 2.22C1.953 2.486 1.93 2.903 2.147 3.196L2.22 3.28l4.034 4.035c-1.922 1.35-3.358 3.365-3.955 5.75-0.1 0.401 0.143 0.809 0.545 0.91 0.402 0.1 0.81-0.144 0.91-0.546 0.53-2.116 1.837-3.89 3.58-5.034l1.81 1.81C8.436 10.924 8 11.914 8 13.004c0 2.209 1.79 4 4 4 1.09 0 2.079-0.437 2.8-1.144l5.92 5.92c0.293 0.292 0.767 0.292 1.06 0 0.267-0.267 0.29-0.684 0.073-0.977L21.78 20.72l-6.113-6.114 0.001-0.002-1.2-1.198-2.87-2.87H11.6L8.719 7.658 8.72 7.656l-1.133-1.13L3.28 2.22c-0.293-0.293-0.767-0.293-1.06 0zm7.984 9.046L13.74 14.8c-0.45 0.435-1.063 0.704-1.739 0.704-1.38 0-2.5-1.12-2.5-2.5 0-0.676 0.268-1.29 0.704-1.74zM12 5.5c-1 0-1.97 0.148-2.889 0.425l1.237 1.236C10.884 7.055 11.436 7 12 7c3.923 0 7.31 2.68 8.247 6.433 0.1 0.402 0.508 0.646 0.91 0.546 0.401-0.1 0.646-0.507 0.545-0.91C20.6 8.654 16.615 5.5 12 5.5zm0.195 3.51l3.801 3.8c-0.102-2.057-1.749-3.702-3.801-3.8z" 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="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20">
<path android:pathData="M10 2c4.418 0 8 3.582 8 8 0 2.706-1.142 4.5-3 4.5-1.226 0-2.14-0.781-2.62-2.09C11.784 13.393 10.781 14 9.5 14 7.36 14 6 12.307 6 10c0-2.337 1.313-4 3.5-4 1.052 0 1.901 0.385 2.5 1.044V6.5C12 6.224 12.224 6 12.5 6c0.245 0 0.45 0.177 0.492 0.41L13 6.5V10c0 2.223 0.813 3.5 2 3.5s2-1.277 2-3.5c0-3.866-3.134-7-7-7s-7 3.134-7 7 3.134 7 7 7c0.823 0 1.626-0.142 2.383-0.416 0.26-0.094 0.547 0.04 0.64 0.3 0.095 0.26-0.04 0.546-0.3 0.64C11.859 17.838 10.94 18 10 18c-4.418 0-8-3.582-8-8s3.582-8 8-8zM9.5 7C7.924 7 7 8.17 7 10c0 1.797 0.966 3 2.5 3s2.5-1.203 2.5-3c0-1.83-0.924-3-2.5-3z" 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="M7.75 12c0 0.966-0.784 1.75-1.75 1.75S4.25 12.966 4.25 12 5.034 10.25 6 10.25 7.75 11.034 7.75 12zm6 0c0 0.966-0.784 1.75-1.75 1.75s-1.75-0.784-1.75-1.75 0.784-1.75 1.75-1.75 1.75 0.784 1.75 1.75zM18 13.75c0.966 0 1.75-0.784 1.75-1.75s-0.784-1.75-1.75-1.75-1.75 0.784-1.75 1.75 0.784 1.75 1.75 1.75z" 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="M6.25 4.5C5.283 4.5 4.5 5.284 4.5 6.25v11.5c0 0.966 0.783 1.75 1.75 1.75h11.5c0.966 0 1.75-0.784 1.75-1.75v-4c0-0.414 0.335-0.75 0.75-0.75 0.414 0 0.75 0.336 0.75 0.75v4c0 1.795-1.456 3.25-3.25 3.25H6.25C4.455 21 3 19.545 3 17.75V6.25C3 4.455 4.455 3 6.25 3h4C10.664 3 11 3.336 11 3.75S10.664 4.5 10.25 4.5h-4zM13 3.75C13 3.336 13.335 3 13.75 3h6.5C20.664 3 21 3.336 21 3.75v6.5c0 0.414-0.336 0.75-0.75 0.75s-0.75-0.336-0.75-0.75V5.56l-5.22 5.22c-0.293 0.293-0.768 0.293-1.06 0-0.293-0.293-0.293-0.768 0-1.06l5.22-5.22h-4.69C13.335 4.5 13 4.164 13 3.75z" 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="M8.502 11.5c0.554 0 1.002 0.448 1.002 1.002 0 0.553-0.448 1.002-1.002 1.002-0.553 0-1.002-0.449-1.002-1.002 0-0.554 0.449-1.003 1.002-1.003zM12 4.353v6.651h7.442L17.72 9.28c-0.267-0.266-0.29-0.683-0.073-0.977L17.72 8.22c0.266-0.266 0.683-0.29 0.976-0.072L18.78 8.22l2.997 2.998c0.266 0.266 0.29 0.682 0.073 0.976l-0.073 0.084-2.996 3.003c-0.293 0.294-0.767 0.294-1.06 0.002-0.267-0.266-0.292-0.683-0.075-0.977l0.073-0.084 1.713-1.717h-7.431L12 19.25c0 0.466-0.421 0.82-0.88 0.738l-8.5-1.501C2.26 18.424 2 18.112 2 17.748V5.75c0-0.368 0.266-0.681 0.628-0.74l8.5-1.396C11.585 3.539 12 3.89 12 4.354zm-1.5 0.883l-7 1.15v10.732l7 1.236V5.237zM13 18.5h0.765l0.102-0.007c0.366-0.05 0.649-0.364 0.648-0.744l-0.007-4.25H13v5zm0.002-8.502L13 8.726V5h0.745c0.38 0 0.693 0.281 0.743 0.647l0.007 0.101L14.502 10h-1.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="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
<path android:pathData="M14.704 3.44C14.895 3.667 15 3.953 15 4.248V19.75c0 0.69-0.56 1.25-1.25 1.25-0.296 0-0.582-0.105-0.808-0.296l-4.967-4.206H4.25c-1.243 0-2.25-1.008-2.25-2.25v-4.5c0-1.243 1.007-2.25 2.25-2.25h3.725l4.968-4.204c0.526-0.446 1.315-0.38 1.761 0.147zM13.5 4.787l-4.975 4.21H4.25c-0.414 0-0.75 0.337-0.75 0.75v4.5c0 0.415 0.336 0.75 0.75 0.75h4.275L13.5 19.21V4.787z" 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="M16.5 4.814c0-1.094-1.307-1.66-2.105-0.912l-4.937 4.63C9.134 8.836 8.706 9.005 8.261 9.005H5.25C3.455 9.005 2 10.46 2 12.255v3.492c0 1.795 1.455 3.25 3.25 3.25h3.012c0.444 0 0.872 0.17 1.196 0.473l4.937 4.626c0.799 0.748 2.105 0.182 2.105-0.912V4.814zm-6.016 4.812L15 5.39v17.216l-4.516-4.232c-0.602-0.564-1.397-0.878-2.222-0.878H5.25c-0.966 0-1.75-0.784-1.75-1.75v-3.492c0-0.966 0.784-1.75 1.75-1.75h3.011c0.826 0 1.62-0.314 2.223-0.88z" 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="M3.28 2.22c-0.293-0.293-0.767-0.293-1.06 0-0.293 0.293-0.293 0.767 0 1.06L6.438 7.5H4.25C3.007 7.499 2 8.506 2 9.749v4.497c0 1.243 1.007 2.25 2.25 2.25h3.68c0.183 0 0.36 0.068 0.498 0.19l4.491 3.994C13.725 21.396 15 20.824 15 19.746V16.06l5.72 5.72c0.292 0.292 0.767 0.292 1.06 0 0.293-0.293 0.293-0.768 0-1.061L3.28 2.22zM13.5 14.56v4.629l-4.075-3.624c-0.412-0.366-0.944-0.569-1.495-0.569H4.25c-0.414 0-0.75-0.335-0.75-0.75V9.75C3.5 9.335 3.836 9 4.25 9h3.688l5.562 5.56zm0-9.753v5.511l1.5 1.5V4.25c0-1.079-1.274-1.65-2.08-0.934l-3.4 3.022 1.063 1.063L13.5 4.807zm3.641 9.152l1.138 1.138C18.741 14.163 19 13.111 19 12c0-1.203-0.304-2.338-0.84-3.328-0.198-0.364-0.653-0.5-1.017-0.303-0.364 0.197-0.5 0.653-0.303 1.017 0.42 0.777 0.66 1.666 0.66 2.614 0 0.691-0.127 1.351-0.359 1.96zm2.247 2.247l1.093 1.094C21.445 15.763 22 13.946 22 12c0-2.226-0.728-4.284-1.96-5.946-0.246-0.333-0.716-0.403-1.048-0.157-0.333 0.247-0.403 0.716-0.157 1.05C19.881 8.358 20.5 10.106 20.5 12c0 1.531-0.404 2.966-1.112 4.206z" 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="M3.28 2.22c-0.293-0.293-0.767-0.293-1.06 0-0.293 0.293-0.293 0.767 0 1.06l5.724 5.725H5.25C3.455 9.005 2 10.46 2 12.255v3.492c0 1.795 1.455 3.25 3.25 3.25h3.012c0.444 0 0.872 0.17 1.196 0.473l4.937 4.626c0.799 0.748 2.105 0.182 2.105-0.912v-5.623l8.22 8.22c0.292 0.292 0.767 0.292 1.06 0 0.293-0.293 0.293-0.768 0-1.061L3.28 2.22zM15 16.06v6.547l-4.516-4.231c-0.602-0.565-1.397-0.879-2.222-0.879H5.25c-0.966 0-1.75-0.783-1.75-1.75v-3.492c0-0.966 0.784-1.75 1.75-1.75h3.011c0.35 0 0.693-0.056 1.02-0.164L15 16.061zm-4.378-8.62l1.061 1.061L15 5.392v6.427l1.5 1.5V4.814c0-1.094-1.307-1.66-2.105-0.912L10.622 7.44zm9.55 9.55l1.137 1.137C21.912 16.88 22.25 15.478 22.25 14c0-2.136-0.706-4.11-1.897-5.697-0.249-0.332-0.719-0.399-1.05-0.15-0.332 0.249-0.399 0.719-0.15 1.05C20.156 10.54 20.75 12.199 20.75 14c0 1.058-0.205 2.067-0.578 2.99zm2.803 2.803l1.095 1.096c1.224-2.008 1.93-4.366 1.93-6.89 0-3.35-1.245-6.414-3.298-8.747-0.274-0.31-0.747-0.341-1.058-0.068-0.311 0.274-0.342 0.748-0.068 1.059C23.396 8.313 24.5 11.027 24.5 14c0 2.107-0.554 4.084-1.525 5.793z" 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="M6.78 4.78c0.293-0.293 0.293-0.767 0-1.06-0.293-0.293-0.767-0.293-1.06 0L3.75 5.69 3.28 5.22c-0.293-0.293-0.767-0.293-1.06 0-0.293 0.293-0.293 0.767 0 1.06l1 1c0.293 0.293 0.767 0.293 1.06 0l2.5-2.5zm14.47 13.227H9.75l-0.102 0.007C9.282 18.064 9 18.377 9 18.757c0 0.414 0.336 0.75 0.75 0.75h11.5l0.102-0.007C21.718 19.45 22 19.137 22 18.757c0-0.414-0.336-0.75-0.75-0.75zm0-6.507H9.75l-0.102 0.007C9.282 11.557 9 11.87 9 12.25 9 12.664 9.336 13 9.75 13h11.5l0.102-0.007C21.718 12.943 22 12.63 22 12.25c0-0.414-0.336-0.75-0.75-0.75zm0-6.5H9.75L9.648 5.007C9.282 5.057 9 5.37 9 5.75 9 6.164 9.336 6.5 9.75 6.5h11.5l0.102-0.007C21.718 6.443 22 6.13 22 5.75 22 5.336 21.664 5 21.25 5zM6.78 17.78c0.293-0.293 0.293-0.767 0-1.06-0.293-0.293-0.767-0.293-1.06 0l-1.97 1.97-0.47-0.47c-0.293-0.293-0.767-0.293-1.06 0-0.293 0.293-0.293 0.767 0 1.06l1 1c0.293 0.293 0.767 0.293 1.06 0l2.5-2.5zm0-7.56c0.293 0.293 0.293 0.767 0 1.06l-2.5 2.5c-0.293 0.293-0.767 0.293-1.06 0l-1-1c-0.293-0.293-0.293-0.767 0-1.06 0.293-0.293 0.767-0.293 1.06 0l0.47 0.47 1.97-1.97c0.293-0.293 0.767-0.293 1.06 0z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This is hidden from screenreaders because that same alt text is set as content description on the ImageView -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/alt_text_wrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:layout_margin="12dp"
android:importantForAccessibility="noHideDescendants"
android:background="@drawable/bg_image_alt_overlay">
<ImageView
android:id="@+id/no_alt_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:src="@drawable/ic_fluent_important_20_filled"
android:tint="?colorGray25" />
<TextView
android:id="@+id/alt_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorGray25"
android:gravity="center"
android:includeFontPadding="false"
android:paddingHorizontal="5dp"
android:paddingVertical="1dp"
android:text="@string/sk_alt_button"/>
<ImageButton
android:id="@+id/alt_text_close"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="end|top"
android:src="@drawable/ic_baseline_close_24"
android:tint="#FFF"
android:background="?android:actionBarItemBackground"/>
<org.joinmastodon.android.ui.views.NestableScrollView
android:id="@+id/alt_text_scroller"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="40dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/alt_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textAppearance="@style/m3_body_medium"
android:textColor="?colorGray25"
tools:text="Alt text goes here"/>
<TextView
android:id="@+id/no_alt_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="14dp"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorGray25"
android:text="@string/sk_no_alt_text"/>
</LinearLayout>
</org.joinmastodon.android.ui.views.NestableScrollView>
</FrameLayout>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fab"
android:contentDescription="@string/new_post"
style="@style/Widget.Mastodon.Button.Compose" />

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/warning_wrap"
android:background="@drawable/bg_timeline_gap">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:padding="16dp"
android:textAppearance="@style/m3_title_medium"
android:textColor="?android:textColorSecondary"
android:text="@string/sk_filtered"/>
<TextView
android:id="@+id/reveal_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:padding="16dp"
android:text="@string/tap_to_reveal"
android:singleLine="true"
android:ellipsize="end"
android:textColor="?android:textColorSecondary" />
</FrameLayout>

View File

@@ -4,8 +4,7 @@
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="48dp"
android:paddingLeft="20dp" android:paddingHorizontal="16dp">
android:paddingRight="20dp">
<FrameLayout <FrameLayout
android:id="@+id/reply_btn" android:id="@+id/reply_btn"
@@ -15,10 +14,11 @@
<TextView <TextView
android:id="@+id/reply" android:id="@+id/reply"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="24dp" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center_vertical"
android:drawableStart="@drawable/ic_fluent_chat_multiple_24_selector_text" android:drawableStart="@drawable/ic_fluent_chat_multiple_24_selector_text"
android:drawablePadding="8dp" android:drawablePadding="8dp"
android:paddingHorizontal="8dp"
android:drawableTint="?android:textColorSecondary" android:drawableTint="?android:textColorSecondary"
android:gravity="center_vertical" android:gravity="center_vertical"
android:textAppearance="@style/m3_label_large" android:textAppearance="@style/m3_label_large"
@@ -38,10 +38,11 @@
<TextView <TextView
android:id="@+id/boost" android:id="@+id/boost"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="24dp" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center_vertical"
android:drawableStart="@drawable/ic_boost" android:drawableStart="@drawable/ic_boost"
android:drawablePadding="8dp" android:drawablePadding="8dp"
android:paddingHorizontal="8dp"
android:drawableTint="@color/boost_icon" android:drawableTint="@color/boost_icon"
android:textColor="@color/boost_icon" android:textColor="@color/boost_icon"
android:gravity="center_vertical" android:gravity="center_vertical"
@@ -62,10 +63,11 @@
<TextView <TextView
android:id="@+id/favorite" android:id="@+id/favorite"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="24dp" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center_vertical"
android:drawableStart="@drawable/ic_fluent_star_24_selector" android:drawableStart="@drawable/ic_fluent_star_24_selector"
android:drawablePadding="8dp" android:drawablePadding="8dp"
android:paddingHorizontal="8dp"
android:drawableTint="@color/favorite_icon" android:drawableTint="@color/favorite_icon"
android:textColor="@color/favorite_icon" android:textColor="@color/favorite_icon"
android:gravity="center_vertical" android:gravity="center_vertical"
@@ -86,10 +88,10 @@
<TextView <TextView
android:id="@+id/bookmark" android:id="@+id/bookmark"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="24dp" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center_vertical"
android:drawableStart="@drawable/ic_fluent_bookmark_24_selector" android:drawableStart="@drawable/ic_fluent_bookmark_24_selector"
android:drawablePadding="8dp" android:paddingHorizontal="8dp"
android:drawableTint="@color/bookmark_icon" android:drawableTint="@color/bookmark_icon"
android:gravity="center_vertical" android:gravity="center_vertical"
android:textAppearance="@style/m3_label_large" /> android:textAppearance="@style/m3_label_large" />
@@ -103,14 +105,14 @@
<FrameLayout <FrameLayout
android:id="@+id/share_btn" android:id="@+id/share_btn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent">
android:minWidth="56dp">
<ImageView <ImageView
android:id="@+id/share" android:id="@+id/share"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="24dp" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center_vertical"
android:src="@drawable/ic_fluent_share_24_regular" android:src="@drawable/ic_fluent_share_24_regular"
android:paddingHorizontal="8dp"
android:tint="?android:textColorSecondary" android:tint="?android:textColorSecondary"
android:gravity="center_vertical"/> android:gravity="center_vertical"/>
</FrameLayout> </FrameLayout>

View File

@@ -25,4 +25,6 @@
android:layout_margin="8dp" android:layout_margin="8dp"
android:background="@drawable/ic_gif"/> android:background="@drawable/ic_gif"/>
<include layout="@layout/alt_badge" />
</org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout> </org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout>

View File

@@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="11dp" android:paddingTop="13dp"
android:paddingEnd="4dp" android:paddingEnd="4dp"
android:paddingStart="16dp"> android:paddingStart="16dp">
@@ -41,11 +41,35 @@
android:src="@drawable/ic_visibility" android:src="@drawable/ic_visibility"
android:tint="?android:textColorSecondary" /> android:tint="?android:textColorSecondary" />
<FrameLayout
android:id="@+id/collapse_btn"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_toStartOf="@id/visibility"
android:background="?android:actionBarItemBackground"
android:visibility="gone"
android:importantForAccessibility="noHideDescendants">
<!-- wrapping this button so the flip animation doesn't flip the background and the tooltip
isn't displaced by the -1 scale -->
<ImageView
android:id="@+id/collapse_btn_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:importantForAccessibility="no"
android:scaleType="center"
android:src="@drawable/ic_fluent_chevron_down_20_filled"
android:tint="?android:textColorSecondary" />
</FrameLayout>
<ImageView <ImageView
android:id="@+id/unread_indicator" android:id="@+id/unread_indicator"
android:layout_width="36dp" android:layout_width="36dp"
android:layout_height="36dp" android:layout_height="36dp"
android:layout_toStartOf="@id/visibility" android:layout_toStartOf="@id/collapse_btn"
android:visibility="gone" android:visibility="gone"
android:tint="?android:colorAccent" android:tint="?android:colorAccent"
android:scaleType="center" android:scaleType="center"
@@ -58,14 +82,15 @@
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_marginEnd="12dp" android:layout_marginEnd="12dp"
android:layout_marginTop="5dp" /> android:layout_marginTop="3dp" />
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout <org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
android:id="@+id/name_wrap" android:id="@+id/name_wrap"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="12dp" android:layout_marginEnd="8dp"
android:layout_marginTop="7dp" android:layout_marginTop="3dp"
android:paddingTop="4sp"
android:layout_toStartOf="@id/unread_indicator" android:layout_toStartOf="@id/unread_indicator"
android:layout_toEndOf="@id/avatar" android:layout_toEndOf="@id/avatar"
android:minHeight="24sp"> android:minHeight="24sp">

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@@ -11,81 +10,6 @@
android:layout_gravity="center" android:layout_gravity="center"
android:scaleType="centerCrop"/> android:scaleType="centerCrop"/>
<!-- This is hidden from screenreaders because that same alt text is set as content description on the ImageView --> <include layout="@layout/alt_badge" />
<FrameLayout
android:id="@+id/alt_text_wrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:layout_margin="12dp"
android:importantForAccessibility="noHideDescendants"
android:background="@drawable/bg_image_alt_overlay">
<ImageView
android:id="@+id/no_alt_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:src="@drawable/ic_fluent_important_20_filled"
android:tint="?colorGray25" />
<TextView
android:id="@+id/alt_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorGray25"
android:gravity="center"
android:includeFontPadding="false"
android:paddingHorizontal="5dp"
android:paddingVertical="1dp"
android:text="@string/sk_alt_button"/>
<ImageButton
android:id="@+id/alt_text_close"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="end|top"
android:src="@drawable/ic_baseline_close_24"
android:tint="#FFF"
android:background="?android:actionBarItemBackground"/>
<org.joinmastodon.android.ui.views.NestableScrollView
android:id="@+id/alt_text_scroller"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="40dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/alt_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textAppearance="@style/m3_body_medium"
android:textColor="?colorGray25"
tools:text="Alt text goes here"/>
<TextView
android:id="@+id/no_alt_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="14dp"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorGray25"
android:text="@string/sk_no_alt_text"/>
</LinearLayout>
</org.joinmastodon.android.ui.views.NestableScrollView>
</FrameLayout>
</org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout> </org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout>

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