From 4e2e3fb4e2f0268438d163a49dc1690943a3af2e Mon Sep 17 00:00:00 2001 From: Grishka Date: Sat, 22 Jun 2024 02:33:06 +0300 Subject: [PATCH] Add donation options to settings --- mastodon/build.gradle | 2 +- .../catalog/GetDonationCampaigns.java | 8 +- .../fragments/HomeTimelineFragment.java | 3 +- .../settings/SettingsMainFragment.java | 80 +++++++++++++++++-- .../res/drawable/ic_settings_heart_24px.xml | 9 +++ .../drawable/ic_volunteer_activism_24px.xml | 9 +++ mastodon/src/main/res/values/strings.xml | 2 + 7 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 mastodon/src/main/res/drawable/ic_settings_heart_24px.xml create mode 100644 mastodon/src/main/res/drawable/ic_volunteer_activism_24px.xml diff --git a/mastodon/build.gradle b/mastodon/build.gradle index b785c1de..902a95a6 100644 --- a/mastodon/build.gradle +++ b/mastodon/build.gradle @@ -13,7 +13,7 @@ android { applicationId "org.joinmastodon.android" minSdk 23 targetSdk 33 - versionCode 103 + versionCode 104 versionName "2.5.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/catalog/GetDonationCampaigns.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/catalog/GetDonationCampaigns.java index ebeda3f7..3ff647fd 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/api/requests/catalog/GetDonationCampaigns.java +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/catalog/GetDonationCampaigns.java @@ -1,18 +1,20 @@ package org.joinmastodon.android.api.requests.catalog; import android.net.Uri; +import android.text.TextUtils; import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.model.donations.DonationCampaign; public class GetDonationCampaigns extends MastodonAPIRequest{ - private final String locale, seed; + private final String locale, seed, source; private boolean staging; - public GetDonationCampaigns(String locale, String seed){ + public GetDonationCampaigns(String locale, String seed, String source){ super(HttpMethod.GET, null, DonationCampaign.class); this.locale=locale; this.seed=seed; + this.source=source; setCacheable(); } @@ -31,6 +33,8 @@ public class GetDonationCampaigns extends MastodonAPIRequest{ .appendQueryParameter("seed", seed); if(staging) builder.appendQueryParameter("environment", "staging"); + if(!TextUtils.isEmpty(source)) + builder.appendQueryParameter("source", source); return builder.build(); } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java index da639b12..260720c8 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/HomeTimelineFragment.java @@ -116,9 +116,8 @@ public class HomeTimelineFragment extends StatusListFragment implements ToolbarD super.onCreate(savedInstanceState); localTimelineBannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.LOCAL_TIMELINE, accountID); - // TODO how often do we do this request? Maybe cache something somewhere? if(AccountSessionManager.get(accountID).isEligibleForDonations()){ - GetDonationCampaigns req=new GetDonationCampaigns(Locale.getDefault().toLanguageTag().replace('-', '_'), String.valueOf(AccountSessionManager.get(accountID).getDonationSeed())); + GetDonationCampaigns req=new GetDonationCampaigns(Locale.getDefault().toLanguageTag().replace('-', '_'), String.valueOf(AccountSessionManager.get(accountID).getDonationSeed()), null); if(BuildConfig.DEBUG && getActivity().getSharedPreferences("debug", Context.MODE_PRIVATE).getBoolean("donationsStaging", false)){ req.setStaging(true); } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/SettingsMainFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/SettingsMainFragment.java index bb5a806d..ab9a5ab3 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/SettingsMainFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/settings/SettingsMainFragment.java @@ -1,10 +1,14 @@ package org.joinmastodon.android.fragments.settings; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Toast; import com.squareup.otto.Subscribe; @@ -12,27 +16,38 @@ import org.joinmastodon.android.BuildConfig; import org.joinmastodon.android.E; import org.joinmastodon.android.MainActivity; import org.joinmastodon.android.R; +import org.joinmastodon.android.api.requests.catalog.GetDonationCampaigns; import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.events.SelfUpdateStateChangedEvent; +import org.joinmastodon.android.model.donations.DonationCampaign; import org.joinmastodon.android.model.viewmodel.ListItem; -import org.joinmastodon.android.ui.sheets.AccountSwitcherSheet; import org.joinmastodon.android.ui.M3AlertDialogBuilder; +import org.joinmastodon.android.ui.sheets.AccountSwitcherSheet; +import org.joinmastodon.android.ui.sheets.DonationSheet; +import org.joinmastodon.android.ui.sheets.DonationSuccessfulSheet; import org.joinmastodon.android.ui.utils.HideableSingleViewRecyclerAdapter; import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.updater.GithubSelfUpdater; +import java.util.ArrayList; import java.util.List; +import java.util.Locale; import androidx.recyclerview.widget.RecyclerView; import me.grishka.appkit.Nav; +import me.grishka.appkit.api.Callback; +import me.grishka.appkit.api.ErrorResponse; import me.grishka.appkit.utils.MergeRecyclerAdapter; public class SettingsMainFragment extends BaseSettingsFragment{ + private static final int DONATION_RESULT=433; + private boolean loggedOut; private HideableSingleViewRecyclerAdapter bannerAdapter; private Button updateButton1, updateButton2; private TextView updateText; + private DonationSheet donationSheet; private Runnable updateDownloadProgressUpdater=new Runnable(){ @Override public void run(){ @@ -49,21 +64,26 @@ public class SettingsMainFragment extends BaseSettingsFragment{ super.onCreate(savedInstanceState); setTitle(R.string.settings); setSubtitle(AccountSessionManager.get(accountID).getFullUsername()); - onDataLoaded(List.of( + ArrayList> items=new ArrayList<>(); + if(BuildConfig.DEBUG || BuildConfig.BUILD_TYPE.equals("appcenterPrivateBeta")){ + items.add(new ListItem<>("Debug settings", null, R.drawable.ic_settings_24px, i->Nav.go(getActivity(), SettingsDebugFragment.class, makeFragmentArgs()), null, 0, true)); + } + items.addAll(List.of( new ListItem<>(R.string.settings_behavior, 0, R.drawable.ic_settings_24px, this::onBehaviorClick), new ListItem<>(R.string.settings_display, 0, R.drawable.ic_style_24px, this::onDisplayClick), new ListItem<>(R.string.settings_privacy, 0, R.drawable.ic_privacy_tip_24px, this::onPrivacyClick), new ListItem<>(R.string.settings_filters, 0, R.drawable.ic_filter_alt_24px, this::onFiltersClick), new ListItem<>(R.string.settings_notifications, 0, R.drawable.ic_notifications_24px, this::onNotificationsClick), new ListItem<>(AccountSessionManager.get(accountID).domain, getString(R.string.settings_server_explanation), R.drawable.ic_dns_24px, this::onServerClick), - new ListItem<>(getString(R.string.about_app, getString(R.string.app_name)), null, R.drawable.ic_info_24px, this::onAboutClick, null, 0, true), - new ListItem<>(R.string.manage_accounts, 0, R.drawable.ic_switch_account_24px, this::onManageAccountsClick), - new ListItem<>(R.string.log_out, 0, R.drawable.ic_logout_24px, this::onLogOutClick, R.attr.colorM3Error, false) + new ListItem<>(getString(R.string.about_app, getString(R.string.app_name)), null, R.drawable.ic_info_24px, this::onAboutClick, null, 0, true) )); - - if(BuildConfig.DEBUG || BuildConfig.BUILD_TYPE.equals("appcenterPrivateBeta")){ - data.add(0, new ListItem<>("Debug settings", null, R.drawable.ic_settings_24px, i->Nav.go(getActivity(), SettingsDebugFragment.class, makeFragmentArgs()), null, 0, true)); + if(AccountSessionManager.get(accountID).isEligibleForDonations()){ + items.add(new ListItem<>(R.string.settings_donate, 0, R.drawable.ic_volunteer_activism_24px, this::onDonateClick)); + items.add(new ListItem<>(R.string.settings_manage_donations, 0, R.drawable.ic_settings_heart_24px, this::onManageDonationClick, 0, true)); } + items.add(new ListItem<>(R.string.manage_accounts, 0, R.drawable.ic_switch_account_24px, this::onManageAccountsClick)); + items.add(new ListItem<>(R.string.log_out, 0, R.drawable.ic_logout_24px, this::onLogOutClick, R.attr.colorM3Error, false)); + onDataLoaded(items); AccountSession session=AccountSessionManager.get(accountID); session.reloadPreferences(null); @@ -117,6 +137,17 @@ public class SettingsMainFragment extends BaseSettingsFragment{ } } + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data){ + if(requestCode==DONATION_RESULT){ + if(donationSheet!=null) + donationSheet.dismissWithoutAnimation(); + if(resultCode==Activity.RESULT_OK){ + new DonationSuccessfulSheet(getActivity(), accountID, data.getStringExtra("postText")).showWithoutAnimation(); + } + } + } + private Bundle makeFragmentArgs(){ Bundle args=new Bundle(); args.putString("account", accountID); @@ -167,6 +198,39 @@ public class SettingsMainFragment extends BaseSettingsFragment{ .show(); } + private void onDonateClick(ListItem item){ + GetDonationCampaigns req=new GetDonationCampaigns(Locale.getDefault().toLanguageTag().replace('-', '_'), String.valueOf(AccountSessionManager.get(accountID).getDonationSeed()), null); + if(BuildConfig.DEBUG && getActivity().getSharedPreferences("debug", Context.MODE_PRIVATE).getBoolean("donationsStaging", false)){ + req.setStaging(true); + } + req.setCallback(new Callback<>(){ + @Override + public void onSuccess(DonationCampaign result){ + Activity activity=getActivity(); + if(activity==null) + return; + if(result==null){ + Toast.makeText(activity, "No campaign available (server misconfiguration?)", Toast.LENGTH_SHORT).show(); + return; + } + donationSheet=new DonationSheet(getActivity(), result, accountID, intent->startActivityForResult(intent, DONATION_RESULT)); + donationSheet.setOnDismissListener(dialog->donationSheet=null); + donationSheet.show(); + } + + @Override + public void onError(ErrorResponse error){ + error.showToast(getActivity()); + } + }) + .wrapProgress(getActivity(), R.string.loading, true) + .execNoAuth(""); + } + + private void onManageDonationClick(ListItem item){ + UiUtils.launchWebBrowser(getActivity(), "https://sponsor.staging.joinmastodon.org/donate/manage"); + } + @Subscribe public void onSelfUpdateStateChanged(SelfUpdateStateChangedEvent ev){ updateUpdateBanner(); diff --git a/mastodon/src/main/res/drawable/ic_settings_heart_24px.xml b/mastodon/src/main/res/drawable/ic_settings_heart_24px.xml new file mode 100644 index 00000000..4d652777 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_settings_heart_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/mastodon/src/main/res/drawable/ic_volunteer_activism_24px.xml b/mastodon/src/main/res/drawable/ic_volunteer_activism_24px.xml new file mode 100644 index 00000000..5a95829b --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_volunteer_activism_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/mastodon/src/main/res/values/strings.xml b/mastodon/src/main/res/values/strings.xml index d022d184..525e3dd3 100644 --- a/mastodon/src/main/res/values/strings.xml +++ b/mastodon/src/main/res/values/strings.xml @@ -775,4 +775,6 @@ Thank you for your contribution! You should receive an email confirming your donation soon. We are sorry, an error occurred and we have not been able to process your donation.\n\nPlease retry in a few minutes. + Donate to Mastodon + Manage donations \ No newline at end of file