From 816c9360cd5884ec76bbf17b5b42ff3a59ac5742 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Mon, 22 Jul 2024 16:42:36 -0300 Subject: [PATCH] Implement backup receipt generation. --- .../RemoteBackupsPaymentHistoryFragment.kt | 48 ++++++-- .../RemoteBackupsPaymentHistoryRepository.kt | 6 +- .../RemoteBackupsPaymentHistoryState.kt | 5 +- .../RemoteBackupsPaymentHistoryViewModel.kt | 8 ++ .../OneTimeInAppPaymentRepository.kt | 12 +- .../receipts/ReceiptImageRenderer.kt | 109 +++++++++++++++++ .../detail/DonationReceiptDetailFragment.kt | 112 ++++-------------- .../detail/DonationReceiptDetailRepository.kt | 6 +- .../detail/DonationReceiptDetailState.kt | 4 +- .../detail/DonationReceiptDetailViewModel.kt | 6 +- .../receipts/list/DonationReceiptBadge.kt | 4 +- .../receipts/list/DonationReceiptListItem.kt | 12 +- .../list/DonationReceiptListPageAdapter.kt | 8 +- .../list/DonationReceiptListPageFragment.kt | 14 +-- .../list/DonationReceiptListPageRepository.kt | 4 +- .../list/DonationReceiptListPageState.kt | 4 +- .../list/DonationReceiptListPageViewModel.kt | 6 +- .../list/DonationReceiptListRepository.kt | 8 +- .../database/DonationReceiptTable.kt | 18 +-- ...Record.kt => InAppPaymentReceiptRecord.kt} | 16 +-- .../jobs/ExternalLaunchDonationJob.kt | 10 +- .../jobs/InAppPaymentAuthCheckJob.kt | 6 +- .../jobs/InAppPaymentRecurringContextJob.kt | 4 +- ...SubscriptionReceiptRequestResponseJob.java | 4 +- 24 files changed, 259 insertions(+), 175 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/ReceiptImageRenderer.kt rename app/src/main/java/org/thoughtcrime/securesms/database/model/{DonationReceiptRecord.kt => InAppPaymentReceiptRecord.kt} (80%) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryFragment.kt index 6543f0230b..83b16f6944 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryFragment.kt @@ -5,6 +5,7 @@ package org.thoughtcrime.securesms.components.settings.app.chats.backups.history +import android.content.Intent import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -37,6 +38,7 @@ import androidx.navigation.navArgument import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.toPersistentList import org.signal.core.ui.Buttons +import org.signal.core.ui.Dialogs import org.signal.core.ui.Dividers import org.signal.core.ui.Previews import org.signal.core.ui.Rows @@ -45,9 +47,10 @@ import org.signal.core.ui.SignalPreview import org.signal.core.ui.Texts import org.signal.core.util.money.FiatMoney import org.thoughtcrime.securesms.R +import org.thoughtcrime.securesms.components.settings.app.subscription.receipts.ReceiptImageRenderer import org.thoughtcrime.securesms.compose.ComposeFragment import org.thoughtcrime.securesms.compose.Nav -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.payments.FiatMoneyUtil import org.thoughtcrime.securesms.util.DateUtils import java.math.BigDecimal @@ -97,18 +100,41 @@ class RemoteBackupsPaymentHistoryFragment : ComposeFragment() { PaymentHistoryDetails( record = record, onNavigationClick = onNavigationClick, - onShareClick = {} // TODO [message-backups] Generate shareable png + onShareClick = this@RemoteBackupsPaymentHistoryFragment::onShareClick ) + + if (state.displayProgressDialog) { + Dialogs.IndeterminateProgressDialog() + } } } } + + private fun onShareClick(record: InAppPaymentReceiptRecord) { + viewModel.onStartRenderingBitmap() + ReceiptImageRenderer.renderPng( + requireContext(), + viewLifecycleOwner, + record, + getString(R.string.RemoteBackupsPaymentHistoryFragment__text_and_all_media_backup), + object : ReceiptImageRenderer.Callback { + override fun onBitmapRendered() { + viewModel.onEndRenderingBitmap() + } + + override fun onStartActivity(intent: Intent) { + startActivity(intent) + } + } + ) + } } @Composable private fun PaymentHistoryContent( state: RemoteBackupsPaymentHistoryState, onNavigationClick: () -> Unit, - onRecordClick: (DonationReceiptRecord) -> Unit + onRecordClick: (InAppPaymentReceiptRecord) -> Unit ) { Scaffolds.Settings( title = stringResource(id = R.string.RemoteBackupsPaymentHistoryFragment__payment_history), @@ -158,8 +184,8 @@ private fun rememberYear(timestamp: Long): Int { @Composable private fun PaymentHistoryRow( - record: DonationReceiptRecord, - onRecordClick: (DonationReceiptRecord) -> Unit + record: InAppPaymentReceiptRecord, + onRecordClick: (InAppPaymentReceiptRecord) -> Unit ) { val date = remember(record.timestamp) { DateUtils.formatDateWithYear(Locale.getDefault(), record.timestamp) @@ -196,9 +222,9 @@ private fun PaymentHistoryRow( @Composable private fun PaymentHistoryDetails( - record: DonationReceiptRecord, + record: InAppPaymentReceiptRecord, onNavigationClick: () -> Unit, - onShareClick: () -> Unit + onShareClick: (InAppPaymentReceiptRecord) -> Unit ) { Scaffolds.Settings( title = stringResource(id = R.string.RemoteBackupsPaymentHistoryFragment__payment_details), @@ -249,7 +275,7 @@ private fun PaymentHistoryDetails( Spacer(modifier = Modifier.weight(1f)) Buttons.LargePrimary( - onClick = onShareClick, + onClick = { onShareClick(record) }, modifier = Modifier .padding(horizontal = dimensionResource(id = R.dimen.core_ui__gutter)) .padding(bottom = 24.dp) @@ -300,12 +326,12 @@ private fun PaymentDetailsContentPreview() { } } -private fun testRecord(): DonationReceiptRecord { - return DonationReceiptRecord( +private fun testRecord(): InAppPaymentReceiptRecord { + return InAppPaymentReceiptRecord( id = 1, amount = FiatMoney(BigDecimal.ONE, Currency.getInstance("USD")), timestamp = 1718739691000, - type = DonationReceiptRecord.Type.RECURRING_BACKUP, + type = InAppPaymentReceiptRecord.Type.RECURRING_BACKUP, subscriptionLevel = 201 ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryRepository.kt index 5c30b35b09..89f1655142 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryRepository.kt @@ -6,11 +6,11 @@ package org.thoughtcrime.securesms.components.settings.app.chats.backups.history import org.thoughtcrime.securesms.database.SignalDatabase -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord object RemoteBackupsPaymentHistoryRepository { - fun getReceipts(): List { - return SignalDatabase.donationReceipts.getReceipts(DonationReceiptRecord.Type.RECURRING_BACKUP) + fun getReceipts(): List { + return SignalDatabase.donationReceipts.getReceipts(InAppPaymentReceiptRecord.Type.RECURRING_BACKUP) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryState.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryState.kt index 1123025cd6..3189026113 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryState.kt @@ -8,9 +8,10 @@ package org.thoughtcrime.securesms.components.settings.app.chats.backups.history import androidx.compose.runtime.Stable import kotlinx.collections.immutable.PersistentMap import kotlinx.collections.immutable.persistentMapOf -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord @Stable data class RemoteBackupsPaymentHistoryState( - val records: PersistentMap = persistentMapOf() + val records: PersistentMap = persistentMapOf(), + val displayProgressDialog: Boolean = false ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryViewModel.kt index 02ac79cc67..9399dfbfe7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/chats/backups/history/RemoteBackupsPaymentHistoryViewModel.kt @@ -29,4 +29,12 @@ class RemoteBackupsPaymentHistoryViewModel : ViewModel() { internalStateFlow.update { state -> state.copy(records = receipts.associateBy { it.id }.toPersistentMap()) } } } + + fun onStartRenderingBitmap() { + internalStateFlow.update { it.copy(displayProgressDialog = true) } + } + + fun onEndRenderingBitmap() { + internalStateFlow.update { it.copy(displayProgressDialog = false) } + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/OneTimeInAppPaymentRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/OneTimeInAppPaymentRepository.kt index ced2d5bd7a..f6e2edbab1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/OneTimeInAppPaymentRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/OneTimeInAppPaymentRepository.kt @@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.errors.Do import org.thoughtcrime.securesms.database.InAppPaymentTable import org.thoughtcrime.securesms.database.RecipientTable import org.thoughtcrime.securesms.database.SignalDatabase -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData import org.thoughtcrime.securesms.dependencies.AppDependencies import org.thoughtcrime.securesms.jobs.InAppPaymentOneTimeContextJob @@ -106,16 +106,16 @@ class OneTimeInAppPaymentRepository(private val donationsService: DonationsServi } return Single.fromCallable { - val donationReceiptRecord = if (isBoost) { - DonationReceiptRecord.createForBoost(inAppPayment.data.amount!!.toFiatMoney()) + val inAppPaymentReceiptRecord = if (isBoost) { + InAppPaymentReceiptRecord.createForBoost(inAppPayment.data.amount!!.toFiatMoney()) } else { - DonationReceiptRecord.createForGift(inAppPayment.data.amount!!.toFiatMoney()) + InAppPaymentReceiptRecord.createForGift(inAppPayment.data.amount!!.toFiatMoney()) } - val donationTypeLabel = donationReceiptRecord.type.code.replaceFirstChar { c -> if (c.isLowerCase()) c.titlecase(Locale.US) else c.toString() } + val donationTypeLabel = inAppPaymentReceiptRecord.type.code.replaceFirstChar { c -> if (c.isLowerCase()) c.titlecase(Locale.US) else c.toString() } Log.d(TAG, "Confirmed payment intent. Recording $donationTypeLabel receipt and submitting badge reimbursement job chain.", true) - SignalDatabase.donationReceipts.addReceipt(donationReceiptRecord) + SignalDatabase.donationReceipts.addReceipt(inAppPaymentReceiptRecord) SignalDatabase.inAppPayments.update( inAppPayment = inAppPayment.copy( diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/ReceiptImageRenderer.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/ReceiptImageRenderer.kt new file mode 100644 index 0000000000..1b10052db4 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/ReceiptImageRenderer.kt @@ -0,0 +1,109 @@ +/* + * Copyright 2024 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.components.settings.app.subscription.receipts + +import android.content.ActivityNotFoundException +import android.content.Context +import android.content.Intent +import android.graphics.Bitmap +import android.net.Uri +import android.view.LayoutInflater +import android.view.View +import android.widget.TextView +import android.widget.Toast +import androidx.core.app.ShareCompat +import androidx.core.view.drawToBitmap +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.signal.core.util.logging.Log +import org.thoughtcrime.securesms.R +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord +import org.thoughtcrime.securesms.payments.FiatMoneyUtil +import org.thoughtcrime.securesms.providers.BlobProvider +import org.thoughtcrime.securesms.util.DateUtils +import java.io.ByteArrayOutputStream +import java.util.Locale + +/** + * Generates a receipt PNG for an in-app payment. + */ +object ReceiptImageRenderer { + + private const val DONATION_RECEIPT_WIDTH = 1916 + private val TAG = Log.tag(ReceiptImageRenderer::class.java) + + fun renderPng( + context: Context, + lifecycleOwner: LifecycleOwner, + record: InAppPaymentReceiptRecord, + subscriptionName: String, + callback: Callback + ) { + val today: String = DateUtils.formatDateWithDayOfWeek(Locale.getDefault(), System.currentTimeMillis()) + val amount: String = FiatMoneyUtil.format(context.resources, record.amount) + val type: String = when (record.type) { + InAppPaymentReceiptRecord.Type.RECURRING_DONATION, InAppPaymentReceiptRecord.Type.RECURRING_BACKUP -> context.getString(R.string.DonationReceiptDetailsFragment__s_dash_s, subscriptionName, context.getString(R.string.DonationReceiptListFragment__recurring)) + InAppPaymentReceiptRecord.Type.ONE_TIME_DONATION -> context.getString(R.string.DonationReceiptListFragment__one_time) + InAppPaymentReceiptRecord.Type.ONE_TIME_GIFT -> context.getString(R.string.DonationReceiptListFragment__donation_for_a_friend) + } + val datePaid: String = DateUtils.formatDate(Locale.getDefault(), record.timestamp) + + lifecycleOwner.lifecycleScope.launch { + val bitmapUri: Uri = withContext(Dispatchers.Default) { + val outputStream = ByteArrayOutputStream() + val view = LayoutInflater + .from(context) + .inflate(R.layout.donation_receipt_png, null) + + view.findViewById(R.id.date).text = today + view.findViewById(R.id.amount).text = amount + view.findViewById(R.id.donation_type).text = type + view.findViewById(R.id.date_paid).text = datePaid + + view.measure(View.MeasureSpec.makeMeasureSpec(DONATION_RECEIPT_WIDTH, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)) + view.layout(0, 0, view.measuredWidth, view.measuredHeight) + + val bitmap = view.drawToBitmap() + bitmap.compress(Bitmap.CompressFormat.PNG, 0, outputStream) + + BlobProvider.getInstance() + .forData(outputStream.toByteArray()) + .withMimeType("image/png") + .withFileName("Signal-Donation-Receipt.png") + .createForSingleSessionInMemory() + } + + withContext(Dispatchers.Main) { + callback.onBitmapRendered() + openShareSheet(context, bitmapUri, callback) + } + } + } + + private fun openShareSheet(context: Context, uri: Uri, callback: Callback) { + val mimeType = Intent.normalizeMimeType("image/png") + val shareIntent = ShareCompat.IntentBuilder(context) + .setStream(uri) + .setType(mimeType) + .createChooserIntent() + .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + + try { + callback.onStartActivity(shareIntent) + } catch (e: ActivityNotFoundException) { + Log.w(TAG, "No activity existed to share the media.", e) + Toast.makeText(context, R.string.MediaPreviewActivity_cant_find_an_app_able_to_share_this_media, Toast.LENGTH_LONG).show() + } + } + + interface Callback { + fun onBitmapRendered() + fun onStartActivity(intent: Intent) + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailFragment.kt index 0368401666..7524181308 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailFragment.kt @@ -1,32 +1,20 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.receipts.detail -import android.content.ActivityNotFoundException import android.content.Intent -import android.graphics.Bitmap -import android.net.Uri -import android.view.LayoutInflater -import android.view.View -import android.widget.TextView -import android.widget.Toast -import androidx.core.app.ShareCompat -import androidx.core.view.drawToBitmap import androidx.fragment.app.viewModels import com.google.android.material.button.MaterialButton -import org.signal.core.util.concurrent.SimpleTask -import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.SignalProgressDialog import org.thoughtcrime.securesms.components.settings.DSLConfiguration import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment import org.thoughtcrime.securesms.components.settings.DSLSettingsText +import org.thoughtcrime.securesms.components.settings.app.subscription.receipts.ReceiptImageRenderer import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.components.settings.models.SplashImage -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.payments.FiatMoneyUtil -import org.thoughtcrime.securesms.providers.BlobProvider import org.thoughtcrime.securesms.util.DateUtils import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter -import java.io.ByteArrayOutputStream import java.util.Locale class DonationReceiptDetailFragment : DSLSettingsFragment(layoutId = R.layout.donation_receipt_detail_fragment) { @@ -49,77 +37,35 @@ class DonationReceiptDetailFragment : DSLSettingsFragment(layoutId = R.layout.do sharePngButton.isEnabled = false viewModel.state.observe(viewLifecycleOwner) { state -> - if (state.donationReceiptRecord != null) { - adapter.submitList(getConfiguration(state.donationReceiptRecord, state.subscriptionName).toMappingModelList()) + if (state.inAppPaymentReceiptRecord != null) { + adapter.submitList(getConfiguration(state.inAppPaymentReceiptRecord, state.subscriptionName).toMappingModelList()) } - if (state.donationReceiptRecord != null && state.subscriptionName != null) { + if (state.inAppPaymentReceiptRecord != null && state.subscriptionName != null) { sharePngButton.isEnabled = true sharePngButton.setOnClickListener { - renderPng(state.donationReceiptRecord, state.subscriptionName) + progressDialog = SignalProgressDialog.show(requireContext()) + ReceiptImageRenderer.renderPng( + context = requireContext(), + lifecycleOwner = viewLifecycleOwner, + record = state.inAppPaymentReceiptRecord, + subscriptionName = state.subscriptionName, + callback = object : ReceiptImageRenderer.Callback { + override fun onBitmapRendered() { + progressDialog.dismiss() + } + + override fun onStartActivity(intent: Intent) { + startActivity(intent) + } + } + ) } } } } - private fun renderPng(record: DonationReceiptRecord, subscriptionName: String) { - progressDialog = SignalProgressDialog.show(requireContext()) - - val today: String = DateUtils.formatDateWithDayOfWeek(Locale.getDefault(), System.currentTimeMillis()) - val amount: String = FiatMoneyUtil.format(resources, record.amount) - val type: String = when (record.type) { - DonationReceiptRecord.Type.RECURRING_DONATION -> getString(R.string.DonationReceiptDetailsFragment__s_dash_s, subscriptionName, getString(R.string.DonationReceiptListFragment__recurring)) - DonationReceiptRecord.Type.ONE_TIME_DONATION -> getString(R.string.DonationReceiptListFragment__one_time) - DonationReceiptRecord.Type.ONE_TIME_GIFT -> getString(R.string.DonationReceiptListFragment__donation_for_a_friend) - DonationReceiptRecord.Type.RECURRING_BACKUP -> error("Not supported in this fragment") - } - val datePaid: String = DateUtils.formatDate(Locale.getDefault(), record.timestamp) - - SimpleTask.run(viewLifecycleOwner.lifecycle, { - val outputStream = ByteArrayOutputStream() - val view = LayoutInflater - .from(requireContext()) - .inflate(R.layout.donation_receipt_png, null) - - view.findViewById(R.id.date).text = today - view.findViewById(R.id.amount).text = amount - view.findViewById(R.id.donation_type).text = type - view.findViewById(R.id.date_paid).text = datePaid - - view.measure(View.MeasureSpec.makeMeasureSpec(DONATION_RECEIPT_WIDTH, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)) - view.layout(0, 0, view.measuredWidth, view.measuredHeight) - - val bitmap = view.drawToBitmap() - bitmap.compress(Bitmap.CompressFormat.PNG, 0, outputStream) - - BlobProvider.getInstance() - .forData(outputStream.toByteArray()) - .withMimeType("image/png") - .withFileName("Signal-Donation-Receipt.png") - .createForSingleSessionInMemory() - }, { - progressDialog.dismiss() - openShareSheet(it) - }) - } - - private fun openShareSheet(uri: Uri) { - val mimeType = Intent.normalizeMimeType("image/png") - val shareIntent = ShareCompat.IntentBuilder(requireContext()) - .setStream(uri) - .setType(mimeType) - .createChooserIntent() - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - - try { - startActivity(shareIntent) - } catch (e: ActivityNotFoundException) { - Log.w(TAG, "No activity existed to share the media.", e) - Toast.makeText(requireContext(), R.string.MediaPreviewActivity_cant_find_an_app_able_to_share_this_media, Toast.LENGTH_LONG).show() - } - } - - private fun getConfiguration(record: DonationReceiptRecord, subscriptionName: String?): DSLConfiguration { + private fun getConfiguration(record: InAppPaymentReceiptRecord, subscriptionName: String?): DSLConfiguration { return configure { customPref( SplashImage.Model( @@ -141,10 +87,10 @@ class DonationReceiptDetailFragment : DSLSettingsFragment(layoutId = R.layout.do title = DSLSettingsText.from(R.string.DonationReceiptDetailsFragment__donation_type), summary = DSLSettingsText.from( when (record.type) { - DonationReceiptRecord.Type.RECURRING_DONATION -> getString(R.string.DonationReceiptDetailsFragment__s_dash_s, subscriptionName, getString(R.string.DonationReceiptListFragment__recurring)) - DonationReceiptRecord.Type.ONE_TIME_DONATION -> getString(R.string.DonationReceiptListFragment__one_time) - DonationReceiptRecord.Type.ONE_TIME_GIFT -> getString(R.string.DonationReceiptListFragment__donation_for_a_friend) - DonationReceiptRecord.Type.RECURRING_BACKUP -> error("Not supported in this fragment.") + InAppPaymentReceiptRecord.Type.RECURRING_DONATION -> getString(R.string.DonationReceiptDetailsFragment__s_dash_s, subscriptionName, getString(R.string.DonationReceiptListFragment__recurring)) + InAppPaymentReceiptRecord.Type.ONE_TIME_DONATION -> getString(R.string.DonationReceiptListFragment__one_time) + InAppPaymentReceiptRecord.Type.ONE_TIME_GIFT -> getString(R.string.DonationReceiptListFragment__donation_for_a_friend) + InAppPaymentReceiptRecord.Type.RECURRING_BACKUP -> error("Not supported in this fragment.") } ) ) @@ -155,10 +101,4 @@ class DonationReceiptDetailFragment : DSLSettingsFragment(layoutId = R.layout.do ) } } - - companion object { - private const val DONATION_RECEIPT_WIDTH = 1916 - - private val TAG = Log.tag(DonationReceiptDetailFragment::class.java) - } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailRepository.kt index 44dd54d09e..86ce7fc1f8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailRepository.kt @@ -4,7 +4,7 @@ import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.schedulers.Schedulers import org.thoughtcrime.securesms.components.settings.app.subscription.getSubscriptionLevels import org.thoughtcrime.securesms.database.SignalDatabase -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.dependencies.AppDependencies import java.util.Locale @@ -22,8 +22,8 @@ class DonationReceiptDetailRepository { .subscribeOn(Schedulers.io()) } - fun getDonationReceiptRecord(id: Long): Single { - return Single.fromCallable { + fun getDonationReceiptRecord(id: Long): Single { + return Single.fromCallable { SignalDatabase.donationReceipts.getReceipt(id)!! }.subscribeOn(Schedulers.io()) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailState.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailState.kt index 4f33b592f9..6acdfdcdf3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailState.kt @@ -1,8 +1,8 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.receipts.detail -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord data class DonationReceiptDetailState( - val donationReceiptRecord: DonationReceiptRecord? = null, + val inAppPaymentReceiptRecord: InAppPaymentReceiptRecord? = null, val subscriptionName: String? = null ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailViewModel.kt index 36165d40b5..396b592db2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/detail/DonationReceiptDetailViewModel.kt @@ -7,7 +7,7 @@ import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.Disposable import io.reactivex.rxjava3.kotlin.plusAssign -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.util.InternetConnectionObserver import org.thoughtcrime.securesms.util.livedata.Store @@ -16,7 +16,7 @@ class DonationReceiptDetailViewModel(id: Long, private val repository: DonationR private val store = Store(DonationReceiptDetailState()) private val disposables = CompositeDisposable() private var networkDisposable: Disposable - private val cachedRecord: Single = repository.getDonationReceiptRecord(id).cache() + private val cachedRecord: Single = repository.getDonationReceiptRecord(id).cache() val state: LiveData = store.stateLiveData @@ -43,7 +43,7 @@ class DonationReceiptDetailViewModel(id: Long, private val repository: DonationR disposables.clear() disposables += cachedRecord.subscribe { record -> - store.update { it.copy(donationReceiptRecord = record) } + store.update { it.copy(inAppPaymentReceiptRecord = record) } } disposables += cachedRecord.flatMap { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptBadge.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptBadge.kt index e706e23cb8..6aabe8c2d4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptBadge.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptBadge.kt @@ -1,10 +1,10 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.receipts.list import org.thoughtcrime.securesms.badges.models.Badge -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord data class DonationReceiptBadge( - val type: DonationReceiptRecord.Type, + val type: InAppPaymentReceiptRecord.Type, val level: Int, val badge: Badge ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListItem.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListItem.kt index 2d2427beb3..a2337ab17f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListItem.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListItem.kt @@ -5,7 +5,7 @@ import android.widget.TextView import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.badges.BadgeImageView import org.thoughtcrime.securesms.badges.models.Badge -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.payments.FiatMoneyUtil import org.thoughtcrime.securesms.util.DateUtils import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory @@ -21,7 +21,7 @@ object DonationReceiptListItem { } class Model( - val record: DonationReceiptRecord, + val record: InAppPaymentReceiptRecord, val badge: Badge? ) : MappingModel { override fun areContentsTheSame(newItem: Model): Boolean = record == newItem.record && badge == newItem.badge @@ -42,10 +42,10 @@ object DonationReceiptListItem { dateView.text = DateUtils.formatDate(Locale.getDefault(), model.record.timestamp) typeView.setText( when (model.record.type) { - DonationReceiptRecord.Type.RECURRING_DONATION -> R.string.DonationReceiptListFragment__recurring - DonationReceiptRecord.Type.ONE_TIME_DONATION -> R.string.DonationReceiptListFragment__one_time - DonationReceiptRecord.Type.ONE_TIME_GIFT -> R.string.DonationReceiptListFragment__donation_for_a_friend - DonationReceiptRecord.Type.RECURRING_BACKUP -> error("Not supported in this fragment") + InAppPaymentReceiptRecord.Type.RECURRING_DONATION -> R.string.DonationReceiptListFragment__recurring + InAppPaymentReceiptRecord.Type.ONE_TIME_DONATION -> R.string.DonationReceiptListFragment__one_time + InAppPaymentReceiptRecord.Type.ONE_TIME_GIFT -> R.string.DonationReceiptListFragment__donation_for_a_friend + InAppPaymentReceiptRecord.Type.RECURRING_BACKUP -> error("Not supported in this fragment") } ) moneyView.text = FiatMoneyUtil.format(context.resources, model.record.amount) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageAdapter.kt index 121cd06800..93949579aa 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageAdapter.kt @@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.receipts import androidx.fragment.app.Fragment import androidx.viewpager2.adapter.FragmentStateAdapter -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord class DonationReceiptListPageAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) { override fun getItemCount(): Int = 4 @@ -10,9 +10,9 @@ class DonationReceiptListPageAdapter(fragment: Fragment) : FragmentStateAdapter( override fun createFragment(position: Int): Fragment { return when (position) { 0 -> DonationReceiptListPageFragment.create(null) - 1 -> DonationReceiptListPageFragment.create(DonationReceiptRecord.Type.RECURRING_DONATION) - 2 -> DonationReceiptListPageFragment.create(DonationReceiptRecord.Type.ONE_TIME_DONATION) - 3 -> DonationReceiptListPageFragment.create(DonationReceiptRecord.Type.ONE_TIME_GIFT) + 1 -> DonationReceiptListPageFragment.create(InAppPaymentReceiptRecord.Type.RECURRING_DONATION) + 2 -> DonationReceiptListPageFragment.create(InAppPaymentReceiptRecord.Type.ONE_TIME_DONATION) + 3 -> DonationReceiptListPageFragment.create(InAppPaymentReceiptRecord.Type.ONE_TIME_GIFT) else -> error("Unsupported position $position") } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageFragment.kt index 615b02ae27..7215e06b9a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageFragment.kt @@ -11,7 +11,7 @@ import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.badges.models.Badge import org.thoughtcrime.securesms.components.settings.DSLSettingsText import org.thoughtcrime.securesms.components.settings.TextPreference -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.util.StickyHeaderDecoration import org.thoughtcrime.securesms.util.livedata.LiveDataUtil import org.thoughtcrime.securesms.util.navigation.safeNavigate @@ -30,8 +30,8 @@ class DonationReceiptListPageFragment : Fragment(R.layout.donation_receipt_list_ } ) - private val type: DonationReceiptRecord.Type? - get() = requireArguments().getString(ARG_TYPE)?.let { DonationReceiptRecord.Type.fromCode(it) } + private val type: InAppPaymentReceiptRecord.Type? + get() = requireArguments().getString(ARG_TYPE)?.let { InAppPaymentReceiptRecord.Type.fromCode(it) } private lateinit var emptyStateGroup: Group @@ -71,10 +71,10 @@ class DonationReceiptListPageFragment : Fragment(R.layout.donation_receipt_list_ } } - private fun getBadgeForRecord(record: DonationReceiptRecord, badges: List): Badge? { + private fun getBadgeForRecord(record: InAppPaymentReceiptRecord, badges: List): Badge? { return when (record.type) { - DonationReceiptRecord.Type.ONE_TIME_DONATION -> badges.firstOrNull { it.type == DonationReceiptRecord.Type.ONE_TIME_DONATION }?.badge - DonationReceiptRecord.Type.ONE_TIME_GIFT -> badges.firstOrNull { it.type == DonationReceiptRecord.Type.ONE_TIME_GIFT }?.badge + InAppPaymentReceiptRecord.Type.ONE_TIME_DONATION -> badges.firstOrNull { it.type == InAppPaymentReceiptRecord.Type.ONE_TIME_DONATION }?.badge + InAppPaymentReceiptRecord.Type.ONE_TIME_GIFT -> badges.firstOrNull { it.type == InAppPaymentReceiptRecord.Type.ONE_TIME_GIFT }?.badge else -> badges.firstOrNull { it.level == record.subscriptionLevel }?.badge } } @@ -83,7 +83,7 @@ class DonationReceiptListPageFragment : Fragment(R.layout.donation_receipt_list_ private const val ARG_TYPE = "arg_type" - fun create(type: DonationReceiptRecord.Type?): Fragment { + fun create(type: InAppPaymentReceiptRecord.Type?): Fragment { return DonationReceiptListPageFragment().apply { arguments = Bundle().apply { putString(ARG_TYPE, type?.code) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageRepository.kt index 5a72ac62a7..48c97cd484 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageRepository.kt @@ -3,10 +3,10 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.receipts import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.schedulers.Schedulers import org.thoughtcrime.securesms.database.SignalDatabase -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord class DonationReceiptListPageRepository { - fun getRecords(type: DonationReceiptRecord.Type?): Single> { + fun getRecords(type: InAppPaymentReceiptRecord.Type?): Single> { return Single.fromCallable { SignalDatabase.donationReceipts.getReceipts(type) }.subscribeOn(Schedulers.io()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageState.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageState.kt index 93af10dbd1..eb96fb32d1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageState.kt @@ -1,8 +1,8 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.receipts.list -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord data class DonationReceiptListPageState( - val records: List = emptyList(), + val records: List = emptyList(), val isLoaded: Boolean = false ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageViewModel.kt index ecabf9a86c..21eacb337b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListPageViewModel.kt @@ -5,10 +5,10 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.kotlin.plusAssign -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.util.livedata.Store -class DonationReceiptListPageViewModel(type: DonationReceiptRecord.Type?, repository: DonationReceiptListPageRepository) : ViewModel() { +class DonationReceiptListPageViewModel(type: InAppPaymentReceiptRecord.Type?, repository: DonationReceiptListPageRepository) : ViewModel() { private val disposables = CompositeDisposable() private val store = Store(DonationReceiptListPageState()) @@ -31,7 +31,7 @@ class DonationReceiptListPageViewModel(type: DonationReceiptRecord.Type?, reposi disposables.clear() } - class Factory(private val type: DonationReceiptRecord.Type?, private val repository: DonationReceiptListPageRepository) : ViewModelProvider.Factory { + class Factory(private val type: InAppPaymentReceiptRecord.Type?, private val repository: DonationReceiptListPageRepository) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { return modelClass.cast(DonationReceiptListPageViewModel(type, repository)) as T } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListRepository.kt index e23c96550d..7c89a788e2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/receipts/list/DonationReceiptListRepository.kt @@ -5,7 +5,7 @@ import org.thoughtcrime.securesms.badges.Badges import org.thoughtcrime.securesms.components.settings.app.subscription.getBoostBadges import org.thoughtcrime.securesms.components.settings.app.subscription.getGiftBadges import org.thoughtcrime.securesms.components.settings.app.subscription.getSubscriptionLevels -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.dependencies.AppDependencies import java.util.Locale @@ -17,13 +17,13 @@ class DonationReceiptListRepository { }.map { response -> if (response.result.isPresent) { val config = response.result.get() - val boostBadge = DonationReceiptBadge(DonationReceiptRecord.Type.ONE_TIME_DONATION, -1, config.getBoostBadges().first()) - val giftBadge = DonationReceiptBadge(DonationReceiptRecord.Type.ONE_TIME_GIFT, -1, config.getGiftBadges().first()) + val boostBadge = DonationReceiptBadge(InAppPaymentReceiptRecord.Type.ONE_TIME_DONATION, -1, config.getBoostBadges().first()) + val giftBadge = DonationReceiptBadge(InAppPaymentReceiptRecord.Type.ONE_TIME_GIFT, -1, config.getGiftBadges().first()) val subBadges = config.getSubscriptionLevels().map { DonationReceiptBadge( level = it.key, badge = Badges.fromServiceBadge(it.value.badge), - type = DonationReceiptRecord.Type.RECURRING_DONATION + type = InAppPaymentReceiptRecord.Type.RECURRING_DONATION ) } subBadges + boostBadge + giftBadge diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/DonationReceiptTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/DonationReceiptTable.kt index 161e8dde9d..4439c6f370 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/DonationReceiptTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/DonationReceiptTable.kt @@ -6,7 +6,7 @@ import androidx.core.content.contentValuesOf import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil import org.signal.core.util.money.FiatMoney -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import java.math.BigDecimal import java.util.Currency @@ -46,7 +46,7 @@ class DonationReceiptTable(context: Context, databaseHelper: SignalDatabase) : D } } - fun addReceipt(record: DonationReceiptRecord) { + fun addReceipt(record: InAppPaymentReceiptRecord) { require(record.id == -1L) val values = contentValuesOf( @@ -60,7 +60,7 @@ class DonationReceiptTable(context: Context, databaseHelper: SignalDatabase) : D writableDatabase.insert(TABLE_NAME, null, values) } - fun getReceipt(id: Long): DonationReceiptRecord? { + fun getReceipt(id: Long): InAppPaymentReceiptRecord? { readableDatabase.query(TABLE_NAME, null, ID_WHERE, SqlUtil.buildArgs(id), null, null, null).use { cursor -> return if (cursor.moveToNext()) { readRecord(cursor) @@ -70,15 +70,15 @@ class DonationReceiptTable(context: Context, databaseHelper: SignalDatabase) : D } } - fun getReceipts(type: DonationReceiptRecord.Type?): List { + fun getReceipts(type: InAppPaymentReceiptRecord.Type?): List { val (where, whereArgs) = if (type != null) { "$TYPE = ?" to SqlUtil.buildArgs(type.code) } else { - "$TYPE != ?" to SqlUtil.buildArgs(DonationReceiptRecord.Type.RECURRING_DONATION) + "$TYPE != ?" to SqlUtil.buildArgs(InAppPaymentReceiptRecord.Type.RECURRING_DONATION) } readableDatabase.query(TABLE_NAME, null, where, whereArgs, null, null, "$DATE DESC").use { cursor -> - val results = ArrayList(cursor.count) + val results = ArrayList(cursor.count) while (cursor.moveToNext()) { results.add(readRecord(cursor)) } @@ -87,10 +87,10 @@ class DonationReceiptTable(context: Context, databaseHelper: SignalDatabase) : D } } - private fun readRecord(cursor: Cursor): DonationReceiptRecord { - return DonationReceiptRecord( + private fun readRecord(cursor: Cursor): InAppPaymentReceiptRecord { + return InAppPaymentReceiptRecord( id = CursorUtil.requireLong(cursor, ID), - type = DonationReceiptRecord.Type.fromCode(CursorUtil.requireString(cursor, TYPE)), + type = InAppPaymentReceiptRecord.Type.fromCode(CursorUtil.requireString(cursor, TYPE)), amount = FiatMoney( BigDecimal(CursorUtil.requireString(cursor, AMOUNT)), Currency.getInstance(CursorUtil.requireString(cursor, CURRENCY)) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/DonationReceiptRecord.kt b/app/src/main/java/org/thoughtcrime/securesms/database/model/InAppPaymentReceiptRecord.kt similarity index 80% rename from app/src/main/java/org/thoughtcrime/securesms/database/model/DonationReceiptRecord.kt rename to app/src/main/java/org/thoughtcrime/securesms/database/model/InAppPaymentReceiptRecord.kt index 858bbd76b7..fe509b873f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/DonationReceiptRecord.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/InAppPaymentReceiptRecord.kt @@ -5,7 +5,7 @@ import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration import java.util.Currency -data class DonationReceiptRecord( +data class InAppPaymentReceiptRecord( val id: Long = -1L, val amount: FiatMoney, val timestamp: Long, @@ -20,18 +20,18 @@ data class DonationReceiptRecord( companion object { fun fromCode(code: String): Type { - return values().first { it.code == code } + return entries.first { it.code == code } } } } companion object { @JvmStatic - fun createForSubscription(subscription: ActiveSubscription.Subscription): DonationReceiptRecord { + fun createForSubscription(subscription: ActiveSubscription.Subscription): InAppPaymentReceiptRecord { val activeCurrency = Currency.getInstance(subscription.currency) val activeAmount = subscription.amount.movePointLeft(activeCurrency.defaultFractionDigits) - return DonationReceiptRecord( + return InAppPaymentReceiptRecord( id = -1L, amount = FiatMoney(activeAmount, activeCurrency), timestamp = System.currentTimeMillis(), @@ -40,8 +40,8 @@ data class DonationReceiptRecord( ) } - fun createForBoost(amount: FiatMoney): DonationReceiptRecord { - return DonationReceiptRecord( + fun createForBoost(amount: FiatMoney): InAppPaymentReceiptRecord { + return InAppPaymentReceiptRecord( id = -1L, amount = amount, timestamp = System.currentTimeMillis(), @@ -50,8 +50,8 @@ data class DonationReceiptRecord( ) } - fun createForGift(amount: FiatMoney): DonationReceiptRecord { - return DonationReceiptRecord( + fun createForGift(amount: FiatMoney): InAppPaymentReceiptRecord { + return InAppPaymentReceiptRecord( id = -1L, amount = amount, timestamp = System.currentTimeMillis(), diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ExternalLaunchDonationJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/ExternalLaunchDonationJob.kt index e3a7e927e4..1145327eeb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ExternalLaunchDonationJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ExternalLaunchDonationJob.kt @@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.donate.st import org.thoughtcrime.securesms.components.settings.app.subscription.errors.DonationError import org.thoughtcrime.securesms.components.settings.app.subscription.errors.DonationError.Companion.toDonationErrorValue import org.thoughtcrime.securesms.database.SignalDatabase -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord import org.thoughtcrime.securesms.database.model.databaseprotos.DonationErrorValue import org.thoughtcrime.securesms.database.model.databaseprotos.TerminalDonationQueue @@ -114,13 +114,13 @@ class ExternalLaunchDonationJob private constructor( checkIntentStatus(stripePaymentIntent.status) Log.i(TAG, "Creating and inserting donation receipt record.", true) - val donationReceiptRecord = if (stripe3DSData.inAppPayment.type == InAppPaymentType.ONE_TIME_DONATION) { - DonationReceiptRecord.createForBoost(stripe3DSData.inAppPayment.data.amount!!.toFiatMoney()) + val inAppPaymentReceiptRecord = if (stripe3DSData.inAppPayment.type == InAppPaymentType.ONE_TIME_DONATION) { + InAppPaymentReceiptRecord.createForBoost(stripe3DSData.inAppPayment.data.amount!!.toFiatMoney()) } else { - DonationReceiptRecord.createForGift(stripe3DSData.inAppPayment.data.amount!!.toFiatMoney()) + InAppPaymentReceiptRecord.createForGift(stripe3DSData.inAppPayment.data.amount!!.toFiatMoney()) } - SignalDatabase.donationReceipts.addReceipt(donationReceiptRecord) + SignalDatabase.donationReceipts.addReceipt(inAppPaymentReceiptRecord) Log.i(TAG, "Creating and inserting one-time pending donation.", true) SignalStore.inAppPayments.setPendingOneTimeDonation( diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentAuthCheckJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentAuthCheckJob.kt index 976322fbf3..108f002f07 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentAuthCheckJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentAuthCheckJob.kt @@ -21,7 +21,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaym import org.thoughtcrime.securesms.components.settings.app.subscription.RecurringInAppPaymentRepository import org.thoughtcrime.securesms.database.InAppPaymentTable import org.thoughtcrime.securesms.database.SignalDatabase -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData import org.thoughtcrime.securesms.dependencies.AppDependencies @@ -141,8 +141,8 @@ class InAppPaymentAuthCheckJob private constructor(parameters: Parameters) : Bas Log.i(TAG, "Creating and inserting receipt.", true) val receipt = when (inAppPayment.type) { - InAppPaymentType.ONE_TIME_DONATION -> DonationReceiptRecord.createForBoost(inAppPayment.data.amount!!.toFiatMoney()) - InAppPaymentType.ONE_TIME_GIFT -> DonationReceiptRecord.createForGift(inAppPayment.data.amount!!.toFiatMoney()) + InAppPaymentType.ONE_TIME_DONATION -> InAppPaymentReceiptRecord.createForBoost(inAppPayment.data.amount!!.toFiatMoney()) + InAppPaymentType.ONE_TIME_GIFT -> InAppPaymentReceiptRecord.createForGift(inAppPayment.data.amount!!.toFiatMoney()) else -> { Log.e(TAG, "Unexpected type ${inAppPayment.type}", true) return CheckResult.Failure() diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentRecurringContextJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentRecurringContextJob.kt index 93b36f8c67..316872e8a1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentRecurringContextJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentRecurringContextJob.kt @@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaym import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentsRepository.toInAppPaymentDataChargeFailure import org.thoughtcrime.securesms.database.InAppPaymentTable import org.thoughtcrime.securesms.database.SignalDatabase -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData import org.thoughtcrime.securesms.dependencies.AppDependencies @@ -456,7 +456,7 @@ class InAppPaymentRecurringContextJob private constructor( } info("Validated credential. Recording receipt and handing off to redemption job.") - SignalDatabase.donationReceipts.addReceipt(DonationReceiptRecord.createForSubscription(subscription)) + SignalDatabase.donationReceipts.addReceipt(InAppPaymentReceiptRecord.createForSubscription(subscription)) SignalDatabase.inAppPayments.update( inAppPayment = inAppPayment.copy( data = inAppPayment.data.copy( diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SubscriptionReceiptRequestResponseJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SubscriptionReceiptRequestResponseJob.java index 720b6ce0f3..a9c06c9d53 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SubscriptionReceiptRequestResponseJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SubscriptionReceiptRequestResponseJob.java @@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.errors.Do import org.thoughtcrime.securesms.components.settings.app.subscription.errors.DonationErrorSource; import org.thoughtcrime.securesms.components.settings.app.subscription.errors.PayPalDeclineCode; import org.thoughtcrime.securesms.database.SignalDatabase; -import org.thoughtcrime.securesms.database.model.DonationReceiptRecord; +import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord; import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord; import org.thoughtcrime.securesms.database.model.databaseprotos.DonationErrorValue; import org.thoughtcrime.securesms.database.model.databaseprotos.TerminalDonationQueue; @@ -233,7 +233,7 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob { ReceiptCredentialPresentation receiptCredentialPresentation = getReceiptCredentialPresentation(receiptCredential); Log.d(TAG, "Validated credential. Recording receipt and handing off to redemption job.", true); - SignalDatabase.donationReceipts().addReceipt(DonationReceiptRecord.createForSubscription(subscription)); + SignalDatabase.donationReceipts().addReceipt(InAppPaymentReceiptRecord.createForSubscription(subscription)); SignalStore.inAppPayments().clearSubscriptionRequestCredential(); SignalStore.inAppPayments().setSubscriptionReceiptCredential(receiptCredentialPresentation);