Some changes

This commit is contained in:
Thomas 2021-01-06 19:23:44 +01:00
parent 761abc013f
commit 6d70bd758a
11 changed files with 324 additions and 97 deletions

1
.gitignore vendored
View File

@ -12,3 +12,4 @@
/app/google_full/ /app/google_full/
/app/google_acad/ /app/google_acad/
/app/src/google_donation/res/values/data.xml /app/src/google_donation/res/values/data.xml
/keystore.properties

View File

@ -1,7 +1,21 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: "androidx.navigation.safeargs" apply plugin: "androidx.navigation.safeargs"
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android { android {
signingConfigs {
full_version {
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
keyPassword keystoreProperties['keyPassword']
keyAlias keystoreProperties['keyAlias']
}
}
compileSdkVersion 30 compileSdkVersion 30
buildToolsVersion "30.0.2" buildToolsVersion "30.0.2"
@ -22,6 +36,7 @@ android {
release { release {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.full_version
} }
} }
compileOptions { compileOptions {
@ -200,7 +215,7 @@ dependencies {
implementation 'com.fasterxml.jackson.core:jackson-core:2.12.0' implementation 'com.fasterxml.jackson.core:jackson-core:2.12.0'
implementation 'org.slf4j:slf4j-simple:1.7.30' implementation 'org.slf4j:slf4j-simple:1.7.30'
google_fullImplementation 'com.anjlab.android.iab.v3:library:1.0.44' google_fullImplementation "com.android.billingclient:billing:3.0.2"
fdroid_peertube_apps_educImplementation 'org.matomo.sdk:tracker:4.1.2' fdroid_peertube_apps_educImplementation 'org.matomo.sdk:tracker:4.1.2'
google_peertube_apps_educImplementation 'org.matomo.sdk:tracker:4.1.2' google_peertube_apps_educImplementation 'org.matomo.sdk:tracker:4.1.2'

View File

@ -14,11 +14,12 @@ package app.fedilab.fedilabtube;
* You should have received a copy of the GNU General Public License along with TubeLab; if not, * You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */ * see <http://www.gnu.org/licenses>. */
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
@ -26,23 +27,39 @@ import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import com.anjlab.android.iab.v3.BillingProcessor; import com.android.billingclient.api.BillingClient;
import com.anjlab.android.iab.v3.TransactionDetails; import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetailsParams;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import app.fedilab.fedilabtube.databinding.ActivityDonationBinding; import app.fedilab.fedilabtube.databinding.ActivityDonationBinding;
import app.fedilab.fedilabtube.fragment.MySubscriptionDonationsFragment;
import app.fedilab.fedilabtube.fragment.DonationsFragment; import app.fedilab.fedilabtube.fragment.DonationsFragment;
import app.fedilab.fedilabtube.fragment.MyDonationsFragment;
public class DonationActivity extends AppCompatActivity implements BillingProcessor.IBillingHandler { public class DonationActivity extends AppCompatActivity implements PurchasesUpdatedListener {
BillingProcessor bp;
DonationsFragment donationsFragment; DonationsFragment donationsFragment;
MyDonationsFragment myDonationsFragment; DonationsFragment subscriptionDonationsFragment;
MySubscriptionDonationsFragment mySubscriptionDonationsFragment;
private ActivityDonationBinding binding; private ActivityDonationBinding binding;
private BillingClient billingClient;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -50,16 +67,87 @@ public class DonationActivity extends AppCompatActivity implements BillingProces
binding = ActivityDonationBinding.inflate(getLayoutInflater()); binding = ActivityDonationBinding.inflate(getLayoutInflater());
View view = binding.getRoot(); View view = binding.getRoot();
setContentView(view); setContentView(view);
bp = new BillingProcessor(this, getString(R.string.google_key), this); billingClient = BillingClient.newBuilder(this)
bp.initialize(); .setListener(this)
.enablePendingPurchases()
.build();
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(@NotNull BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
donationsFragment.initialized(billingClient);
subscriptionDonationsFragment.initialized(billingClient);
Purchase.PurchasesResult purchasesResult = billingClient.queryPurchases(BillingClient.SkuType.SUBS);
List<Purchase> purchases = purchasesResult.getPurchasesList();
List<String> isSubscriptions = new ArrayList<>();
if (purchases != null) {
for (Purchase purchase : purchases) {
try {
JSONObject purchaseJson = new JSONObject(purchase.getOriginalJson());
String productId = purchaseJson.getString("productId");
isSubscriptions.add(productId);
} catch (JSONException e) {
e.printStackTrace();
}
}
SkuDetailsParams.Builder paramsSub = SkuDetailsParams.newBuilder();
paramsSub.setSkusList(isSubscriptions).setType(BillingClient.SkuType.SUBS);
billingClient.querySkuDetailsAsync(paramsSub.build(),
(billingResult2, skuDetailsList) -> mySubscriptionDonationsFragment.initialized(skuDetailsList, billingClient));
} else {
mySubscriptionDonationsFragment.initialized(new ArrayList<>(), billingClient);
}
purchasesResult = billingClient.queryPurchases(BillingClient.SkuType.INAPP);
purchases = purchasesResult.getPurchasesList();
if (purchases != null) {
for (Purchase purchase : purchases) {
if (!purchase.isAutoRenewing()) {
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
ConsumeResponseListener listener = (billingResult1, purchaseToken) -> {
if (billingResult1.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// Handle the success of the consume operation.
}
};
billingClient.consumeAsync(consumeParams, listener);
}
}
}
}
}
@Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});
if (getSupportActionBar() != null) if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
donationsFragment = new DonationsFragment(); donationsFragment = new DonationsFragment();
myDonationsFragment = new MyDonationsFragment(); Bundle bundle1 = new Bundle();
bundle1.putSerializable("isSubscriptions", false);
donationsFragment.setArguments(bundle1);
binding.tablayout.addTab(binding.tablayout.newTab().setText(getString(R.string.donate)));
binding.tablayout.addTab(binding.tablayout.newTab().setText(getString(R.string.my_donations))); subscriptionDonationsFragment = new DonationsFragment();
binding.viewpager.setOffscreenPageLimit(2); Bundle bundle2 = new Bundle();
bundle2.putSerializable("isSubscriptions", true);
subscriptionDonationsFragment.setArguments(bundle2);
mySubscriptionDonationsFragment = new MySubscriptionDonationsFragment();
binding.tablayout.addTab(binding.tablayout.newTab().setText(getString(R.string.one_time)));
binding.tablayout.addTab(binding.tablayout.newTab().setText(getString(R.string.subscriptions)));
binding.tablayout.addTab(binding.tablayout.newTab().setText(getString(R.string.my_subscriptions)));
binding.viewpager.setOffscreenPageLimit(3);
PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
binding.viewpager.setAdapter(mPagerAdapter); binding.viewpager.setAdapter(mPagerAdapter);
@ -110,33 +198,38 @@ public class DonationActivity extends AppCompatActivity implements BillingProces
} }
@Override @Override
public void onProductPurchased(@NotNull String productId, TransactionDetails details) { public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases) {
String message;
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& purchases != null) {
for (Purchase purchase : purchases) {
if (!purchase.isAutoRenewing()) {
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
} ConsumeResponseListener listener = (billingResult1, purchaseToken) -> {
if (billingResult1.getResponseCode() == BillingClient.BillingResponseCode.OK) {
@Override // Handle the success of the consume operation.
public void onPurchaseHistoryRestored() { }
};
} billingClient.consumeAsync(consumeParams, listener);
}
@Override }
public void onBillingError(int errorCode, Throwable error) { message = getString(R.string.donation_succeeded_null);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
} message = getString(R.string.donation_cancelled);
} else {
@Override message = getString(R.string.toast_error);
public void onBillingInitialized() {
donationsFragment.initialized(bp);
myDonationsFragment.initialized(bp);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (!bp.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
} }
View parentLayout = findViewById(android.R.id.content);
Snackbar snackbar = Snackbar.make(parentLayout, message, Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.close, view -> snackbar.dismiss());
snackbar.show();
} }
/** /**
* Pager adapter for the 2 fragments * Pager adapter for the 2 fragments
*/ */
@ -151,15 +244,17 @@ public class DonationActivity extends AppCompatActivity implements BillingProces
public Fragment getItem(int position) { public Fragment getItem(int position) {
if (position == 0) { if (position == 0) {
return donationsFragment; return donationsFragment;
} else if (position == 1) {
return subscriptionDonationsFragment;
} else { } else {
return myDonationsFragment; return mySubscriptionDonationsFragment;
} }
} }
@Override @Override
public int getCount() { public int getCount() {
return 2; return 3;
} }
} }
} }

View File

@ -21,26 +21,29 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.anjlab.android.iab.v3.BillingProcessor; import com.android.billingclient.api.BillingClient;
import com.anjlab.android.iab.v3.SkuDetails; import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.SkuDetails;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import app.fedilab.fedilabtube.DonationActivity; import app.fedilab.fedilabtube.DonationActivity;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.databinding.DrawerDonationBinding; import app.fedilab.fedilabtube.databinding.DrawerDonationBinding;
import app.fedilab.fedilabtube.helper.Helper;
public class DonationButtonAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class DonationButtonAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<String> items; private final List<SkuDetails> skuDetails;
private final BillingProcessor billingProcessor; private final BillingClient billingClient;
private Context context; private Context context;
private final boolean isSubscription;
public DonationButtonAdapter(List<String> items, BillingProcessor billingProcessor) { public DonationButtonAdapter(List<SkuDetails> skuDetails, BillingClient billingClient, boolean subscription) {
this.items = items; this.isSubscription = subscription;
this.billingProcessor = billingProcessor; this.skuDetails = skuDetails;
this.billingClient = billingClient;
} }
@NonNull @NonNull
@ -54,19 +57,27 @@ public class DonationButtonAdapter extends RecyclerView.Adapter<RecyclerView.Vie
@Override @Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
final ViewHolder holder = (ViewHolder) viewHolder; final ViewHolder holder = (ViewHolder) viewHolder;
String item = items.get(position); SkuDetails skuDetail = skuDetails.get(position);
String product_item = "tubelab_donation_" + item; String currency = skuDetail.getPriceCurrencyCode();
SkuDetails skuDetails = billingProcessor.getPurchaseListingDetails(product_item); String price = skuDetail.getPrice();
String currency = skuDetails.currency; if (isSubscription) {
Double price = skuDetails.priceValue; holder.binding.buttonDonation.setText(String.format(Locale.getDefault(), "%s %s / %s", price, currency, context.getString(R.string.month)));
holder.binding.buttonDonation.setText(String.format(Locale.getDefault(), "%.2f %s", price, currency)); } else {
holder.binding.buttonDonation.setOnClickListener(v -> billingProcessor.purchase((DonationActivity) context, product_item)); holder.binding.buttonDonation.setText(String.format(Locale.getDefault(), "%s %s", price, currency));
}
holder.binding.buttonDonation.setOnClickListener(v -> {
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetail)
.build();
billingClient.launchBillingFlow((DonationActivity) context, billingFlowParams);
});
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return items.size(); return skuDetails.size();
} }
static class ViewHolder extends RecyclerView.ViewHolder { static class ViewHolder extends RecyclerView.ViewHolder {

View File

@ -21,60 +21,61 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.anjlab.android.iab.v3.BillingProcessor; import com.android.billingclient.api.BillingClient;
import com.anjlab.android.iab.v3.SkuDetails; import com.android.billingclient.api.SkuDetails;
import java.util.List; import java.util.List;
import java.util.Locale;
import app.fedilab.fedilabtube.DonationActivity; import app.fedilab.fedilabtube.databinding.DrawerMyDonationBinding;
import app.fedilab.fedilabtube.databinding.DrawerDonationBinding;
import app.fedilab.fedilabtube.helper.Helper;
public class DonationHistoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class DonationHistoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<SkuDetails> items; private final List<SkuDetails> skuDetailsList;
private final BillingProcessor billingProcessor; private final BillingClient billingClient;
private Context context; private Context context;
public DonationHistoryAdapter(List<SkuDetails> items, BillingProcessor billingProcessor) { public DonationHistoryAdapter(List<SkuDetails> SkuDetailsList, BillingClient billingClient) {
this.items = items; this.skuDetailsList = SkuDetailsList;
this.billingProcessor = billingProcessor; this.billingClient = billingClient;
} }
@NonNull @NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext(); context = parent.getContext();
DrawerDonationBinding itemBinding = DrawerDonationBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); DrawerMyDonationBinding itemBinding = DrawerMyDonationBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new ViewHolder(itemBinding); return new ViewHolder(itemBinding);
} }
@Override @Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
final ViewHolder holder = (ViewHolder) viewHolder; final ViewHolder holder = (ViewHolder) viewHolder;
SkuDetails item = items.get(position); SkuDetails skuDetails = skuDetailsList.get(position);
String product_item = "tubelab_donation_" + item; holder.binding.productTitle.setText(skuDetails.getTitle());
SkuDetails skuDetails = billingProcessor.getPurchaseListingDetails(product_item); holder.binding.productName.setText(skuDetails.getDescription());
String currency = skuDetails.currency; holder.binding.productInfo.setText(skuDetails.getOriginalPrice());
Double price = skuDetails.priceValue; holder.binding.cancelDonation.setOnClickListener(v -> {
holder.binding.buttonDonation.setText(String.format(Locale.getDefault(), "%.2f %s", price, currency));
holder.binding.buttonDonation.setOnClickListener(v -> billingProcessor.purchase((DonationActivity) context, product_item)); });
} }
@Override @Override
public int getItemCount() { public int getItemCount() {
return items.size(); return skuDetailsList.size();
} }
static class ViewHolder extends RecyclerView.ViewHolder { static class ViewHolder extends RecyclerView.ViewHolder {
DrawerDonationBinding binding; DrawerMyDonationBinding binding;
ViewHolder(DrawerDonationBinding itemView) { ViewHolder(DrawerMyDonationBinding itemView) {
super(itemView.getRoot()); super(itemView.getRoot());
binding = itemView; binding = itemView;
} }
} }
} }

View File

@ -24,14 +24,17 @@ import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import com.anjlab.android.iab.v3.BillingProcessor; import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.SkuDetailsParams;
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 app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.databinding.FragmentDonationsBinding; import app.fedilab.fedilabtube.databinding.FragmentDonationsBinding;
import app.fedilab.fedilabtube.drawable.DonationButtonAdapter; import app.fedilab.fedilabtube.drawable.DonationButtonAdapter;
import app.fedilab.fedilabtube.helper.Helper;
public class DonationsFragment extends Fragment { public class DonationsFragment extends Fragment {
@ -40,25 +43,52 @@ public class DonationsFragment extends Fragment {
private FragmentDonationsBinding binding; private FragmentDonationsBinding binding;
private View rootView; private View rootView;
private Context context; private Context context;
private boolean isSubscriptions;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = FragmentDonationsBinding.inflate(LayoutInflater.from(context)); binding = FragmentDonationsBinding.inflate(LayoutInflater.from(context));
rootView = binding.getRoot(); rootView = binding.getRoot();
context = getContext(); context = getContext();
Bundle bundle = this.getArguments();
if (bundle != null) {
isSubscriptions = bundle.getBoolean("isSubscriptions", false);
}
int donationText;
if (isSubscriptions) {
donationText = R.string.recurrent_donation_text;
} else {
donationText = R.string.one_time_donation_text;
}
binding.donationText.setText(donationText);
binding.loader.setVisibility(View.VISIBLE); binding.loader.setVisibility(View.VISIBLE);
binding.lvProducts.setVisibility(View.GONE); binding.lvProducts.setVisibility(View.GONE);
return rootView; return rootView;
} }
public void initialized(BillingProcessor bp) { public void initialized(BillingClient bc) {
binding.loader.setVisibility(View.GONE);
binding.lvProducts.setVisibility(View.VISIBLE);
List<String> donationsList = new ArrayList<>(); List<String> donationsList = new ArrayList<>();
Collections.addAll(donationsList, donations); for (String val : donations) {
DonationButtonAdapter donationButtonAdapter = new DonationButtonAdapter(donationsList, bp); donationsList.add("tubelab_donation_" + val + (isSubscriptions ? "_s" : ""));
binding.lvProducts.setAdapter(donationButtonAdapter); }
binding.lvProducts.setLayoutManager(new LinearLayoutManager(context)); SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
if (isSubscriptions) {
params.setSkusList(donationsList).setType(BillingClient.SkuType.SUBS);
} else {
params.setSkusList(donationsList).setType(BillingClient.SkuType.INAPP);
}
bc.querySkuDetailsAsync(params.build(),
(billingResult, skuDetailsList) -> {
binding.loader.setVisibility(View.GONE);
binding.lvProducts.setVisibility(View.VISIBLE);
DonationButtonAdapter donationButtonAdapter = new DonationButtonAdapter(skuDetailsList, bc, isSubscriptions);
binding.lvProducts.setAdapter(donationButtonAdapter);
binding.lvProducts.setLayoutManager(new LinearLayoutManager(context));
});
} }
@Override @Override

View File

@ -24,20 +24,21 @@ import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import com.anjlab.android.iab.v3.BillingProcessor; import com.android.billingclient.api.BillingClient;
import com.anjlab.android.iab.v3.SkuDetails; import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.SkuDetails;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import app.fedilab.fedilabtube.databinding.FragmentMyDonationsBinding; import app.fedilab.fedilabtube.databinding.FragmentMyDonationsBinding;
import app.fedilab.fedilabtube.drawable.DonationHistoryAdapter; import app.fedilab.fedilabtube.drawable.DonationHistoryAdapter;
import app.fedilab.fedilabtube.helper.Helper;
import static app.fedilab.fedilabtube.fragment.DonationsFragment.donations; import static app.fedilab.fedilabtube.fragment.DonationsFragment.donations;
public class MyDonationsFragment extends Fragment { public class MySubscriptionDonationsFragment extends Fragment {
private FragmentMyDonationsBinding binding; private FragmentMyDonationsBinding binding;
private View rootView; private View rootView;
@ -54,15 +55,14 @@ public class MyDonationsFragment extends Fragment {
return rootView; return rootView;
} }
public void initialized(BillingProcessor bp) { public void initialized(List<SkuDetails> skuDetailsList, BillingClient bc) {
binding.loader.setVisibility(View.GONE); binding.loader.setVisibility(View.GONE);
binding.lvPurchases.setVisibility(View.VISIBLE); binding.lvPurchases.setVisibility(View.VISIBLE);
ArrayList<String> donationsList = new ArrayList<>();
Collections.addAll(donationsList, donations); DonationHistoryAdapter donationHistoryAdapter = new DonationHistoryAdapter(skuDetailsList, bc);
List<SkuDetails> skuDetailsList = bp.getPurchaseListingDetails(donationsList);
DonationHistoryAdapter donationHistoryAdapter = new DonationHistoryAdapter(skuDetailsList, bp);
binding.lvPurchases.setAdapter(donationHistoryAdapter); binding.lvPurchases.setAdapter(donationHistoryAdapter);
binding.lvPurchases.setLayoutManager(new LinearLayoutManager(context)); binding.lvPurchases.setLayoutManager(new LinearLayoutManager(context));
} }
@Override @Override

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<TextView
android:id="@+id/product_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="16sp"
app:layout_constraintEnd_toStartOf="@+id/cancel_donation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/product_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toStartOf="@+id/cancel_donation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/product_title" />
<TextView
android:id="@+id/product_info"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toStartOf="@+id/cancel_donation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/product_name" />
<ImageButton
android:id="@+id/cancel_donation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/cancel"
android:src="@drawable/ic_baseline_delete_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

View File

@ -30,7 +30,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="20dp" android:layout_margin="20dp"
android:gravity="center" android:gravity="center"
android:text="@string/donation_text" /> android:id="@+id/donation_text" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/lv_products" android:id="@+id/lv_products"

View File

@ -457,9 +457,16 @@
<string name="remote_account_from"><b>%1$s</b> remote account connected with the app.\n\nYou can proceed to some limited actions.</string> <string name="remote_account_from"><b>%1$s</b> remote account connected with the app.\n\nYou can proceed to some limited actions.</string>
<string name="donate">Donate</string> <string name="donate">Donate</string>
<string name="my_donations">My donations</string> <string name="my_donations">My donations</string>
<string name="donation_text">Here, you can make a donation for supporting the development of the app. This action will not bring extra features!</string> <string name="one_time_donation_text">Here, you can make a one time donation for supporting the development of the app. This action will not bring extra features!</string>
<string name="recurrent_donation_text">Here, you can make a recurrent donation for supporting the development of the app. This action will not bring extra features!</string>
<string name="make_a_donation">Make a donation</string> <string name="make_a_donation">Make a donation</string>
<string name="donations_description">Here you will find the list of donations made to the app! Thank you!</string> <string name="donations_description">Here you will find the list of your recurrent donations made to support the development of the app! Thank you!</string>
<string name="support_the_app">Support the app</string> <string name="support_the_app">Support the app</string>
<string name="donation_cancelled">Donation has been cancelled!</string>
<string name="donation_succeeded_null">Thank you for your donation!</string>
<string name="donation_succeeded">Thank you for your donation of %1$s!</string>
<string name="one_time">One time</string>
<string name="my_subscriptions">My subscription</string>
<string name="month">Month</string>
</resources> </resources>

View File

@ -20,7 +20,19 @@ apply plugin: 'de.undercouch.download'
group='com.github.TorrentStream' group='com.github.TorrentStream'
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android { android {
signingConfigs {
full_version {
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
}
}
compileSdkVersion 30 compileSdkVersion 30
defaultConfig { defaultConfig {
@ -32,6 +44,7 @@ android {
release { release {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.full_version
} }
} }