Compare commits

..

509 Commits

Author SHA1 Message Date
LucasGGamerM
b1cb75d45f feat: still show the attach menu even if no PhotoPicker is avaiable
This is due to the newly added camera shortcut, which makes the menu necessary even if no PhotoPicker is available
2023-06-11 18:12:30 -03:00
LucasGGamerM
1675c8ab79 fix: unregister ComposeFragment for events on its destruction 2023-06-11 18:06:11 -03:00
LucasGGamerM
986b9731a1 fix: fix attachment not adding only after accepting the permission prompt on camera shortcut 2023-06-11 18:04:30 -03:00
LucasGGamerM
dc66b27c8a feat: add camera shortcut to compose screen 2023-06-11 16:48:19 -03:00
LucasGGamerM
3924c65e8c Merge remote-tracking branch 'weblate/master'
# Conflicts:
#	mastodon/src/main/res/values-es-rES/strings_mo.xml
#	mastodon/src/main/res/values-es-rES/strings_sk.xml
#	mastodon/src/main/res/values-in-rID/strings_sk.xml
#	mastodon/src/main/res/values-pt-rPT/strings_sk.xml
#	mastodon/src/main/res/values-ru-rRU/strings_mo.xml
2023-06-11 16:18:33 -03:00
Anonymous
df7da2d7f6 Translated using Weblate (Arabic (Algeria))
Currently translated at 6.0% (2 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/ar_DZ/
2023-06-11 19:15:50 +00:00
Anonymous
697f95f3e3 Translated using Weblate (Occitan)
Currently translated at 6.0% (2 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/oc/
2023-06-11 19:15:26 +00:00
Anonymous
f0d7da7194 Translated using Weblate (Kabyle)
Currently translated at 6.0% (2 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/kab/
2023-06-11 19:15:25 +00:00
legiz
b641e83470 Translated using Weblate (Russian)
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/ru/
2023-06-11 15:37:39 +00:00
gicorada
f22f9c2dcc Translated using Weblate (Italian)
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/it/
2023-06-11 15:37:39 +00:00
Linerly
9ef2c278f6 Translated using Weblate (Indonesian)
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/id/
2023-06-11 15:37:38 +00:00
gicorada
4a7cb4f129 Translated using Weblate (Italian)
Currently translated at 39.3% (13 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/it/
2023-06-11 15:37:38 +00:00
legiz
3a47e8eea3 Translated using Weblate (Russian)
Currently translated at 100.0% (33 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/ru/
2023-06-11 15:37:38 +00:00
legiz
4defd9c420 Translated using Weblate (Russian)
Currently translated at 95.7% (68 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/ru/
2023-06-11 15:37:38 +00:00
gicorada
3bbff120f0 Translated using Weblate (Italian)
Currently translated at 100.0% (71 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/it/
2023-06-11 15:37:37 +00:00
Linerly
bf07e9f079 Translated using Weblate (Indonesian)
Currently translated at 100.0% (71 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/id/
2023-06-11 15:37:37 +00:00
LucasGGamerM
72fdff96c8 fix: fix crash when onDenied runnable is null on dialogs 2023-06-10 18:15:25 -03:00
LucasGGamerM
4e21b60087 Merge branch 'master' of https://github.com/LucasGGamerM/moshidon 2023-06-10 14:31:17 -03:00
LucasGGamerM
7c786e55a5 fix: fix follow button on ProfileFragment 2023-06-10 14:30:29 -03:00
LucasGGamerM
51294bbb14 build(nightly): compile appkit dependency with workflow 2023-06-10 11:18:15 -03:00
LucasGGamerM
5dcda4f37a feat: merge megalodon's always reveal equal spoilers in threads/discussions 2023-06-10 11:00:34 -03:00
LucasGGamerM
33d725acb4 refactor: use isRemote instead of reloadWhenClicked
Why are my variable naming abilities be so awful?
2023-06-10 10:44:56 -03:00
LucasGGamerM
fb78ac1243 feat: use megalodon's setting item and strings for remote followers 2023-06-10 10:33:30 -03:00
LucasGGamerM
ccfa614dc7 fix(boost-button): fix it not updating its state on non-boostable items 2023-06-10 10:26:54 -03:00
LucasGGamerM
bc7f614573 refactor: fix compilation problems by refactoring old code 2023-06-09 18:52:08 -03:00
LucasGGamerM
7700288dbe fix: fix compilation problems with isScrolledToTop method not being implemented 2023-06-09 18:31:45 -03:00
LucasGGamerM
e2c62aa76b Merge remote-tracking branch 'megalodon_main/main'
# Conflicts:
#	mastodon/build.gradle
#	mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java
#	mastodon/src/main/java/org/joinmastodon/android/api/requests/accounts/GetAccountByHandle.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/ComposeFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/ThreadFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/account_list/BaseAccountListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/account_list/FollowerListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/account_list/FollowingListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/account_list/PaginatedAccountListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/model/Account.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/text/ClickableLinksDelegate.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/values/dimens.xml
2023-06-09 18:09:23 -03:00
sk
35bf858a83 auto-reveal equal spoilers in threads 2023-06-09 14:54:03 +02:00
sk
870bfaf08c don't use switch for android ids 2023-06-09 14:50:21 +02:00
sk
c4238fb19b keep revealed states when reloading
closes sk22#561
2023-06-09 13:27:25 +02:00
sk
ba7aeb358b fix thread status not clickable if filter revealed
closes sk22#554
2023-06-09 12:50:10 +02:00
sk
6f3fd4d454 fix opening browser twice
closes sk22#559
2023-06-09 12:47:32 +02:00
sk
97547f334f returning optionals for the optional god
closes sk22#555
2023-06-08 15:31:58 +02:00
sk
1ab953d819 fix spoiler button being hidden while editing
closes sk22#553
2023-06-08 15:03:04 +02:00
LucasGGamerM
161c19b628 fix(account-sheet): fix wrong coloring for add account drawawble 2023-06-07 21:26:15 -03:00
sk
307d483a56 add comment 2023-06-07 21:59:56 +02:00
sk
9612248695 remove unused imports 2023-06-07 21:51:17 +02:00
sk
1f63401e5b fix pixelfed post editing 2023-06-07 21:50:50 +02:00
sk
d35ec18a88 increase akkoma scheduled posts compatibility 2023-06-07 21:12:38 +02:00
sk
b93b1847c3 increase pixelfed compatibility 2023-06-07 21:12:30 +02:00
sk
cd46ed565f open browser if login redirects to website 2023-06-07 21:11:20 +02:00
sk
4a0e4edef8 load more if screen isn't full yet 2023-06-07 20:28:56 +02:00
sk
2ea7333daa only reload main status when refreshing
closes sk22#552
2023-06-07 18:45:50 +02:00
sk
fa7a66809d change profile loading error behavior 2023-06-07 16:09:41 +02:00
sk
71884ab760 don't show wrong relationship with remote accounts 2023-06-07 15:50:30 +02:00
sk
f31205c670 generalize lookup error handling 2023-06-07 15:45:22 +02:00
sk
0091ae87ce fix issues with external share
closes sk22#550
2023-06-07 15:17:44 +02:00
LucasGGamerM
c196dc563f fix(follow-more): fix follow more fragment pointing to edit profile
This was probably made to be used on the create new account procedure, and it was being reused on the Home tab long click action. As we don't have an account creation procedure on Moshidon, we can just stop pointing to the OnboardingProfileSetup fragment
2023-06-06 19:38:04 -03:00
LucasGGamerM
2baf51616c fix(settings): update max lines number in settings items
This fixes the bug where settings secondary text would go missing if a screen was too small. This addresses that. It's also something for you @sk22
2023-06-06 19:25:51 -03:00
LucasGGamerM
b75e2ce26f Merge branch 'master' of https://github.com/LucasGGamerM/moshidon 2023-06-06 19:17:19 -03:00
LucasGGamerM
15976a991b refactor(settings): refactor settings toolbar animations
Also fixes wrong elevation on toolbar hidden mode
2023-06-06 19:17:07 -03:00
LucasGGamerM
16ee7371e7 build: make nightly builds not debuggable 2023-06-06 16:52:35 -03:00
LucasGGamerM
02f0c794c7 feat(settings): add fadeIn and fadeOut animations to toolbar title 2023-06-06 14:10:06 -03:00
sk
ad13b1e927 bump version 2023-06-06 17:13:30 +02:00
sk
a354ea80ab Merge remote-tracking branch 'upstream/l10n_master' 2023-06-06 17:09:06 +02:00
sk22
9f65b8112a Translated using Weblate (German)
Currently translated at 100.0% (297 of 297 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-06-06 15:08:53 +00:00
Choukajohn
6ac5d957fe Translated using Weblate (French)
Currently translated at 100.0% (293 of 293 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-06-06 15:05:05 +00:00
sk
4258c55b88 implement fetching listings from remote instances 2023-06-06 17:04:29 +02:00
sk
969f29e2e9 support string res for small text item 2023-06-06 16:55:20 +02:00
sk
68921d0f0b fix footer being too close to next header 2023-06-06 14:23:34 +02:00
Eugen Rochko
c4ac4ee173 New translations strings.xml (Swedish) 2023-06-06 13:23:46 +02:00
Eugen Rochko
659b4e2fcd New translations strings.xml (Swedish) 2023-06-06 11:55:59 +02:00
sk
24e5bda8d3 fix profile options icons 2023-06-06 10:30:32 +02:00
Eugen Rochko
02b1ad8d7a New translations strings.xml (Swedish) 2023-06-06 00:56:52 +02:00
Eugen Rochko
47eeb01b75 New translations strings.xml (Turkish) 2023-06-05 21:08:28 +02:00
ihor_ck
4288814138 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (293 of 293 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-06-05 16:09:08 +00:00
sk
ac4458e106 fix badged toolbar icons with new appkit version 2023-06-05 18:07:22 +02:00
sk
3d24b2de10 add status counters event listener to notifications 2023-06-05 16:19:55 +02:00
sk
ed994b23e9 fix wrong views' states being modified
closes sk22#549
2023-06-05 16:12:07 +02:00
sk
8c4678aba5 fix updated main status not being applied 2023-06-05 16:05:58 +02:00
Eugen Rochko
3d5fb2dfea New translations strings.xml (Swedish) 2023-06-05 15:00:47 +02:00
Eugen Rochko
ef6238b593 New translations strings.xml (Swedish) 2023-06-05 13:45:02 +02:00
Eugen Rochko
bc9bec3d66 New translations strings.xml (Swedish) 2023-06-05 12:47:38 +02:00
sk
d16e199dd1 scroll up when posting on profile fragment
closes sk22#546
2023-06-05 11:48:40 +02:00
sk
a9c2df2e83 do copy spoilerRevealed on clone
closes sk22#547
2023-06-05 11:26:36 +02:00
sk
4673a4b9f7 add missing database column in post notification table 2023-06-05 11:22:01 +02:00
Grishka
d4a5286895 Fix #553 2023-06-04 23:47:08 +02:00
Grishka
1b4579346b Fix #548 2023-06-04 23:39:06 +02:00
sk
0665b8dd3b fix incompatibility with upstream bugfix 2023-06-04 23:33:04 +02:00
LucasGGamerM
4f367d3e88 feat: add instance url to toolbar on instance about fragment 2023-06-04 18:32:47 -03:00
Grishka
853124e2ce Fix it again 2023-06-04 23:32:13 +02:00
Grishka
5dcd6e5a0d Fix it again 2023-06-04 23:31:12 +02:00
Grishka
6f25c8be0f Fix #583 2023-06-04 23:26:48 +02:00
sk
1db4b1319e use latest appkit version 2023-06-04 23:26:39 +02:00
Grishka
76a97fcb47 Fix #591 2023-06-04 23:20:29 +02:00
sk
4baaa39f35 bump version 2023-06-04 23:16:32 +02:00
sk
52f025ae5a Merge remote-tracking branch 'upstream/l10n_master' 2023-06-04 23:14:49 +02:00
sk22
14b805e883 Translated using Weblate (German)
Currently translated at 100.0% (293 of 293 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-06-04 21:13:53 +00:00
sk
433a7b15fe change bubble string 2023-06-04 23:03:29 +02:00
sk
6c8cbbc34a Merge remote-tracking branch 'weblate/main' 2023-06-04 22:58:56 +02:00
sk
d4fbb298c1 use sp for reply line inline icons 2023-06-04 22:57:06 +02:00
LucasGGamerM
9d78bb508a feat: better toolbar behavior on instance about fragment 2023-06-04 17:45:38 -03:00
sk
2aeb5f03d6 remove unused sp drawables 2023-06-04 22:32:54 +02:00
sk
6522403c37 fix footer text margins 2023-06-04 22:12:45 +02:00
sk
f090ca7f75 use sp for scaled footer 2023-06-04 21:08:45 +02:00
LucasGGamerM
ac8b950893 feat: remove colorful refreshLayout from ProfileFragment 2023-06-04 16:02:50 -03:00
sk
2f02a238df refresh updated main status 2023-06-04 20:56:44 +02:00
LucasGGamerM
22f9e941aa feat: share instance menu item on instance about screen 2023-06-04 15:45:26 -03:00
sk
0d5fa97800 fix wrong index 2023-06-04 20:40:27 +02:00
sk
b102deaee1 don't let interaction counts go negative 2023-06-04 19:08:18 +02:00
LucasGGamerM
3a73dbf304 build(nightly): make nightly builds debuggable and not resource shrinked 2023-06-04 11:23:52 -03:00
LucasGGamerM
faabc068ca fix: remoteFollowers feature
This fixes the remoteFollowers feature, which was broken after the merge from Megalodon
2023-06-04 11:18:33 -03:00
LucasGGamerM
443a69b10d feat: use correct title for confirmLogOut dialog 2023-06-04 11:00:02 -03:00
LucasGGamerM
6881651ce7 feat: even denser AccountSwitcherSheet 2023-06-04 10:53:29 -03:00
LucasGGamerM
04aadf48f2 feat: use secondary text color for username in AccountSwitcherSheet 2023-06-04 10:43:24 -03:00
Andrewblasco
fc7ff07f40 Translated using Weblate (Spanish)
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/es/
2023-06-04 10:37:37 +00:00
Eryk Michalak
968b2ee460 Translated using Weblate (Polish)
Currently translated at 97.9% (286 of 292 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2023-06-04 10:37:37 +00:00
Andrewblasco
890340de94 Translated using Weblate (Spanish)
Currently translated at 99.6% (291 of 292 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-06-04 10:37:37 +00:00
Andrewblasco
c0589da549 Translated using Weblate (Spanish)
Currently translated at 100.0% (71 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-06-04 10:37:36 +00:00
sk
4ca1a7b29e fix index out of bounds exception 2023-06-04 11:45:12 +02:00
sk
5432f2590c fine-tune footer layout 2023-06-04 05:00:48 +02:00
sk
60ccf5cf0a only shift selection box if footer is present 2023-06-04 04:15:15 +02:00
sk
bc717f5b10 tweak footer margins and hitboxes 2023-06-04 04:08:38 +02:00
LucasGGamerM
3aead05ad4 feat: use megalogon's lighter grays on colors.xml 2023-06-03 22:03:41 -03:00
LucasGGamerM
9ef43cc6d3 feat: make nav bar color consistent with account switcher sheet
Merge this commit and the one before this one @sk22
2023-06-03 21:54:39 -03:00
LucasGGamerM
24df7d49d5 feat: make ProfileFragment not reloadable when in edit mode 2023-06-03 21:46:23 -03:00
sk
486eef21dd responsive footer width 2023-06-04 02:16:47 +02:00
sk
44a4d02815 remove redundant suppress annotation 2023-06-04 01:36:38 +02:00
sk
336a8194bd fix settings button binding not reset visibility and events 2023-06-04 01:36:05 +02:00
LucasGGamerM
ac7c1c8497 fix: wrong pixel launcher url for customLocalTimelines 2023-06-03 20:30:24 -03:00
LucasGGamerM
d72f66b9bf fix: NPE when getInstance().pleroma.metadata.fieldsLimits is null 2023-06-03 20:25:27 -03:00
LucasGGamerM
1d445b8b27 fix: compilation problems 2023-06-03 20:21:28 -03:00
LucasGGamerM
14175a9140 Merge remote-tracking branch 'megalodon_main/main'
# Conflicts:
#	mastodon/build.gradle
#	mastodon/src/main/java/org/joinmastodon/android/ExternalShareActivity.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/fragments/BaseStatusListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/EditTimelinesFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/FollowRequestsListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/FollowedHashtagsFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/HomeFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTabFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/ListTimelinesFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/NotificationsFragment.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/ThreadFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/account_list/FollowerListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/account_list/FollowingListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/account_list/StatusFavoritesListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/account_list/StatusReblogsListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/discover/DiscoverAccountsFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/discover/DiscoverFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/discover/DiscoverHashtagsFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/discover/DiscoverNewsFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/discover/FederatedTimelineFragment.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/model/TimelineDefinition.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/AccountSwitcherSheet.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FooterStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HashtagStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/utils/UiUtils.java
#	mastodon/src/main/res/layout/item_account_switcher.xml
#	mastodon/src/main/res/values-ar-rDZ/strings_sk.xml
#	mastodon/src/main/res/values-es-rES/strings_sk.xml
#	mastodon/src/main/res/values-nl-rNL/strings_sk.xml
#	mastodon/src/main/res/values-pt-rPT/strings_sk.xml
#	mastodon/src/main/res/values-v31/colors.xml
#	mastodon/src/main/res/values/colors.xml
#	mastodon/src/main/res/values/styles.xml
2023-06-03 19:56:16 -03:00
sk
7859f4cd05 support parsing mailto links
i mean, why not - if github decided every @username@example.social is actually
an email address, might as well support sharing that mailto link to megalodon
2023-06-03 23:39:43 +02:00
sk
37622ba9ce generalize notification handling, open reports in browser 2023-06-03 22:47:20 +02:00
sk
7a6af89375 fix unwanted fab animation when scrolling and switching tab
closes sk22#528
2023-06-03 22:07:58 +02:00
sk
056bfaacfe fix fab being hidden when scrolling to top
closes sk22#528
2023-06-03 21:54:57 +02:00
sk
6684311ec5 fix button state/char counter not updating when empty
closes sk22#537
2023-06-03 21:24:40 +02:00
sk
11943571ad fix thread replies not added to data
closes sk22#543
2023-06-03 21:10:45 +02:00
sk
f696fcd412 simplify ancestry code 2023-06-03 21:03:47 +02:00
sk
2919e109ca remove unused member 2023-06-03 20:40:29 +02:00
sk
995f478708 allow sharing @-handles with megalodon
closes sk22#540
2023-06-03 20:31:00 +02:00
LucasGGamerM
04fdea0296 docs: update readme 2023-06-03 10:27:01 -03:00
LucasGGamerM
b112c3a0b2 docs: add monero wallet address to readme 2023-06-03 09:43:28 -03:00
LucasGGamerM
47149dd394 Update FUNDING.yml 2023-06-02 18:54:19 -03:00
LucasGGamerM
d1e0c1ebad Update FUNDING.yml 2023-06-02 18:48:51 -03:00
LucasGGamerM
2ef9d87250 docs: add liberapay donations link 2023-06-02 18:46:37 -03:00
sk
fb8764bcd7 refactor ancestry, fix case regarding reply line
fix case where reply line was removed despite having no direct ancestor
2023-06-02 22:08:03 +02:00
Eugen Rochko
d7f73e02c5 New translations strings.xml (German) 2023-06-02 20:22:32 +02:00
Eugen Rochko
e897b3af57 New translations strings.xml (German) 2023-06-02 19:23:23 +02:00
sk
e04fd8a004 bump version 2023-06-02 19:10:08 +02:00
sk
ada70ae1b5 Merge remote-tracking branch 'upstream/l10n_master' 2023-06-02 19:09:44 +02:00
Espasant3
5fdec0900e Translated using Weblate (Galician)
Currently translated at 100.0% (292 of 292 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-06-02 17:09:12 +00:00
sk
56a93288c4 reimplement thread ancestry 2023-06-02 19:05:18 +02:00
sk
02e3421f98 fix null pointer exception 2023-06-02 19:03:29 +02:00
LucasGGamerM
df7b53e10f feat(settings): move timeline settings around
This moves the button to the topmost item on pleroma based instances
2023-06-02 13:48:26 -03:00
Eugen Rochko
fdbf331432 New translations strings.xml (Bengali) 2023-06-02 18:01:03 +02:00
Eugen Rochko
aed86ac6f0 New translations strings.xml (Bengali) 2023-06-02 16:50:10 +02:00
Eugen Rochko
3a13d4d6c0 New translations strings.xml (Bengali) 2023-06-02 05:45:51 +02:00
Eugen Rochko
f5336564d0 New translations strings.xml (Bengali) 2023-06-02 04:39:21 +02:00
sk
1ce49c68fe bump version 2023-06-02 01:45:55 +02:00
sk
d37e880993 don't close sheet after logging out 2023-06-02 01:45:30 +02:00
sk
6fdb81a01f Merge remote-tracking branch 'upstream/l10n_master' 2023-06-02 01:37:14 +02:00
ihor_ck
f9d6827572 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (292 of 292 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-06-01 23:36:24 +00:00
Linerly
10bf72b9ff Translated using Weblate (Indonesian)
Currently translated at 100.0% (292 of 292 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-06-01 23:36:24 +00:00
Choukajohn
800f929a15 Translated using Weblate (French)
Currently translated at 100.0% (292 of 292 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-06-01 23:36:24 +00:00
sk
bfcff1e19f fix null pointer exception
closes sk22#539
2023-06-02 01:34:31 +02:00
sk
f373e7df3e put code in method, add todo 2023-06-02 01:16:21 +02:00
sk
3985de5b14 visually connect descendant replies in threads
closes sk22#256
closes sk22#510
2023-06-02 00:55:42 +02:00
LucasGGamerM
4d75621384 fix(settings): fix on theme change crash
This fixes such bug by only registering for listening to events on the onCreate method, and not on the onViewCreated method. For some wacky reason, when the activity gets recreated, the onViewCreated method runs again, but the onDestroy method doesn't, which makes the fragment register for events twice without unregistering, which causes the app to crash. Also refactors some duplicate code.
2023-06-01 19:46:45 -03:00
sk
e175a721d4 remove additional padding with translate button 2023-06-02 00:17:50 +02:00
sk
d9784ebc31 use /about web uri for akkoma 2023-06-01 19:28:46 +02:00
sk
f241092277 use isInstanceAkkoma() 2023-06-01 19:22:01 +02:00
sk
0702703d78 normalize instance uri 2023-06-01 19:13:03 +02:00
sk
2c4504bad3 fix current fragment detection 2023-06-01 19:12:50 +02:00
Eugen Rochko
07ca5a8b77 New translations strings.xml (Bengali) 2023-06-01 19:07:10 +02:00
sk
798a43906f denser account switcher
this one's for @experiencersinternational
2023-06-01 18:46:53 +02:00
sk
41cb0f2e09 implement assist url in instance rules 2023-06-01 18:38:45 +02:00
sk
e12c0fb81f bump version 2023-06-01 18:10:30 +02:00
Oliebol
ac39f119e2 Translated using Weblate (Dutch)
Currently translated at 88.4% (253 of 286 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/nl/
2023-06-01 16:08:59 +00:00
Espasant3
016faf3df0 Translated using Weblate (Galician)
Currently translated at 99.6% (285 of 286 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-06-01 16:08:59 +00:00
sk
b2d6879282 reimplement assist content 2023-06-01 18:02:33 +02:00
Eugen Rochko
6926a212f4 New translations strings.xml (Bengali) 2023-06-01 17:46:40 +02:00
LucasGGamerM
addb6e06bf feat(settings): add horizontal padding to SettingsFooterItem
This addresses a minor annoyance where the version name would be glued to the sides of the display
2023-06-01 11:55:31 -03:00
LucasGGamerM
8ea752fbf7 fix: fix updateItem not updating state after UpdateState change
This fixes the auto updater on the new settings redesign
2023-06-01 11:51:26 -03:00
sk
89afc05d5c Merge branch 'main' into pr/FineFindus/530 2023-06-01 16:32:04 +02:00
Eugen Rochko
936f39161b New translations strings.xml (German) 2023-05-31 20:11:48 +02:00
sk
ee20ee0722 include mentions in reply from notification
closes sk22#536
2023-05-31 12:42:48 +02:00
sk
02f9f8c8ea always update active account, but not others 2023-05-31 12:23:04 +02:00
sk
de3a252884 not as huge share sheet heading 2023-05-31 10:12:12 +02:00
sk
5e7a00de3e fix crash when logging out active account 2023-05-31 10:05:31 +02:00
sk
2858aeb55e only set last account id if creating new activity 2023-05-31 09:45:24 +02:00
sk
357104efa9 set checked on basis of fragment's account id
closes sk22#538
2023-05-31 09:42:29 +02:00
sk
bb8027c7ef open externally opened content in main activity
closes sk22#533
2023-05-31 01:44:00 +02:00
sk
f9dd787009 fix rules crashing the app
closes sk22#535
2023-05-31 00:19:38 +02:00
LucasGGamerM
9478258caa Merge remote-tracking branch 'weblate/master' 2023-05-30 19:04:34 -03:00
Tânia Marques Silva
9432bf9f38 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/pt_PT/
2023-05-30 22:01:22 +00:00
Andrewblasco
c935a00763 Translated using Weblate (Spanish)
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/es/
2023-05-30 22:01:22 +00:00
legiz
404c4a3fdd Translated using Weblate (Russian)
Currently translated at 6.0% (2 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/ru/
2023-05-30 22:01:22 +00:00
Tânia Marques Silva
4fa8f6deb5 Translated using Weblate (Portuguese (Portugal))
Currently translated at 27.2% (9 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/pt_PT/
2023-05-30 22:01:22 +00:00
legiz
f55b05012d Translated using Weblate (Russian)
Currently translated at 85.9% (61 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/ru/
2023-05-30 22:01:22 +00:00
Tânia Marques Silva
ae81fee449 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (71 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/pt_PT/
2023-05-30 22:01:22 +00:00
Oliebol
ec8dda4501 Translated using Weblate (Dutch)
Currently translated at 70.4% (50 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/nl/
2023-05-30 22:01:22 +00:00
Andrewblasco
269b0b36b0 Translated using Weblate (Spanish)
Currently translated at 100.0% (71 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-05-30 22:01:22 +00:00
Clyde
c8ed7c364b Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/zh_Hans/
2023-05-30 22:01:22 +00:00
Clyde
356833e248 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (33 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/zh_Hans/
2023-05-30 22:01:22 +00:00
Clyde
1aa80270b4 Translated using Weblate (Chinese (Simplified))
Currently translated at 94.9% (56 of 59 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/zh_Hans/
2023-05-30 22:01:22 +00:00
Andrewblasco
1fccecdbf6 Translated using Weblate (Spanish)
Currently translated at 100.0% (59 of 59 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-05-30 22:01:22 +00:00
Andrewblasco
8be396e801 Translated using Weblate (Spanish)
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/es/
2023-05-30 22:01:22 +00:00
Andrewblasco
6755ff836e Translated using Weblate (Spanish)
Currently translated at 100.0% (59 of 59 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-05-30 22:01:22 +00:00
Andrewblasco
a3fc9710f7 Translated using Weblate (Spanish)
Currently translated at 100.0% (48 of 48 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-05-30 22:01:22 +00:00
sk
e005731ba6 theming support for m3 colors 2023-05-30 23:52:26 +02:00
sk
18ae3f4f61 Merge branch 'pr/FineFindus/531'
Co-authored-by: FineFindus <63370021+finefindus@users.noreply.github.com>
2023-05-30 22:46:08 +02:00
sk
10dfe0327e use new account switcher 2023-05-30 22:42:56 +02:00
Jacoco
1d1e921137 Fix GoToSocial crash when markers are null (#529) 2023-05-30 19:07:34 +02:00
sk
0985a4c968 getInstance returns optional 2023-05-30 18:57:17 +02:00
sk
8df589c103 safer file writing 2023-05-30 18:56:55 +02:00
LucasGGamerM
3ac9c09338 feat: shows toolbar when scrolled past title
This still needs to be redone with the same style as the profile fragment
2023-05-30 13:19:04 -03:00
FineFindus
71b6b2f451 feat(share): add option open URL 2023-05-30 16:33:09 +02:00
FineFindus
d85940ded8 fix: re-add removed imports 2023-05-30 16:28:04 +02:00
LucasGGamerM
e9e491c0b0 feat: redesign account picker sheet 2023-05-30 16:25:04 +02:00
FineFindus
c73562fb75 feat(external-share): use AccountSwitcherSheet 2023-05-30 16:24:43 +02:00
FineFindus
3feacb59c8 feat(external-share): use transparent background 2023-05-30 16:19:28 +02:00
FineFindus
a033d711c1 feat: show page URL in recents 2023-05-30 15:40:20 +02:00
LucasGGamerM
ba31afda27 fix: fixes wrong status bar background color on light mode in settings
This addresses #204
2023-05-29 20:24:13 -03:00
Tânia Marques Silva
3029c37755 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/pt_PT/
2023-05-29 18:37:37 +00:00
Andrewblasco
728d55ffa0 Translated using Weblate (Spanish)
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/es/
2023-05-29 18:37:37 +00:00
legiz
265e9a9f56 Translated using Weblate (Russian)
Currently translated at 6.0% (2 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/ru/
2023-05-29 18:37:37 +00:00
Tânia Marques Silva
7fbe205902 Translated using Weblate (Portuguese (Portugal))
Currently translated at 27.2% (9 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/pt_PT/
2023-05-29 18:37:36 +00:00
legiz
9b84333868 Translated using Weblate (Russian)
Currently translated at 85.9% (61 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/ru/
2023-05-29 18:37:36 +00:00
Tânia Marques Silva
9525893bf7 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (71 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/pt_PT/
2023-05-29 18:37:36 +00:00
Oliebol
daf15dcc62 Translated using Weblate (Dutch)
Currently translated at 70.4% (50 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/nl/
2023-05-29 18:37:36 +00:00
Andrewblasco
b3e2b69b70 Translated using Weblate (Spanish)
Currently translated at 100.0% (71 of 71 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-05-29 18:37:36 +00:00
sk
32081b71f5 throw exception if no instance for session 2023-05-29 13:31:42 +02:00
sk
7849c34d1f fix account list alignment 2023-05-29 13:25:14 +02:00
sk
24977ec613 bump version 2023-05-29 13:03:18 +02:00
sk
786bbab0d5 Merge remote-tracking branch 'weblate/main' 2023-05-29 13:01:36 +02:00
sk
1facb07c28 Merge remote-tracking branch 'upstream/l10n_master' 2023-05-29 13:01:24 +02:00
sk
bba5aba22d settings icons not important for accessibility 2023-05-29 12:56:36 +02:00
sk
d7b85d6eba move invalid strings 2023-05-29 12:47:38 +02:00
sk
6832bfb95c don't display blocked_by relationship
closes sk22#526
2023-05-29 12:34:53 +02:00
sk
4c379b67a3 only auto-open search on pleroma instances 2023-05-29 03:33:31 +02:00
sk
3a2ae1ce71 clean up preferences when removing account 2023-05-29 02:40:15 +02:00
sk
c80afaf9c0 avoid sessions without instance info 2023-05-29 02:40:02 +02:00
sk
31d22bac47 remove unused method 2023-05-29 02:38:52 +02:00
Jacoco
b5f6687925 More Akkoma improvements (#524)
* Only open account if domain matches
Akkoma will seemingly show results that don't match well. This checks if the domain matches before continuing

* Add "RE:" for quotes where it's missing

* Fix no hashtag history in search

* Skip not implemented discovery and select search on Pleroma

* Set proper max account fields for Pleroma

* Use Pleroma's non-standard poll limits

* Mark notifications as read properly on Pleroma

* Akkoma bubble timeline

* Respect Reply Visibility preference on all timelines

* vertically center if hashtag has no history

* only open account search result if uri equals

* add getInstance and isPleroma methods

* change timelines api, support compatibility checks

---------

Co-authored-by: sk <sk22@mailbox.org>
2023-05-29 02:37:46 +02:00
taniamarquessilva
b3f25af923 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (286 of 286 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_PT/
2023-05-28 20:19:30 +00:00
taniamarquessilva
78c141e946 Translated using Weblate (Portuguese)
Currently translated at 14.6% (42 of 286 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt/
2023-05-28 20:19:30 +00:00
taniamarquessilva
83d36ce736 Translated using Weblate (Portuguese)
Currently translated at 52.9% (9 of 17 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pt/
2023-05-28 20:19:30 +00:00
taniamarquessilva
b928357ff1 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (286 of 286 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pt_PT/
2023-05-28 20:19:30 +00:00
ihor_ck
c074bc57bc Translated using Weblate (Ukrainian)
Currently translated at 100.0% (286 of 286 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-05-28 20:19:30 +00:00
Linerly
0e80c88b7d Translated using Weblate (Indonesian)
Currently translated at 100.0% (286 of 286 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-05-28 20:19:30 +00:00
Choukajohn
5ffa5b01fc Translated using Weblate (French)
Currently translated at 100.0% (286 of 286 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-05-28 20:19:30 +00:00
gallegonovato
61d9929485 Translated using Weblate (Spanish)
Currently translated at 100.0% (286 of 286 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-05-28 20:19:30 +00:00
sk
231f19d113 ugly workaround for sk22#520
it's really, really ugly :(
2023-05-28 22:14:03 +02:00
sk
bb41f62db5 Merge remote-tracking branch 'upstream/master' 2023-05-28 19:55:27 +02:00
Gregory K
47edc3180b Merge pull request #586 from sk22/fix/hashtags-crash-akkoma
Fix crash when searching for Hashtags on Akkoma servers
2023-05-28 20:55:04 +03:00
sk
9939d99c4b Merge branch 'fix/hashtags-crash-akkoma' 2023-05-28 19:54:39 +02:00
sk
8053e8bb05 fix hashtag search crash on akkoma servers
closes mastodon#468
closes sk22#523
2023-05-28 19:51:29 +02:00
sk
b7e9380bc4 enable unspecified as default formatting option
closes sk22#521
2023-05-28 14:55:53 +02:00
Jacoco
83600087e1 Fix images being stretched on Pleroma (#522)
Closes sk22#488

* Update image bounds after load when metadata is null

* Fix broken image layout in some scenarios

* Transition when image dimensions update

* Replace blurhash with accent color on Pleroma

* fall back to solid color regardless of server

* use fragment's context instead of passing it down

---------

Co-authored-by: sk <sk22@mailbox.org>
2023-05-28 14:44:23 +02:00
Clyde
b3dd5a2279 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/zh_Hans/
2023-05-28 12:27:27 +00:00
Clyde
f9a8e10a85 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (33 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/zh_Hans/
2023-05-28 12:27:27 +00:00
Clyde
d982331e21 Translated using Weblate (Chinese (Simplified))
Currently translated at 94.9% (56 of 59 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/zh_Hans/
2023-05-28 12:27:27 +00:00
Andrewblasco
68dfab9a44 Translated using Weblate (Spanish)
Currently translated at 100.0% (59 of 59 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-05-28 12:27:27 +00:00
Andrewblasco
c4f736a3fb Translated using Weblate (Spanish)
Currently translated at 100.0% (286 of 286 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/es/
2023-05-28 12:27:27 +00:00
Andrewblasco
b5abc86428 Translated using Weblate (Spanish)
Currently translated at 100.0% (59 of 59 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-05-28 12:27:27 +00:00
Andrewblasco
6b356c4dfd Translated using Weblate (Spanish)
Currently translated at 100.0% (48 of 48 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-05-28 12:27:27 +00:00
LucasGGamerM
9e6723be41 fix: fixes wrong margin on Settings Button views
This addresses a visual bug where a button item without an icon appears to be glued to the left side of the screen. This commit addresses that

cc: @sk22
2023-05-27 13:00:54 -03:00
Eugen Rochko
fe84dc4823 New translations strings.xml (Chinese Simplified) 2023-05-27 16:39:55 +02:00
LucasGGamerM
08023a104c fix: fix wrong window insets on instance rules and block list fragment 2023-05-27 09:54:58 -03:00
LucasGGamerM
fd97cc6e87 Merge pull request #203 from FineFindus/feat/instance-info-improvements
fix(instance-info): hide menu until loaded
2023-05-27 09:44:34 -03:00
LucasGGamerM
78e5f0f011 Merge pull request #202 from FineFindus/feat/filter-warning-click
feat: reveal filter warning on click
2023-05-27 09:41:02 -03:00
LucasGGamerM
73944675fa fix: fix compilation errors 2023-05-27 09:40:04 -03:00
LucasGGamerM
c6ded3d505 Merge remote-tracking branch 'megalodon_main/main'
# Conflicts:
#	mastodon/build.gradle
#	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/ScheduledStatusListFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/fragments/StatusEditHistoryFragment.java
#	mastodon/src/main/java/org/joinmastodon/android/model/Filter.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/FileStatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/StatusDisplayItem.java
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/WarningFilteredStatusDisplayItem.java
#	mastodon/src/main/res/layout/display_item_file.xml
2023-05-27 09:31:27 -03:00
LucasGGamerM
45b97de615 feat: don't show changelog headers if changelog is empty 2023-05-27 09:16:58 -03:00
LucasGGamerM
ec11a5e8e3 feat: update visual appearance settings icon 2023-05-27 09:10:24 -03:00
LucasGGamerM
d71d17e5af feat: update mention reblogger automatically settings icon 2023-05-27 09:07:25 -03:00
LucasGGamerM
e49e485ba3 Merge pull request #183 from FineFindus/feat/settings-redesign
feat(settings): refactor and redesign
2023-05-27 08:58:38 -03:00
LucasGGamerM
2d4fc2166a feat: increase top padding in theme item for consistency 2023-05-27 08:55:04 -03:00
LucasGGamerM
84ba4ea999 feat: use correct background colors in settings 2023-05-27 08:46:04 -03:00
sk
c38eb545b1 use matched filter for determining warning title
fixes a bug where, when multiple filters apply, the
WarningFilteredStatusDisplayItem would not check if the warning applies to the
current context. now, matched filter is determined through the predicate
(though not exactly what a predicate is supposed to do, i guess) and passed
down to the WarningFilteredStatusDisplayItem. cc @LucasGGamerM
2023-05-27 13:09:36 +02:00
FineFindus
b2d4a5aab0 fix(instance.info): hide menu until loaded 2023-05-27 11:21:09 +02:00
FineFindus
201995849c feat: reveal filter warning on click 2023-05-27 11:12:43 +02:00
sk
1fc2f81dab fix creating posts on other people's account timelines
closes sk22#508
2023-05-27 01:50:10 +02:00
LucasGGamerM
69ddc95c2c fix crash when notification markers are null
This would happen when an account had 0 notifications and received one.
After which, the user would tap on the notification icon on the tab bar
and the app would crash.
2023-05-27 01:40:05 +02:00
sk
a6ac68499c use url as fallback for remote url 2023-05-27 01:37:10 +02:00
sk
c10d7cfee4 use remote url; file name as fallback for alt text 2023-05-27 01:32:49 +02:00
sk
f933bdbc53 button with ripple for files and instance picker 2023-05-27 01:13:32 +02:00
LucasGGamerM
274bca84d9 Add display item for unknown/file attachments
Co-authored-by: LucasGGamerM <lucassggabriel@gmail.com>
2023-05-27 01:11:26 +02:00
FineFindus
1e286dbc7a Merge branch 'feat/settings-redesign' of https://github.com/FineFindus/moshidon into feat/settings-redesign 2023-05-26 20:36:01 +02:00
FineFindus
724d872491 fix: remove theme transition
Removes the fade effect when changing themes, as took a long time to apply
2023-05-26 20:35:46 +02:00
LucasGGamerM
64d5f9190a fix: compilation problems
Uses show instead of see on strings_sk.xml
2023-05-26 15:34:20 -03:00
FineFindus
f1ab6833d3 feat: add content type setting
Re-add settings from 8b502b605c\#diff-29b258979e7004d7e5473b71e91747f57a36af0e0b07e0a119968a1e8e72669f
2023-05-26 20:22:53 +02:00
FineFindus
140395f3cd fix: use autoHideCompose variable 2023-05-26 20:14:21 +02:00
FineFindus
f922e028a7 feat(settings): invert default post-divider value 2023-05-26 20:13:09 +02:00
FineFindus
9aac0c007e feat(settings): invert post-divider setting 2023-05-26 20:13:08 +02:00
FineFindus
e682cae7e7 feat(settings/notifications): improve sub-header title 2023-05-26 20:13:08 +02:00
FineFindus
f14977ba24 feat(settings): add summary to reblog action 2023-05-26 20:13:08 +02:00
FineFindus
e8290e2f78 feat(settings): move reblog notificaiton to notification page 2023-05-26 20:13:08 +02:00
FineFindus
197110cfaf feat(settings): improve unlisted reply default title and summary 2023-05-26 20:13:08 +02:00
FineFindus
f320ac066c feat(settings): improve autoplay gif summary 2023-05-26 20:12:42 +02:00
FineFindus
78acb5e7ea feat(settings): invert double tab to swipe setting 2023-05-26 20:12:41 +02:00
FineFindus
a14e864731 feat(settings): allow complete button row to be clicked 2023-05-26 20:12:41 +02:00
FineFindus
a87da87aad refactor(settings): adjust amoled summary 2023-05-26 20:12:41 +02:00
FineFindus
8befbb5a62 refactor(settings): adjust icon color 2023-05-26 20:12:41 +02:00
FineFindus
28893bc50b refactor(settings): remove unused code 2023-05-26 20:12:34 +02:00
FineFindus
b73ef28f12 feat(settings): move interaction count to timeline page 2023-05-26 20:00:51 +02:00
FineFindus
a71dc7f481 feat(settings): move uniform icon to notifications page 2023-05-26 20:00:51 +02:00
FineFindus
de4e7c1822 refactor(settings/about): use local var 2023-05-26 20:00:51 +02:00
FineFindus
62090475f9 fix(settings): remove duplicated auto-hide compose 2023-05-26 20:00:46 +02:00
FineFindus
3c8715a7c4 feat(settings): add giant header to all subpages 2023-05-26 19:55:17 +02:00
FineFindus
4e188503a2 feat(settings): add summary to ambiguous settings 2023-05-26 19:55:14 +02:00
FineFindus
6fb7e97f13 feat(settings): use secondary text color for summary 2023-05-26 19:54:36 +02:00
FineFindus
80c9c591fc feat(settings): add updater 2023-05-26 19:54:36 +02:00
FineFindus
992fb5fefe feat(settings): add giant header 2023-05-26 19:54:35 +02:00
FineFindus
f7c76f7503 feat(settings): add summary label to button 2023-05-26 19:54:32 +02:00
FineFindus
e94364ecf6 feat(settings): use default text size for switch summary 2023-05-26 19:54:05 +02:00
FineFindus
1fab3d3743 feat(settings): add summary label to switch 2023-05-26 19:54:05 +02:00
FineFindus
35477055a9 refactor(settings): add red header item 2023-05-26 19:54:05 +02:00
FineFindus
e585f1df29 refactor(settings): move about to about page 2023-05-26 19:54:05 +02:00
FineFindus
6311d18751 refactor: move account and instance setttings to account page 2023-05-26 19:54:05 +02:00
FineFindus
d29eef51ca refactor: move miscellanious settings 2023-05-26 19:54:05 +02:00
FineFindus
c9692ef27b refactor: move notifications to NotificationsFragment 2023-05-26 19:54:05 +02:00
FineFindus
c36d3e9011 refactor: move timelines to TimelineFragment 2023-05-26 19:54:04 +02:00
FineFindus
9409bbb9b2 refactor: add compose behaviour to behaviour page 2023-05-26 19:54:04 +02:00
FineFindus
3497747015 refactor: move behaviour settings to behaviour page 2023-05-26 19:53:55 +02:00
FineFindus
6343da1410 refactor: use SettingsCategory to move between pages 2023-05-26 19:41:13 +02:00
FineFindus
78a0c60600 fix: move method to fix compiler error 2023-05-26 19:41:13 +02:00
LucasGGamerM
ea152234a9 feat: trying to add the theme settings. Still missing some things
What is an enclosed class? What am I missing?
2023-05-26 19:41:13 +02:00
LucasGGamerM
03612fcf64 feat: add settings category view holder
Also adds a small proof of concept
2023-05-26 19:41:13 +02:00
LucasGGamerM
a6a67512f4 feat: add all previously missing view holders
This includes: Updater View holder, theme view holder and notification policy view holder
2023-05-26 19:41:13 +02:00
FineFindus
dc9e977d40 refactor: add abstract settingsbase fragment 2023-05-26 19:41:13 +02:00
FineFindus
5657df8db2 feat: move Settingsfragment to settings folder 2023-05-26 19:41:07 +02:00
sk
6abfe6ddd7 add unit tests for status filter predicate 2023-05-26 17:02:39 +02:00
sk
ab7489a049 bump version 2023-05-26 02:37:32 +02:00
sk
a6fd6ae135 add javadoc 2023-05-26 02:37:25 +02:00
Espasant3
b30d4a025f Translated using Weblate (Galician)
Currently translated at 99.6% (274 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-05-26 00:16:40 +00:00
Daudix_UFO
5b747bfc74 Translated using Weblate (Russian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2023-05-26 00:16:40 +00:00
gallegonovato
a410d19114 Translated using Weblate (Spanish)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-05-26 00:16:39 +00:00
gicorada
a8589cc5b0 Translated using Weblate (Italian)
Currently translated at 100.0% (17 of 17 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/it/
2023-05-26 00:16:39 +00:00
Eryk Michalak
b057c9f7a8 Translated using Weblate (Polish)
Currently translated at 100.0% (17 of 17 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pl/
2023-05-26 00:16:39 +00:00
ihor_ck
96e4a4933c Translated using Weblate (Ukrainian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-05-26 00:16:39 +00:00
Eryk Michalak
630064500d Translated using Weblate (Polish)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2023-05-26 00:16:39 +00:00
gicorada
9543294996 Translated using Weblate (Italian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/it/
2023-05-26 00:16:39 +00:00
Linerly
56e9cc3406 Translated using Weblate (Indonesian)
Currently translated at 100.0% (275 of 275 strings)

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

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-05-26 00:16:39 +00:00
sk
99f0817bdb generalize filtering logic 2023-05-26 02:07:50 +02:00
sk
220cd35d82 fix context not checked for warnings
closes sk22#518
2023-05-25 21:25:09 +02:00
sk
07f4ef1697 remove unused imports 2023-05-25 21:22:27 +02:00
sk
f20732ddc2 Merge remote-tracking branch 'upstream/master' 2023-05-25 20:27:23 +02:00
sk
b1e0dc5843 show compose button when switching tab
closes sk22#506
2023-05-25 20:26:59 +02:00
Gregory K
285eb25706 Merge pull request #584 from sk22/fix-restored-tab-selection
Fix wrong tab being selected on restore
2023-05-25 21:00:12 +03:00
sk
ec556511e6 Merge branch 'fix-restored-tab-selection' 2023-05-25 19:57:34 +02:00
sk
85c3d9f65f fix wrong tab being selected on restore 2023-05-25 19:51:45 +02:00
sk
a7ebadf269 increase read timeout
re: sk22#392
2023-05-25 15:11:40 +02:00
sk
94c09d46c2 fix contentType being a required field
re: sk22#516
2023-05-25 14:53:26 +02:00
LucasGGamerM
889fbc688d fix: removes @RequiredField for contentType
Removes that, as its null on mastodon, and makes editing statuses impossible
2023-05-25 11:45:32 +00:00
LucasGGamerM
85d971242e feat: use less margin on compose screen bottom view
This is due to the new option to use post content types uses a new icon in there, making it cram the post button into the side. Which is not good
2023-05-23 20:20:14 -03:00
LucasGGamerM
23f82197c6 Merge pull request #200
Feat: Instance info
2023-05-23 20:08:36 -03:00
LucasGGamerM
b4b16e2f37 feat: use Moshidon user agent instead of Megalodon's 2023-05-23 19:49:34 -03:00
LucasGGamerM
2d838a8a23 Merge branch 'master' of https://github.com/LucasGGamerM/moshidon 2023-05-23 19:47:43 -03:00
LucasGGamerM
7dab63cfe8 fix: using new string name instead of old one to allow compilation
Git was screwing with me, so I copied the file from their repo and yanked it in here
2023-05-23 19:42:33 -03:00
LucasGGamerM
6548751bb0 Merge remote-tracking branch 'megalodon_weblate/main'
# Conflicts:
#	mastodon/src/main/res/values-es-rES/strings_sk.xml
#	mastodon/src/main/res/values-pl-rPL/strings_sk.xml
#	mastodon/src/main/res/values-uk-rUA/strings_sk.xml
2023-05-23 19:31:49 -03:00
LucasGGamerM
65c158391f Merge remote-tracking branch 'megalodon_main/main'
# Conflicts:
#	mastodon/src/main/java/org/joinmastodon/android/fragments/SettingsFragment.java
#	mastodon/src/main/res/layout/fragment_compose.xml
2023-05-23 19:30:52 -03:00
FineFindus
556fc4d31e feat(instance-info): use about url 2023-05-23 21:55:26 +02:00
FineFindus
c673f08aec fix(instance-info): race condition for collapsing description 2023-05-23 21:39:33 +02:00
FineFindus
818024d8dd fix: instance info refresh not working 2023-05-23 21:34:31 +02:00
FineFindus
cb3b893f72 refactor: move fake attachment to attachment class 2023-05-23 20:02:43 +02:00
FineFindus
f482b4bfe9 feat: add weekly activities api request 2023-05-23 18:43:24 +02:00
FineFindus
333c47339d fix(instance-info): remove space below description 2023-05-23 16:07:07 +02:00
FineFindus
a9283bfec8 fix(instance-info): only collapse long descriptions 2023-05-23 16:05:16 +02:00
sk
f6f08d176c change user-agent string 2023-05-23 10:26:48 +02:00
FineFindus
4c9f29e949 refactor(instance-info): remove unused code 2023-05-22 22:15:28 +02:00
FineFindus
4ff5136652 feat(instance-info): show- egistration status 2023-05-22 22:05:25 +02:00
FineFindus
56835b4f2d feat: show blocked domains 2023-05-22 21:37:56 +02:00
FineFindus
c43f734101 feat(instance-info): replace moderated server icon 2023-05-22 20:29:05 +02:00
FineFindus
d4e1850d8c feat(instance-info): increase max description height 2023-05-22 20:24:55 +02:00
FineFindus
0b08072dfc feat(instance-info): add options menu 2023-05-22 20:21:11 +02:00
sk
66cdd63496 use fedinuke block list
closes sk22#511
2023-05-22 18:04:37 +02:00
Jacoco
8b502b605c Alternative content types (#516)
* Akkoma content types

* Default content type preference

* per-account content types, compatible with glitch

* disable content types by default, change icon

* persist content type to state

* update string

* fall back to plain text if formatting enabled

---------

Co-authored-by: sk <sk22@mailbox.org>
2023-05-22 17:56:50 +02:00
FineFindus
936a86acd7 feat: collapse long description 2023-05-22 16:41:34 +02:00
FineFindus
64fc052c55 feat: show extended description in info 2023-05-22 14:52:04 +02:00
FineFindus
9897b8bfcd feat: add instance info fragment 2023-05-22 14:06:00 +02:00
LucasGGamerM
bcb50a9dd1 docs: add roadmap link to readme 2023-05-22 08:48:24 -03:00
LucasGGamerM
0b0775a86e Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.0% (264 of 275 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/pt_BR/
2023-05-21 13:25:17 +00:00
FineFindus
73253f5f64 Translated using Weblate (German)
Currently translated at 97.9% (47 of 48 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/de/
2023-05-21 13:25:17 +00:00
FineFindus
591b1cd9bf Translated using Weblate (German)
Currently translated at 100.0% (33 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/de/
2023-05-21 13:25:16 +00:00
Espasant3
47a5d18ee0 Translated using Weblate (Galician)
Currently translated at 99.6% (274 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-05-20 14:42:56 +00:00
Daudix_UFO
b3f43804b0 Translated using Weblate (Russian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2023-05-20 14:42:56 +00:00
gallegonovato
139ec08d9d Translated using Weblate (Spanish)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-05-20 14:42:56 +00:00
gicorada
bc8846c351 Translated using Weblate (Italian)
Currently translated at 100.0% (17 of 17 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/it/
2023-05-20 14:42:56 +00:00
Eryk Michalak
85066f8ae6 Translated using Weblate (Polish)
Currently translated at 100.0% (17 of 17 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/pl/
2023-05-20 14:42:56 +00:00
ihor_ck
1aec319e1c Translated using Weblate (Ukrainian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-05-20 14:42:56 +00:00
Eryk Michalak
9848a94853 Translated using Weblate (Polish)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/pl/
2023-05-20 14:42:56 +00:00
gicorada
18ed3b44b4 Translated using Weblate (Italian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/it/
2023-05-20 14:42:56 +00:00
Linerly
a4043cc0e5 Translated using Weblate (Indonesian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-05-20 14:42:56 +00:00
Choukajohn
2b94d0c147 Translated using Weblate (French)
Currently translated at 100.0% (275 of 275 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-05-20 14:42:56 +00:00
LucasGGamerM
7e6395192b Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (48 of 48 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/pt_BR/
2023-05-20 13:31:11 +00:00
LucasGGamerM
31db1cae7c Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (48 of 48 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/pt_BR/
2023-05-20 13:29:12 +00:00
Linerly
f2c80a92c4 Translated using Weblate (Indonesian)
Currently translated at 21.2% (7 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/id/
2023-05-20 13:26:05 +00:00
Linerly
2cd107b400 Translated using Weblate (Indonesian)
Currently translated at 65.2% (30 of 46 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/id/
2023-05-20 13:26:04 +00:00
ca
eef4f42203 Translated using Weblate (Catalan)
Currently translated at 60.8% (28 of 46 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/ca/
2023-05-20 13:26:04 +00:00
nitrogenez47ab3e44720c4675
7eba69f574 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (275 of 275 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/uk/
2023-05-20 13:26:04 +00:00
Andrewblasco
cd226125cd Translated using Weblate (Spanish)
Currently translated at 100.0% (46 of 46 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/es/
2023-05-20 13:26:04 +00:00
Pegasus89
1f543b4aa5 Translated using Weblate (Croatian)
Currently translated at 94.5% (260 of 275 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/hr/
2023-05-20 13:26:04 +00:00
OwenP
bd752824d9 Translated using Weblate (French)
Currently translated at 71.7% (33 of 46 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/fr/
2023-05-20 13:26:04 +00:00
Tyketc
a67dcbbf66 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (275 of 275 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/zh_Hans/
2023-05-20 13:26:04 +00:00
Tyketc
e0c77d3399 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (33 of 33 strings)

Translation: Moshidon/metadata
Translate-URL: https://translate.codeberg.org/projects/moshidon/metadata/zh_Hans/
2023-05-20 13:26:04 +00:00
Tyketc
caf3ab5ce1 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (46 of 46 strings)

Translation: Moshidon/values
Translate-URL: https://translate.codeberg.org/projects/moshidon/values/zh_Hans/
2023-05-20 13:26:04 +00:00
Eryk Michalak
e549636645 Translated using Weblate (Polish)
Currently translated at 100.0% (275 of 275 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/pl/
2023-05-20 13:26:04 +00:00
Andrewblasco
3e2c3f40c7 Translated using Weblate (Spanish)
Currently translated at 100.0% (275 of 275 strings)

Translation: Moshidon/values_sk
Translate-URL: https://translate.codeberg.org/projects/moshidon/values_sk/es/
2023-05-20 13:26:04 +00:00
LucasGGamerM
40e20ead44 Merge pull request #195
feat: hide reblogs count on non-rebloggable status
2023-05-20 10:05:32 -03:00
LucasGGamerM
dfeba71abe Merge pull request #196 from FineFindus/feat/unfollow-confirmation
Feat: show unfollow confirmation dialog
2023-05-20 09:54:06 -03:00
FineFindus
2c0ec28803 Panic responder (#512)
* feat: add panic responder

* refactor: logOut before removing session

* fix(panic): close app after logOut to avoid crash

* build: reset gradle.properties
2023-05-20 13:20:25 +02:00
Eugen Rochko
2e1795dc6f New translations strings.xml (Russian) 2023-05-20 13:04:15 +02:00
LucasGGamerM
74b06a4997 fix: crash when account.note field is null
This sometimes happens on calckey. And this fixes the crash
2023-05-19 11:04:39 -03:00
LucasGGamerM
346610dd04 fix: make note not a RequiredField in account
This was making some profiles with no description not load under CalcKey
2023-05-18 20:43:00 -03:00
LucasGGamerM
37cdc7116d Merge branch 'master' of https://github.com/LucasGGamerM/moshidon 2023-05-16 18:33:05 -03:00
LucasGGamerM
d403f4ef01 Merge remote-tracking branch 'megalodon_main/main'
# Conflicts:
#	mastodon/build.gradle
#	mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/MediaGridStatusDisplayItem.java
2023-05-16 18:26:23 -03:00
Eugen Rochko
cd1be782fa New translations strings.xml (Armenian) 2023-05-16 18:44:56 +02:00
FineFindus
7f7eed1dec fix: add missing string 2023-05-16 18:26:24 +02:00
FineFindus
4843d574ca feat: show confirmation dialog on unfollow 2023-05-16 18:21:10 +02:00
Eugen Rochko
67059f3d71 New translations strings.xml (Armenian) 2023-05-16 17:30:41 +02:00
FineFindus
0f0291074e refactor: remove seding duplicated follow request 2023-05-16 16:52:52 +02:00
LucasGGamerM
4e143abfb9 fix: fix compilation problem caused by typo
I did the latest commits from my chromebook, which I accidentally typed the wrong variable name.
2023-05-16 11:29:38 -03:00
LucasGGamerM
558c5fba56 fix: fix crash on profile when saving a note fails
This fixes a crash on calckey, where notes dont exist
2023-05-16 11:24:37 -03:00
FineFindus
e50df3ea6d feat: hide bossts on non-boostable status 2023-05-16 16:18:56 +02:00
FineFindus
4383b11947 refactor: move bosst check to status 2023-05-16 16:18:02 +02:00
LucasGGamerM
22209efc37 docs(faq): add Moshidon for iOS question
Many people have asked me about the possibility of Moshidon for iOS. This F.A.Q. entry addresses that
2023-05-16 08:46:48 -03:00
LucasGGamerM
c3b5bb409b fix: fix crash on calckey on profile reload
Adds null check in account avatar/header load function
2023-05-15 19:54:13 -03:00
Eugen Rochko
15f4d3326b New translations strings.xml (Russian) 2023-05-15 08:47:41 +02:00
Jacoco
a9ab9cb249 Fix crashes on Calckey and GoToSocial (#515)
* Fix crashes on calckey and gts

* Use url if previewUrl is null
2023-05-14 23:26:03 +02:00
LucasGGamerM
ac2e7cde41 chore: remove unused files
Idk how it got there, but its now gone :D
2023-05-14 14:39:39 -03:00
Eugen Rochko
e65404a466 New translations strings.xml (Dutch) 2023-05-13 20:26:36 +02:00
Eugen Rochko
3d47d1b4db New translations full_description.txt (Dutch) 2023-05-13 19:05:00 +02:00
Eugen Rochko
d1749ab610 New translations strings.xml (Dutch) 2023-05-13 19:04:59 +02:00
Eugen Rochko
806c264686 New translations strings.xml (Vietnamese) 2023-05-13 17:46:17 +02:00
Eugen Rochko
34a9cb5a74 New translations strings.xml (Dutch) 2023-05-13 17:46:16 +02:00
Eugen Rochko
64fad2e871 New translations strings.xml (Vietnamese) 2023-05-13 16:36:00 +02:00
sk
961c69b525 Merge remote-tracking branch 'upstream/master' 2023-05-13 15:15:00 +02:00
sk
c70f393559 account card layout adjustments 2023-05-13 15:13:43 +02:00
sk
9abdc174f4 guarantee space for display name in header
closes sk22#513
2023-05-13 14:07:44 +02:00
LucasGGamerM
2e5bfa1d9c fix: NPE when instance is null and attempts to get new notifications
For some weird reason, someone saw a pixelfed instance return null as the instance, causing a crash on the updateNotificationsBadge method. This reminds me of why java is such a shit language
2023-05-13 13:37:19 +02:00
Eugen Rochko
9c89c26097 New translations strings.xml (Dutch) 2023-05-13 01:52:41 +02:00
Eugen Rochko
e3b6a5d389 New translations strings.xml (Dutch) 2023-05-13 00:57:05 +02:00
Eugen Rochko
0fb54efde5 New translations strings.xml (Dutch) 2023-05-12 23:58:21 +02:00
Eugen Rochko
a4a3f32dba New translations strings.xml (Dutch) 2023-05-12 22:45:52 +02:00
Eugen Rochko
03a1e29e0c New translations strings.xml (Dutch) 2023-05-12 19:43:17 +02:00
Eugen Rochko
eda9ff272b New translations strings.xml (Dutch) 2023-05-12 18:35:16 +02:00
Eugen Rochko
b3728e06ac New translations strings.xml (Swedish) 2023-05-11 12:28:06 +02:00
Grishka
33cbd85e19 Bump version 2023-05-11 05:42:40 +03:00
Grishka
8cb1f3f387 Merge branch 'l10n_master' 2023-05-11 05:40:54 +03:00
Eugen Rochko
3f0c6fcec5 New translations strings.xml (Icelandic) 2023-05-10 13:59:12 +02:00
Eugen Rochko
797cf893da New translations strings.xml (Italian) 2023-05-08 15:58:22 +02:00
Eugen Rochko
a3564b70e1 New translations strings.xml (Ukrainian) 2023-05-08 07:52:51 +02:00
Eugen Rochko
43004307b8 New translations strings.xml (Ukrainian) 2023-05-08 06:34:46 +02:00
Eugen Rochko
acd1e4ced3 New translations full_description.txt (Scottish Gaelic) 2023-05-06 07:17:18 +02:00
Eugen Rochko
6717070f93 New translations strings.xml (Scottish Gaelic) 2023-05-06 07:17:17 +02:00
Eugen Rochko
387499ae49 New translations strings.xml (Vietnamese) 2023-05-05 08:49:53 +02:00
Eugen Rochko
8ab140c55d New translations strings.xml (Japanese) 2023-05-04 22:50:38 +02:00
Eugen Rochko
914abb95dd New translations strings.xml (Japanese) 2023-05-04 21:34:45 +02:00
Eugen Rochko
5360c0f0f7 New translations strings.xml (Greek) 2023-05-04 01:44:50 +02:00
Eugen Rochko
243d803b51 New translations strings.xml (Turkish) 2023-05-03 23:31:14 +02:00
Eugen Rochko
b343fe3835 New translations strings.xml (Turkish) 2023-05-03 22:27:36 +02:00
Eugen Rochko
3c42c1120f New translations strings.xml (Japanese) 2023-05-03 17:42:48 +02:00
Eugen Rochko
ad840dcef6 New translations strings.xml (Japanese) 2023-05-03 16:47:22 +02:00
Eugen Rochko
f73072d95e New translations strings.xml (Spanish) 2023-05-03 01:08:32 +02:00
Eugen Rochko
95cb9b5079 New translations strings.xml (Thai) 2023-05-02 21:12:14 +02:00
Eugen Rochko
c6684d3c9b New translations strings.xml (Thai) 2023-05-02 19:41:48 +02:00
Eugen Rochko
5c5989d8c0 New translations strings.xml (Chinese Traditional) 2023-05-02 18:13:38 +02:00
Eugen Rochko
60e92d30b0 New translations strings.xml (Italian) 2023-05-02 14:58:27 +02:00
Eugen Rochko
8bf8e3f86b New translations strings.xml (Slovenian) 2023-05-02 00:17:51 +02:00
Eugen Rochko
891ee2d06b New translations strings.xml (Indonesian) 2023-05-01 21:04:03 +02:00
Eugen Rochko
b450bc7ae8 New translations strings.xml (Icelandic) 2023-05-01 21:04:02 +02:00
Eugen Rochko
4ca1e0d5db New translations strings.xml (Vietnamese) 2023-05-01 21:04:01 +02:00
Eugen Rochko
859213dd9e New translations strings.xml (Chinese Simplified) 2023-05-01 21:04:01 +02:00
Eugen Rochko
ad2857791d New translations strings.xml (Turkish) 2023-05-01 21:03:59 +02:00
Eugen Rochko
497827f2e2 New translations strings.xml (Slovenian) 2023-05-01 21:03:57 +02:00
Eugen Rochko
967e333022 New translations strings.xml (Japanese) 2023-05-01 21:03:54 +02:00
Eugen Rochko
8df1406006 New translations strings.xml (Dutch) 2023-05-01 21:03:46 +02:00
Eugen Rochko
4af42fafdc New translations strings.xml (Russian) 2023-05-01 21:03:45 +02:00
Eugen Rochko
a9e6a452c1 New translations strings.xml (Galician) 2023-05-01 21:03:43 +02:00
Eugen Rochko
a4a4632397 New translations strings.xml (Chinese Traditional) 2023-05-01 21:03:42 +02:00
Eugen Rochko
421f39e414 New translations strings.xml (Italian) 2023-05-01 21:03:41 +02:00
Eugen Rochko
f8121e2dc4 New translations strings.xml (German) 2023-05-01 21:03:41 +02:00
Eugen Rochko
b1784fc51c New translations strings.xml (Danish) 2023-05-01 21:03:40 +02:00
Eugen Rochko
96db0d7de7 New translations strings.xml (Greek) 2023-05-01 21:03:39 +02:00
Eugen Rochko
3837ed9cb1 New translations strings.xml (Thai) 2023-05-01 21:03:38 +02:00
Eugen Rochko
2be789a43c New translations strings.xml (Spanish) 2023-05-01 21:03:37 +02:00
Grishka
fd8d96169a Update string 2023-05-01 21:38:16 +03:00
Eugen Rochko
1562dc32c1 New translations strings.xml (Dutch) 2023-05-01 13:44:56 +02:00
Eugen Rochko
38f377ca09 New translations full_description.txt (Armenian) 2023-04-28 20:21:00 +02:00
Eugen Rochko
cc28bba884 New translations strings.xml (Armenian) 2023-04-28 20:20:59 +02:00
Eugen Rochko
beb3081918 New translations strings.xml (Armenian) 2023-04-28 19:06:20 +02:00
Eugen Rochko
1b3c9106b5 New translations strings.xml (Russian) 2023-04-28 09:05:19 +02:00
Eugen Rochko
385b91761b New translations strings.xml (Portuguese, Brazilian) 2023-04-28 02:45:25 +02:00
Eugen Rochko
43600756c0 New translations strings.xml (Chinese Traditional) 2023-04-25 18:41:49 +02:00
Eugen Rochko
3c3e0633ad New translations strings.xml (Danish) 2023-04-25 12:23:29 +02:00
Eugen Rochko
f819ad6917 New translations strings.xml (Danish) 2023-04-25 11:26:19 +02:00
Eugen Rochko
e7ad396fc6 New translations strings.xml (Italian) 2023-04-22 19:15:42 +02:00
Eugen Rochko
b1cb4d4257 New translations strings.xml (German) 2023-04-22 16:44:30 +02:00
Eugen Rochko
100bd4b062 New translations strings.xml (Galician) 2023-04-19 07:36:52 +02:00
Eugen Rochko
7da09d9b37 New translations strings.xml (Spanish) 2023-04-19 07:36:51 +02:00
Eugen Rochko
f46eb07228 New translations strings.xml (Galician) 2023-04-19 06:04:49 +02:00
Eugen Rochko
7627b5eb25 New translations strings.xml (Greek) 2023-04-17 15:01:08 +02:00
Eugen Rochko
c710448c6b New translations strings.xml (Greek) 2023-04-17 13:59:43 +02:00
Eugen Rochko
1ad270b1d6 New translations strings.xml (Chinese Simplified) 2023-04-16 18:13:11 +02:00
Eugen Rochko
099e253b2b New translations strings.xml (Chinese Simplified) 2023-04-16 17:11:48 +02:00
Eugen Rochko
66de4a5b91 New translations strings.xml (Thai) 2023-04-16 09:19:23 +02:00
Eugen Rochko
41437d91d5 New translations strings.xml (Icelandic) 2023-04-15 11:54:07 +02:00
Eugen Rochko
d33d5a6efa New translations strings.xml (Icelandic) 2023-04-15 10:45:31 +02:00
Eugen Rochko
4f9248d040 New translations strings.xml (Vietnamese) 2023-04-15 05:15:40 +02:00
Eugen Rochko
f40c0e41f3 New translations strings.xml (Japanese) 2023-04-14 20:26:49 +02:00
Eugen Rochko
deeb03ff2b New translations strings.xml (Indonesian) 2023-04-13 21:36:15 +02:00
Eugen Rochko
5c2a09e243 New translations strings.xml (Indonesian) 2023-04-13 20:38:20 +02:00
Eugen Rochko
2473c999db New translations strings.xml (German) 2023-04-13 14:38:33 +02:00
Eugen Rochko
ea2cc265e3 New translations strings.xml (Turkish) 2023-04-13 05:12:38 +02:00
Eugen Rochko
a0cd2d42cf New translations strings.xml (Turkish) 2023-04-13 04:16:05 +02:00
410 changed files with 10973 additions and 3134 deletions

1
.github/FUNDING.yml vendored
View File

@@ -1,6 +1,7 @@
# These are supported funding model platforms # These are supported funding model platforms
github: LucasGGamerM github: LucasGGamerM
custom: ["https://liberapay.com/LucasGGamerM/donate", liberapay.com]
patreon: # mastodon patreon: # mastodon
open_collective: # Replace with a single Open Collective username e.g., user1 open_collective: # Replace with a single Open Collective username e.g., user1
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel

View File

@@ -10,6 +10,28 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Appkit Repo
uses: actions/checkout@v3
with:
repository: grishka/appkit
- name: set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'corretto'
cache: gradle
- name: Comment out signing config in appkits gradle file
run: |
sed -i 's/sign publishing\.publications\.release/\/\/ sign publishing.publications.release/' appkit/maven-push.gradle
- name: Grant execute permission for gradlew for Appkit
run: chmod +x gradlew
- name: Compile appkit
run: ./gradlew publishToMavenLocal
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: set up JDK 17 - name: set up JDK 17
uses: actions/setup-java@v3 uses: actions/setup-java@v3

4
FAQ.md
View File

@@ -3,3 +3,7 @@
Q: What are the main differences between Moshidon and Megalodon? Q: What are the main differences between Moshidon and Megalodon?
A: There are many, but the most outstanding differences are: the ability to have other server's local timeline inside the app. It can be acessed in the "Add community" option in the top right corner of the Edit timelines screen. Other outstanding features that Moshidon has are some quality of life improvements, such as notification actions and allowing for unlisted replies by default. Most other features are pretty minor, such as profile notes directly available in the person's profile. Other features are quite minor usability and visibility improvements. All of which can be found in the settings page. A: There are many, but the most outstanding differences are: the ability to have other server's local timeline inside the app. It can be acessed in the "Add community" option in the top right corner of the Edit timelines screen. Other outstanding features that Moshidon has are some quality of life improvements, such as notification actions and allowing for unlisted replies by default. Most other features are pretty minor, such as profile notes directly available in the person's profile. Other features are quite minor usability and visibility improvements. All of which can be found in the settings page.
Q: Will there ever be a versjon of Moshidon for iOS?
A: No. As android and iOS apps do not share code, it is incredibly hard to port.

View File

@@ -19,6 +19,10 @@
<a href="https://apt.izzysoft.de/fdroid/index/apk/org.joinmastodon.android.moshinda"><img height="50" alt="Get it on IzzyOnDroid" src="img/izzy-badge.png"></a> <a href="https://apt.izzysoft.de/fdroid/index/apk/org.joinmastodon.android.moshinda"><img height="50" alt="Get it on IzzyOnDroid" src="img/izzy-badge.png"></a>
## Help out the project by donating at: https://github.com/sponsors/LucasGGamerM! ## Help out the project by donating at: https://github.com/sponsors/LucasGGamerM!
### We also support LiberaPay at: https://liberapay.com/LucasGGamerM/donate!
### You can also donate some Monero through this wallet address as well:
4886mdarcyB6Yf8Qc6vDJBK1fz6ibHFLZUmHb4GZZz9yLGNhcG3XC64e5UZ8dVQYTLZb82W6P9WhteowW4STJEec97Gf22j
--- ---
@@ -191,6 +195,8 @@ This project is released under the [GPL-3 License](./LICENSE).
[Official matrix chatroom:](https://matrix.to/#/#moshidon:floss.social) https://matrix.to/#/#moshidon:floss.social [Official matrix chatroom:](https://matrix.to/#/#moshidon:floss.social) https://matrix.to/#/#moshidon:floss.social
[Moshidon roadmap](https://github.com/users/LucasGGamerM/projects/1)
<a rel="me" href="https://floss.social/@moshidon">@moshidon<wbr>@floss.social</a> <a rel="me" href="https://floss.social/@moshidon">@moshidon<wbr>@floss.social</a>
--- ---

View File

@@ -3,6 +3,7 @@ buildscript {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
mavenLocal()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:8.0.0' classpath 'com.android.tools.build:gradle:8.0.0'

View File

@@ -20,7 +20,7 @@ android {
versionName "1.3.0+fork.100.moshinda" versionName "1.3.0+fork.100.moshinda"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resourceConfigurations += ['ar-rSA', 'ar-rDZ', 'be-rBY', 'bn-rBD', 'bs-rBA', 'ca-rES', 'cs-rCZ', 'da-rDK', 'de-rDE', 'el-rGR', 'es-rES', 'eu-rES', 'fa-rIR', 'fi-rFI', 'fil-rPH', 'fr-rFR', 'ga-rIE', 'gd-rGB', 'gl-rES', 'hi-rIN', 'hr-rHR', 'hu-rHU', 'hy-rAM', 'ig-rNG', 'in-rID', 'is-rIS', 'it-rIT', 'iw-rIL', 'ja-rJP', 'kab', 'ko-rKR', 'my-rMM', 'nl-rNL', 'no-rNO', 'oc-rFR', 'pl-rPL', 'pt-rBR', 'pt-rPT', 'ro-rRO', 'ru-rRU', 'si-rLK', 'sl-rSI', 'sv-rSE', 'th-rTH', 'tr-rTR', 'uk-rUA', 'ur-rIN', 'vi-rVN', 'zh-rCN', 'zh-rTW'] resourceConfigurations += ['ar-rSA', 'ar-rDZ', 'be-rBY', 'bn-rBD', 'bs-rBA', 'ca-rES', 'cs-rCZ', 'da-rDK', 'de-rDE', 'el-rGR', 'es-rES', 'eu-rES', 'fa-rIR', 'fi-rFI', 'fil-rPH', 'fr-rFR', 'ga-rIE', 'gd-rGB', 'gl-rES', 'hi-rIN', 'hr-rHR', 'hu-rHU', 'hy-rAM', 'ig-rNG', 'in-rID', 'is-rIS', 'it-rIT', 'iw-rIL', 'ja-rJP', 'kab', 'ko-rKR', 'my-rMM', 'nl-rNL', 'no-rNO', 'oc-rFR', 'pl-rPL', 'pt-rBR', 'pt-rPT', 'ro-rRO', 'ru-rRU', 'si-rLK', 'sl-rSI', 'sv-rSE', 'th-rTH', 'tr-rTR', 'uk-rUA', 'ur-rIN', 'vi-rVN', 'zh-rCN', 'zh-rTW']
} }
signingConfigs { signingConfigs {
nightly{ nightly{
@@ -62,7 +62,6 @@ android {
initWith release initWith release
} }
nightly{ nightly{
initWith release
if(System.getenv("CURRENT_DATE") != null){ if(System.getenv("CURRENT_DATE") != null){
versionNameSuffix '-nightly+@' + System.getenv("CURRENT_DATE") versionNameSuffix '-nightly+@' + System.getenv("CURRENT_DATE")
} else { } else {
@@ -71,6 +70,7 @@ android {
versionNameSuffix '-nightly+@' + properties.getProperty('CURRENT_DATE') versionNameSuffix '-nightly+@' + properties.getProperty('CURRENT_DATE')
} }
applicationIdSuffix '.nightly' applicationIdSuffix '.nightly'
signingConfig signingConfigs.nightly signingConfig signingConfigs.nightly
manifestPlaceholders = [oAuthScheme:"moshidon-android-nightly-auth"] manifestPlaceholders = [oAuthScheme:"moshidon-android-nightly-auth"]
} }
@@ -114,7 +114,7 @@ dependencies {
implementation 'me.grishka.litex:dynamicanimation:1.1.0-alpha03' implementation 'me.grishka.litex:dynamicanimation:1.1.0-alpha03'
implementation 'me.grishka.litex:viewpager:1.0.0' implementation 'me.grishka.litex:viewpager:1.0.0'
implementation 'me.grishka.litex:viewpager2:1.0.0' implementation 'me.grishka.litex:viewpager2:1.0.0'
implementation 'me.grishka.appkit:appkit:1.2.7' implementation 'me.grishka.appkit:appkit:1.2.8'
implementation 'com.google.code.gson:gson:2.9.0' implementation 'com.google.code.gson:gson:2.9.0'
implementation 'org.jsoup:jsoup:1.14.3' implementation 'org.jsoup:jsoup:1.14.3'
implementation 'com.squareup:otto:1.3.8' implementation 'com.squareup:otto:1.3.8'

View File

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

View File

@@ -1,8 +1,10 @@
package org.joinmastodon.android.test; package org.joinmastodon.android.test;
import android.app.Instrumentation;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
@@ -12,10 +14,10 @@ import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.MainActivity; import org.joinmastodon.android.MainActivity;
import org.joinmastodon.android.MastodonApp; import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.mastodon.requests.instance.GetInstance; import org.joinmastodon.android.api.requests.instance.GetInstance;
import org.joinmastodon.android.api.mastodon.requests.statuses.GetStatusByID; import org.joinmastodon.android.api.requests.statuses.GetStatusByID;
import org.joinmastodon.android.api.mastodon.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.mastodon.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.fragments.ThreadFragment; import org.joinmastodon.android.fragments.ThreadFragment;
import org.joinmastodon.android.fragments.onboarding.InstanceRulesFragment; import org.joinmastodon.android.fragments.onboarding.InstanceRulesFragment;
@@ -30,9 +32,12 @@ import org.parceler.Parcels;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier; import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import androidx.test.core.app.ActivityScenario;
import androidx.test.espresso.PerformException; import androidx.test.espresso.PerformException;
import androidx.test.espresso.UiController; import androidx.test.espresso.UiController;
import androidx.test.espresso.ViewAction; import androidx.test.espresso.ViewAction;
@@ -42,15 +47,18 @@ import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest; import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.screenshot.ScreenCapture;
import androidx.test.runner.screenshot.Screenshot; import androidx.test.runner.screenshot.Screenshot;
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 okio.BufferedSink; import okio.BufferedSink;
import okio.Okio; import okio.Okio;
import okio.Sink;
import okio.Source; import okio.Source;
import static androidx.test.espresso.Espresso.*; import static androidx.test.espresso.Espresso.*;
import static androidx.test.espresso.action.ViewActions.*; import static androidx.test.espresso.action.ViewActions.*;
import static androidx.test.espresso.assertion.ViewAssertions.*;
import static androidx.test.espresso.matcher.ViewMatchers.*; import static androidx.test.espresso.matcher.ViewMatchers.*;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)

View File

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

View File

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

View File

@@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"/> <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
@@ -40,6 +41,22 @@
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".PanicResponderActivity"
android:exported="true"
android:launchMode="singleInstance"
android:noHistory="true"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="info.guardianproject.panic.action.TRIGGER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".ExitActivity"
android:exported="false"
android:theme="@android:style/Theme.NoDisplay" />
<activity android:name=".OAuthActivity" android:exported="true" android:configChanges="orientation|screenSize" android:launchMode="singleTask"> <activity android:name=".OAuthActivity" android:exported="true" android:configChanges="orientation|screenSize" android:launchMode="singleTask">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW"/> <action android:name="android.intent.action.VIEW"/>

View File

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

View File

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

View File

@@ -1,5 +1,62 @@
package org.joinmastodon.android; package org.joinmastodon.android;
import android.app.Activity;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.browser.customtabs.CustomTabsIntent;
import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.PushSubscriptionManager;
import org.joinmastodon.android.api.requests.accounts.GetOwnAccount;
import org.joinmastodon.android.api.requests.accounts.GetPreferences;
import org.joinmastodon.android.api.requests.accounts.GetWordFilters;
import org.joinmastodon.android.api.requests.instance.GetCustomEmojis;
import org.joinmastodon.android.api.requests.instance.GetInstance;
import org.joinmastodon.android.api.requests.oauth.CreateOAuthApp;
import org.joinmastodon.android.api.session.AccountActivationInfo;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.EmojiUpdatedEvent;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Application;
import org.joinmastodon.android.model.Emoji;
import org.joinmastodon.android.model.EmojiCategory;
import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Preferences;
import org.joinmastodon.android.model.Token;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
public class DomainManager { public class DomainManager {
private static final String TAG="DomainManager"; private static final String TAG="DomainManager";

View File

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

View File

@@ -1,16 +1,17 @@
package org.joinmastodon.android; package org.joinmastodon.android;
import android.app.Fragment; import android.app.Fragment;
import android.app.assist.AssistContent;
import android.content.ClipData; import android.content.ClipData;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Pair;
import android.widget.Toast; import android.widget.Toast;
import org.joinmastodon.android.api.mastodon.session.AccountSession; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.mastodon.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.ComposeFragment; import org.joinmastodon.android.fragments.ComposeFragment;
import org.joinmastodon.android.ui.AccountSwitcherSheet; import org.joinmastodon.android.ui.AccountSwitcherSheet;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
@@ -19,6 +20,8 @@ import org.jsoup.internal.StringUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import me.grishka.appkit.FragmentStackActivity; import me.grishka.appkit.FragmentStackActivity;
@@ -30,22 +33,51 @@ public class ExternalShareActivity extends FragmentStackActivity{
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if(savedInstanceState==null){ if(savedInstanceState==null){
String text = getIntent().getStringExtra(Intent.EXTRA_TEXT); Optional<String> text = Optional.ofNullable(getIntent().getStringExtra(Intent.EXTRA_TEXT));
boolean isMastodonURL = UiUtils.looksLikeMastodonUrl(text); Optional<Pair<String, Optional<String>>> fediHandle = text.flatMap(UiUtils::parseFediverseHandle);
boolean isFediUrl = text.map(UiUtils::looksLikeMastodonUrl).orElse(false);
boolean isOpenable = isFediUrl || fediHandle.isPresent();
List<AccountSession> sessions=AccountSessionManager.getInstance().getLoggedInAccounts(); List<AccountSession> sessions=AccountSessionManager.getInstance().getLoggedInAccounts();
if(sessions.isEmpty()){ if (sessions.isEmpty()){
Toast.makeText(this, R.string.err_not_logged_in, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.err_not_logged_in, Toast.LENGTH_SHORT).show();
finish(); finish();
}else if(sessions.size()==1 && !isMastodonURL){ } else if (isOpenable || sessions.size() > 1) {
AccountSwitcherSheet sheet = new AccountSwitcherSheet(this, null, true, isOpenable);
sheet.setOnClick((accountId, open) -> {
if (open && text.isPresent()) {
BiConsumer<Class<? extends Fragment>, Bundle> callback = (clazz, args) -> {
if (clazz == null) {
Toast.makeText(this, R.string.sk_open_in_app_failed, Toast.LENGTH_SHORT).show();
// TODO: do something about the window getting leaked
sheet.dismiss();
finish();
return;
}
args.putString("fromExternalShare", clazz.getSimpleName());
Intent intent = new Intent(this, MainActivity.class);
intent.putExtras(args);
finish();
startActivity(intent);
};
fediHandle
.<MastodonAPIRequest<?>>map(handle ->
UiUtils.lookupAccountHandle(this, accountId, handle, callback))
.or(() ->
UiUtils.lookupURL(this, accountId, text.get(), callback))
.ifPresent(req ->
req.wrapProgress(this, R.string.loading, true, d -> {
UiUtils.transformDialogForLookup(this, accountId, isFediUrl ? text.get() : null, d);
d.setOnDismissListener((ev) -> finish());
}));
} else {
openComposeFragment(accountId);
}
});
sheet.show();
} else if (sessions.size() == 1) {
openComposeFragment(sessions.get(0).getID()); openComposeFragment(sessions.get(0).getID());
}else{
new AccountSwitcherSheet(this, false, false, isMastodonURL, accountSession -> {
if(accountSession!=null)
openComposeFragment(accountSession.getID());
else
UiUtils.openURL(this, AccountSessionManager.getInstance().getLastActiveAccountID(), text);
}).show();
} }
} }
} }
@@ -108,11 +140,4 @@ public class ExternalShareActivity extends FragmentStackActivity{
return null; return null;
return new ArrayList<>(l); return new ArrayList<>(l);
} }
@Override
public void onProvideAssistContent(AssistContent outContent) {
super.onProvideAssistContent(outContent);
outContent.setWebUri(Uri.parse(DomainManager.getInstance().getCurrentDomain()));
}
} }

View File

@@ -9,6 +9,7 @@ import android.os.Build;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.model.ContentType;
import org.joinmastodon.android.model.TimelineDefinition; import org.joinmastodon.android.model.TimelineDefinition;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@@ -30,14 +31,14 @@ public class GlobalUserPreferences{
public static boolean alwaysExpandContentWarnings; public static boolean alwaysExpandContentWarnings;
public static boolean disableMarquee; public static boolean disableMarquee;
public static boolean disableSwipe; public static boolean disableSwipe;
public static boolean disableDividers; public static boolean showDividers;
public static boolean voteButtonForSingleChoice; public static boolean voteButtonForSingleChoice;
public static boolean uniformNotificationIcon;
public static boolean enableDeleteNotifications; public static boolean enableDeleteNotifications;
public static boolean translateButtonOpenedOnly;
public static boolean uniformNotificationIcon;
public static boolean relocatePublishButton; public static boolean relocatePublishButton;
public static boolean reduceMotion; public static boolean reduceMotion;
public static boolean keepOnlyLatestNotification; public static boolean keepOnlyLatestNotification;
public static boolean enableFabAutoHide;
public static boolean disableAltTextReminder; public static boolean disableAltTextReminder;
public static boolean showAltIndicator; public static boolean showAltIndicator;
public static boolean showNoAltIndicator; public static boolean showNoAltIndicator;
@@ -48,23 +49,28 @@ public class GlobalUserPreferences{
public static boolean spectatorMode; public static boolean spectatorMode;
public static boolean autoHideFab; public static boolean autoHideFab;
public static boolean defaultToUnlistedReplies; public static boolean defaultToUnlistedReplies;
public static boolean disableDoubleTapToSwipe; public static boolean doubleTapToSwipe;
public static boolean compactReblogReplyLine; public static boolean compactReblogReplyLine;
public static boolean confirmBeforeReblog; public static boolean confirmBeforeReblog;
public static boolean replyLineAboveHeader; public static boolean replyLineAboveHeader;
public static boolean swapBookmarkWithBoostAction; public static boolean swapBookmarkWithBoostAction;
public static boolean loadRemoteAccountFollowers; public static boolean loadRemoteAccountFollowers;
public static boolean mentionRebloggerAutomatically; public static boolean mentionRebloggerAutomatically;
public static boolean allowRemoteLoading;
public static AutoRevealMode autoRevealEqualSpoilers;
public static String publishButtonText; public static String publishButtonText;
public static ThemePreference theme; public static ThemePreference theme;
public static ColorPreference color; public static ColorPreference color;
private final static Type recentLanguagesType = new TypeToken<Map<String, List<String>>>() {}.getType(); private final static Type recentLanguagesType = new TypeToken<Map<String, List<String>>>() {}.getType();
private final static Type pinnedTimelinesType = new TypeToken<Map<String, List<TimelineDefinition>>>() {}.getType(); private final static Type pinnedTimelinesType = new TypeToken<Map<String, List<TimelineDefinition>>>() {}.getType();
private final static Type accountsDefaultContentTypesType = new TypeToken<Map<String, ContentType>>() {}.getType();
public static Map<String, List<String>> recentLanguages; public static Map<String, List<String>> recentLanguages;
public static Map<String, List<TimelineDefinition>> pinnedTimelines; public static Map<String, List<TimelineDefinition>> pinnedTimelines;
public static Set<String> accountsWithLocalOnlySupport; public static Set<String> accountsWithLocalOnlySupport;
public static Set<String> accountsInGlitchMode; public static Set<String> accountsInGlitchMode;
public static Set<String> accountsWithContentTypesEnabled;
public static Map<String, ContentType> accountsDefaultContentTypes;
private final static Type recentEmojisType = new TypeToken<Map<String, Integer>>() {}.getType(); private final static Type recentEmojisType = new TypeToken<Map<String, Integer>>() {}.getType();
public static Map<String, Integer> recentEmojis; public static Map<String, Integer> recentEmojis;
@@ -74,7 +80,6 @@ public class GlobalUserPreferences{
*/ */
public static String replyVisibility; public static String replyVisibility;
public static SharedPreferences getPrefs(){ public static SharedPreferences getPrefs(){
return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE); return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE);
} }
@@ -85,6 +90,16 @@ public class GlobalUserPreferences{
catch (JsonSyntaxException ignored) { return orElse; } catch (JsonSyntaxException ignored) { return orElse; }
} }
public static void removeAccount(String accountId) {
recentLanguages.remove(accountId);
pinnedTimelines.remove(accountId);
accountsInGlitchMode.remove(accountId);
accountsWithLocalOnlySupport.remove(accountId);
accountsWithContentTypesEnabled.remove(accountId);
accountsDefaultContentTypes.remove(accountId);
save();
}
public static void load(){ public static void load(){
SharedPreferences prefs=getPrefs(); SharedPreferences prefs=getPrefs();
playGifs=prefs.getBoolean("playGifs", true); playGifs=prefs.getBoolean("playGifs", true);
@@ -99,13 +114,14 @@ public class GlobalUserPreferences{
alwaysExpandContentWarnings=prefs.getBoolean("alwaysExpandContentWarnings", false); alwaysExpandContentWarnings=prefs.getBoolean("alwaysExpandContentWarnings", false);
disableMarquee=prefs.getBoolean("disableMarquee", false); disableMarquee=prefs.getBoolean("disableMarquee", false);
disableSwipe=prefs.getBoolean("disableSwipe", false); disableSwipe=prefs.getBoolean("disableSwipe", false);
disableDividers=prefs.getBoolean("disableDividers", true); showDividers =prefs.getBoolean("showDividers", false);
relocatePublishButton=prefs.getBoolean("relocatePublishButton", true); relocatePublishButton=prefs.getBoolean("relocatePublishButton", true);
voteButtonForSingleChoice=prefs.getBoolean("voteButtonForSingleChoice", true); voteButtonForSingleChoice=prefs.getBoolean("voteButtonForSingleChoice", true);
enableDeleteNotifications=prefs.getBoolean("enableDeleteNotifications", false); enableDeleteNotifications=prefs.getBoolean("enableDeleteNotifications", false);
translateButtonOpenedOnly=prefs.getBoolean("translateButtonOpenedOnly", false);
uniformNotificationIcon=prefs.getBoolean("uniformNotificationIcon", false);
reduceMotion=prefs.getBoolean("reduceMotion", false); reduceMotion=prefs.getBoolean("reduceMotion", false);
keepOnlyLatestNotification=prefs.getBoolean("keepOnlyLatestNotification", false); keepOnlyLatestNotification=prefs.getBoolean("keepOnlyLatestNotification", false);
enableFabAutoHide=prefs.getBoolean("enableFabAutoHide", true);
disableAltTextReminder=prefs.getBoolean("disableAltTextReminder", false); disableAltTextReminder=prefs.getBoolean("disableAltTextReminder", false);
showAltIndicator=prefs.getBoolean("showAltIndicator", true); showAltIndicator=prefs.getBoolean("showAltIndicator", true);
showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true); showNoAltIndicator=prefs.getBoolean("showNoAltIndicator", true);
@@ -117,7 +133,7 @@ public class GlobalUserPreferences{
autoHideFab=prefs.getBoolean("autoHideFab", true); autoHideFab=prefs.getBoolean("autoHideFab", true);
compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true); compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true);
defaultToUnlistedReplies=prefs.getBoolean("defaultToUnlistedReplies", false); defaultToUnlistedReplies=prefs.getBoolean("defaultToUnlistedReplies", false);
disableDoubleTapToSwipe=prefs.getBoolean("disableDoubleTapToSwipe", false); doubleTapToSwipe =prefs.getBoolean("doubleTapToSwipe", true);
replyLineAboveHeader=prefs.getBoolean("replyLineAboveHeader", true); replyLineAboveHeader=prefs.getBoolean("replyLineAboveHeader", true);
compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true); compactReblogReplyLine=prefs.getBoolean("compactReblogReplyLine", true);
confirmBeforeReblog=prefs.getBoolean("confirmBeforeReblog", false); confirmBeforeReblog=prefs.getBoolean("confirmBeforeReblog", false);
@@ -133,6 +149,10 @@ public class GlobalUserPreferences{
accountsWithLocalOnlySupport=prefs.getStringSet("accountsWithLocalOnlySupport", new HashSet<>()); accountsWithLocalOnlySupport=prefs.getStringSet("accountsWithLocalOnlySupport", new HashSet<>());
accountsInGlitchMode=prefs.getStringSet("accountsInGlitchMode", new HashSet<>()); accountsInGlitchMode=prefs.getStringSet("accountsInGlitchMode", new HashSet<>());
replyVisibility=prefs.getString("replyVisibility", null); replyVisibility=prefs.getString("replyVisibility", null);
accountsWithContentTypesEnabled=prefs.getStringSet("accountsWithContentTypesEnabled", new HashSet<>());
accountsDefaultContentTypes=fromJson(prefs.getString("accountsDefaultContentTypes", null), accountsDefaultContentTypesType, new HashMap<>());
allowRemoteLoading=prefs.getBoolean("allowRemoteLoading", true);
autoRevealEqualSpoilers=AutoRevealMode.valueOf(prefs.getString("autoRevealEqualSpoilers", AutoRevealMode.THREADS.name()));
try { try {
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){ if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
@@ -159,13 +179,12 @@ public class GlobalUserPreferences{
.putBoolean("alwaysExpandContentWarnings", alwaysExpandContentWarnings) .putBoolean("alwaysExpandContentWarnings", alwaysExpandContentWarnings)
.putBoolean("disableMarquee", disableMarquee) .putBoolean("disableMarquee", disableMarquee)
.putBoolean("disableSwipe", disableSwipe) .putBoolean("disableSwipe", disableSwipe)
.putBoolean("disableDividers", disableDividers) .putBoolean("showDividers", showDividers)
.putBoolean("relocatePublishButton", relocatePublishButton) .putBoolean("relocatePublishButton", relocatePublishButton)
.putBoolean("uniformNotificationIcon", uniformNotificationIcon) .putBoolean("uniformNotificationIcon", uniformNotificationIcon)
.putBoolean("enableDeleteNotifications", enableDeleteNotifications) .putBoolean("enableDeleteNotifications", enableDeleteNotifications)
.putBoolean("reduceMotion", reduceMotion) .putBoolean("reduceMotion", reduceMotion)
.putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification) .putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification)
.putBoolean("enableFabAutoHide", enableFabAutoHide)
.putBoolean("disableAltTextReminder", disableAltTextReminder) .putBoolean("disableAltTextReminder", disableAltTextReminder)
.putBoolean("showAltIndicator", showAltIndicator) .putBoolean("showAltIndicator", showAltIndicator)
.putBoolean("showNoAltIndicator", showNoAltIndicator) .putBoolean("showNoAltIndicator", showNoAltIndicator)
@@ -174,10 +193,11 @@ public class GlobalUserPreferences{
.putBoolean("collapseLongPosts", collapseLongPosts) .putBoolean("collapseLongPosts", collapseLongPosts)
.putBoolean("spectatorMode", spectatorMode) .putBoolean("spectatorMode", spectatorMode)
.putBoolean("autoHideFab", autoHideFab) .putBoolean("autoHideFab", autoHideFab)
.putBoolean("compactReblogReplyLine", compactReblogReplyLine)
.putString("publishButtonText", publishButtonText) .putString("publishButtonText", publishButtonText)
.putBoolean("bottomEncoding", bottomEncoding) .putBoolean("bottomEncoding", bottomEncoding)
.putBoolean("defaultToUnlistedReplies", defaultToUnlistedReplies) .putBoolean("defaultToUnlistedReplies", defaultToUnlistedReplies)
.putBoolean("disableDoubleTapToSwipe", disableDoubleTapToSwipe) .putBoolean("doubleTapToSwipe", doubleTapToSwipe)
.putBoolean("compactReblogReplyLine", compactReblogReplyLine) .putBoolean("compactReblogReplyLine", compactReblogReplyLine)
.putBoolean("replyLineAboveHeader", replyLineAboveHeader) .putBoolean("replyLineAboveHeader", replyLineAboveHeader)
.putBoolean("confirmBeforeReblog", confirmBeforeReblog) .putBoolean("confirmBeforeReblog", confirmBeforeReblog)
@@ -192,6 +212,10 @@ public class GlobalUserPreferences{
.putStringSet("accountsWithLocalOnlySupport", accountsWithLocalOnlySupport) .putStringSet("accountsWithLocalOnlySupport", accountsWithLocalOnlySupport)
.putStringSet("accountsInGlitchMode", accountsInGlitchMode) .putStringSet("accountsInGlitchMode", accountsInGlitchMode)
.putString("replyVisibility", replyVisibility) .putString("replyVisibility", replyVisibility)
.putStringSet("accountsWithContentTypesEnabled", accountsWithContentTypesEnabled)
.putString("accountsDefaultContentTypes", gson.toJson(accountsDefaultContentTypes))
.putBoolean("allowRemoteLoading", allowRemoteLoading)
.putString("autoRevealEqualSpoilers", autoRevealEqualSpoilers.name())
.apply(); .apply();
} }
@@ -212,5 +236,10 @@ public class GlobalUserPreferences{
LIGHT, LIGHT,
DARK DARK
} }
}
public enum AutoRevealMode {
NEVER,
THREADS,
DISCUSSIONS
}
}

View File

@@ -1,18 +1,28 @@
package org.joinmastodon.android; package org.joinmastodon.android;
import static org.joinmastodon.android.fragments.ComposeFragment.CAMERA_PERMISSION_CODE;
import static org.joinmastodon.android.fragments.ComposeFragment.CAMERA_PIC_REQUEST_CODE;
import android.Manifest; import android.Manifest;
import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.app.assist.AssistContent; import android.app.assist.AssistContent;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log; import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Toast;
import org.joinmastodon.android.api.ObjectValidationException; import org.joinmastodon.android.api.ObjectValidationException;
import org.joinmastodon.android.api.mastodon.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.mastodon.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.PictureTakenEvent;
import org.joinmastodon.android.fragments.ComposeFragment; import org.joinmastodon.android.fragments.ComposeFragment;
import org.joinmastodon.android.fragments.HomeFragment; import org.joinmastodon.android.fragments.HomeFragment;
import org.joinmastodon.android.fragments.ProfileFragment; import org.joinmastodon.android.fragments.ProfileFragment;
@@ -22,13 +32,13 @@ import org.joinmastodon.android.fragments.onboarding.CustomWelcomeFragment;
import org.joinmastodon.android.model.Notification; import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.updater.GithubSelfUpdater; import org.joinmastodon.android.updater.GithubSelfUpdater;
import org.joinmastodon.android.utils.ProvidesAssistContent;
import org.parceler.Parcels; import org.parceler.Parcels;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import me.grishka.appkit.FragmentStackActivity; import me.grishka.appkit.FragmentStackActivity;
public class MainActivity extends FragmentStackActivity{ public class MainActivity extends FragmentStackActivity implements ProvidesAssistContent {
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState){ protected void onCreate(@Nullable Bundle savedInstanceState){
UiUtils.setUserPreferredTheme(this); UiUtils.setUserPreferredTheme(this);
@@ -38,10 +48,18 @@ public class MainActivity extends FragmentStackActivity{
if(AccountSessionManager.getInstance().getLoggedInAccounts().isEmpty()){ if(AccountSessionManager.getInstance().getLoggedInAccounts().isEmpty()){
showFragmentClearingBackStack(new CustomWelcomeFragment()); showFragmentClearingBackStack(new CustomWelcomeFragment());
}else{ }else{
AccountSessionManager.getInstance().maybeUpdateLocalInfo();
AccountSession session; AccountSession session;
Bundle args=new Bundle(); Bundle args=new Bundle();
Intent intent=getIntent(); Intent intent=getIntent();
if(intent.hasExtra("fromExternalShare")) {
AccountSessionManager.getInstance()
.setLastActiveAccountID(intent.getStringExtra("account"));
AccountSessionManager.getInstance().maybeUpdateLocalInfo(
AccountSessionManager.getInstance().getLastActiveAccount());
showFragmentForExternalShare(intent.getExtras());
return;
}
boolean fromNotification = intent.getBooleanExtra("fromNotification", false); boolean fromNotification = intent.getBooleanExtra("fromNotification", false);
boolean hasNotification = intent.hasExtra("notification"); boolean hasNotification = intent.hasExtra("notification");
if(fromNotification){ if(fromNotification){
@@ -55,6 +73,7 @@ public class MainActivity extends FragmentStackActivity{
}else{ }else{
session=AccountSessionManager.getInstance().getLastActiveAccount(); session=AccountSessionManager.getInstance().getLastActiveAccount();
} }
AccountSessionManager.getInstance().maybeUpdateLocalInfo(session);
args.putString("account", session.getID()); args.putString("account", session.getID());
Fragment fragment=session.activated ? new HomeFragment() : new AccountActivationFragment(); Fragment fragment=session.activated ? new HomeFragment() : new AccountActivationFragment();
fragment.setArguments(args); fragment.setArguments(args);
@@ -78,12 +97,12 @@ public class MainActivity extends FragmentStackActivity{
@Override @Override
protected void onNewIntent(Intent intent){ protected void onNewIntent(Intent intent){
super.onNewIntent(intent); super.onNewIntent(intent);
if(intent.getBooleanExtra("fromNotification", false)){ AccountSessionManager.getInstance().maybeUpdateLocalInfo();
if (intent.hasExtra("fromExternalShare")) showFragmentForExternalShare(intent.getExtras());
else if (intent.getBooleanExtra("fromNotification", false)) {
String accountID=intent.getStringExtra("accountID"); String accountID=intent.getStringExtra("accountID");
AccountSession accountSession;
try{ try{
accountSession=AccountSessionManager.getInstance().getAccount(accountID); AccountSessionManager.getInstance().getAccount(accountID);
DomainManager.getInstance().setCurrentDomain(accountSession.domain);
}catch(IllegalStateException x){ }catch(IllegalStateException x){
return; return;
} }
@@ -107,23 +126,24 @@ public class MainActivity extends FragmentStackActivity{
} }
private void showFragmentForNotification(Notification notification, String accountID){ private void showFragmentForNotification(Notification notification, String accountID){
Fragment fragment;
Bundle args=new Bundle();
args.putString("account", accountID);
args.putBoolean("_can_go_back", true);
try{ try{
notification.postprocess(); notification.postprocess();
}catch(ObjectValidationException x){ }catch(ObjectValidationException x){
Log.w("MainActivity", x); Log.w("MainActivity", x);
return; return;
} }
if(notification.status!=null){ UiUtils.showFragmentForNotification(this, notification, accountID, null);
fragment=new ThreadFragment(); }
args.putParcelable("status", Parcels.wrap(notification.status));
}else{ private void showFragmentForExternalShare(Bundle args) {
fragment=new ProfileFragment(); String className = args.getString("fromExternalShare");
args.putParcelable("profileAccount", Parcels.wrap(notification.account)); Fragment fragment = switch (className) {
} case "ThreadFragment" -> new ThreadFragment();
case "ProfileFragment" -> new ProfileFragment();
default -> null;
};
if (fragment == null) return;
args.putBoolean("_can_go_back", true);
fragment.setArguments(args); fragment.setArguments(args);
showFragment(fragment); showFragment(fragment);
} }
@@ -157,25 +177,61 @@ public class MainActivity extends FragmentStackActivity{
(fragmentContainers.get(fragmentContainers.size() - 1)).getId() (fragmentContainers.get(fragmentContainers.size() - 1)).getId()
); );
Bundle currentArgs = currentFragment.getArguments(); Bundle currentArgs = currentFragment.getArguments();
if (this.fragmentContainers.size() == 1 if (fragmentContainers.size() != 1
&& currentArgs != null || currentArgs == null
&& currentArgs.getBoolean("_can_go_back", false) || !currentArgs.getBoolean("_can_go_back", false)) {
&& currentArgs.containsKey("account")) { super.onBackPressed();
return;
}
if (currentArgs.getBoolean("_finish_on_back", false)) {
finish();
} else if (currentArgs.containsKey("account")) {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("account", currentArgs.getString("account")); args.putString("account", currentArgs.getString("account"));
args.putString("tab", "notifications"); if (getIntent().getBooleanExtra("fromNotification", false)) {
args.putString("tab", "notifications");
}
Fragment fragment=new HomeFragment(); Fragment fragment=new HomeFragment();
fragment.setArguments(args); fragment.setArguments(args);
showFragmentClearingBackStack(fragment); showFragmentClearingBackStack(fragment);
} else {
super.onBackPressed();
} }
} }
@Override
public void onProvideAssistContent(AssistContent outContent) {
super.onProvideAssistContent(outContent);
outContent.setWebUri(Uri.parse(DomainManager.getInstance().getCurrentDomain())); @Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode==CAMERA_PIC_REQUEST_CODE && resultCode== Activity.RESULT_OK){
Bitmap image = (Bitmap) data.getExtras().get("data");
String path = MediaStore.Images.Media.insertImage(this.getContentResolver(), image, null, null);
E.post(new PictureTakenEvent(Uri.parse(path)));
}
} }
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CAMERA_PERMISSION_CODE && (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST_CODE);
} else {
Toast.makeText(this, R.string.permission_required, Toast.LENGTH_SHORT);
}
}
public Fragment getCurrentFragment() {
for (int i = fragmentContainers.size() - 1; i >= 0; i--) {
FrameLayout fl = fragmentContainers.get(i);
if (fl.getVisibility() == View.VISIBLE) {
return getFragmentManager().findFragmentById(fl.getId());
}
}
return null;
}
@Override
public void onProvideAssistContent(AssistContent assistContent) {
super.onProvideAssistContent(assistContent);
Fragment fragment = getCurrentFragment();
if (fragment != null) callFragmentToProvideAssistContent(fragment, assistContent);
}
} }

View File

@@ -6,11 +6,12 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import org.joinmastodon.android.api.mastodon.requests.accounts.GetOwnAccount; import org.joinmastodon.android.api.requests.accounts.GetOwnAccount;
import org.joinmastodon.android.api.mastodon.requests.oauth.GetOauthToken; import org.joinmastodon.android.api.requests.oauth.GetOauthToken;
import org.joinmastodon.android.api.mastodon.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Account; 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;
@@ -60,6 +61,9 @@ public class OAuthActivity extends Activity{
@Override @Override
public void onSuccess(Token token){ public void onSuccess(Token token){
new GetOwnAccount() new GetOwnAccount()
// in case the instance (looking at pixelfed) wants to redirect to a
// website, we need to pass a context so we can launch a browser
.setContext(OAuthActivity.this)
.setCallback(new Callback<>(){ .setCallback(new Callback<>(){
@Override @Override
public void onSuccess(Account account){ public void onSuccess(Account account){

View File

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

View File

@@ -12,29 +12,34 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.opengl.Visibility;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import org.joinmastodon.android.api.MastodonAPIController; import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.mastodon.requests.accounts.SetAccountFollowed; import org.joinmastodon.android.api.requests.accounts.SetAccountFollowed;
import org.joinmastodon.android.api.mastodon.requests.notifications.GetNotificationByID; import org.joinmastodon.android.api.requests.notifications.GetNotificationByID;
import org.joinmastodon.android.api.mastodon.requests.statuses.CreateStatus; import org.joinmastodon.android.api.requests.statuses.CreateStatus;
import org.joinmastodon.android.api.mastodon.requests.statuses.SetStatusBookmarked; import org.joinmastodon.android.api.requests.statuses.SetStatusBookmarked;
import org.joinmastodon.android.api.mastodon.requests.statuses.SetStatusFavorited; import org.joinmastodon.android.api.requests.statuses.SetStatusFavorited;
import org.joinmastodon.android.api.mastodon.requests.statuses.SetStatusReblogged; import org.joinmastodon.android.api.requests.statuses.SetStatusReblogged;
import org.joinmastodon.android.api.mastodon.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.mastodon.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.NotificationReceivedEvent; import org.joinmastodon.android.events.NotificationReceivedEvent;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Mention;
import org.joinmastodon.android.model.NotificationAction; import org.joinmastodon.android.model.NotificationAction;
import org.joinmastodon.android.model.Preferences; import org.joinmastodon.android.model.Preferences;
import org.joinmastodon.android.model.PushNotification; import org.joinmastodon.android.model.PushNotification;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.StatusPrivacy;
import org.joinmastodon.android.model.StatusPrivacy; import org.joinmastodon.android.model.StatusPrivacy;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import org.parceler.Parcels; import org.parceler.Parcels;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
@@ -54,7 +59,7 @@ public class PushNotificationReceiver extends BroadcastReceiver{
private static final String ACTION_KEY_TEXT_REPLY = "ACTION_KEY_TEXT_REPLY"; private static final String ACTION_KEY_TEXT_REPLY = "ACTION_KEY_TEXT_REPLY";
private static final int SUMMARY_ID = 791; private static final int SUMMARY_ID = 791;
private static int notificationId; private static int notificationId = 0;
@Override @Override
public void onReceive(Context context, Intent intent){ public void onReceive(Context context, Intent intent){
@@ -295,27 +300,60 @@ public class PushNotificationReceiver extends BroadcastReceiver{
} }
CharSequence input = remoteInput.getCharSequence(ACTION_KEY_TEXT_REPLY); CharSequence input = remoteInput.getCharSequence(ACTION_KEY_TEXT_REPLY);
// copied from ComposeFragment - TODO: generalize?
ArrayList<String> mentions=new ArrayList<>();
Status status = notification.status;
String ownID=AccountSessionManager.getInstance().getAccount(accountID).self.id;
if(!status.account.id.equals(ownID))
mentions.add('@'+status.account.acct);
for(Mention mention:status.mentions){
if(mention.id.equals(ownID))
continue;
String m='@'+mention.acct;
if(!mentions.contains(m))
mentions.add(m);
}
String initialText=mentions.isEmpty() ? "" : TextUtils.join(" ", mentions)+" ";
CreateStatus.Request req=new CreateStatus.Request(); CreateStatus.Request req=new CreateStatus.Request();
req.status = input.toString() + "\n\n" + "@" + notification.status.account.acct; req.status = initialText + input.toString();
req.language = notification.status.language; req.language = preferences.postingDefaultLanguage;
req.visibility = (notification.status.visibility == StatusPrivacy.PUBLIC && GlobalUserPreferences.defaultToUnlistedReplies ? StatusPrivacy.UNLISTED : notification.status.visibility); req.visibility = preferences.postingDefaultVisibility;
req.inReplyToId = notification.status.id; req.inReplyToId = notification.status.id;
if(!notification.status.spoilerText.isEmpty() && GlobalUserPreferences.prefixRepliesWithRe && !notification.status.spoilerText.startsWith("re: ")){ if(!notification.status.spoilerText.isEmpty() && GlobalUserPreferences.prefixRepliesWithRe && !notification.status.spoilerText.startsWith("re: ")){
req.spoilerText = "re: " + notification.status.spoilerText; req.spoilerText = "re: " + notification.status.spoilerText;
} }
new CreateStatus(req, UUID.randomUUID().toString()).exec(accountID); new CreateStatus(req, UUID.randomUUID().toString()).setCallback(new Callback<>() {
@Override
public void onSuccess(Status status) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ?
new Notification.Builder(context, accountID+"_"+notification.type) :
new Notification.Builder(context)
.setPriority(Notification.PRIORITY_DEFAULT)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); notification.status = status;
Notification.Builder builder = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ? Intent contentIntent=new Intent(context, MainActivity.class);
new Notification.Builder(context, accountID+"_"+notification.type) : contentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
new Notification.Builder(context) contentIntent.putExtra("fromNotification", true);
.setPriority(Notification.PRIORITY_DEFAULT) contentIntent.putExtra("accountID", accountID);
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE); contentIntent.putExtra("notification", Parcels.wrap(notification));
Notification repliedNotification = builder.setSmallIcon(R.drawable.ic_ntf_logo) Notification repliedNotification = builder.setSmallIcon(R.drawable.ic_ntf_logo)
.setContentText(context.getString(R.string.mo_notification_action_replied, notification.status.account.getDisplayUsername())) .setContentTitle(context.getString(R.string.sk_notification_action_replied, notification.status.account.displayName))
.build(); .setContentText(status.getStrippedText())
notificationManager.notify(accountID, notificationId, repliedNotification); .setCategory(Notification.CATEGORY_SOCIAL)
.setContentIntent(PendingIntent.getActivity(context, notificationId, contentIntent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT))
.build();
notificationManager.notify(accountID, notificationId, repliedNotification);
}
@Override
public void onError(ErrorResponse errorResponse) {
}
}).exec(accountID);
} }
} }

View File

@@ -11,10 +11,10 @@ import android.util.Log;
import org.joinmastodon.android.BuildConfig; import org.joinmastodon.android.BuildConfig;
import org.joinmastodon.android.MastodonApp; import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.api.adapter.ApiAdapter; import org.joinmastodon.android.api.requests.notifications.GetNotifications;
import org.joinmastodon.android.api.mastodon.requests.notifications.GetNotifications; import org.joinmastodon.android.api.requests.timelines.GetHomeTimeline;
import org.joinmastodon.android.api.mastodon.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.mastodon.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.CacheablePaginatedResponse; import org.joinmastodon.android.model.CacheablePaginatedResponse;
import org.joinmastodon.android.model.Filter; import org.joinmastodon.android.model.Filter;
import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Instance;
@@ -36,7 +36,7 @@ import me.grishka.appkit.utils.WorkerThread;
public class CacheController{ public class CacheController{
private static final String TAG="CacheController"; private static final String TAG="CacheController";
private static final int DB_VERSION=3; private static final int DB_VERSION=4;
private static final WorkerThread databaseThread=new WorkerThread("databaseThread"); private static final WorkerThread databaseThread=new WorkerThread("databaseThread");
private static final Handler uiHandler=new Handler(Looper.getMainLooper()); private static final Handler uiHandler=new Handler(Looper.getMainLooper());
@@ -61,7 +61,7 @@ public class CacheController{
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(Filter.FilterContext.HOME)).collect(Collectors.toList());
if(!forceReload){ if(!forceReload){
SQLiteDatabase db=getOrOpenDatabase(); SQLiteDatabase db=getOrOpenDatabase();
try(Cursor cursor=db.query("home_timeline", new String[]{"json", "flags"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`id` DESC", count+"")){ try(Cursor cursor=db.query("home_timeline", new String[]{"json", "flags"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`time` DESC", count+"")){
if(cursor.getCount()==count){ if(cursor.getCount()==count){
ArrayList<Status> result=new ArrayList<>(); ArrayList<Status> result=new ArrayList<>();
cursor.moveToFirst(); cursor.moveToFirst();
@@ -73,10 +73,8 @@ public class CacheController{
int flags=cursor.getInt(1); int flags=cursor.getInt(1);
status.hasGapAfter=((flags & POST_FLAG_GAP_AFTER)!=0); status.hasGapAfter=((flags & POST_FLAG_GAP_AFTER)!=0);
newMaxID=status.id; newMaxID=status.id;
for(Filter filter:filters){ if (!new StatusFilterPredicate(filters, Filter.FilterContext.HOME).test(status))
if(filter.matches(status)) continue outer;
continue outer;
}
result.add(status); result.add(status);
}while(cursor.moveToNext()); }while(cursor.moveToNext());
String _newMaxID=newMaxID; String _newMaxID=newMaxID;
@@ -87,12 +85,11 @@ public class CacheController{
Log.w(TAG, "getHomeTimeline: corrupted status object in database", x); Log.w(TAG, "getHomeTimeline: corrupted status object in database", x);
} }
} }
ApiAdapter apiAdapter = new ApiAdapter(ApiAdapter.ServerType.MASTODON); new GetHomeTimeline(maxID, null, count, null)
apiAdapter.getHomeTimeline(maxID, null, count, null)
.setCallback(new Callback<>(){ .setCallback(new Callback<>(){
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
callback.onSuccess(new CacheablePaginatedResponse<>(result.stream().filter(new StatusFilterPredicate(filters)).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id, false)); callback.onSuccess(new CacheablePaginatedResponse<>(result.stream().filter(new StatusFilterPredicate(filters, Filter.FilterContext.HOME)).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id, false));
putHomeTimeline(result, maxID==null); putHomeTimeline(result, maxID==null);
} }
@@ -115,7 +112,7 @@ public class CacheController{
runOnDbThread((db)->{ runOnDbThread((db)->{
if(clear) if(clear)
db.delete("home_timeline", null, null); db.delete("home_timeline", null, null);
ContentValues values=new ContentValues(3); ContentValues values=new ContentValues(4);
for(Status s:posts){ for(Status s:posts){
values.put("id", s.id); values.put("id", s.id);
values.put("json", MastodonAPIController.gson.toJson(s)); values.put("json", MastodonAPIController.gson.toJson(s));
@@ -123,6 +120,7 @@ public class CacheController{
if(s.hasGapAfter) if(s.hasGapAfter)
flags|=POST_FLAG_GAP_AFTER; flags|=POST_FLAG_GAP_AFTER;
values.put("flags", flags); values.put("flags", flags);
values.put("time", s.createdAt.getEpochSecond());
db.insertWithOnConflict("home_timeline", null, values, SQLiteDatabase.CONFLICT_REPLACE); db.insertWithOnConflict("home_timeline", null, values, SQLiteDatabase.CONFLICT_REPLACE);
} }
}); });
@@ -137,7 +135,7 @@ public class CacheController{
if(!forceReload){ if(!forceReload){
SQLiteDatabase db=getOrOpenDatabase(); SQLiteDatabase db=getOrOpenDatabase();
String table=onlyPosts ? "notifications_posts" : onlyMentions ? "notifications_mentions" : "notifications_all"; String table=onlyPosts ? "notifications_posts" : onlyMentions ? "notifications_mentions" : "notifications_all";
try(Cursor cursor=db.query(table, new String[]{"json"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`id` DESC", count+"")){ try(Cursor cursor=db.query(table, new String[]{"json"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`time` DESC", count+"")){
if(cursor.getCount()==count){ if(cursor.getCount()==count){
ArrayList<Notification> result=new ArrayList<>(); ArrayList<Notification> result=new ArrayList<>();
cursor.moveToFirst(); cursor.moveToFirst();
@@ -148,10 +146,8 @@ public class CacheController{
ntf.postprocess(); ntf.postprocess();
newMaxID=ntf.id; newMaxID=ntf.id;
if(ntf.status!=null){ if(ntf.status!=null){
for(Filter filter:filters){ if (!new StatusFilterPredicate(filters, Filter.FilterContext.NOTIFICATIONS).test(ntf.status))
if(filter.matches(ntf.status)) continue outer;
continue outer;
}
} }
result.add(ntf); result.add(ntf);
}while(cursor.moveToNext()); }while(cursor.moveToNext());
@@ -164,17 +160,13 @@ public class CacheController{
} }
} }
Instance instance=AccountSessionManager.getInstance().getInstanceInfo(accountSession.domain); Instance instance=AccountSessionManager.getInstance().getInstanceInfo(accountSession.domain);
new GetNotifications(maxID, count, onlyPosts ? EnumSet.of(Notification.Type.STATUS) : onlyMentions ? EnumSet.of(Notification.Type.MENTION): EnumSet.allOf(Notification.Type.class), instance.pleroma != null) new GetNotifications(maxID, count, onlyPosts ? EnumSet.of(Notification.Type.STATUS) : onlyMentions ? EnumSet.of(Notification.Type.MENTION): EnumSet.allOf(Notification.Type.class), instance.isAkkoma())
.setCallback(new Callback<>(){ .setCallback(new Callback<>(){
@Override @Override
public void onSuccess(List<Notification> result){ public void onSuccess(List<Notification> result){
callback.onSuccess(new CacheablePaginatedResponse<>(result.stream().filter(ntf->{ callback.onSuccess(new CacheablePaginatedResponse<>(result.stream().filter(ntf->{
if(ntf.status!=null){ if(ntf.status!=null){
for(Filter filter:filters){ return new StatusFilterPredicate(filters, Filter.FilterContext.NOTIFICATIONS).test(ntf.status);
if(filter.matches(ntf.status)){
return false;
}
}
} }
return true; return true;
}).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id, false)); }).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id, false));
@@ -201,7 +193,7 @@ public class CacheController{
String table=onlyPosts ? "notifications_posts" : onlyMentions ? "notifications_mentions" : "notifications_all"; String table=onlyPosts ? "notifications_posts" : onlyMentions ? "notifications_mentions" : "notifications_all";
if(clear) if(clear)
db.delete(table, null, null); db.delete(table, null, null);
ContentValues values=new ContentValues(3); ContentValues values=new ContentValues(4);
for(Notification n:notifications){ for(Notification n:notifications){
if(n.type==null){ if(n.type==null){
continue; continue;
@@ -209,6 +201,7 @@ public class CacheController{
values.put("id", n.id); values.put("id", n.id);
values.put("json", MastodonAPIController.gson.toJson(n)); values.put("json", MastodonAPIController.gson.toJson(n));
values.put("type", n.type.ordinal()); values.put("type", n.type.ordinal());
values.put("time", n.createdAt.getEpochSecond());
db.insertWithOnConflict(table, null, values, SQLiteDatabase.CONFLICT_REPLACE); db.insertWithOnConflict(table, null, values, SQLiteDatabase.CONFLICT_REPLACE);
} }
}); });
@@ -305,21 +298,24 @@ public class CacheController{
CREATE TABLE `home_timeline` ( CREATE TABLE `home_timeline` (
`id` VARCHAR(25) NOT NULL PRIMARY KEY, `id` VARCHAR(25) NOT NULL PRIMARY KEY,
`json` TEXT NOT NULL, `json` TEXT NOT NULL,
`flags` INTEGER NOT NULL DEFAULT 0 `flags` INTEGER NOT NULL DEFAULT 0,
`time` INTEGER NOT NULL
)"""); )""");
db.execSQL(""" db.execSQL("""
CREATE TABLE `notifications_all` ( CREATE TABLE `notifications_all` (
`id` VARCHAR(25) NOT NULL PRIMARY KEY, `id` VARCHAR(25) NOT NULL PRIMARY KEY,
`json` TEXT NOT NULL, `json` TEXT NOT NULL,
`flags` INTEGER NOT NULL DEFAULT 0, `flags` INTEGER NOT NULL DEFAULT 0,
`type` INTEGER NOT NULL `type` INTEGER NOT NULL,
`time` INTEGER NOT NULL
)"""); )""");
db.execSQL(""" db.execSQL("""
CREATE TABLE `notifications_mentions` ( CREATE TABLE `notifications_mentions` (
`id` VARCHAR(25) NOT NULL PRIMARY KEY, `id` VARCHAR(25) NOT NULL PRIMARY KEY,
`json` TEXT NOT NULL, `json` TEXT NOT NULL,
`flags` INTEGER NOT NULL DEFAULT 0, `flags` INTEGER NOT NULL DEFAULT 0,
`type` INTEGER NOT NULL `type` INTEGER NOT NULL,
`time` INTEGER NOT NULL
)"""); )""");
createRecentSearchesTable(db); createRecentSearchesTable(db);
createPostsNotificationsTable(db); createPostsNotificationsTable(db);
@@ -327,12 +323,16 @@ public class CacheController{
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
if(oldVersion==1){ if(oldVersion<2){
createRecentSearchesTable(db); createRecentSearchesTable(db);
} }
if(oldVersion==2){ if(oldVersion<3){
// MEGALODON-SPECIFIC
createPostsNotificationsTable(db); createPostsNotificationsTable(db);
} }
if(oldVersion<4){
addTimeColumns(db);
}
} }
private void createRecentSearchesTable(SQLiteDatabase db){ private void createRecentSearchesTable(SQLiteDatabase db){
@@ -350,9 +350,21 @@ public class CacheController{
`id` VARCHAR(25) NOT NULL PRIMARY KEY, `id` VARCHAR(25) NOT NULL PRIMARY KEY,
`json` TEXT NOT NULL, `json` TEXT NOT NULL,
`flags` INTEGER NOT NULL DEFAULT 0, `flags` INTEGER NOT NULL DEFAULT 0,
`type` INTEGER NOT NULL `type` INTEGER NOT NULL,
`time` INTEGER NOT NULL
)"""); )""");
} }
private void addTimeColumns(SQLiteDatabase db){
db.execSQL("DELETE FROM `home_timeline`");
db.execSQL("DELETE FROM `notifications_all`");
db.execSQL("DELETE FROM `notifications_mentions`");
db.execSQL("DELETE FROM `notifications_posts`");
db.execSQL("ALTER TABLE `home_timeline` ADD `time` INTEGER NOT NULL DEFAULT 0");
db.execSQL("ALTER TABLE `notifications_all` ADD `time` INTEGER NOT NULL DEFAULT 0");
db.execSQL("ALTER TABLE `notifications_mentions` ADD `time` INTEGER NOT NULL DEFAULT 0");
db.execSQL("ALTER TABLE `notifications_posts` ADD `time` INTEGER NOT NULL DEFAULT 0");
}
} }
@FunctionalInterface @FunctionalInterface

View File

@@ -15,8 +15,9 @@ import org.joinmastodon.android.BuildConfig;
import org.joinmastodon.android.MastodonApp; import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.api.gson.IsoInstantTypeAdapter; import org.joinmastodon.android.api.gson.IsoInstantTypeAdapter;
import org.joinmastodon.android.api.gson.IsoLocalDateTypeAdapter; import org.joinmastodon.android.api.gson.IsoLocalDateTypeAdapter;
import org.joinmastodon.android.api.mastodon.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.utils.UiUtils;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@@ -28,6 +29,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -51,7 +53,9 @@ public class MastodonAPIController{
.registerTypeAdapter(Status.class, new Status.StatusDeserializer()) .registerTypeAdapter(Status.class, new Status.StatusDeserializer())
.create(); .create();
private static WorkerThread thread=new WorkerThread("MastodonAPIController"); private static WorkerThread thread=new WorkerThread("MastodonAPIController");
private static OkHttpClient httpClient=new OkHttpClient.Builder().build(); private static OkHttpClient httpClient=new OkHttpClient.Builder()
.readTimeout(5, TimeUnit.MINUTES)
.build();
private AccountSession session; private AccountSession session;
private static List<String> badDomains = new ArrayList<>(); private static List<String> badDomains = new ArrayList<>();
@@ -60,7 +64,7 @@ public class MastodonAPIController{
thread.start(); thread.start();
try { try {
final BufferedReader reader = new BufferedReader(new InputStreamReader( final BufferedReader reader = new BufferedReader(new InputStreamReader(
MastodonApp.context.getAssets().open("blocks.tsv") MastodonApp.context.getAssets().open("blocks.txt")
)); ));
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
@@ -91,7 +95,7 @@ public class MastodonAPIController{
Request.Builder builder=new Request.Builder() Request.Builder builder=new Request.Builder()
.url(req.getURL().toString()) .url(req.getURL().toString())
.method(req.getMethod(), req.getRequestBody()) .method(req.getMethod(), req.getRequestBody())
.header("User-Agent", "MastodonAndroid/"+BuildConfig.VERSION_NAME); .header("User-Agent", "MoshidonAndroid/"+BuildConfig.VERSION_NAME);
String token=null; String token=null;
if(session!=null) if(session!=null)
@@ -158,6 +162,11 @@ public class MastodonAPIController{
respObj=gson.fromJson(reader, req.respClass); respObj=gson.fromJson(reader, req.respClass);
} }
}catch(JsonIOException|JsonSyntaxException x){ }catch(JsonIOException|JsonSyntaxException x){
if (req.context != null && response.body().contentType().subtype().equals("html")) {
UiUtils.launchWebBrowser(req.context, response.request().url().toString());
req.cancel();
return;
}
if(BuildConfig.DEBUG) if(BuildConfig.DEBUG)
Log.w(TAG, "["+(session==null ? "no-auth" : session.getID())+"] "+response+" error parsing or reading body", x); Log.w(TAG, "["+(session==null ? "no-auth" : session.getID())+"] "+response+" error parsing or reading body", x);
req.onError(x.getLocalizedMessage(), response.code(), x); req.onError(x.getLocalizedMessage(), response.code(), x);

View File

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

View File

@@ -12,10 +12,10 @@ import android.util.Log;
import org.joinmastodon.android.BuildConfig; import org.joinmastodon.android.BuildConfig;
import org.joinmastodon.android.MastodonApp; import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.api.mastodon.requests.notifications.RegisterForPushNotifications; import org.joinmastodon.android.api.requests.notifications.RegisterForPushNotifications;
import org.joinmastodon.android.api.mastodon.requests.notifications.UpdatePushSettings; import org.joinmastodon.android.api.requests.notifications.UpdatePushSettings;
import org.joinmastodon.android.api.mastodon.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.mastodon.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.PushNotification; import org.joinmastodon.android.model.PushNotification;
import org.joinmastodon.android.model.PushSubscription; import org.joinmastodon.android.model.PushSubscription;
@@ -45,6 +45,7 @@ import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyAgreement; import javax.crypto.KeyAgreement;
import javax.crypto.Mac; import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException; import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;

View File

@@ -4,9 +4,9 @@ import android.os.Looper;
import org.joinmastodon.android.E; import org.joinmastodon.android.E;
import org.joinmastodon.android.MastodonApp; import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.api.mastodon.requests.statuses.SetStatusBookmarked; import org.joinmastodon.android.api.requests.statuses.SetStatusBookmarked;
import org.joinmastodon.android.api.mastodon.requests.statuses.SetStatusFavorited; import org.joinmastodon.android.api.requests.statuses.SetStatusFavorited;
import org.joinmastodon.android.api.mastodon.requests.statuses.SetStatusReblogged; import org.joinmastodon.android.api.requests.statuses.SetStatusReblogged;
import org.joinmastodon.android.events.StatusCountersUpdatedEvent; import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.StatusPrivacy; import org.joinmastodon.android.model.StatusPrivacy;
@@ -46,7 +46,7 @@ public class StatusInteractionController{
@Override @Override
public void onSuccess(Status result){ public void onSuccess(Status result){
runningFavoriteRequests.remove(status.id); runningFavoriteRequests.remove(status.id);
result.favouritesCount = Math.max(0, status.favouritesCount) + (favorited ? 1 : -1); result.favouritesCount = Math.max(0, status.favouritesCount + (favorited ? 1 : -1));
cb.accept(result); cb.accept(result);
if (updateCounters) E.post(new StatusCountersUpdatedEvent(result)); if (updateCounters) E.post(new StatusCountersUpdatedEvent(result));
} }
@@ -80,7 +80,7 @@ public class StatusInteractionController{
public void onSuccess(Status reblog){ public void onSuccess(Status reblog){
Status result = reblog.getContentStatus(); Status result = reblog.getContentStatus();
runningReblogRequests.remove(status.id); runningReblogRequests.remove(status.id);
result.reblogsCount = Math.max(0, status.reblogsCount) + (reblogged ? 1 : -1); result.reblogsCount = Math.max(0, status.reblogsCount + (reblogged ? 1 : -1));
cb.accept(result); cb.accept(result);
if (updateCounters) E.post(new StatusCountersUpdatedEvent(result)); if (updateCounters) E.post(new StatusCountersUpdatedEvent(result));
} }

View File

@@ -1,47 +0,0 @@
package org.joinmastodon.android.api.adapter;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.mastodon.requests.statuses.GetStatusByID;
import org.joinmastodon.android.api.mastodon.requests.timelines.GetHomeTimeline;
import org.joinmastodon.android.model.Status;
import java.util.List;
public class ApiAdapter {
public final ServerType serverType;
public ApiAdapter(ServerType serverType){
this.serverType = serverType;
}
public MastodonAPIRequest<?> getPostById(String id){
switch (serverType){
case MASTODON -> {
return new GetStatusByID(id);
}
case MISSKEY -> {
return null;
}
}
return null;
}
public MastodonAPIRequest<List<Status>> getHomeTimeline(String maxID, String minID, int limit, String sinceID){
switch (serverType){
case MASTODON -> {
return new GetHomeTimeline(maxID, minID, limit, sinceID);
}
case MISSKEY -> {
return null;
}
}
return null;
}
public enum ServerType {
MASTODON,
MISSKEY,
}
}

View File

@@ -1,25 +0,0 @@
package org.joinmastodon.android.api.mastodon.requests.timelines;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status;
import java.util.List;
public class GetHomeTimeline extends MastodonAPIRequest<List<Status>>{
public GetHomeTimeline(String maxID, String minID, int limit, String sinceID){
super(HttpMethod.GET, "/timelines/home", new TypeToken<>(){});
if(maxID!=null)
addQueryParameter("max_id", maxID);
if(minID!=null)
addQueryParameter("min_id", minID);
if(sinceID!=null)
addQueryParameter("since_id", sinceID);
if(limit>0)
addQueryParameter("limit", ""+limit);
if(GlobalUserPreferences.replyVisibility != null)
addQueryParameter("reply_visibility", GlobalUserPreferences.replyVisibility);
}
}

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests; package org.joinmastodon.android.api.requests;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Relationship; import org.joinmastodon.android.model.Relationship;

View File

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

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;

View File

@@ -1,8 +1,8 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.mastodon.requests.HeaderPaginationRequest; import org.joinmastodon.android.api.requests.HeaderPaginationRequest;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
public class GetAccountFollowers extends HeaderPaginationRequest<Account>{ public class GetAccountFollowers extends HeaderPaginationRequest<Account>{

View File

@@ -1,8 +1,8 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.mastodon.requests.HeaderPaginationRequest; import org.joinmastodon.android.api.requests.HeaderPaginationRequest;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
public class GetAccountFollowing extends HeaderPaginationRequest<Account>{ public class GetAccountFollowing extends HeaderPaginationRequest<Account>{

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;

View File

@@ -1,8 +1,8 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.mastodon.requests.HeaderPaginationRequest; import org.joinmastodon.android.api.requests.HeaderPaginationRequest;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
public class GetFollowRequests extends HeaderPaginationRequest<Account>{ public class GetFollowRequests extends HeaderPaginationRequest<Account>{

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Preferences; import org.joinmastodon.android.model.Preferences;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Token; import org.joinmastodon.android.model.Token;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Relationship; import org.joinmastodon.android.model.Relationship;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Relationship; import org.joinmastodon.android.model.Relationship;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Relationship; import org.joinmastodon.android.model.Relationship;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Relationship; import org.joinmastodon.android.model.Relationship;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Relationship; import org.joinmastodon.android.model.Relationship;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.accounts; package org.joinmastodon.android.api.requests.accounts;
import android.net.Uri; import android.net.Uri;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.announcements; package org.joinmastodon.android.api.requests.announcements;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.announcements; package org.joinmastodon.android.api.requests.announcements;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.catalog; package org.joinmastodon.android.api.requests.catalog;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.catalog; package org.joinmastodon.android.api.requests.catalog;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.instance; package org.joinmastodon.android.api.requests.instance;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;

View File

@@ -0,0 +1,16 @@
package org.joinmastodon.android.api.requests.instance;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.DomainBlock;
import org.joinmastodon.android.model.ExtendedDescription;
import java.util.List;
public class GetDomainBlocks extends MastodonAPIRequest<List<DomainBlock>>{
public GetDomainBlocks(){
super(HttpMethod.GET, "/instance/domain_blocks", new TypeToken<>(){});
}
}

View File

@@ -0,0 +1,12 @@
package org.joinmastodon.android.api.requests.instance;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.ExtendedDescription;
import org.joinmastodon.android.model.Instance;
public class GetExtendedDescription extends MastodonAPIRequest<ExtendedDescription>{
public GetExtendedDescription(){
super(HttpMethod.GET, "/instance/extended_description", ExtendedDescription.class);
}
}

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.instance; package org.joinmastodon.android.api.requests.instance;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Instance; import org.joinmastodon.android.model.Instance;

View File

@@ -0,0 +1,15 @@
package org.joinmastodon.android.api.requests.instance;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.WeeklyActivity;
import java.util.List;
public class GetWeeklyActivity extends MastodonAPIRequest<List<WeeklyActivity>>{
public GetWeeklyActivity(){
super(HttpMethod.GET, "/instance/activity", new TypeToken<>(){});
}
}

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.lists; package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import java.util.List; import java.util.List;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.lists; package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import java.util.List; import java.util.List;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.lists; package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.ListTimeline; import org.joinmastodon.android.model.ListTimeline;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.lists; package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.ListTimeline; import org.joinmastodon.android.model.ListTimeline;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.lists; package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import java.util.List; import java.util.List;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.lists; package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.ListTimeline; import org.joinmastodon.android.model.ListTimeline;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.lists; package org.joinmastodon.android.api.requests.lists;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.lists; package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import java.util.List; import java.util.List;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.lists; package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import java.util.List; import java.util.List;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.lists; package org.joinmastodon.android.api.requests.lists;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.ListTimeline; import org.joinmastodon.android.model.ListTimeline;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.markers; package org.joinmastodon.android.api.requests.markers;
import org.joinmastodon.android.api.ApiUtils; import org.joinmastodon.android.api.ApiUtils;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.markers; package org.joinmastodon.android.api.requests.markers;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.gson.JsonObjectBuilder; import org.joinmastodon.android.api.gson.JsonObjectBuilder;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.notifications; package org.joinmastodon.android.api.requests.notifications;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.notifications; package org.joinmastodon.android.api.requests.notifications;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Notification; import org.joinmastodon.android.model.Notification;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.notifications; package org.joinmastodon.android.api.requests.notifications;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;

View File

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

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.notifications; package org.joinmastodon.android.api.requests.notifications;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.PushSubscription; import org.joinmastodon.android.model.PushSubscription;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.notifications; package org.joinmastodon.android.api.requests.notifications;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.PushSubscription; import org.joinmastodon.android.model.PushSubscription;

View File

@@ -1,7 +1,7 @@
package org.joinmastodon.android.api.mastodon.requests.oauth; package org.joinmastodon.android.api.requests.oauth;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.mastodon.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Application; import org.joinmastodon.android.model.Application;
public class CreateOAuthApp extends MastodonAPIRequest<Application>{ public class CreateOAuthApp extends MastodonAPIRequest<Application>{

View File

@@ -1,9 +1,9 @@
package org.joinmastodon.android.api.mastodon.requests.oauth; package org.joinmastodon.android.api.requests.oauth;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.mastodon.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Token; import org.joinmastodon.android.model.Token;
public class GetOauthToken extends MastodonAPIRequest<Token>{ public class GetOauthToken extends MastodonAPIRequest<Token>{

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.oauth; package org.joinmastodon.android.api.requests.oauth;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.polls; package org.joinmastodon.android.api.requests.polls;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Poll; import org.joinmastodon.android.model.Poll;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.reports; package org.joinmastodon.android.api.requests.reports;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.ReportReason; import org.joinmastodon.android.model.ReportReason;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.search; package org.joinmastodon.android.api.requests.search;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.SearchResults; import org.joinmastodon.android.model.SearchResults;

View File

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

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Attachment; import org.joinmastodon.android.model.Attachment;

View File

@@ -1,8 +1,8 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.mastodon.requests.HeaderPaginationRequest; import org.joinmastodon.android.api.requests.HeaderPaginationRequest;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
public class GetBookmarkedStatuses extends HeaderPaginationRequest<Status>{ public class GetBookmarkedStatuses extends HeaderPaginationRequest<Status>{

View File

@@ -1,8 +1,8 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.mastodon.requests.HeaderPaginationRequest; import org.joinmastodon.android.api.requests.HeaderPaginationRequest;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
public class GetFavoritedStatuses extends HeaderPaginationRequest<Status>{ public class GetFavoritedStatuses extends HeaderPaginationRequest<Status>{

View File

@@ -1,8 +1,8 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.mastodon.requests.HeaderPaginationRequest; import org.joinmastodon.android.api.requests.HeaderPaginationRequest;
import org.joinmastodon.android.model.ScheduledStatus; import org.joinmastodon.android.model.ScheduledStatus;
public class GetScheduledStatuses extends HeaderPaginationRequest<ScheduledStatus>{ public class GetScheduledStatuses extends HeaderPaginationRequest<ScheduledStatus>{

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.StatusContext; import org.joinmastodon.android.model.StatusContext;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;

View File

@@ -1,8 +1,8 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.mastodon.requests.HeaderPaginationRequest; import org.joinmastodon.android.api.requests.HeaderPaginationRequest;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
public class GetStatusFavorites extends HeaderPaginationRequest<Account>{ public class GetStatusFavorites extends HeaderPaginationRequest<Account>{

View File

@@ -1,8 +1,8 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.mastodon.requests.HeaderPaginationRequest; import org.joinmastodon.android.api.requests.HeaderPaginationRequest;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
public class GetStatusReblogs extends HeaderPaginationRequest<Account>{ public class GetStatusReblogs extends HeaderPaginationRequest<Account>{

View File

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

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;

View File

@@ -1,4 +1,4 @@
package org.joinmastodon.android.api.mastodon.requests.statuses; package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;

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