Repo created
This commit is contained in:
parent
75dc487a7a
commit
39c29d175b
6317 changed files with 388324 additions and 2 deletions
13
feature/funding/api/build.gradle.kts
Normal file
13
feature/funding/api/build.gradle.kts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
plugins {
|
||||
id(ThunderbirdPlugins.Library.androidCompose)
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "app.k9mail.feature.funding.api"
|
||||
resourcePrefix = "funding_api_"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.core.ui.compose.navigation)
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package app.k9mail.feature.funding.api
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
interface FundingManager {
|
||||
/**
|
||||
* Returns the type of funding.
|
||||
*/
|
||||
fun getFundingType(): FundingType
|
||||
|
||||
/**
|
||||
* Adds a funding reminder.
|
||||
*
|
||||
* The reminder is registered to the current lifecycle of the Activity.
|
||||
*
|
||||
* @param activity The activity to register the reminder to.
|
||||
* @param onOpenFunding The callback to be called when the user opens the funding.
|
||||
*/
|
||||
fun addFundingReminder(activity: AppCompatActivity, onOpenFunding: () -> Unit)
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package app.k9mail.feature.funding.api
|
||||
|
||||
import app.k9mail.core.ui.compose.navigation.Navigation
|
||||
import app.k9mail.core.ui.compose.navigation.Route
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
const val FUNDING_BASE_DEEP_LINK = "app://feature/funding"
|
||||
|
||||
sealed interface FundingRoute : Route {
|
||||
@Serializable
|
||||
data object Contribution : FundingRoute {
|
||||
override val basePath: String = BASE_PATH
|
||||
|
||||
override fun route(): String = basePath
|
||||
|
||||
const val BASE_PATH = "$FUNDING_BASE_DEEP_LINK/contribution"
|
||||
}
|
||||
}
|
||||
|
||||
interface FundingNavigation : Navigation<FundingRoute>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package app.k9mail.feature.funding.api
|
||||
|
||||
interface FundingSettings {
|
||||
fun getReminderReferenceTimestamp(): Long
|
||||
fun setReminderReferenceTimestamp(timestamp: Long)
|
||||
|
||||
fun getReminderShownTimestamp(): Long
|
||||
fun setReminderShownTimestamp(timestamp: Long)
|
||||
|
||||
fun getActivityCounterInMillis(): Long
|
||||
fun setActivityCounterInMillis(activeTime: Long)
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package app.k9mail.feature.funding.api
|
||||
|
||||
enum class FundingType {
|
||||
GOOGLE_PLAY,
|
||||
LINK,
|
||||
NO_FUNDING,
|
||||
}
|
||||
27
feature/funding/googleplay/build.gradle.kts
Normal file
27
feature/funding/googleplay/build.gradle.kts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
plugins {
|
||||
id(ThunderbirdPlugins.Library.androidCompose)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "app.k9mail.feature.funding.googleplay"
|
||||
resourcePrefix = "funding_googleplay_"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.feature.funding.api)
|
||||
|
||||
implementation(projects.core.common)
|
||||
implementation(projects.core.outcome)
|
||||
implementation(projects.core.logging.api)
|
||||
implementation(projects.core.ui.compose.designsystem)
|
||||
|
||||
implementation(libs.android.billing)
|
||||
implementation(libs.android.billing.ktx)
|
||||
implementation(libs.android.material)
|
||||
|
||||
testImplementation(projects.core.testing)
|
||||
testImplementation(projects.core.ui.compose.testing)
|
||||
|
||||
testImplementation(libs.androidx.lifecycle.runtime.testing)
|
||||
testImplementation(libs.androidx.fragment.testing)
|
||||
}
|
||||
18
feature/funding/googleplay/src/debug/AndroidManifest.xml
Normal file
18
feature/funding/googleplay/src/debug/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application>
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.play.largest_release_audience.NONPRODUCTION"
|
||||
android:value=""
|
||||
/>
|
||||
<meta-data
|
||||
android:name="com.google.android.play.billingclient.enableBillingOverridesTesting"
|
||||
android:value="true"
|
||||
/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ContributionListState
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.State
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionContentPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionContent(
|
||||
state = State(
|
||||
listState = ContributionListState(
|
||||
recurringContributions = FakeData.recurringContributions,
|
||||
oneTimeContributions = FakeData.oneTimeContributions,
|
||||
selectedContribution = FakeData.recurringContributions.first(),
|
||||
isLoading = false,
|
||||
),
|
||||
),
|
||||
onEvent = {},
|
||||
contentPadding = PaddingValues(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionContentEmptyPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionContent(
|
||||
state = State(
|
||||
listState = ContributionListState(
|
||||
isLoading = false,
|
||||
),
|
||||
),
|
||||
onEvent = {},
|
||||
contentPadding = PaddingValues(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionContentLoadingPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionContent(
|
||||
state = State(
|
||||
listState = ContributionListState(
|
||||
isLoading = true,
|
||||
),
|
||||
),
|
||||
onEvent = {},
|
||||
contentPadding = PaddingValues(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionContentListErrorPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionContent(
|
||||
state = State(
|
||||
listState = ContributionListState(
|
||||
error = DomainContract.BillingError.DeveloperError("Developer error"),
|
||||
isLoading = false,
|
||||
),
|
||||
),
|
||||
onEvent = {},
|
||||
contentPadding = PaddingValues(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionContentPurchaseErrorPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionContent(
|
||||
state = State(
|
||||
purchaseError = DomainContract.BillingError.DeveloperError("Developer error"),
|
||||
),
|
||||
onEvent = {},
|
||||
contentPadding = PaddingValues(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionErrorPurchaseFailedPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionError(
|
||||
error = BillingError.PurchaseFailed("Purchase failed"),
|
||||
onDismissClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionErrorServiceDisconnectedPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionError(
|
||||
error = BillingError.ServiceDisconnected("Service disconnected"),
|
||||
onDismissClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionErrorUnknownErrorPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionError(
|
||||
error = BillingError.DeveloperError("Unknown error"),
|
||||
onDismissClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionErrorDeveloperErrorPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionError(
|
||||
error = BillingError.UserCancelled("User cancelled"),
|
||||
onDismissClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionFooterPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionFooter(
|
||||
onPurchaseClick = {},
|
||||
onManagePurchaseClick = {},
|
||||
onShowContributionListClick = {},
|
||||
purchasedContribution = null,
|
||||
isPurchaseEnabled = true,
|
||||
isContributionListShown = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionFooterDisabledPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionFooter(
|
||||
purchasedContribution = null,
|
||||
onPurchaseClick = {},
|
||||
onManagePurchaseClick = {},
|
||||
onShowContributionListClick = {},
|
||||
isContributionListShown = false,
|
||||
isPurchaseEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionFooterWithRecurringContributionPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionFooter(
|
||||
purchasedContribution = FakeData.recurringContribution,
|
||||
onPurchaseClick = {},
|
||||
onManagePurchaseClick = {},
|
||||
onShowContributionListClick = {},
|
||||
isPurchaseEnabled = true,
|
||||
isContributionListShown = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionFooterWithOneTimeContributionPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionFooter(
|
||||
purchasedContribution = FakeData.oneTimeContribution,
|
||||
onPurchaseClick = {},
|
||||
onManagePurchaseClick = {},
|
||||
onShowContributionListClick = {},
|
||||
isPurchaseEnabled = true,
|
||||
isContributionListShown = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
fun ContributionFooterWithOneTimeContributionAndListPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionFooter(
|
||||
purchasedContribution = FakeData.oneTimeContribution,
|
||||
onPurchaseClick = {},
|
||||
onManagePurchaseClick = {},
|
||||
onShowContributionListClick = {},
|
||||
isPurchaseEnabled = true,
|
||||
isContributionListShown = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionHeaderPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionHeader(purchasedContribution = null)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionHeaderWithPurchasedOneTimeContributionPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionHeader(
|
||||
purchasedContribution = FakeData.oneTimeContribution,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionHeaderWithPurchasedRecurringContributionPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionHeader(
|
||||
purchasedContribution = FakeData.recurringContribution,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionListItemPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionListItem(
|
||||
text = "Monthly",
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionListItemPreviewSelected() {
|
||||
PreviewWithTheme {
|
||||
ContributionListItem(
|
||||
text = "Monthly",
|
||||
onClick = {},
|
||||
isSelected = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ContributionListState
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionListPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionList(
|
||||
state = ContributionListState(
|
||||
oneTimeContributions = FakeData.oneTimeContributions,
|
||||
recurringContributions = FakeData.recurringContributions,
|
||||
selectedContribution = FakeData.recurringContributions.first(),
|
||||
isRecurringContributionSelected = true,
|
||||
isLoading = false,
|
||||
),
|
||||
onOneTimeContributionTypeClick = {},
|
||||
onRecurringContributionTypeClick = {},
|
||||
onItemClick = {},
|
||||
onRetryClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionListRecurringPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionList(
|
||||
state = ContributionListState(
|
||||
oneTimeContributions = FakeData.oneTimeContributions,
|
||||
recurringContributions = FakeData.recurringContributions,
|
||||
selectedContribution = FakeData.oneTimeContributions.last(),
|
||||
isRecurringContributionSelected = false,
|
||||
isLoading = false,
|
||||
),
|
||||
onOneTimeContributionTypeClick = {},
|
||||
onRecurringContributionTypeClick = {},
|
||||
onItemClick = {},
|
||||
onRetryClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionListOneTimeOnlyPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionList(
|
||||
state = ContributionListState(
|
||||
oneTimeContributions = FakeData.oneTimeContributions,
|
||||
recurringContributions = persistentListOf(),
|
||||
selectedContribution = null,
|
||||
isRecurringContributionSelected = false,
|
||||
isLoading = false,
|
||||
),
|
||||
onOneTimeContributionTypeClick = {},
|
||||
onRecurringContributionTypeClick = {},
|
||||
onItemClick = {},
|
||||
onRetryClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionListRecurringOnlyPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionList(
|
||||
state = ContributionListState(
|
||||
oneTimeContributions = persistentListOf(),
|
||||
recurringContributions = FakeData.recurringContributions,
|
||||
selectedContribution = null,
|
||||
isRecurringContributionSelected = true,
|
||||
isLoading = false,
|
||||
),
|
||||
onOneTimeContributionTypeClick = {},
|
||||
onRecurringContributionTypeClick = {},
|
||||
onItemClick = {},
|
||||
onRetryClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionListEmptyPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionList(
|
||||
state = ContributionListState(
|
||||
oneTimeContributions = persistentListOf(),
|
||||
recurringContributions = persistentListOf(),
|
||||
selectedContribution = null,
|
||||
isRecurringContributionSelected = false,
|
||||
isLoading = false,
|
||||
),
|
||||
onOneTimeContributionTypeClick = {},
|
||||
onRecurringContributionTypeClick = {},
|
||||
onItemClick = {},
|
||||
onRetryClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionListLoadingPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionList(
|
||||
state = ContributionListState(
|
||||
oneTimeContributions = persistentListOf(),
|
||||
recurringContributions = persistentListOf(),
|
||||
selectedContribution = null,
|
||||
isRecurringContributionSelected = false,
|
||||
isLoading = true,
|
||||
),
|
||||
onOneTimeContributionTypeClick = {},
|
||||
onRecurringContributionTypeClick = {},
|
||||
onItemClick = {},
|
||||
onRetryClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContributionListErrorPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionList(
|
||||
state = ContributionListState(
|
||||
oneTimeContributions = persistentListOf(),
|
||||
recurringContributions = persistentListOf(),
|
||||
selectedContribution = null,
|
||||
isRecurringContributionSelected = false,
|
||||
isLoading = false,
|
||||
error = DomainContract.BillingError.UnknownError(
|
||||
"An error occurred",
|
||||
),
|
||||
),
|
||||
onOneTimeContributionTypeClick = {},
|
||||
onRecurringContributionTypeClick = {},
|
||||
onItemClick = {},
|
||||
onRetryClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import app.k9mail.core.ui.compose.common.annotation.PreviewDevicesWithBackground
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ContributionListState
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.State
|
||||
|
||||
@Composable
|
||||
@PreviewDevicesWithBackground
|
||||
fun ContributionScreenPreview() {
|
||||
PreviewWithTheme {
|
||||
ContributionScreen(
|
||||
onBack = {},
|
||||
viewModel = FakeContributionViewModel(
|
||||
initialState = State(
|
||||
listState = ContributionListState(
|
||||
recurringContributions = FakeData.recurringContributions,
|
||||
oneTimeContributions = FakeData.oneTimeContributions,
|
||||
selectedContribution = FakeData.recurringContributions.first(),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.Effect
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.Event
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.State
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ViewModel
|
||||
|
||||
internal class FakeContributionViewModel(
|
||||
initialState: State,
|
||||
) : BaseViewModel<State, Event, Effect>(initialState = initialState), ViewModel {
|
||||
|
||||
val events = mutableListOf<Event>()
|
||||
|
||||
override fun event(event: Event) {
|
||||
events.add(event)
|
||||
}
|
||||
|
||||
fun applyState(state: State) {
|
||||
updateState { state }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal object FakeData {
|
||||
|
||||
val recurringContribution = RecurringContribution(
|
||||
id = "contribution_tfa_monthly_m",
|
||||
title = "Monthly subscription: $50",
|
||||
description = "Monthly subscription for $50",
|
||||
price = 5000L,
|
||||
priceFormatted = "50 $",
|
||||
)
|
||||
|
||||
val recurringContributions = persistentListOf(
|
||||
RecurringContribution(
|
||||
id = "contribution_tfa_monthly_xxl",
|
||||
title = "Monthly subscription: $250",
|
||||
description = "Monthly subscription for $250",
|
||||
price = 25000L,
|
||||
priceFormatted = "250 $",
|
||||
),
|
||||
RecurringContribution(
|
||||
id = "contribution_tfa_monthly_xl",
|
||||
title = "Monthly subscription: $140",
|
||||
description = "Monthly subscription for $140",
|
||||
price = 14000L,
|
||||
priceFormatted = "140 $",
|
||||
),
|
||||
RecurringContribution(
|
||||
id = "contribution_tfa_monthly_l",
|
||||
title = "Monthly subscription: $80",
|
||||
description = "Monthly subscription for $80",
|
||||
price = 8000L,
|
||||
priceFormatted = "80 $",
|
||||
),
|
||||
RecurringContribution(
|
||||
id = "contribution_tfa_monthly_m",
|
||||
title = "Monthly subscription: $50",
|
||||
description = "Monthly subscription for $50",
|
||||
price = 5000L,
|
||||
priceFormatted = "50 $",
|
||||
),
|
||||
RecurringContribution(
|
||||
id = "contribution_tfa_monthly_s",
|
||||
title = "Monthly subscription: $25",
|
||||
description = "Monthly subscription for $25",
|
||||
price = 2500L,
|
||||
priceFormatted = "25 $",
|
||||
),
|
||||
RecurringContribution(
|
||||
id = "contribution_tfa_monthly_xs",
|
||||
title = "Monthly subscription: $15",
|
||||
description = "Monthly subscription for $15",
|
||||
price = 1500L,
|
||||
priceFormatted = "15 $",
|
||||
),
|
||||
)
|
||||
|
||||
val oneTimeContribution = OneTimeContribution(
|
||||
id = "contribution_tfa_onetime_m",
|
||||
title = "One time payment: $50",
|
||||
description = "One time payment for $50",
|
||||
price = 5000L,
|
||||
priceFormatted = "50 $",
|
||||
)
|
||||
|
||||
val oneTimeContributions = persistentListOf(
|
||||
OneTimeContribution(
|
||||
id = "contribution_tfa_onetime_xxl",
|
||||
title = "One time payment: $250",
|
||||
description = "One time payment for $250",
|
||||
price = 25000L,
|
||||
priceFormatted = "250 $",
|
||||
),
|
||||
OneTimeContribution(
|
||||
id = "contribution_tfa_onetime_xl",
|
||||
title = "One time payment: $140",
|
||||
description = "One time payment for $140",
|
||||
price = 14000L,
|
||||
priceFormatted = "140 $",
|
||||
),
|
||||
OneTimeContribution(
|
||||
id = "contribution_tfa_onetime_l",
|
||||
title = "One time payment: $80",
|
||||
description = "One time payment for $80",
|
||||
price = 8000L,
|
||||
priceFormatted = "80 $",
|
||||
),
|
||||
OneTimeContribution(
|
||||
id = "contribution_tfa_onetime_m",
|
||||
title = "One time payment: $50",
|
||||
description = "One time payment for $50",
|
||||
price = 5000L,
|
||||
priceFormatted = "50 $",
|
||||
),
|
||||
OneTimeContribution(
|
||||
id = "contribution_tfa_onetime_s",
|
||||
title = "One time payment: $25",
|
||||
description = "One time payment for $25",
|
||||
price = 2500L,
|
||||
priceFormatted = "25 $",
|
||||
),
|
||||
OneTimeContribution(
|
||||
id = "contribution_tfa_onetime_xs",
|
||||
title = "One time payment: $15",
|
||||
description = "One time payment for $15",
|
||||
price = 1500L,
|
||||
priceFormatted = "15 $",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
package app.k9mail.feature.funding
|
||||
|
||||
import app.k9mail.feature.funding.api.FundingManager
|
||||
import app.k9mail.feature.funding.api.FundingNavigation
|
||||
import app.k9mail.feature.funding.googleplay.GooglePlayFundingManager
|
||||
import app.k9mail.feature.funding.googleplay.GooglePlayFundingNavigation
|
||||
import app.k9mail.feature.funding.googleplay.data.DataContract
|
||||
import app.k9mail.feature.funding.googleplay.data.GoogleBillingClient
|
||||
import app.k9mail.feature.funding.googleplay.data.mapper.BillingResultMapper
|
||||
import app.k9mail.feature.funding.googleplay.data.mapper.ProductDetailsMapper
|
||||
import app.k9mail.feature.funding.googleplay.data.remote.GoogleBillingClientProvider
|
||||
import app.k9mail.feature.funding.googleplay.data.remote.GoogleBillingPurchaseHandler
|
||||
import app.k9mail.feature.funding.googleplay.domain.BillingManager
|
||||
import app.k9mail.feature.funding.googleplay.domain.ContributionIdProvider
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract
|
||||
import app.k9mail.feature.funding.googleplay.domain.usecase.GetAvailableContributions
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionViewModel
|
||||
import app.k9mail.feature.funding.googleplay.ui.reminder.ActivityLifecycleObserver
|
||||
import app.k9mail.feature.funding.googleplay.ui.reminder.FragmentLifecycleObserver
|
||||
import app.k9mail.feature.funding.googleplay.ui.reminder.FundingReminder
|
||||
import app.k9mail.feature.funding.googleplay.ui.reminder.FundingReminderContract
|
||||
import app.k9mail.feature.funding.googleplay.ui.reminder.FundingReminderDialog
|
||||
import com.android.billingclient.api.ProductDetails
|
||||
import kotlin.time.ExperimentalTime
|
||||
import net.thunderbird.core.common.cache.Cache
|
||||
import net.thunderbird.core.common.cache.InMemoryCache
|
||||
import org.koin.core.module.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
|
||||
val featureFundingModule = module {
|
||||
single<FundingReminderContract.Dialog> {
|
||||
FundingReminderDialog()
|
||||
}
|
||||
|
||||
single<FundingReminderContract.FragmentLifecycleObserver> {
|
||||
FragmentLifecycleObserver(
|
||||
targetFragmentTag = "MessageViewContainerFragment",
|
||||
)
|
||||
}
|
||||
|
||||
single<FundingReminderContract.ActivityLifecycleObserver> {
|
||||
@OptIn(ExperimentalTime::class)
|
||||
ActivityLifecycleObserver(
|
||||
settings = get(),
|
||||
)
|
||||
}
|
||||
|
||||
single<FundingReminderContract.Reminder> {
|
||||
@OptIn(ExperimentalTime::class)
|
||||
FundingReminder(
|
||||
settings = get(),
|
||||
fragmentObserver = get(),
|
||||
activityCounterObserver = get(),
|
||||
dialog = get(),
|
||||
)
|
||||
}
|
||||
|
||||
single<FundingManager> {
|
||||
GooglePlayFundingManager(
|
||||
reminder = get(),
|
||||
)
|
||||
}
|
||||
|
||||
single<FundingNavigation> { GooglePlayFundingNavigation() }
|
||||
|
||||
single<DataContract.Mapper.Product> {
|
||||
ProductDetailsMapper()
|
||||
}
|
||||
|
||||
single<DataContract.Mapper.BillingResult> {
|
||||
BillingResultMapper()
|
||||
}
|
||||
|
||||
single<DataContract.Remote.GoogleBillingClientProvider> {
|
||||
GoogleBillingClientProvider(
|
||||
context = get(),
|
||||
)
|
||||
}
|
||||
|
||||
single<Cache<String, ProductDetails>> {
|
||||
InMemoryCache()
|
||||
}
|
||||
|
||||
single<DataContract.Remote.GoogleBillingPurchaseHandler> {
|
||||
GoogleBillingPurchaseHandler(
|
||||
productCache = get(),
|
||||
productMapper = get(),
|
||||
logger = get(),
|
||||
)
|
||||
}
|
||||
|
||||
single<DataContract.BillingClient> {
|
||||
GoogleBillingClient(
|
||||
clientProvider = get(),
|
||||
productMapper = get(),
|
||||
resultMapper = get(),
|
||||
productCache = get(),
|
||||
purchaseHandler = get(),
|
||||
logger = get(),
|
||||
)
|
||||
}
|
||||
|
||||
single<DomainContract.ContributionIdProvider> {
|
||||
ContributionIdProvider()
|
||||
}
|
||||
|
||||
single<DomainContract.BillingManager> {
|
||||
BillingManager(
|
||||
billingClient = get(),
|
||||
contributionIdProvider = get(),
|
||||
)
|
||||
}
|
||||
|
||||
single<DomainContract.UseCase.GetAvailableContributions> {
|
||||
GetAvailableContributions(
|
||||
billingManager = get(),
|
||||
)
|
||||
}
|
||||
|
||||
viewModel {
|
||||
ContributionViewModel(
|
||||
billingManager = get(),
|
||||
getAvailableContributions = get(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package app.k9mail.feature.funding.googleplay
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import app.k9mail.feature.funding.api.FundingManager
|
||||
import app.k9mail.feature.funding.api.FundingType
|
||||
import app.k9mail.feature.funding.googleplay.ui.reminder.FundingReminderContract
|
||||
|
||||
class GooglePlayFundingManager(
|
||||
private val reminder: FundingReminderContract.Reminder,
|
||||
) : FundingManager {
|
||||
override fun getFundingType(): FundingType {
|
||||
return FundingType.GOOGLE_PLAY
|
||||
}
|
||||
|
||||
override fun addFundingReminder(activity: AppCompatActivity, onOpenFunding: () -> Unit) {
|
||||
reminder.registerReminder(activity, onOpenFunding)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package app.k9mail.feature.funding.googleplay
|
||||
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import app.k9mail.core.ui.compose.navigation.deepLinkComposable
|
||||
import app.k9mail.feature.funding.api.FundingNavigation
|
||||
import app.k9mail.feature.funding.api.FundingRoute
|
||||
import app.k9mail.feature.funding.api.FundingRoute.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionScreen
|
||||
|
||||
class GooglePlayFundingNavigation : FundingNavigation {
|
||||
|
||||
override fun registerRoutes(
|
||||
navGraphBuilder: NavGraphBuilder,
|
||||
onBack: () -> Unit,
|
||||
onFinish: (FundingRoute) -> Unit,
|
||||
) {
|
||||
with(navGraphBuilder) {
|
||||
deepLinkComposable<Contribution>(Contribution.BASE_PATH) {
|
||||
ContributionScreen(
|
||||
onBack = onBack,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package app.k9mail.feature.funding.googleplay.data
|
||||
|
||||
import android.app.Activity
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
import com.android.billingclient.api.ProductDetails
|
||||
import com.android.billingclient.api.Purchase
|
||||
import com.android.billingclient.api.PurchasesUpdatedListener
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import net.thunderbird.core.outcome.Outcome
|
||||
import com.android.billingclient.api.BillingClient as GoogleBillingClient
|
||||
import com.android.billingclient.api.BillingResult as GoogleBillingResult
|
||||
|
||||
internal interface DataContract {
|
||||
|
||||
interface Mapper {
|
||||
interface Product {
|
||||
fun mapToContribution(product: ProductDetails): Contribution
|
||||
|
||||
fun mapToOneTimeContribution(product: ProductDetails): OneTimeContribution
|
||||
fun mapToRecurringContribution(product: ProductDetails): RecurringContribution
|
||||
}
|
||||
|
||||
interface BillingResult {
|
||||
suspend fun <T> mapToOutcome(
|
||||
billingResult: GoogleBillingResult,
|
||||
transformSuccess: suspend () -> T,
|
||||
): Outcome<T, BillingError>
|
||||
}
|
||||
}
|
||||
|
||||
interface Remote {
|
||||
interface GoogleBillingClientProvider {
|
||||
val current: GoogleBillingClient
|
||||
|
||||
/**
|
||||
* Set the listener to be notified of purchase updates.
|
||||
*/
|
||||
fun setPurchasesUpdatedListener(listener: PurchasesUpdatedListener)
|
||||
|
||||
/**
|
||||
* Disconnect from the billing service and clear the instance.
|
||||
*/
|
||||
fun clear()
|
||||
}
|
||||
|
||||
interface GoogleBillingPurchaseHandler {
|
||||
suspend fun handlePurchases(
|
||||
clientProvider: GoogleBillingClientProvider,
|
||||
purchases: List<Purchase>,
|
||||
): List<Contribution>
|
||||
|
||||
suspend fun handleOneTimePurchases(
|
||||
clientProvider: GoogleBillingClientProvider,
|
||||
purchases: List<Purchase>,
|
||||
): List<OneTimeContribution>
|
||||
|
||||
suspend fun handleRecurringPurchases(
|
||||
clientProvider: GoogleBillingClientProvider,
|
||||
purchases: List<Purchase>,
|
||||
): List<RecurringContribution>
|
||||
}
|
||||
}
|
||||
|
||||
interface BillingClient {
|
||||
|
||||
/**
|
||||
* Flow that emits the last purchased contribution.
|
||||
*/
|
||||
val purchasedContribution: StateFlow<Outcome<Contribution?, BillingError>>
|
||||
|
||||
/**
|
||||
* Connect to the billing service.
|
||||
*
|
||||
* @param onConnected Callback to be invoked when the billing service is connected.
|
||||
*/
|
||||
suspend fun <T> connect(onConnected: suspend () -> Outcome<T, BillingError>): Outcome<T, BillingError>
|
||||
|
||||
/**
|
||||
* Disconnect from the billing service.
|
||||
*/
|
||||
fun disconnect()
|
||||
|
||||
/**
|
||||
* Load one-time contributions.
|
||||
*/
|
||||
suspend fun loadOneTimeContributions(
|
||||
productIds: List<String>,
|
||||
): Outcome<List<OneTimeContribution>, BillingError>
|
||||
|
||||
/**
|
||||
* Load recurring contributions.
|
||||
*/
|
||||
suspend fun loadRecurringContributions(
|
||||
productIds: List<String>,
|
||||
): Outcome<List<RecurringContribution>, BillingError>
|
||||
|
||||
/**
|
||||
* Load purchased one-time contributions.
|
||||
*/
|
||||
suspend fun loadPurchasedOneTimeContributions(): Outcome<List<OneTimeContribution>, BillingError>
|
||||
|
||||
/**
|
||||
* Load purchased recurring contributions.
|
||||
*/
|
||||
suspend fun loadPurchasedRecurringContributions(): Outcome<List<RecurringContribution>, BillingError>
|
||||
|
||||
/**
|
||||
* Load the most recent one-time contribution.
|
||||
*/
|
||||
suspend fun loadPurchasedOneTimeContributionHistory(): Outcome<OneTimeContribution?, BillingError>
|
||||
|
||||
/**
|
||||
* Purchase a contribution.
|
||||
*/
|
||||
suspend fun purchaseContribution(
|
||||
activity: Activity,
|
||||
contribution: Contribution,
|
||||
): Outcome<Unit, BillingError>
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
package app.k9mail.feature.funding.googleplay.data
|
||||
|
||||
import android.app.Activity
|
||||
import app.k9mail.feature.funding.googleplay.data.DataContract.Remote
|
||||
import app.k9mail.feature.funding.googleplay.data.remote.startConnection
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
import com.android.billingclient.api.BillingClient.ProductType
|
||||
import com.android.billingclient.api.BillingFlowParams
|
||||
import com.android.billingclient.api.BillingFlowParams.ProductDetailsParams
|
||||
import com.android.billingclient.api.BillingResult
|
||||
import com.android.billingclient.api.ProductDetails
|
||||
import com.android.billingclient.api.ProductDetailsResult
|
||||
import com.android.billingclient.api.Purchase
|
||||
import com.android.billingclient.api.PurchasesResult
|
||||
import com.android.billingclient.api.PurchasesUpdatedListener
|
||||
import com.android.billingclient.api.QueryProductDetailsParams
|
||||
import com.android.billingclient.api.QueryPurchaseHistoryParams
|
||||
import com.android.billingclient.api.QueryPurchasesParams
|
||||
import com.android.billingclient.api.queryProductDetails
|
||||
import com.android.billingclient.api.queryPurchaseHistory
|
||||
import com.android.billingclient.api.queryPurchasesAsync
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import net.thunderbird.core.common.cache.Cache
|
||||
import net.thunderbird.core.logging.Logger
|
||||
import net.thunderbird.core.outcome.Outcome
|
||||
import net.thunderbird.core.outcome.handleAsync
|
||||
import net.thunderbird.core.outcome.mapFailure
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
internal class GoogleBillingClient(
|
||||
private val clientProvider: Remote.GoogleBillingClientProvider,
|
||||
private val productMapper: DataContract.Mapper.Product,
|
||||
private val resultMapper: DataContract.Mapper.BillingResult,
|
||||
private val productCache: Cache<String, ProductDetails>,
|
||||
private val purchaseHandler: Remote.GoogleBillingPurchaseHandler,
|
||||
private val logger: Logger,
|
||||
backgroundDispatcher: CoroutineContext = Dispatchers.IO,
|
||||
) : DataContract.BillingClient, PurchasesUpdatedListener {
|
||||
|
||||
init {
|
||||
clientProvider.setPurchasesUpdatedListener(this)
|
||||
}
|
||||
|
||||
private val coroutineScope = CoroutineScope(backgroundDispatcher)
|
||||
|
||||
private val _purchasedContribution = MutableStateFlow<Outcome<Contribution?, BillingError>>(
|
||||
value = Outcome.success(null),
|
||||
)
|
||||
override val purchasedContribution: StateFlow<Outcome<Contribution?, BillingError>> =
|
||||
_purchasedContribution.asStateFlow()
|
||||
|
||||
override suspend fun <T> connect(onConnected: suspend () -> Outcome<T, BillingError>): Outcome<T, BillingError> {
|
||||
val connectionResult = clientProvider.current.startConnection()
|
||||
val result = resultMapper.mapToOutcome(connectionResult) {}
|
||||
|
||||
return when (result) {
|
||||
is Outcome.Success -> {
|
||||
onConnected()
|
||||
}
|
||||
|
||||
is Outcome.Failure -> result
|
||||
}
|
||||
}
|
||||
|
||||
override fun disconnect() {
|
||||
productCache.clear()
|
||||
_purchasedContribution.value = Outcome.success(null)
|
||||
clientProvider.clear()
|
||||
}
|
||||
|
||||
override suspend fun loadOneTimeContributions(
|
||||
productIds: List<String>,
|
||||
): Outcome<List<OneTimeContribution>, BillingError> {
|
||||
val oneTimeProductsResult = queryProducts(ProductType.INAPP, productIds)
|
||||
return resultMapper.mapToOutcome(oneTimeProductsResult.billingResult) {
|
||||
oneTimeProductsResult.productDetailsList.orEmpty().map {
|
||||
val contribution = productMapper.mapToOneTimeContribution(it)
|
||||
productCache[it.productId] = it
|
||||
contribution
|
||||
}
|
||||
}.mapFailure { billingError, _ ->
|
||||
logger.error(message = {
|
||||
"Error loading one-time products: ${oneTimeProductsResult.billingResult.debugMessage}"
|
||||
})
|
||||
billingError
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadRecurringContributions(
|
||||
productIds: List<String>,
|
||||
): Outcome<List<RecurringContribution>, BillingError> {
|
||||
val recurringProductsResult = queryProducts(ProductType.SUBS, productIds)
|
||||
return resultMapper.mapToOutcome(recurringProductsResult.billingResult) {
|
||||
recurringProductsResult.productDetailsList.orEmpty().map {
|
||||
val contribution = productMapper.mapToRecurringContribution(it)
|
||||
productCache[it.productId] = it
|
||||
contribution
|
||||
}
|
||||
}.mapFailure { billingError, _ ->
|
||||
logger.error(message = {
|
||||
"Error loading recurring products: ${recurringProductsResult.billingResult.debugMessage}"
|
||||
})
|
||||
billingError
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadPurchasedOneTimeContributions(): Outcome<List<OneTimeContribution>, BillingError> {
|
||||
val purchasesResult = queryPurchase(ProductType.INAPP)
|
||||
return resultMapper.mapToOutcome(purchasesResult.billingResult) {
|
||||
purchaseHandler.handleOneTimePurchases(clientProvider, purchasesResult.purchasesList)
|
||||
}.mapFailure { billingError, _ ->
|
||||
logger.error(message = {
|
||||
"Error loading one-time purchases: ${purchasesResult.billingResult.debugMessage}"
|
||||
})
|
||||
billingError
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadPurchasedRecurringContributions(): Outcome<List<RecurringContribution>, BillingError> {
|
||||
val purchasesResult = queryPurchase(ProductType.SUBS)
|
||||
return resultMapper.mapToOutcome(purchasesResult.billingResult) {
|
||||
purchaseHandler.handleRecurringPurchases(clientProvider, purchasesResult.purchasesList)
|
||||
}.mapFailure { billingError, _ ->
|
||||
logger.error(message = {
|
||||
"Error loading recurring purchases: ${purchasesResult.billingResult.debugMessage}"
|
||||
})
|
||||
billingError
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadPurchasedOneTimeContributionHistory(): Outcome<OneTimeContribution?, BillingError> {
|
||||
val queryPurchaseHistoryParams = QueryPurchaseHistoryParams.newBuilder()
|
||||
.setProductType(ProductType.INAPP)
|
||||
.build()
|
||||
|
||||
val purchasesResult = clientProvider.current.queryPurchaseHistory(queryPurchaseHistoryParams)
|
||||
return resultMapper.mapToOutcome(purchasesResult.billingResult) {
|
||||
val recentPurchaseId =
|
||||
purchasesResult.purchaseHistoryRecordList.orEmpty().firstOrNull()?.products?.firstOrNull {
|
||||
productCache.hasKey(it)
|
||||
}
|
||||
|
||||
if (recentPurchaseId != null) {
|
||||
val recentPurchase = productCache[recentPurchaseId]
|
||||
productMapper.mapToOneTimeContribution(recentPurchase!!)
|
||||
} else {
|
||||
logger.error(message = { "No recent purchase found: ${purchasesResult.billingResult.debugMessage}" })
|
||||
null
|
||||
}
|
||||
}.mapFailure { billingError, _ ->
|
||||
logger.error(message = {
|
||||
"Error loading one-time purchase history: ${purchasesResult.billingResult.debugMessage}"
|
||||
})
|
||||
billingError
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun queryProducts(
|
||||
productType: String,
|
||||
productIds: List<String>,
|
||||
): ProductDetailsResult {
|
||||
val productList = productIds.map { mapIdToProduct(productType, it) }
|
||||
|
||||
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder()
|
||||
.setProductList(productList)
|
||||
.build()
|
||||
|
||||
return clientProvider.current.queryProductDetails(queryProductDetailsParams)
|
||||
}
|
||||
|
||||
private fun mapIdToProduct(
|
||||
productType: String,
|
||||
productId: String,
|
||||
): QueryProductDetailsParams.Product {
|
||||
return QueryProductDetailsParams.Product.newBuilder()
|
||||
.setProductType(productType)
|
||||
.setProductId(productId)
|
||||
.build()
|
||||
}
|
||||
|
||||
private suspend fun queryPurchase(productType: String): PurchasesResult {
|
||||
val queryPurchaseParams = QueryPurchasesParams.newBuilder()
|
||||
.setProductType(productType)
|
||||
.build()
|
||||
|
||||
return clientProvider.current.queryPurchasesAsync(queryPurchaseParams)
|
||||
}
|
||||
|
||||
override suspend fun purchaseContribution(
|
||||
activity: Activity,
|
||||
contribution: Contribution,
|
||||
): Outcome<Unit, BillingError> {
|
||||
val productDetails = productCache[contribution.id]
|
||||
?: return Outcome.failure(BillingError.PurchaseFailed("ProductDetails not found: ${contribution.id}"))
|
||||
val offerToken = productDetails.subscriptionOfferDetails?.firstOrNull()?.offerToken
|
||||
|
||||
val productDetailsParamsList = listOf(
|
||||
ProductDetailsParams.newBuilder()
|
||||
.setProductDetails(productDetails)
|
||||
.apply {
|
||||
if (offerToken != null) {
|
||||
setOfferToken(offerToken)
|
||||
}
|
||||
}
|
||||
.build(),
|
||||
)
|
||||
|
||||
val billingFlowParams = BillingFlowParams.newBuilder()
|
||||
.setProductDetailsParamsList(productDetailsParamsList)
|
||||
.build()
|
||||
|
||||
val billingResult = clientProvider.current.launchBillingFlow(activity, billingFlowParams)
|
||||
return resultMapper.mapToOutcome(billingResult) { }.mapFailure(
|
||||
transformFailure = { error, _ ->
|
||||
logger.error(message = { "Error launching billing flow: ${error.message}" })
|
||||
error
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: MutableList<Purchase>?) {
|
||||
coroutineScope.launch {
|
||||
resultMapper.mapToOutcome(billingResult) { }.handleAsync(
|
||||
onSuccess = {
|
||||
if (purchases != null) {
|
||||
val contributions = purchaseHandler.handlePurchases(clientProvider, purchases)
|
||||
if (contributions.isNotEmpty()) {
|
||||
_purchasedContribution.emit(
|
||||
Outcome.success(
|
||||
contributions.firstOrNull(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
onFailure = { error ->
|
||||
logger.error(
|
||||
message = {
|
||||
"Error onPurchasesUpdated: " +
|
||||
"${billingResult.responseCode}: ${billingResult.debugMessage}"
|
||||
},
|
||||
)
|
||||
_purchasedContribution.value = Outcome.failure(error)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package app.k9mail.feature.funding.googleplay.data.mapper
|
||||
|
||||
import app.k9mail.feature.funding.googleplay.data.DataContract.Mapper
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError
|
||||
import com.android.billingclient.api.BillingClient.BillingResponseCode
|
||||
import com.android.billingclient.api.BillingResult
|
||||
import net.thunderbird.core.outcome.Outcome
|
||||
|
||||
class BillingResultMapper : Mapper.BillingResult {
|
||||
|
||||
override suspend fun <T> mapToOutcome(
|
||||
billingResult: BillingResult,
|
||||
transformSuccess: suspend () -> T,
|
||||
): Outcome<T, BillingError> {
|
||||
return when (billingResult.responseCode) {
|
||||
BillingResponseCode.OK -> {
|
||||
Outcome.success(transformSuccess())
|
||||
}
|
||||
|
||||
else -> {
|
||||
Outcome.failure(mapToBillingError(billingResult))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapToBillingError(billingResult: BillingResult): BillingError {
|
||||
return when (billingResult.responseCode) {
|
||||
BillingResponseCode.SERVICE_DISCONNECTED,
|
||||
BillingResponseCode.SERVICE_UNAVAILABLE,
|
||||
BillingResponseCode.BILLING_UNAVAILABLE,
|
||||
BillingResponseCode.NETWORK_ERROR,
|
||||
-> BillingError.ServiceDisconnected(billingResult.debugMessage)
|
||||
|
||||
BillingResponseCode.ITEM_ALREADY_OWNED,
|
||||
BillingResponseCode.ITEM_NOT_OWNED,
|
||||
BillingResponseCode.ITEM_UNAVAILABLE,
|
||||
-> BillingError.PurchaseFailed(billingResult.debugMessage)
|
||||
|
||||
BillingResponseCode.USER_CANCELED -> BillingError.UserCancelled(billingResult.debugMessage)
|
||||
|
||||
BillingResponseCode.DEVELOPER_ERROR -> BillingError.DeveloperError(billingResult.debugMessage)
|
||||
|
||||
else -> BillingError.UnknownError(billingResult.debugMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package app.k9mail.feature.funding.googleplay.data.mapper
|
||||
|
||||
import app.k9mail.feature.funding.googleplay.data.DataContract.Mapper
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
import com.android.billingclient.api.BillingClient
|
||||
import com.android.billingclient.api.ProductDetails
|
||||
|
||||
class ProductDetailsMapper : Mapper.Product {
|
||||
|
||||
override fun mapToContribution(product: ProductDetails): Contribution {
|
||||
return when (product.productType) {
|
||||
BillingClient.ProductType.INAPP -> mapToOneTimeContribution(product)
|
||||
BillingClient.ProductType.SUBS -> mapToRecurringContribution(product)
|
||||
else -> throw IllegalArgumentException("Unknown product type: ${product.productType}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun mapToOneTimeContribution(product: ProductDetails): OneTimeContribution {
|
||||
require(product.productType == BillingClient.ProductType.INAPP) { "Product type must be INAPP" }
|
||||
|
||||
val offerDetails = product.oneTimePurchaseOfferDetails
|
||||
|
||||
return if (offerDetails != null) {
|
||||
OneTimeContribution(
|
||||
id = product.productId,
|
||||
title = product.name,
|
||||
description = product.description.replace("\n", ""),
|
||||
price = offerDetails.priceAmountMicros,
|
||||
priceFormatted = offerDetails.formattedPrice,
|
||||
)
|
||||
} else {
|
||||
error("One-time product has no offer details: ${product.productId}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun mapToRecurringContribution(product: ProductDetails): RecurringContribution {
|
||||
require(product.productType == BillingClient.ProductType.SUBS) { "Product type must be SUBS" }
|
||||
|
||||
// We assume the product has only one offer and one pricing phase
|
||||
val pricingPhase =
|
||||
product.subscriptionOfferDetails?.firstOrNull()?.pricingPhases?.pricingPhaseList?.firstOrNull()
|
||||
|
||||
return if (pricingPhase != null) {
|
||||
RecurringContribution(
|
||||
id = product.productId,
|
||||
title = product.name,
|
||||
description = product.description.replace("\n", ""),
|
||||
price = pricingPhase.priceAmountMicros,
|
||||
priceFormatted = pricingPhase.formattedPrice,
|
||||
)
|
||||
} else {
|
||||
error("Subscription product has no pricing phase: ${product.productId}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package app.k9mail.feature.funding.googleplay.data.remote
|
||||
|
||||
import com.android.billingclient.api.BillingClient
|
||||
import com.android.billingclient.api.BillingClient.BillingResponseCode
|
||||
import com.android.billingclient.api.BillingClientStateListener
|
||||
import com.android.billingclient.api.BillingResult
|
||||
import kotlin.coroutines.resume
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
|
||||
/**
|
||||
* Starts the billing client connection.
|
||||
*
|
||||
* Kotlin coroutines are used to suspend the coroutine until the connection is established.
|
||||
*/
|
||||
internal suspend fun BillingClient.startConnection(): BillingResult = suspendCancellableCoroutine { continuation ->
|
||||
startConnection(
|
||||
object : BillingClientStateListener {
|
||||
override fun onBillingSetupFinished(billingResult: BillingResult) {
|
||||
continuation.resume(billingResult)
|
||||
}
|
||||
|
||||
override fun onBillingServiceDisconnected() {
|
||||
continuation.resume(
|
||||
BillingResult.newBuilder()
|
||||
.setResponseCode(BillingResponseCode.SERVICE_DISCONNECTED)
|
||||
.setDebugMessage("Service disconnected: onBillingServiceDisconnected")
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package app.k9mail.feature.funding.googleplay.data.remote
|
||||
|
||||
import android.content.Context
|
||||
import app.k9mail.feature.funding.googleplay.data.DataContract
|
||||
import com.android.billingclient.api.BillingClient
|
||||
import com.android.billingclient.api.PendingPurchasesParams
|
||||
import com.android.billingclient.api.PurchasesUpdatedListener
|
||||
|
||||
/**
|
||||
* Google Billing client provider.
|
||||
*
|
||||
* It is responsible for creating and managing the billing client instance
|
||||
*/
|
||||
class GoogleBillingClientProvider(
|
||||
private val context: Context,
|
||||
) : DataContract.Remote.GoogleBillingClientProvider {
|
||||
|
||||
private var clientInstance: BillingClient? = null
|
||||
|
||||
override val current: BillingClient
|
||||
get() = clientInstance ?: createBillingClient().also { clientInstance = it }
|
||||
|
||||
private var listener: PurchasesUpdatedListener? = null
|
||||
|
||||
override fun setPurchasesUpdatedListener(listener: PurchasesUpdatedListener) {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
private fun createBillingClient(): BillingClient {
|
||||
require(listener != null) { "PurchasesUpdatedListener must be set before creating the billing client" }
|
||||
|
||||
return BillingClient.newBuilder(context)
|
||||
.setListener(listener!!)
|
||||
.enablePendingPurchases(
|
||||
PendingPurchasesParams.newBuilder()
|
||||
.enableOneTimeProducts()
|
||||
.build(),
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
clientInstance?.endConnection()
|
||||
clientInstance = null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
package app.k9mail.feature.funding.googleplay.data.remote
|
||||
|
||||
import app.k9mail.feature.funding.googleplay.data.DataContract
|
||||
import app.k9mail.feature.funding.googleplay.data.DataContract.Remote
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
import com.android.billingclient.api.AcknowledgePurchaseParams
|
||||
import com.android.billingclient.api.BillingClient
|
||||
import com.android.billingclient.api.BillingClient.BillingResponseCode
|
||||
import com.android.billingclient.api.BillingClient.ProductType
|
||||
import com.android.billingclient.api.BillingResult
|
||||
import com.android.billingclient.api.ConsumeParams
|
||||
import com.android.billingclient.api.ProductDetails
|
||||
import com.android.billingclient.api.Purchase
|
||||
import com.android.billingclient.api.acknowledgePurchase
|
||||
import com.android.billingclient.api.consumePurchase
|
||||
import net.thunderbird.core.common.cache.Cache
|
||||
import net.thunderbird.core.logging.Logger
|
||||
|
||||
// TODO propagate errors via Outcome
|
||||
// TODO optimize purchase handling and reduce duplicate code
|
||||
@Suppress("TooManyFunctions")
|
||||
internal class GoogleBillingPurchaseHandler(
|
||||
private val productCache: Cache<String, ProductDetails>,
|
||||
private val productMapper: DataContract.Mapper.Product,
|
||||
private val logger: Logger,
|
||||
) : Remote.GoogleBillingPurchaseHandler {
|
||||
|
||||
override suspend fun handlePurchases(
|
||||
clientProvider: Remote.GoogleBillingClientProvider,
|
||||
purchases: List<Purchase>,
|
||||
): List<Contribution> {
|
||||
return purchases.flatMap { purchase ->
|
||||
handlePurchase(clientProvider.current, purchase)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun handleOneTimePurchases(
|
||||
clientProvider: Remote.GoogleBillingClientProvider,
|
||||
purchases: List<Purchase>,
|
||||
): List<OneTimeContribution> {
|
||||
return purchases.flatMap { purchase ->
|
||||
handleOneTimePurchase(clientProvider.current, purchase)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun handleRecurringPurchases(
|
||||
clientProvider: Remote.GoogleBillingClientProvider,
|
||||
purchases: List<Purchase>,
|
||||
): List<RecurringContribution> {
|
||||
return purchases.flatMap { purchase ->
|
||||
handleRecurringPurchase(clientProvider.current, purchase)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handlePurchase(
|
||||
billingClient: BillingClient,
|
||||
purchase: Purchase,
|
||||
): List<Contribution> {
|
||||
// TODO verify purchase with public key
|
||||
consumePurchase(billingClient, purchase)
|
||||
acknowledgePurchase(billingClient, purchase)
|
||||
|
||||
return extractContributions(purchase)
|
||||
}
|
||||
|
||||
private suspend fun handleOneTimePurchase(
|
||||
billingClient: BillingClient,
|
||||
purchase: Purchase,
|
||||
): List<OneTimeContribution> {
|
||||
// TODO verify purchase with public key
|
||||
consumePurchase(billingClient, purchase)
|
||||
|
||||
return extractOneTimeContributions(purchase)
|
||||
}
|
||||
|
||||
private suspend fun handleRecurringPurchase(
|
||||
billingClient: BillingClient,
|
||||
purchase: Purchase,
|
||||
): List<RecurringContribution> {
|
||||
// TODO verify purchase with public key
|
||||
acknowledgePurchase(billingClient, purchase)
|
||||
|
||||
return extractRecurringContributions(purchase)
|
||||
}
|
||||
|
||||
private suspend fun acknowledgePurchase(
|
||||
billingClient: BillingClient,
|
||||
purchase: Purchase,
|
||||
) {
|
||||
if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
|
||||
if (!purchase.isAcknowledged) {
|
||||
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
|
||||
.setPurchaseToken(purchase.purchaseToken)
|
||||
.build()
|
||||
|
||||
val acknowledgeResult: BillingResult = billingClient.acknowledgePurchase(acknowledgePurchaseParams)
|
||||
|
||||
if (acknowledgeResult.responseCode != BillingResponseCode.OK) {
|
||||
// TODO success
|
||||
} else {
|
||||
// handle acknowledge error
|
||||
logger.error(message = { "acknowledgePurchase failed" })
|
||||
}
|
||||
} else {
|
||||
logger.error(message = { "purchase already acknowledged" })
|
||||
}
|
||||
} else {
|
||||
logger.error(message = { "purchase not purchased" })
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun consumePurchase(
|
||||
billingClient: BillingClient,
|
||||
purchase: Purchase,
|
||||
) {
|
||||
val consumeParams = ConsumeParams.newBuilder()
|
||||
.setPurchaseToken(purchase.purchaseToken)
|
||||
.build()
|
||||
|
||||
// This could fail but we can ignore the error as we handle purchases
|
||||
// the next time the purchases are requested
|
||||
billingClient.consumePurchase(consumeParams)
|
||||
}
|
||||
|
||||
private fun extractContributions(purchase: Purchase): List<Contribution> {
|
||||
if (purchase.purchaseState != Purchase.PurchaseState.PURCHASED) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
return extractOneTimeContributions(purchase) + extractRecurringContributions(purchase)
|
||||
}
|
||||
|
||||
private fun extractOneTimeContributions(purchase: Purchase): List<OneTimeContribution> {
|
||||
if (purchase.purchaseState != Purchase.PurchaseState.PURCHASED) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
return purchase.products.mapNotNull { product ->
|
||||
productCache[product]
|
||||
}.filter { it.productType == ProductType.INAPP }
|
||||
.map { productMapper.mapToOneTimeContribution(it) }
|
||||
}
|
||||
|
||||
private fun extractRecurringContributions(purchase: Purchase): List<RecurringContribution> {
|
||||
if (purchase.purchaseState != Purchase.PurchaseState.PURCHASED) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
return purchase.products.mapNotNull { product ->
|
||||
productCache[product]
|
||||
}.filter { it.productType == ProductType.SUBS }
|
||||
.map { productMapper.mapToRecurringContribution(it) }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package app.k9mail.feature.funding.googleplay.domain
|
||||
|
||||
import android.app.Activity
|
||||
import app.k9mail.feature.funding.googleplay.data.DataContract
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import net.thunderbird.core.outcome.Outcome
|
||||
import net.thunderbird.core.outcome.flatMapSuccess
|
||||
import net.thunderbird.core.outcome.mapSuccess
|
||||
|
||||
internal class BillingManager(
|
||||
private val billingClient: DataContract.BillingClient,
|
||||
private val contributionIdProvider: DomainContract.ContributionIdProvider,
|
||||
) : DomainContract.BillingManager {
|
||||
|
||||
override val purchasedContribution: StateFlow<Outcome<Contribution?, BillingError>> =
|
||||
billingClient.purchasedContribution
|
||||
|
||||
override suspend fun loadOneTimeContributions(): Outcome<List<OneTimeContribution>, BillingError> {
|
||||
return billingClient.connect {
|
||||
billingClient.loadOneTimeContributions(
|
||||
productIds = contributionIdProvider.oneTimeContributionIds,
|
||||
).mapSuccess { contributions ->
|
||||
contributions.sortedByDescending { it.price }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadRecurringContributions(): Outcome<List<RecurringContribution>, BillingError> {
|
||||
return billingClient.connect {
|
||||
billingClient.loadRecurringContributions(
|
||||
productIds = contributionIdProvider.recurringContributionIds,
|
||||
).mapSuccess { contributions ->
|
||||
contributions.sortedByDescending { it.price }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadPurchasedContributions(): Outcome<List<Contribution>, BillingError> {
|
||||
return billingClient.connect {
|
||||
billingClient.loadPurchasedRecurringContributions().flatMapSuccess { recurringContributions ->
|
||||
if (recurringContributions.isEmpty()) {
|
||||
billingClient.loadPurchasedOneTimeContributionHistory().flatMapSuccess { contribution ->
|
||||
if (contribution != null) {
|
||||
Outcome.success(listOf(contribution))
|
||||
} else {
|
||||
Outcome.success(emptyList())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Outcome.success(recurringContributions.sortedByDescending { it.price })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun purchaseContribution(
|
||||
activity: Activity,
|
||||
contribution: Contribution,
|
||||
): Outcome<Unit, BillingError> {
|
||||
return billingClient.connect {
|
||||
billingClient.purchaseContribution(activity, contribution)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
billingClient.disconnect()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package app.k9mail.feature.funding.googleplay.domain
|
||||
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
// TODO should be provided externally per app variant
|
||||
class ContributionIdProvider :
|
||||
DomainContract.ContributionIdProvider {
|
||||
override val oneTimeContributionIds: ImmutableList<String> = persistentListOf(
|
||||
"contribution_tfa_onetime_xs",
|
||||
"contribution_tfa_onetime_s",
|
||||
"contribution_tfa_onetime_m",
|
||||
"contribution_tfa_onetime_l",
|
||||
"contribution_tfa_onetime_xl",
|
||||
"contribution_tfa_onetime_xxl",
|
||||
)
|
||||
|
||||
override val recurringContributionIds: ImmutableList<String> = persistentListOf(
|
||||
"contribution_tfa_monthly_xs",
|
||||
"contribution_tfa_monthly_s",
|
||||
"contribution_tfa_monthly_m",
|
||||
"contribution_tfa_monthly_l",
|
||||
"contribution_tfa_monthly_xl",
|
||||
"contribution_tfa_monthly_xxl",
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package app.k9mail.feature.funding.googleplay.domain
|
||||
|
||||
import android.app.Activity
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.AvailableContributions
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import net.thunderbird.core.outcome.Outcome
|
||||
|
||||
interface DomainContract {
|
||||
|
||||
interface UseCase {
|
||||
fun interface GetAvailableContributions {
|
||||
suspend operator fun invoke(): Outcome<AvailableContributions, BillingError>
|
||||
}
|
||||
}
|
||||
|
||||
interface ContributionIdProvider {
|
||||
val oneTimeContributionIds: ImmutableList<String>
|
||||
val recurringContributionIds: ImmutableList<String>
|
||||
}
|
||||
|
||||
interface BillingManager {
|
||||
/**
|
||||
* Flow that emits the last purchased contribution.
|
||||
*/
|
||||
val purchasedContribution: StateFlow<Outcome<Contribution?, BillingError>>
|
||||
|
||||
/**
|
||||
* Load contributions.
|
||||
*/
|
||||
suspend fun loadOneTimeContributions(): Outcome<List<OneTimeContribution>, BillingError>
|
||||
|
||||
/**
|
||||
* Load recurring contributions.
|
||||
*/
|
||||
suspend fun loadRecurringContributions(): Outcome<List<RecurringContribution>, BillingError>
|
||||
|
||||
/**
|
||||
* Load purchased contributions.
|
||||
*/
|
||||
suspend fun loadPurchasedContributions(): Outcome<List<Contribution>, BillingError>
|
||||
|
||||
/**
|
||||
* Purchase a contribution.
|
||||
*
|
||||
* @param activity The activity to use for the purchase flow.
|
||||
* @param contribution The contribution to purchase.
|
||||
* @return Outcome of the purchase.
|
||||
*/
|
||||
suspend fun purchaseContribution(
|
||||
activity: Activity,
|
||||
contribution: Contribution,
|
||||
): Outcome<Unit, BillingError>
|
||||
|
||||
/**
|
||||
* Release all resources.
|
||||
*/
|
||||
fun clear()
|
||||
}
|
||||
|
||||
sealed interface BillingError {
|
||||
val message: String
|
||||
|
||||
data class UserCancelled(
|
||||
override val message: String,
|
||||
) : BillingError
|
||||
|
||||
data class PurchaseFailed(
|
||||
override val message: String,
|
||||
) : BillingError
|
||||
|
||||
data class ServiceDisconnected(
|
||||
override val message: String,
|
||||
) : BillingError
|
||||
|
||||
data class DeveloperError(
|
||||
override val message: String,
|
||||
) : BillingError
|
||||
|
||||
data class UnknownError(
|
||||
override val message: String,
|
||||
) : BillingError
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package app.k9mail.feature.funding.googleplay.domain.entity
|
||||
|
||||
data class AvailableContributions(
|
||||
val oneTimeContributions: List<OneTimeContribution>,
|
||||
val recurringContributions: List<RecurringContribution>,
|
||||
val purchasedContribution: Contribution? = null,
|
||||
)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package app.k9mail.feature.funding.googleplay.domain.entity
|
||||
|
||||
interface Contribution {
|
||||
val id: String
|
||||
val title: String
|
||||
val description: String
|
||||
val price: Long
|
||||
val priceFormatted: String
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package app.k9mail.feature.funding.googleplay.domain.entity
|
||||
|
||||
data class OneTimeContribution(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val description: String,
|
||||
override val price: Long,
|
||||
override val priceFormatted: String,
|
||||
) : Contribution
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package app.k9mail.feature.funding.googleplay.domain.entity
|
||||
|
||||
data class RecurringContribution(
|
||||
override val id: String,
|
||||
override val title: String,
|
||||
override val description: String,
|
||||
override val price: Long,
|
||||
override val priceFormatted: String,
|
||||
) : Contribution
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package app.k9mail.feature.funding.googleplay.domain.usecase
|
||||
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingManager
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.UseCase
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.AvailableContributions
|
||||
import net.thunderbird.core.outcome.Outcome
|
||||
|
||||
class GetAvailableContributions(
|
||||
private val billingManager: BillingManager,
|
||||
) : UseCase.GetAvailableContributions {
|
||||
override suspend fun invoke(): Outcome<AvailableContributions, BillingError> {
|
||||
val oneTimeContributionsResult = billingManager.loadOneTimeContributions()
|
||||
val recurringContributionsResult = billingManager.loadRecurringContributions()
|
||||
val purchasedContributionResult = billingManager.loadPurchasedContributions()
|
||||
|
||||
return if (oneTimeContributionsResult is Outcome.Success &&
|
||||
recurringContributionsResult is Outcome.Success &&
|
||||
purchasedContributionResult is Outcome.Success
|
||||
) {
|
||||
Outcome.success(
|
||||
AvailableContributions(
|
||||
oneTimeContributions = oneTimeContributionsResult.data,
|
||||
recurringContributions = recurringContributionsResult.data,
|
||||
purchasedContribution = purchasedContributionResult.data.firstOrNull(),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
// TODO handle errors
|
||||
Outcome.failure(BillingError.UnknownError("Failed to load contributions"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.Event
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.State
|
||||
import net.thunderbird.core.ui.compose.common.modifier.testTagAsResourceId
|
||||
|
||||
@Composable
|
||||
internal fun ContributionContent(
|
||||
state: State,
|
||||
onEvent: (Event) -> Unit,
|
||||
contentPadding: PaddingValues,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
ResponsiveWidthContainer(
|
||||
modifier = modifier
|
||||
.testTagAsResourceId("ContributionContent")
|
||||
.padding(contentPadding),
|
||||
) { contentPadding ->
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = MainTheme.spacings.quadruple)
|
||||
.verticalScroll(scrollState)
|
||||
.padding(contentPadding),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.triple),
|
||||
) {
|
||||
ContributionHeader(
|
||||
purchasedContribution = state.purchasedContribution,
|
||||
)
|
||||
|
||||
if (state.showContributionList) {
|
||||
ContributionList(
|
||||
state = state.listState,
|
||||
onOneTimeContributionTypeClick = {
|
||||
onEvent(Event.OnOneTimeContributionSelected)
|
||||
},
|
||||
onRecurringContributionTypeClick = {
|
||||
onEvent(Event.OnRecurringContributionSelected)
|
||||
},
|
||||
onItemClick = {
|
||||
onEvent(Event.OnContributionItemClicked(it))
|
||||
},
|
||||
onRetryClick = {
|
||||
onEvent(Event.OnRetryClicked)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if (state.purchaseError != null) {
|
||||
ContributionError(
|
||||
error = state.purchaseError,
|
||||
onDismissClick = { onEvent(Event.OnDismissPurchaseErrorClicked) },
|
||||
)
|
||||
}
|
||||
|
||||
ContributionFooter(
|
||||
purchasedContribution = state.purchasedContribution,
|
||||
onPurchaseClick = { onEvent(Event.OnPurchaseClicked) },
|
||||
onManagePurchaseClick = { onEvent(Event.OnManagePurchaseClicked(it)) },
|
||||
onShowContributionListClick = { onEvent(Event.OnShowContributionListClicked) },
|
||||
isPurchaseEnabled = state.listState.selectedContribution != null,
|
||||
isContributionListShown = state.showContributionList,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.runtime.Stable
|
||||
import app.k9mail.core.ui.compose.common.mvi.UnidirectionalViewModel
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.LoadingErrorState
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal class ContributionContract {
|
||||
|
||||
interface ViewModel : UnidirectionalViewModel<State, Event, Effect>
|
||||
|
||||
@Stable
|
||||
data class State(
|
||||
val listState: ContributionListState = ContributionListState(),
|
||||
val purchasedContribution: Contribution? = null,
|
||||
|
||||
val showContributionList: Boolean = true,
|
||||
val showRecurringContributions: Boolean = false,
|
||||
|
||||
val purchaseError: BillingError? = null,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class ContributionListState(
|
||||
val oneTimeContributions: ImmutableList<OneTimeContribution> = persistentListOf(),
|
||||
val recurringContributions: ImmutableList<RecurringContribution> = persistentListOf(),
|
||||
val selectedContribution: Contribution? = null,
|
||||
val isRecurringContributionSelected: Boolean = true,
|
||||
|
||||
override val error: BillingError? = null,
|
||||
override val isLoading: Boolean = true,
|
||||
) : LoadingErrorState<BillingError>
|
||||
|
||||
sealed interface Event {
|
||||
data object OnOneTimeContributionSelected : Event
|
||||
data object OnRecurringContributionSelected : Event
|
||||
|
||||
data object OnShowContributionListClicked : Event
|
||||
|
||||
data class OnContributionItemClicked(
|
||||
val item: Contribution,
|
||||
) : Event
|
||||
|
||||
data object OnPurchaseClicked : Event
|
||||
|
||||
data class OnManagePurchaseClicked(
|
||||
val contribution: Contribution,
|
||||
) : Event
|
||||
|
||||
data object OnDismissPurchaseErrorClicked : Event
|
||||
|
||||
data object OnRetryClicked : Event
|
||||
}
|
||||
|
||||
sealed interface Effect {
|
||||
data class PurchaseContribution(
|
||||
val startPurchaseFlow: (Activity) -> Unit,
|
||||
) : Effect
|
||||
|
||||
data class ManageSubscription(
|
||||
val productId: String,
|
||||
) : Effect
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Surface
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icon
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyLarge
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodySmall
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import app.k9mail.feature.funding.googleplay.R
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError
|
||||
|
||||
@Composable
|
||||
fun ContributionError(
|
||||
error: BillingError?,
|
||||
onDismissClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
when (error) {
|
||||
is BillingError.DeveloperError,
|
||||
is BillingError.PurchaseFailed,
|
||||
is BillingError.ServiceDisconnected,
|
||||
is BillingError.UnknownError,
|
||||
-> ContributionErrorView(
|
||||
title = mapErrorToTitle(error),
|
||||
description = error.message,
|
||||
onDismissClick = onDismissClick,
|
||||
modifier = modifier,
|
||||
)
|
||||
|
||||
is BillingError.UserCancelled -> Unit // could be ignored
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContributionErrorView(
|
||||
title: String,
|
||||
description: String,
|
||||
onDismissClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val showDetails = remember { mutableStateOf(false) }
|
||||
|
||||
Surface(
|
||||
modifier = modifier
|
||||
.fillMaxWidth(),
|
||||
color = MainTheme.colors.errorContainer,
|
||||
shape = MainTheme.shapes.medium,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = MainTheme.spacings.double,
|
||||
vertical = MainTheme.spacings.default,
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.half),
|
||||
) {
|
||||
TextBodyLarge(
|
||||
text = title,
|
||||
color = MainTheme.colors.onErrorContainer,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
if (description.isNotEmpty()) {
|
||||
Icon(
|
||||
imageVector = if (showDetails.value) Icons.Outlined.ExpandLess else Icons.Outlined.ExpandMore,
|
||||
contentDescription = stringResource(R.string.funding_googleplay_contribution_error_show_more),
|
||||
modifier = Modifier
|
||||
.clickable { showDetails.value = !showDetails.value }
|
||||
.padding(MainTheme.spacings.quarter),
|
||||
)
|
||||
}
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Close,
|
||||
contentDescription = stringResource(R.string.funding_googleplay_contribution_error_dismiss_button),
|
||||
modifier = Modifier
|
||||
.clickable { onDismissClick() }
|
||||
.padding(MainTheme.spacings.quarter),
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility(visible = showDetails.value) {
|
||||
TextBodySmall(
|
||||
text = description,
|
||||
color = MainTheme.colors.onErrorContainer,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun mapErrorToTitle(error: BillingError): String {
|
||||
return when (error) {
|
||||
is BillingError.PurchaseFailed -> {
|
||||
stringResource(R.string.funding_googleplay_contribution_error_purchase_failed)
|
||||
}
|
||||
|
||||
is BillingError.ServiceDisconnected -> {
|
||||
stringResource(R.string.funding_googleplay_contribution_error_service_disconnected)
|
||||
}
|
||||
|
||||
is BillingError.DeveloperError,
|
||||
is BillingError.UnknownError,
|
||||
-> {
|
||||
stringResource(R.string.funding_googleplay_contribution_error_unknown)
|
||||
}
|
||||
|
||||
is BillingError.UserCancelled -> error("User cancelled not supported")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonFilled
|
||||
import app.k9mail.feature.funding.googleplay.R
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
|
||||
@Composable
|
||||
internal fun ContributionFooter(
|
||||
purchasedContribution: Contribution?,
|
||||
onPurchaseClick: () -> Unit,
|
||||
onManagePurchaseClick: (Contribution) -> Unit,
|
||||
onShowContributionListClick: () -> Unit,
|
||||
isPurchaseEnabled: Boolean,
|
||||
isContributionListShown: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
) {
|
||||
if (purchasedContribution != null && !isContributionListShown) {
|
||||
when (purchasedContribution) {
|
||||
is RecurringContribution -> {
|
||||
ButtonFilled(
|
||||
text = stringResource(
|
||||
R.string.funding_googleplay_contribution_footer_manage_button,
|
||||
),
|
||||
onClick = { onManagePurchaseClick(purchasedContribution) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
|
||||
is OneTimeContribution -> {
|
||||
ButtonFilled(
|
||||
text = stringResource(
|
||||
R.string.funding_googleplay_contribution_footer_show_contribution_list_button,
|
||||
),
|
||||
onClick = onShowContributionListClick,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ButtonFilled(
|
||||
text = stringResource(
|
||||
if (isPurchaseEnabled) {
|
||||
R.string.funding_googleplay_contribution_footer_payment_button
|
||||
} else {
|
||||
R.string.funding_googleplay_contribution_footer_payment_unavailable_button
|
||||
},
|
||||
),
|
||||
onClick = onPurchaseClick,
|
||||
enabled = isPurchaseEnabled,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icon
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.image.FixedScaleImage
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextHeadlineSmall
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import app.k9mail.feature.funding.googleplay.R
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.image.GoldenHearthSunburst
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.image.HearthSunburst
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun ContributionHeader(
|
||||
purchasedContribution: Contribution?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
AnimatedContent(
|
||||
targetState = purchasedContribution != null,
|
||||
label = "ContributionHeaderLogo",
|
||||
) { targetState ->
|
||||
when (targetState) {
|
||||
true -> {
|
||||
val contribution = purchasedContribution!!
|
||||
ContributionHeaderView(
|
||||
logo = GoldenHearthSunburst,
|
||||
title = ContributionIdStringMapper.mapToContributionTitle(contribution.id),
|
||||
description = ContributionIdStringMapper.mapToContributionDescription(contribution.id),
|
||||
showThankYou = true,
|
||||
benefits = ContributionIdStringMapper.mapToContributionBenefits(contribution.id),
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
false -> {
|
||||
ContributionHeaderView(
|
||||
logo = HearthSunburst,
|
||||
title = stringResource(R.string.funding_googleplay_contribution_header_title),
|
||||
description = stringResource(R.string.funding_googleplay_contribution_header_description),
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContributionHeaderView(
|
||||
logo: ImageVector,
|
||||
title: String,
|
||||
description: String,
|
||||
modifier: Modifier = Modifier,
|
||||
showThankYou: Boolean = false,
|
||||
benefits: ImmutableList<String> = persistentListOf(),
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.triple),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = MainTheme.spacings.triple)
|
||||
.height(MainTheme.sizes.large),
|
||||
) {
|
||||
FixedScaleImage(
|
||||
imageVector = logo,
|
||||
contentDescription = null,
|
||||
alignment = Alignment.TopCenter,
|
||||
allowOverflow = true,
|
||||
)
|
||||
}
|
||||
|
||||
TextHeadlineSmall(
|
||||
text = title,
|
||||
color = MainTheme.colors.primary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
if (showThankYou) {
|
||||
TextBodyMedium(
|
||||
text = stringResource(R.string.funding_googleplay_contribution_header_thank_you),
|
||||
)
|
||||
TextBodyMedium(
|
||||
text = stringResource(R.string.funding_googleplay_contribution_header_thank_you_message),
|
||||
)
|
||||
}
|
||||
|
||||
if (benefits.isNotEmpty()) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
) {
|
||||
benefits.forEach { benefit ->
|
||||
ContributionBenefit(
|
||||
benefit = benefit,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextBodyMedium(
|
||||
text = description,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContributionBenefit(
|
||||
benefit: String,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.half),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Dot,
|
||||
modifier = Modifier.size(MainTheme.sizes.small),
|
||||
)
|
||||
TextBodyMedium(
|
||||
text = benefit,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringArrayResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.k9mail.feature.funding.googleplay.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
// Ids need to be kept in sync with ContributionIdProvider.kt
|
||||
internal object ContributionIdStringMapper {
|
||||
|
||||
@Composable
|
||||
fun mapToContributionTitle(contributionId: String): String {
|
||||
return when (contributionId) {
|
||||
"contribution_tfa_onetime_xs" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_xs_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_onetime_s" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_s_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_onetime_m" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_m_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_onetime_l" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_l_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_onetime_xl" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_xl_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_onetime_xxl" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_xxl_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_xs" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_xs_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_s" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_s_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_m" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_m_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_l" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_l_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_xl" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_xl_title,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_xxl" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_xxl_title,
|
||||
)
|
||||
|
||||
else -> throw IllegalArgumentException("Unknown contribution ID: $contributionId")
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun mapToContributionDescription(contributionId: String): String {
|
||||
return when (contributionId) {
|
||||
"contribution_tfa_onetime_xs" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_xs_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_onetime_s" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_s_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_onetime_m" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_m_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_onetime_l" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_l_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_onetime_xl" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_xl_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_onetime_xxl" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_onetime_xxl_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_xs" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_xs_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_s" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_s_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_m" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_m_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_l" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_l_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_xl" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_xl_description,
|
||||
)
|
||||
|
||||
"contribution_tfa_monthly_xxl" -> stringResource(
|
||||
R.string.funding_googleplay_contribution_tfa_recurring_xxl_description,
|
||||
)
|
||||
|
||||
else -> throw IllegalArgumentException("Unknown contribution ID: $contributionId")
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun mapToContributionBenefits(contributionId: String): ImmutableList<String> {
|
||||
return when (contributionId) {
|
||||
"contribution_tfa_monthly_xs" -> stringArrayResource(
|
||||
R.array.funding_googleplay_contribution_tfa_recurring_xs_benefits,
|
||||
).toImmutableList()
|
||||
|
||||
"contribution_tfa_monthly_s" -> stringArrayResource(
|
||||
R.array.funding_googleplay_contribution_tfa_recurring_s_benefits,
|
||||
).toImmutableList()
|
||||
|
||||
"contribution_tfa_monthly_m" -> stringArrayResource(
|
||||
R.array.funding_googleplay_contribution_tfa_recurring_m_benefits,
|
||||
).toImmutableList()
|
||||
|
||||
"contribution_tfa_monthly_l" -> stringArrayResource(
|
||||
R.array.funding_googleplay_contribution_tfa_recurring_l_benefits,
|
||||
).toImmutableList()
|
||||
|
||||
"contribution_tfa_monthly_xl" -> stringArrayResource(
|
||||
R.array.funding_googleplay_contribution_tfa_recurring_xl_benefits,
|
||||
).toImmutableList()
|
||||
|
||||
"contribution_tfa_monthly_xxl" -> stringArrayResource(
|
||||
R.array.funding_googleplay_contribution_tfa_recurring_xxl_benefits,
|
||||
).toImmutableList()
|
||||
|
||||
else -> persistentListOf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.LinkAnnotation
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.text.withLink
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import app.k9mail.core.ui.compose.common.resources.annotatedStringResource
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Surface
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonText
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icon
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyLarge
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodySmall
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextLabelLarge
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorView
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.LoadingView
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import app.k9mail.feature.funding.googleplay.R
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ContributionListState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
internal fun ContributionList(
|
||||
state: ContributionListState,
|
||||
onOneTimeContributionTypeClick: () -> Unit,
|
||||
onRecurringContributionTypeClick: () -> Unit,
|
||||
onItemClick: (Contribution) -> Unit,
|
||||
onRetryClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Surface(
|
||||
color = MainTheme.colors.surfaceContainerLowest,
|
||||
shape = MainTheme.shapes.small,
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(MainTheme.spacings.double),
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
) {
|
||||
TextLabelLarge(
|
||||
text = stringResource(R.string.funding_googleplay_contribution_list_title),
|
||||
)
|
||||
|
||||
ContentLoadingErrorView(
|
||||
state = state,
|
||||
loading = {
|
||||
LoadingView()
|
||||
},
|
||||
error = { error ->
|
||||
ListErrorView(
|
||||
error = error,
|
||||
onRetryClick = onRetryClick,
|
||||
)
|
||||
},
|
||||
content = { state ->
|
||||
if (state.oneTimeContributions.isEmpty() && state.recurringContributions.isEmpty()) {
|
||||
ListEmptyView()
|
||||
} else {
|
||||
ListContentView(
|
||||
state = state,
|
||||
onOneTimeContributionTypeClick = onOneTimeContributionTypeClick,
|
||||
onRecurringContributionTypeClick = onRecurringContributionTypeClick,
|
||||
onItemClick = onItemClick,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
TextBodyMedium(
|
||||
text = buildAnnotatedString {
|
||||
withStyle(SpanStyle(fontStyle = FontStyle.Italic)) {
|
||||
append(stringResource(R.string.funding_googleplay_contribution_list_disclaimer))
|
||||
}
|
||||
},
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.default),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TypeSelectionRow(
|
||||
oneTimeContributions: ImmutableList<OneTimeContribution>,
|
||||
recurringContributions: ImmutableList<RecurringContribution>,
|
||||
isRecurringContributionSelected: Boolean,
|
||||
onOneTimeContributionTypeClick: () -> Unit,
|
||||
onRecurringContributionTypeClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = MainTheme.spacings.default),
|
||||
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
) {
|
||||
if (oneTimeContributions.isEmpty() && recurringContributions.isEmpty()) {
|
||||
ContributionListItem(
|
||||
text = stringResource(R.string.funding_googleplay_contribution_list_type_none_available),
|
||||
onClick = {},
|
||||
isSelected = true,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
} else {
|
||||
if (oneTimeContributions.isNotEmpty()) {
|
||||
ContributionListItem(
|
||||
text = stringResource(R.string.funding_googleplay_contribution_list_type_one_time),
|
||||
onClick = onOneTimeContributionTypeClick,
|
||||
isSelected = !isRecurringContributionSelected,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
if (recurringContributions.isNotEmpty()) {
|
||||
ContributionListItem(
|
||||
text = stringResource(R.string.funding_googleplay_contribution_list_type_recurring),
|
||||
onClick = onRecurringContributionTypeClick,
|
||||
isSelected = isRecurringContributionSelected,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
private fun ChoicesRow(
|
||||
contributions: ImmutableList<Contribution>,
|
||||
onItemClick: (Contribution) -> Unit,
|
||||
selectedItem: Contribution?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
modifier = modifier,
|
||||
) {
|
||||
contributions.forEach {
|
||||
ContributionListItem(
|
||||
text = it.priceFormatted,
|
||||
onClick = { onItemClick(it) },
|
||||
isSelected = it == selectedItem,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ListContentView(
|
||||
state: ContributionListState,
|
||||
onOneTimeContributionTypeClick: () -> Unit,
|
||||
onRecurringContributionTypeClick: () -> Unit,
|
||||
onItemClick: (Contribution) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
modifier = modifier,
|
||||
) {
|
||||
TypeSelectionRow(
|
||||
oneTimeContributions = state.oneTimeContributions,
|
||||
recurringContributions = state.recurringContributions,
|
||||
isRecurringContributionSelected = state.isRecurringContributionSelected,
|
||||
onOneTimeContributionTypeClick = onOneTimeContributionTypeClick,
|
||||
onRecurringContributionTypeClick = onRecurringContributionTypeClick,
|
||||
)
|
||||
|
||||
ChoicesRow(
|
||||
contributions = if (state.isRecurringContributionSelected) {
|
||||
state.recurringContributions
|
||||
} else {
|
||||
state.oneTimeContributions
|
||||
},
|
||||
selectedItem = state.selectedContribution,
|
||||
onItemClick = onItemClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ListEmptyView(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.double),
|
||||
modifier = modifier.padding(vertical = MainTheme.spacings.double),
|
||||
) {
|
||||
val annotatedString = annotatedStringResource(
|
||||
id = R.string.funding_googleplay_contribution_list_empty_message,
|
||||
argument = buildAnnotatedString {
|
||||
withStyle(
|
||||
style = SpanStyle(
|
||||
color = MainTheme.colors.primary,
|
||||
textDecoration = TextDecoration.Underline,
|
||||
),
|
||||
) {
|
||||
withLink(
|
||||
LinkAnnotation.Url(
|
||||
url = stringResource(R.string.funding_googleplay_thunderbird_website_url),
|
||||
),
|
||||
) {
|
||||
append(stringResource(R.string.funding_googleplay_thunderbird_website_domain))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
TextBodyMedium(
|
||||
text = stringResource(R.string.funding_googleplay_contribution_list_empty_title),
|
||||
)
|
||||
|
||||
TextBodyMedium(
|
||||
text = annotatedString,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ListErrorView(
|
||||
error: BillingError,
|
||||
onRetryClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val showDetails = remember { mutableStateOf(false) }
|
||||
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
modifier = modifier,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.half),
|
||||
) {
|
||||
TextBodyLarge(
|
||||
text = mapErrorToTitle(error),
|
||||
)
|
||||
if (error.message.isNotEmpty()) {
|
||||
Icon(
|
||||
imageVector = if (showDetails.value) Icons.Outlined.ExpandLess else Icons.Outlined.ExpandMore,
|
||||
contentDescription = "Show more details",
|
||||
modifier = Modifier
|
||||
.clickable { showDetails.value = !showDetails.value }
|
||||
.padding(MainTheme.spacings.quarter),
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility(visible = showDetails.value) {
|
||||
TextBodySmall(
|
||||
text = error.message,
|
||||
color = MainTheme.colors.onErrorContainer,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ButtonText(
|
||||
text = stringResource(R.string.funding_googleplay_contribution_list_error_retry_button),
|
||||
onClick = onRetryClick,
|
||||
modifier = Modifier.padding(top = MainTheme.spacings.default),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
internal fun ContributionListItem(
|
||||
text: String,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
isSelected: Boolean = false,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.border(
|
||||
width = if (isSelected) 2.dp else 1.dp,
|
||||
color = if (isSelected) MainTheme.colors.primary else MainTheme.colors.outlineVariant,
|
||||
shape = MainTheme.shapes.small,
|
||||
)
|
||||
.selectable(
|
||||
selected = isSelected,
|
||||
role = Role.RadioButton,
|
||||
onClick = onClick,
|
||||
),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
TextBodyMedium(
|
||||
text = text,
|
||||
modifier = Modifier.padding(
|
||||
horizontal = MainTheme.spacings.triple,
|
||||
vertical = MainTheme.spacings.oneHalf,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.LocalActivity
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.k9mail.core.ui.compose.common.mvi.observe
|
||||
import app.k9mail.core.ui.compose.designsystem.organism.TopAppBarWithBackButton
|
||||
import app.k9mail.core.ui.compose.designsystem.template.Scaffold
|
||||
import app.k9mail.feature.funding.googleplay.R
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ViewModel
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@Composable
|
||||
internal fun ContributionScreen(
|
||||
onBack: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: ViewModel = koinViewModel<ContributionViewModel>(),
|
||||
) {
|
||||
val activity = LocalActivity.current as ComponentActivity
|
||||
val context = LocalContext.current
|
||||
|
||||
val (state, dispatch) = viewModel.observe { effect ->
|
||||
when (effect) {
|
||||
is ContributionContract.Effect.ManageSubscription -> {
|
||||
context.startActivity(
|
||||
getManageSubscriptionIntent(
|
||||
productId = effect.productId,
|
||||
packageName = context.packageName,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
is ContributionContract.Effect.PurchaseContribution -> {
|
||||
effect.startPurchaseFlow(activity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BackHandler {
|
||||
onBack()
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = {
|
||||
TopAppBarWithBackButton(
|
||||
title = stringResource(R.string.funding_googleplay_contribution_title),
|
||||
onBackClick = onBack,
|
||||
)
|
||||
},
|
||||
) { innerPadding ->
|
||||
ContributionContent(
|
||||
state = state.value,
|
||||
onEvent = { dispatch(it) },
|
||||
contentPadding = innerPadding,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private const val SUBSCRIPTION_URL = "https://play.google.com/store/account/subscriptions"
|
||||
|
||||
private fun getManageSubscriptionIntent(
|
||||
productId: String,
|
||||
packageName: String,
|
||||
): Intent {
|
||||
val uri = Uri.parse(SUBSCRIPTION_URL)
|
||||
.buildUpon()
|
||||
.appendQueryParameter("sku", productId)
|
||||
.appendQueryParameter("package", packageName)
|
||||
.build()
|
||||
|
||||
return Intent(Intent.ACTION_VIEW, uri)
|
||||
}
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.contribution
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract
|
||||
import app.k9mail.feature.funding.googleplay.domain.DomainContract.UseCase
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.AvailableContributions
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.Contribution
|
||||
import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.Effect
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.Event
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.State
|
||||
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ViewModel
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.launch
|
||||
import net.thunderbird.core.outcome.handle
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
internal class ContributionViewModel(
|
||||
private val getAvailableContributions: UseCase.GetAvailableContributions,
|
||||
private val billingManager: DomainContract.BillingManager,
|
||||
initialState: State = State(),
|
||||
) : BaseViewModel<State, Event, Effect>(initialState),
|
||||
ViewModel {
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
loadAvailableContributions()
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
billingManager.purchasedContribution.collect { result ->
|
||||
result.handle(
|
||||
onSuccess = { purchasedContribution ->
|
||||
updateState { state ->
|
||||
state.copy(
|
||||
listState = state.listState.copy(
|
||||
isLoading = false,
|
||||
),
|
||||
purchasedContribution = purchasedContribution,
|
||||
showContributionList = purchasedContribution == null,
|
||||
purchaseError = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
onFailure = {
|
||||
updateState { state ->
|
||||
state.copy(
|
||||
listState = state.listState.copy(
|
||||
isLoading = false,
|
||||
),
|
||||
purchasedContribution = null,
|
||||
showContributionList = true,
|
||||
purchaseError = it,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadAvailableContributions() {
|
||||
getAvailableContributions().handle(
|
||||
onSuccess = { data ->
|
||||
updateState { state ->
|
||||
val selectedContribution = selectContribution(data)
|
||||
|
||||
state.copy(
|
||||
listState = state.listState.copy(
|
||||
oneTimeContributions = data.oneTimeContributions.toImmutableList(),
|
||||
recurringContributions = data.recurringContributions.toImmutableList(),
|
||||
selectedContribution = selectedContribution,
|
||||
isRecurringContributionSelected = selectedContribution is RecurringContribution,
|
||||
isLoading = false,
|
||||
),
|
||||
purchasedContribution = data.purchasedContribution,
|
||||
showContributionList = data.purchasedContribution == null,
|
||||
)
|
||||
}
|
||||
},
|
||||
onFailure = {
|
||||
updateState { state ->
|
||||
state.copy(
|
||||
listState = state.listState.copy(
|
||||
isLoading = false,
|
||||
error = it,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun selectContribution(data: AvailableContributions): Contribution? {
|
||||
val hasSelectedContribution = state.value.listState.selectedContribution != null &&
|
||||
(
|
||||
data.oneTimeContributions.contains(state.value.listState.selectedContribution) ||
|
||||
data.recurringContributions.contains(state.value.listState.selectedContribution)
|
||||
)
|
||||
|
||||
return if (hasSelectedContribution) {
|
||||
state.value.listState.selectedContribution
|
||||
} else {
|
||||
if (state.value.listState.isRecurringContributionSelected) {
|
||||
data.recurringContributions.getSecondLowestOrNull()
|
||||
} else {
|
||||
data.oneTimeContributions.getSecondLowestOrNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun event(event: Event) {
|
||||
when (event) {
|
||||
Event.OnOneTimeContributionSelected -> onOneTimeContributionSelected()
|
||||
Event.OnRecurringContributionSelected -> onRecurringContributionSelected()
|
||||
is Event.OnContributionItemClicked -> onContributionItemClicked(event.item)
|
||||
is Event.OnPurchaseClicked -> onPurchaseClicked()
|
||||
is Event.OnManagePurchaseClicked -> onManagePurchaseClicked(event.contribution)
|
||||
Event.OnShowContributionListClicked -> onShowContributionListClicked()
|
||||
Event.OnDismissPurchaseErrorClicked -> updateState {
|
||||
it.copy(
|
||||
purchaseError = null,
|
||||
)
|
||||
}
|
||||
|
||||
Event.OnRetryClicked -> onRetryClicked()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onOneTimeContributionSelected() {
|
||||
updateState {
|
||||
it.copy(
|
||||
listState = it.listState.copy(
|
||||
isRecurringContributionSelected = false,
|
||||
selectedContribution = it.listState.oneTimeContributions.getSecondLowestOrNull(),
|
||||
),
|
||||
showContributionList = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onRecurringContributionSelected() {
|
||||
updateState {
|
||||
it.copy(
|
||||
listState = it.listState.copy(
|
||||
isRecurringContributionSelected = true,
|
||||
selectedContribution = it.listState.recurringContributions.getSecondLowestOrNull(),
|
||||
),
|
||||
showContributionList = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<Contribution>.getSecondLowestOrNull(): Contribution? {
|
||||
return when {
|
||||
this.size > 1 -> this.sortedBy { it.price }[1]
|
||||
this.size == 1 -> this[0]
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun onContributionItemClicked(item: Contribution) {
|
||||
updateState {
|
||||
it.copy(
|
||||
it.listState.copy(
|
||||
selectedContribution = item,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onPurchaseClicked() {
|
||||
val selectedContribution = state.value.listState.selectedContribution ?: return
|
||||
|
||||
updateState {
|
||||
it.copy(
|
||||
listState = it.listState.copy(
|
||||
isLoading = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
emitEffect(
|
||||
Effect.PurchaseContribution(
|
||||
startPurchaseFlow = { activity ->
|
||||
viewModelScope.launch {
|
||||
billingManager.purchaseContribution(activity, selectedContribution).handle(
|
||||
onSuccess = {
|
||||
// we need to wait for the callback to be called
|
||||
},
|
||||
onFailure = { error ->
|
||||
updateState { state ->
|
||||
state.copy(
|
||||
listState = state.listState.copy(
|
||||
isLoading = false,
|
||||
),
|
||||
purchaseError = error,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun onManagePurchaseClicked(contribution: Contribution) {
|
||||
emitEffect(Effect.ManageSubscription(contribution.id))
|
||||
}
|
||||
|
||||
private fun onShowContributionListClicked() {
|
||||
updateState {
|
||||
it.copy(
|
||||
showContributionList = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onRetryClicked() {
|
||||
updateState {
|
||||
it.copy(
|
||||
listState = it.listState.copy(
|
||||
isLoading = true,
|
||||
error = null,
|
||||
),
|
||||
)
|
||||
}
|
||||
viewModelScope.launch {
|
||||
loadAvailableContributions()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
billingManager.clear()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
@file:Suppress("MagicNumber")
|
||||
|
||||
package app.k9mail.feature.funding.googleplay.ui.contribution.image
|
||||
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.graphics.vector.path
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
val GoldenHearthSunburst: ImageVector
|
||||
get() {
|
||||
if (goldenInstance != null) {
|
||||
return goldenInstance!!
|
||||
}
|
||||
goldenInstance = createInstance(
|
||||
name = "GoldenHearthSunburst",
|
||||
hearthColor = Color(0xFFFFC107),
|
||||
hearthOutline = Color(0xFFFFA500),
|
||||
)
|
||||
|
||||
return goldenInstance!!
|
||||
}
|
||||
|
||||
val HearthSunburst: ImageVector
|
||||
get() {
|
||||
if (instance != null) {
|
||||
return instance!!
|
||||
}
|
||||
instance = createInstance(
|
||||
name = "HearthSunburst",
|
||||
hearthColor = Color(0xFFEF4444),
|
||||
hearthOutline = Color(0xFFB91C1C),
|
||||
)
|
||||
|
||||
return instance!!
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
private fun createInstance(
|
||||
name: String,
|
||||
defaultWidth: Dp = 270.dp,
|
||||
defaultHeight: Dp = 204.dp,
|
||||
viewportWidth: Float = 270f,
|
||||
viewportHeight: Float = 204f,
|
||||
hearthColor: Color,
|
||||
hearthOutline: Color,
|
||||
): ImageVector {
|
||||
return ImageVector.Builder(
|
||||
name = name,
|
||||
defaultWidth = defaultWidth,
|
||||
defaultHeight = defaultHeight,
|
||||
viewportWidth = viewportWidth,
|
||||
viewportHeight = viewportHeight,
|
||||
).apply {
|
||||
path(fill = SolidColor(hearthColor)) {
|
||||
moveTo(120.38f, 18.74f)
|
||||
curveTo(120.1f, 18.74f, 119.82f, 18.88f, 119.66f, 19.15f)
|
||||
curveTo(119.43f, 19.54f, 119.64f, 19.76f, 119.92f, 20.26f)
|
||||
curveTo(121.35f, 22.8f, 121.49f, 21.82f, 121.01f, 19.95f)
|
||||
curveTo(120.87f, 19.41f, 121.09f, 19.05f, 120.75f, 18.85f)
|
||||
curveTo(120.64f, 18.78f, 120.51f, 18.74f, 120.38f, 18.74f)
|
||||
close()
|
||||
moveTo(117.56f, 19.82f)
|
||||
curveTo(117.25f, 19.82f, 117.11f, 20.29f, 117.44f, 21.18f)
|
||||
curveTo(117.94f, 22.48f, 119.4f, 22.63f, 118.62f, 20.97f)
|
||||
curveTo(118.35f, 20.4f, 118.05f, 20.05f, 117.81f, 19.9f)
|
||||
curveTo(117.72f, 19.85f, 117.63f, 19.83f, 117.56f, 19.82f)
|
||||
close()
|
||||
moveTo(150.85f, 20.17f)
|
||||
curveTo(150.72f, 20.17f, 150.59f, 20.21f, 150.48f, 20.27f)
|
||||
curveTo(150.14f, 20.48f, 150.36f, 20.84f, 150.22f, 21.38f)
|
||||
curveTo(149.74f, 23.25f, 149.88f, 24.23f, 151.31f, 21.68f)
|
||||
curveTo(151.59f, 21.19f, 151.8f, 20.97f, 151.57f, 20.58f)
|
||||
curveTo(151.41f, 20.31f, 151.13f, 20.16f, 150.85f, 20.17f)
|
||||
close()
|
||||
moveTo(114.53f, 20.85f)
|
||||
curveTo(114.24f, 20.86f, 113.93f, 21.05f, 113.77f, 21.31f)
|
||||
curveTo(113.53f, 21.72f, 113.67f, 22.24f, 114.07f, 22.48f)
|
||||
curveTo(114.48f, 22.72f, 115.86f, 23.35f, 116.27f, 23.14f)
|
||||
curveTo(116.62f, 22.96f, 115.57f, 21.71f, 114.94f, 21.02f)
|
||||
curveTo(114.9f, 20.98f, 114.85f, 20.94f, 114.81f, 20.92f)
|
||||
curveTo(114.72f, 20.87f, 114.63f, 20.85f, 114.53f, 20.85f)
|
||||
close()
|
||||
moveTo(153.67f, 21.25f)
|
||||
curveTo(153.6f, 21.25f, 153.51f, 21.28f, 153.42f, 21.33f)
|
||||
curveTo(153.18f, 21.48f, 152.88f, 21.83f, 152.61f, 22.4f)
|
||||
curveTo(151.83f, 24.06f, 153.29f, 23.91f, 153.79f, 22.61f)
|
||||
curveTo(154.12f, 21.72f, 153.98f, 21.25f, 153.67f, 21.25f)
|
||||
close()
|
||||
moveTo(156.7f, 22.28f)
|
||||
curveTo(156.6f, 22.28f, 156.51f, 22.3f, 156.42f, 22.35f)
|
||||
curveTo(156.38f, 22.37f, 156.33f, 22.41f, 156.29f, 22.45f)
|
||||
curveTo(155.66f, 23.14f, 154.61f, 24.39f, 154.96f, 24.57f)
|
||||
curveTo(155.37f, 24.78f, 156.75f, 24.15f, 157.15f, 23.91f)
|
||||
curveTo(157.56f, 23.67f, 157.7f, 23.14f, 157.46f, 22.74f)
|
||||
curveTo(157.3f, 22.48f, 156.99f, 22.28f, 156.7f, 22.28f)
|
||||
close()
|
||||
moveTo(113.29f, 24.11f)
|
||||
curveTo(113.01f, 24.12f, 112.69f, 24.32f, 112.55f, 24.55f)
|
||||
curveTo(112.33f, 24.93f, 112.47f, 25.43f, 112.87f, 25.66f)
|
||||
curveTo(113.27f, 25.9f, 115.03f, 26f, 115.21f, 25.6f)
|
||||
curveTo(115.39f, 25.21f, 114.01f, 24.9f, 113.67f, 24.3f)
|
||||
curveTo(113.64f, 24.24f, 113.59f, 24.19f, 113.54f, 24.16f)
|
||||
curveTo(113.46f, 24.12f, 113.38f, 24.1f, 113.29f, 24.11f)
|
||||
close()
|
||||
moveTo(157.94f, 25.53f)
|
||||
curveTo(157.85f, 25.53f, 157.77f, 25.55f, 157.69f, 25.59f)
|
||||
curveTo(157.64f, 25.62f, 157.59f, 25.67f, 157.56f, 25.73f)
|
||||
curveTo(157.21f, 26.32f, 155.84f, 26.64f, 156.02f, 27.03f)
|
||||
curveTo(156.2f, 27.43f, 157.96f, 27.33f, 158.36f, 27.09f)
|
||||
curveTo(158.76f, 26.85f, 158.9f, 26.36f, 158.68f, 25.98f)
|
||||
curveTo(158.54f, 25.75f, 158.22f, 25.55f, 157.94f, 25.53f)
|
||||
close()
|
||||
moveTo(113.96f, 27.5f)
|
||||
curveTo(113.74f, 27.51f, 113.55f, 27.54f, 113.38f, 27.72f)
|
||||
curveTo(113.06f, 28.06f, 113.11f, 28.44f, 113.58f, 28.54f)
|
||||
curveTo(113.9f, 28.6f, 114.14f, 28.53f, 114.39f, 28.32f)
|
||||
curveTo(114.79f, 27.98f, 114.82f, 27.73f, 114.61f, 27.6f)
|
||||
curveTo(114.52f, 27.55f, 114.37f, 27.51f, 114.19f, 27.51f)
|
||||
curveTo(114.11f, 27.5f, 114.03f, 27.5f, 113.96f, 27.5f)
|
||||
close()
|
||||
moveTo(157.27f, 28.93f)
|
||||
curveTo(157.2f, 28.93f, 157.12f, 28.93f, 157.04f, 28.94f)
|
||||
curveTo(156.86f, 28.94f, 156.71f, 28.97f, 156.62f, 29.03f)
|
||||
curveTo(156.41f, 29.16f, 156.43f, 29.41f, 156.84f, 29.75f)
|
||||
curveTo(157.09f, 29.96f, 157.33f, 30.03f, 157.65f, 29.96f)
|
||||
curveTo(158.12f, 29.87f, 158.17f, 29.49f, 157.85f, 29.15f)
|
||||
curveTo(157.68f, 28.97f, 157.49f, 28.93f, 157.27f, 28.93f)
|
||||
close()
|
||||
moveTo(143.51f, 48.26f)
|
||||
curveTo(142.89f, 48.3f, 142.71f, 49.43f, 141.91f, 50.3f)
|
||||
curveTo(140.81f, 51.5f, 139.65f, 52.62f, 140.7f, 53.15f)
|
||||
curveTo(142.39f, 53.97f, 144.52f, 48.64f, 143.68f, 48.28f)
|
||||
curveTo(143.67f, 48.28f, 143.65f, 48.27f, 143.64f, 48.27f)
|
||||
curveTo(143.59f, 48.26f, 143.55f, 48.26f, 143.51f, 48.26f)
|
||||
close()
|
||||
}
|
||||
path(
|
||||
fill = Brush.radialGradient(
|
||||
colorStops = arrayOf(
|
||||
0f to hearthColor,
|
||||
1f to hearthColor.copy(alpha = 0f),
|
||||
),
|
||||
center = Offset(134.18f, 39.04f),
|
||||
radius = 155.24f,
|
||||
),
|
||||
fillAlpha = 0.15f,
|
||||
strokeAlpha = 0.15f,
|
||||
) {
|
||||
moveTo(10.03f, 9.37f)
|
||||
curveTo(-6.4f, 9.37f, -0.97f, 89.68f, 14.26f, 85.6f)
|
||||
lineTo(97.33f, 37.63f)
|
||||
curveTo(94.06f, 29.77f, 94.39f, 26.19f, 96.7f, 18.26f)
|
||||
lineTo(10.03f, 9.37f)
|
||||
close()
|
||||
moveTo(258.49f, 9.37f)
|
||||
lineTo(171.82f, 18.26f)
|
||||
curveTo(174.7f, 26.17f, 173.89f, 29.99f, 171.19f, 37.63f)
|
||||
lineTo(254.26f, 85.6f)
|
||||
curveTo(274.78f, 91.1f, 273.85f, 9.37f, 258.49f, 9.37f)
|
||||
close()
|
||||
moveTo(105.07f, 47.53f)
|
||||
lineTo(25.02f, 146.39f)
|
||||
curveTo(6.37f, 178.71f, 66.1f, 215.9f, 85.07f, 183.03f)
|
||||
lineTo(117.92f, 60.39f)
|
||||
lineTo(105.07f, 47.53f)
|
||||
close()
|
||||
moveTo(163.45f, 47.53f)
|
||||
lineTo(150.59f, 60.39f)
|
||||
lineTo(183.45f, 183.03f)
|
||||
curveTo(207.39f, 224.52f, 273.35f, 198.12f, 243.49f, 146.39f)
|
||||
lineTo(163.45f, 47.53f)
|
||||
close()
|
||||
}
|
||||
path(
|
||||
fill = SolidColor(hearthOutline),
|
||||
fillAlpha = 0.2f,
|
||||
strokeAlpha = 0.2f,
|
||||
) {
|
||||
moveTo(161.54f, 39.01f)
|
||||
curveTo(164.61f, 35.95f, 166.16f, 32.4f, 166.16f, 28.11f)
|
||||
curveTo(166.16f, 23.82f, 164.61f, 19.38f, 161.54f, 16.31f)
|
||||
curveTo(158.47f, 13.25f, 154.47f, 11.71f, 150.46f, 11.71f)
|
||||
curveTo(146.46f, 11.71f, 142.45f, 14.33f, 139.38f, 17.39f)
|
||||
lineTo(135.69f, 21.08f)
|
||||
lineTo(132f, 17.39f)
|
||||
curveTo(128.93f, 14.33f, 124.92f, 11.71f, 120.92f, 11.71f)
|
||||
curveTo(116.91f, 11.71f, 112.91f, 13.25f, 109.84f, 16.31f)
|
||||
curveTo(106.77f, 19.38f, 105.25f, 23.82f, 105.25f, 28.11f)
|
||||
curveTo(105.25f, 32.4f, 106.77f, 35.95f, 109.84f, 39.01f)
|
||||
curveTo(117.43f, 46.42f, 124.46f, 53.41f, 131.63f, 61.22f)
|
||||
curveTo(132.65f, 62.24f, 134.17f, 63.25f, 135.69f, 63.25f)
|
||||
curveTo(137.21f, 63.25f, 138.73f, 62.24f, 139.75f, 61.22f)
|
||||
curveTo(146.77f, 53.28f, 154.04f, 46.51f, 161.54f, 39.01f)
|
||||
close()
|
||||
}
|
||||
path(fill = SolidColor(hearthOutline)) {
|
||||
moveTo(120.92f, 9.37f)
|
||||
curveTo(116.32f, 9.37f, 111.69f, 11.15f, 108.18f, 14.66f)
|
||||
curveTo(104.58f, 18.25f, 102.91f, 23.27f, 102.91f, 28.11f)
|
||||
curveTo(102.91f, 32.96f, 104.75f, 37.24f, 108.18f, 40.68f)
|
||||
curveTo(108.19f, 40.68f, 108.19f, 40.69f, 108.2f, 40.69f)
|
||||
curveTo(115.78f, 48.09f, 122.78f, 55.04f, 129.9f, 62.8f)
|
||||
curveTo(129.93f, 62.83f, 129.95f, 62.85f, 129.98f, 62.88f)
|
||||
curveTo(131.27f, 64.16f, 133.13f, 65.59f, 135.69f, 65.59f)
|
||||
curveTo(138.25f, 65.59f, 140.12f, 64.16f, 141.41f, 62.88f)
|
||||
curveTo(141.44f, 62.84f, 141.47f, 62.81f, 141.5f, 62.77f)
|
||||
curveTo(148.43f, 54.94f, 155.66f, 48.2f, 163.2f, 40.68f)
|
||||
curveTo(166.62f, 37.25f, 168.5f, 32.97f, 168.5f, 28.11f)
|
||||
curveTo(168.5f, 23.25f, 166.78f, 18.25f, 163.2f, 14.66f)
|
||||
curveTo(159.68f, 11.15f, 155.06f, 9.37f, 150.46f, 9.37f)
|
||||
curveTo(145.43f, 9.37f, 141.05f, 12.42f, 137.73f, 15.74f)
|
||||
lineTo(135.69f, 17.77f)
|
||||
lineTo(133.66f, 15.74f)
|
||||
curveTo(130.34f, 12.42f, 125.94f, 9.37f, 120.92f, 9.37f)
|
||||
close()
|
||||
moveTo(120.92f, 14.06f)
|
||||
curveTo(123.9f, 14.06f, 127.53f, 16.24f, 130.34f, 19.05f)
|
||||
lineTo(134.03f, 22.74f)
|
||||
curveTo(134.47f, 23.18f, 135.07f, 23.43f, 135.69f, 23.43f)
|
||||
curveTo(136.31f, 23.43f, 136.9f, 23.18f, 137.34f, 22.74f)
|
||||
lineTo(141.04f, 19.05f)
|
||||
curveTo(143.86f, 16.24f, 147.47f, 14.06f, 150.46f, 14.06f)
|
||||
curveTo(153.86f, 14.06f, 157.26f, 15.35f, 159.88f, 17.97f)
|
||||
curveTo(162.43f, 20.52f, 163.82f, 24.38f, 163.82f, 28.11f)
|
||||
curveTo(163.82f, 31.84f, 162.59f, 34.65f, 159.88f, 37.35f)
|
||||
curveTo(152.46f, 44.77f, 145.18f, 51.56f, 138.09f, 59.56f)
|
||||
curveTo(137.36f, 60.3f, 136.17f, 60.91f, 135.69f, 60.91f)
|
||||
curveTo(135.21f, 60.91f, 134.03f, 60.3f, 133.29f, 59.56f)
|
||||
curveTo(126.1f, 51.74f, 119.07f, 44.74f, 111.49f, 37.35f)
|
||||
curveTo(108.79f, 34.65f, 107.6f, 31.85f, 107.6f, 28.11f)
|
||||
curveTo(107.6f, 24.37f, 108.95f, 20.51f, 111.49f, 17.97f)
|
||||
curveTo(114.12f, 15.35f, 117.51f, 14.06f, 120.92f, 14.06f)
|
||||
close()
|
||||
}
|
||||
}.build()
|
||||
}
|
||||
|
||||
private var goldenInstance: ImageVector? = null
|
||||
private var instance: ImageVector? = null
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.reminder
|
||||
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import app.k9mail.feature.funding.api.FundingSettings
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.ExperimentalTime
|
||||
|
||||
class ActivityLifecycleObserver
|
||||
@OptIn(ExperimentalTime::class)
|
||||
constructor(
|
||||
private val settings: FundingSettings,
|
||||
private val clock: Clock = Clock.System,
|
||||
) : FundingReminderContract.ActivityLifecycleObserver {
|
||||
|
||||
private var lifecycleObserver: LifecycleObserver? = null
|
||||
|
||||
override fun register(lifecycle: Lifecycle, onDestroy: () -> Unit) {
|
||||
lifecycleObserver = createLifecycleObserver(onDestroy)
|
||||
|
||||
lifecycleObserver?.let {
|
||||
lifecycle.addObserver(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun unregister(lifecycle: Lifecycle) {
|
||||
lifecycleObserver?.let {
|
||||
lifecycle.removeObserver(it)
|
||||
lifecycleObserver = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLifecycleObserver(onDestroy: () -> Unit): DefaultLifecycleObserver {
|
||||
return object : DefaultLifecycleObserver {
|
||||
private var startTime: Long = 0L
|
||||
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
super.onResume(owner)
|
||||
@OptIn(ExperimentalTime::class)
|
||||
startTime = clock.now().toEpochMilliseconds()
|
||||
}
|
||||
|
||||
override fun onPause(owner: LifecycleOwner) {
|
||||
super.onPause(owner)
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
val endTime = clock.now().toEpochMilliseconds()
|
||||
val newActiveTime = endTime - startTime
|
||||
val oldActiveTime = settings.getActivityCounterInMillis()
|
||||
|
||||
if (newActiveTime >= 0) {
|
||||
settings.setActivityCounterInMillis(oldActiveTime + newActiveTime)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
super.onDestroy(owner)
|
||||
onDestroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.reminder
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
|
||||
|
||||
class FragmentLifecycleObserver(
|
||||
private val targetFragmentTag: String,
|
||||
) : FundingReminderContract.FragmentLifecycleObserver {
|
||||
|
||||
private var lifecycleCallbacks: FragmentLifecycleCallbacks? = null
|
||||
|
||||
override fun register(fragmentManager: FragmentManager, onShow: () -> Unit) {
|
||||
lifecycleCallbacks = createFragmentLifecycleCallback(
|
||||
onCallback = {
|
||||
onShow()
|
||||
unregister(fragmentManager)
|
||||
},
|
||||
)
|
||||
|
||||
// Register the lifecycle observer with the fragment manager.
|
||||
lifecycleCallbacks?.let {
|
||||
fragmentManager.registerFragmentLifecycleCallbacks(it, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun unregister(fragmentManager: FragmentManager) {
|
||||
lifecycleCallbacks?.let {
|
||||
fragmentManager.unregisterFragmentLifecycleCallbacks(it)
|
||||
lifecycleCallbacks = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFragmentLifecycleCallback(onCallback: () -> Unit): FragmentLifecycleCallbacks {
|
||||
return object : FragmentLifecycleCallbacks() {
|
||||
override fun onFragmentDetached(fragmentManager: FragmentManager, fragment: Fragment) {
|
||||
super.onFragmentDetached(fragmentManager, fragment)
|
||||
|
||||
if (fragment.tag == targetFragmentTag) {
|
||||
onCallback()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.reminder
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager.NameNotFoundException
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import app.k9mail.feature.funding.api.FundingSettings
|
||||
import app.k9mail.feature.funding.googleplay.ui.reminder.FundingReminderContract.ActivityLifecycleObserver
|
||||
import app.k9mail.feature.funding.googleplay.ui.reminder.FundingReminderContract.FragmentLifecycleObserver
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.ExperimentalTime
|
||||
|
||||
class FundingReminder
|
||||
@OptIn(ExperimentalTime::class)
|
||||
constructor(
|
||||
private val settings: FundingSettings,
|
||||
private val fragmentObserver: FragmentLifecycleObserver,
|
||||
private val activityCounterObserver: ActivityLifecycleObserver,
|
||||
private val dialog: FundingReminderContract.Dialog,
|
||||
private val clock: Clock = Clock.System,
|
||||
) : FundingReminderContract.Reminder {
|
||||
|
||||
override fun registerReminder(
|
||||
activity: AppCompatActivity,
|
||||
onOpenFunding: () -> Unit,
|
||||
) {
|
||||
// TODO: Let the caller make the decision on which FragmentManager to use.
|
||||
val dialogFragmentManager = activity.supportFragmentManager
|
||||
|
||||
// TODO: Let the caller provide this. Or, better yet, let the caller notify FundingReminder when it's a good
|
||||
// time to display the funding reminder dialog.
|
||||
val observedFragmentManager = activity.supportFragmentManager
|
||||
|
||||
dialogFragmentManager.setFragmentResultListener(
|
||||
FundingReminderContract.Dialog.FRAGMENT_REQUEST_KEY,
|
||||
activity,
|
||||
) { _, result ->
|
||||
if (result.getBoolean(FundingReminderContract.Dialog.FRAGMENT_RESULT_SHOW_FUNDING, false)) {
|
||||
onOpenFunding()
|
||||
}
|
||||
}
|
||||
|
||||
// If the reminder reference timestamp is not set, we set it to the first install time.
|
||||
if (settings.getReminderReferenceTimestamp() == 0L) {
|
||||
resetReminderReferenceTimestamp(activity)
|
||||
}
|
||||
|
||||
// We register the activity counter observer to keep track of the time the user spends in the app.
|
||||
// We also ensure that the observers are unregistered when the activity is destroyed.
|
||||
activityCounterObserver.register(activity.lifecycle) {
|
||||
fragmentObserver.unregister(observedFragmentManager)
|
||||
activityCounterObserver.unregister(activity.lifecycle)
|
||||
}
|
||||
|
||||
// If the reminder has already been shown, we don't need to show it again.
|
||||
if (wasReminderShown()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (shouldShowReminder()) {
|
||||
fragmentObserver.register(observedFragmentManager) {
|
||||
showFundingReminderDialog(dialogFragmentManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun wasReminderShown(): Boolean {
|
||||
return settings.getReminderShownTimestamp() != 0L
|
||||
}
|
||||
|
||||
private fun shouldShowReminder(): Boolean {
|
||||
@OptIn(ExperimentalTime::class)
|
||||
val currentTime = clock.now().toEpochMilliseconds()
|
||||
|
||||
return settings.getReminderShownTimestamp() == 0L &&
|
||||
settings.getReminderReferenceTimestamp() + FUNDING_REMINDER_DELAY_MILLIS <= currentTime &&
|
||||
settings.getActivityCounterInMillis() >= FUNDING_REMINDER_MIN_ACTIVITY_MILLIS
|
||||
}
|
||||
|
||||
@Suppress("SwallowedException")
|
||||
private fun resetReminderReferenceTimestamp(context: Context) {
|
||||
try {
|
||||
val installTime = context.packageManager.getPackageInfo(context.packageName, 0).firstInstallTime
|
||||
settings.setReminderReferenceTimestamp(installTime)
|
||||
} catch (exception: NameNotFoundException) {
|
||||
@OptIn(ExperimentalTime::class)
|
||||
settings.setReminderReferenceTimestamp(clock.now().toEpochMilliseconds())
|
||||
}
|
||||
}
|
||||
|
||||
private fun showFundingReminderDialog(fragmentManager: FragmentManager) {
|
||||
// We're about to show the funding reminder dialog. So mark it as being shown. This way, if there's an error,
|
||||
// we err on the side of the dialog not being shown rather than it being shown more than once.
|
||||
@OptIn(ExperimentalTime::class)
|
||||
settings.setReminderShownTimestamp(clock.now().toEpochMilliseconds())
|
||||
|
||||
dialog.show(fragmentManager)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.reminder
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.lifecycle.Lifecycle
|
||||
|
||||
// 1 week in milliseconds
|
||||
const val FUNDING_REMINDER_DELAY_MILLIS = 7 * 24 * 60 * 60 * 1000L
|
||||
|
||||
// 30 minutes in milliseconds
|
||||
const val FUNDING_REMINDER_MIN_ACTIVITY_MILLIS = 30 * 60 * 1000L
|
||||
|
||||
interface FundingReminderContract {
|
||||
|
||||
interface Reminder {
|
||||
fun registerReminder(activity: AppCompatActivity, onOpenFunding: () -> Unit)
|
||||
}
|
||||
|
||||
fun interface Dialog {
|
||||
fun show(fragmentManager: FragmentManager)
|
||||
|
||||
companion object {
|
||||
const val FRAGMENT_REQUEST_KEY = "funding_reminder_dialog"
|
||||
const val FRAGMENT_RESULT_SHOW_FUNDING = "show_funding"
|
||||
}
|
||||
}
|
||||
|
||||
interface FragmentLifecycleObserver {
|
||||
fun register(fragmentManager: FragmentManager, onShow: () -> Unit)
|
||||
fun unregister(fragmentManager: FragmentManager)
|
||||
}
|
||||
|
||||
interface ActivityLifecycleObserver {
|
||||
fun register(lifecycle: Lifecycle, onDestroy: () -> Unit)
|
||||
fun unregister(lifecycle: Lifecycle)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.reminder
|
||||
|
||||
import androidx.fragment.app.FragmentManager
|
||||
|
||||
class FundingReminderDialog : FundingReminderContract.Dialog {
|
||||
override fun show(fragmentManager: FragmentManager) {
|
||||
val dialogFragment = FundingReminderDialogFragment()
|
||||
dialogFragment.show(fragmentManager, null)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package app.k9mail.feature.funding.googleplay.ui.reminder
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import app.k9mail.feature.funding.googleplay.R
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
internal class FundingReminderDialogFragment : DialogFragment() {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val contentView = layoutInflater.inflate(R.layout.funding_googleplay_contribution_reminder, null)
|
||||
|
||||
return MaterialAlertDialogBuilder(requireContext())
|
||||
.setIcon(R.drawable.funding_googleplay_contribution_reminder_icon)
|
||||
.setTitle(R.string.funding_googleplay_contribution_reminder_title)
|
||||
.setView(contentView)
|
||||
.setPositiveButton(R.string.funding_googleplay_contribution_reminder_positive_button) { _, _ ->
|
||||
handlePositiveButton()
|
||||
}
|
||||
.setNegativeButton(R.string.funding_googleplay_contribution_reminder_negative_button, null)
|
||||
.create()
|
||||
}
|
||||
|
||||
private fun handlePositiveButton() {
|
||||
setFragmentResult(
|
||||
FundingReminderContract.Dialog.FRAGMENT_REQUEST_KEY,
|
||||
bundleOf(FundingReminderContract.Dialog.FRAGMENT_RESULT_SHOW_FUNDING to true),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:fillColor="#FFFEFFFF"
|
||||
android:pathData="M24 0A24 24 0 1 0 24 48 24 24 0 1 0 24 0z"/>
|
||||
<path
|
||||
android:fillColor="#FFB91C1C"
|
||||
android:fillAlpha="0.2"
|
||||
android:pathData="M35.23 26.78c1.32-1.32 1.98-2.85 1.98-4.7 0-1.84-0.66-3.75-1.98-5.07-1.32-1.31-3.05-1.97-4.77-1.97-1.72 0-3.44 1.12-4.76 2.44l-1.59 1.59-1.59-1.6c-1.32-1.31-3.04-2.43-4.76-2.43-1.72 0-3.45 0.66-4.77 1.97-1.32 1.32-1.97 3.23-1.97 5.08 0 1.84 0.65 3.37 1.97 4.69 3.27 3.18 6.29 6.19 9.37 9.55 0.44 0.43 1.1 0.87 1.75 0.87 0.65 0 1.3-0.44 1.75-0.87C28.88 32.9 32 30 35.23 26.78Z"/>
|
||||
<path
|
||||
android:fillColor="#FFB91C1C"
|
||||
android:pathData="M17.76 14.03c-1.98 0-3.97 0.76-5.48 2.27-1.54 1.55-2.27 3.7-2.27 5.79 0 2.08 0.8 3.92 2.27 5.4 3.27 3.19 6.28 6.18 9.34 9.51l0.03 0.04c0.56 0.55 1.36 1.16 2.46 1.16 1.1 0 1.9-0.6 2.46-1.16l0.04-0.05c2.98-3.37 6.09-6.26 9.33-9.5 1.47-1.47 2.28-3.31 2.28-5.4 0-2.09-0.74-4.24-2.28-5.79-1.51-1.5-3.5-2.27-5.48-2.27-2.16 0-4.05 1.31-5.47 2.74l-0.88 0.87-0.87-0.87c-1.43-1.43-3.32-2.74-5.48-2.74Zm0 2.01c1.28 0 2.84 0.94 4.05 2.15l1.59 1.59c0.19 0.19 0.44 0.3 0.7 0.3 0.28 0 0.53-0.11 0.72-0.3l1.6-1.59c1.2-1.2 2.76-2.15 4.04-2.15 1.46 0 2.92 0.56 4.05 1.69 1.1 1.1 1.7 2.75 1.7 4.36 0 1.6-0.53 2.8-1.7 3.97-3.19 3.2-6.32 6.11-9.37 9.55-0.31 0.32-0.82 0.58-1.03 0.58-0.2 0-0.71-0.26-1.03-0.58-3.1-3.36-6.12-6.37-9.37-9.55-1.17-1.16-1.68-2.36-1.68-3.97 0-1.61 0.58-3.27 1.68-4.36 1.12-1.13 2.58-1.69 4.05-1.69Z"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/funding_googleplay_contribution_reminder_statement"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/funding_googleplay_contribution_reminder_statement"
|
||||
android:textAppearance="?textAppearanceBodyMedium"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="•"
|
||||
android:textAppearance="?textAppearanceBodyMedium"
|
||||
tools:ignore="HardcodedText"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/funding_googleplay_contribution_reminder_statement_point_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="@string/funding_googleplay_contribution_reminder_statement_point_1"
|
||||
android:textAppearance="?textAppearanceBodyMedium"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="•"
|
||||
android:textAppearance="?textAppearanceBodyMedium"
|
||||
tools:ignore="HardcodedText"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/funding_googleplay_contribution_reminder_statement_point_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="@string/funding_googleplay_contribution_reminder_statement_point_2"
|
||||
android:textAppearance="?textAppearanceBodyMedium"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/funding_googleplay_contribution_reminder_claim"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/funding_googleplay_contribution_reminder_claim"
|
||||
android:textAppearance="?textAppearanceBodyMedium"
|
||||
android:textStyle="bold"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/funding_googleplay_contribution_reminder_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/funding_googleplay_contribution_reminder_message"
|
||||
android:textAppearance="?textAppearanceBodyMedium"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_title">ادعمْ ثَندَربِرْد</string>
|
||||
<string name="funding_googleplay_contribution_header_title">ادعم ثندربيرد</string>
|
||||
<string name="funding_googleplay_contribution_header_description">يتم تمويل ثندربيرد بالكامل من مساهمات مستخدمين مثلك. نحن لا نعرض إعلانات أو نبيع بياناتك أبداً. إذا كنت تستمتع بثندربيرد، يرجى المساعدة في دعمه. لا يمكننا القيام بذلك بدونك!</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">خالص الشكر منّا جميعاً!</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">إن مساهمتك تعزز من تطوير ثندربرد ونحن ممتنون حقاً لدعمك.</string>
|
||||
<string name="funding_googleplay_contribution_list_title">المساهمة آمنة</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">تبرع مرة واحدة</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">شهرياً</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">لا يوجد</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">المساهمات غير معفاة من الضرائب كتبرعات خيرية.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">المساهمات داخل التطبيق غير متاحة حالياً.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">أعد المحاولة</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">مواصلة الدفع</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">الدفع غير متاح حالياً</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">تعديل الدفع الشهري</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">قدم مساهمة أخرى مؤثرة</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">عرض المزيد من التفاصيل</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">استبعاد الخطأ</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">خطأ غير معروف</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">فشلت عملية الشراء.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">المساهمات غير متاحة حالياً.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">المساهمة الأساسية</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">المساهمة القيمة</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">مساهمة هامة</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">مساهمة كبرى</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">مساهمة بارزة</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">مساهمة استثنائية</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">دعمكم يدفعنا إلى الأمام! فحتى أصغر المساهمات تخلق طفرات من التغيير، ونحن ممتنون للغاية لوجودكم معنا.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">أنت تساعدنا في تحقيق أشياء عظيمة! بمساهمتكم على هذا المستوى، فإنكم تساعدوننا على اتخاذ خطوات مجدية إلى الأمام مما يسمح لنا بمواصلة النمو.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">مساهمتك تتألق حقاً! إنكم تلعبون دوراً رئيسياً في النهوض برسالتنا، وتساعدوننا على تحقيق إنجازات مهمة وتحقيق تأثير أكبر.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">أنتم سبب كبير في قدرتنا على القيام بما نقوم به! فبفضل كرمكم، يمكننا أن نقوم بمشاريع أكبر ونحقق إنجازات جديدة معاً.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">دعمكم ملهم حقاً! فبفضل مساهمتكم الكبيرة، أصبحنا قادرين على تخطي الحدود والابتكار وتحقيق خطوات كبيرة نحو تحقيق أهدافنا.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">أنت تساعدنا حقاً في تحقيق أحلامنا الكبيرة! إن دعمكم المذهل يمكّننا من تحقيق ما هو استثنائي، ويترك أثراً دائماً على كل ما نقوم به.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">المساهمة الشهرية الأساسية</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">المساهمة الشهرية المقدرة</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">مساهمة شهرية هامة</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">مساهمتك تساعدنا على النمو واتخاذ خطوات هادفة إلى الأمام - شكراً لك!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">دعمكم يدفعنا إلى الأمام! كل مساهمة تُحدث تغييراً - شكراً لكم!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">مساهمة شهرية استثنائية</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">مساهمة شهرية متميزة</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">مساهمة شهرية ضخمة</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">قم بزيارة <xliff:g id="link_text">%s</xliff:g> لمزيد من الطرق لدعم ثندربرد.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">ليس الآن</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">نعم</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">انضم إلى مهمتنا لابتكار أفضل تجربة بريد إلكتروني تحترم الخصوصية وقابلة للتخصيص.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">يتم تمويلنا فقط من خلال مستخدمين مثلك.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">نحن لا نبيع بياناتك.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">نحن لا نعرض الإعلانات.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">ثندربرد مجاني ومفتوح المصدر.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">ادعم ثندربرد</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">أنت تساعدنا على تحقيق أحلام كبيرة! دعمكم لنا يمكّننا من تحقيق أشياء غير عادية.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">دعمكم ملهم! فمساهمتكم تساعدنا على تخطي الحدود وتحقيق أهدافنا.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">أنت سبب كبير في قدرتنا على القيام بما نقوم به! إن كرمكم يساعدنا على تحقيق إنجازات جديدة.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">مساهمتك تلمع! أنت مفتاح النهوض بمهمتنا وتحقيق الأثر.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_title">Падтрымаць Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Падтрымаць Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Бяспечны ўнёсак</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Шчырая падзяка ад усіх нас!</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Ахвяраваць раз</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Штомесячна</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Працягнуць аплату</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Аплата зараз недаступная</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Невядомая памылка</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Каштоўныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Значныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Ваша падтрымка сапраўды натхняе! Дзякуючы вашаму значнаму ўнёску мы можам пашыраць межы, укараняць інавацыі і рабіць значныя крокі ў дасягненні нашых мэтаў.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Значныя штомесячныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Вялікія ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Мы не паказваем рэкламу.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Мы не прадаем вашы дадзеныя.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Мы фінансуемся выключна такімі карыстальнікамі, як вы.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Ваш унёсак спрыяе развіццю Thunderbird, і мы шчыра ўдзячныя за вашу падтрымку.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Ахвяраванні праз дадатак зараз немагчымыя.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Паўтарыць спробу</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Няма даступных</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Зрабіце яшчэ адзін важны ўнёсак</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Змяніць штомесячны плацёж</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Адхіліць памылку</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Паказаць больш падрабязнасцей</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Плацёж не выкананы.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Ахвяраванні пакуль недаступныя.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Істотныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Выключныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Выдатныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Ваш унёсак сапраўды ззяе! Вы адыгрываеце важную ролю ў прасоўванні нашай місіі, дапамагаеце нам дасягнуць важных этапаў і дасягнуць большага ўплыву.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Вы — вялікая прычына таго, чаму мы можам рабіць тое, што робім! Дзякуючы вашай шчодрасці мы можам брацца за больш маштабныя праекты і разам дасягаць новых вынікаў.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Вы сапраўды дапамагаеце нам марыць па-буйному! Ваша неверагодная падтрымка дае нам сілы дасягаць незвычайнага, пакідаючы працяглы ўплыў на ўсё, што мы робім.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Істотныя штомесячныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Вялікія штомесячныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Выдатныя штомесячныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Выключныя штомесячныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Ваш унёсак дапамагае нам развівацца і рабіць значныя крокі наперад — дзякуй!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">Ваш унёсак ззяе! Вы — ключ да прасоўвання нашай місіі і дасягнення вынікаў.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Ваша падтрымка рухае нас наперад! Кожны ўнёсак стварае змены — дзякуй!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Вы дапамагаеце нам марыць па-буйному! Ваша падтрымка дае нам сілы дасягаць незвычайных вынікаў.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Падтрымаць Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Далучайцеся да нашай місіі па стварэнні максімальна зручнай і наладжвальнай электроннай пошты, якая забезпечвае канфідэнцыяльнасць.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Так</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Не зараз</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird цалкам фінансуецца за кошт унёскаў такіх карыстальнікаў, як вы. Мы ніколі не паказваем рэкламу і не прадаем вашы даныя. Калі вам падабаецца Thunderbird, калі ласка, падтрымайце яго. Мы не можам зрабіць гэта без вас!</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Унёскі не вылічваюцца з падаткаў як дабрачынныя ахвяраванні.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Каштоўныя штомесячныя ахвяраванні</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird — гэта бясплатная праграма з адкрытым зыходным кодам.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Наведайце <xliff:g id="link_text">%s</xliff:g> каб даведацца больш пра спосабы падтрымкі Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Вы дапамагаеце нам рабіць вялікія справы! Робячы такі ўнёсак, вы дапамагаеце нам рабіць значныя крокі наперад, што дазваляе нам працягваць развіццё.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Ваша падтрымка дапамагае нам рухацца наперад! Нават самы маленькі ўнёсак стварае хвалі пераменаў, і мы вельмі ўдзячныя вам за вашу падтрымку.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Вы — вялікая прычына, чаму мы можам рабіць тое, што робім! Ваша шчодрасць дапамагае нам дасягаць новых вышынь.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Ваша падтрымка натхняе! Ваш унёсак дапамагае нам пашыраць межы і дасягаць нашых мэтаў.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_title">Подкрепа на Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Подкрепа на Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird се финансира изцяло от дарения от потребители като вас. Никога не показваме реклами и не продаваме вашите данни. Ако харесвате Thunderbird, моля, подкрепете ни. Не можем да го направим без вас!</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Сърдечно ви благодарим!</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Вашият принос допринася за развитието на Thunderbird и ние сме искрено благодарни за вашата подкрепа.</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Еднократно</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Защитенa вноска</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Месечно</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Не е достъпна</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Даренията не се признават за данъчни облекчения като благотворителни дарения.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">В момента не е възможно да се правят дарения в приложението.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Посетете <xliff:g id="link_text">%s</xliff:g>, за да видите как да подкрепите Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Отново</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Продължаване към плащането</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Плащането в момента не е достъпно</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Промяна на месечното плащане</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Направете друг значим принос</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Показване на повече детайли</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Отхвърлане на грешка</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Непозната грешка</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Неуспешна покупка.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Към момента даренията не са достъпни.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Съществен принос</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Ценен принос</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Значителен принос</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Голям принос</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Изключителен принос</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Невероятен принос</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Вашата подкрепа ни помага да продължаваме напред! Дори и най-малките приноси създават вълни на промяна и ние сме много благодарни, че сте с нас.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Вие ни помагате да постигнем велики неща! С вашия принос на това ниво ни помагате да направим значими стъпки напред, които ни позволяват да продължим да се развиваме.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Вашият принос наистина блести! Вие играете важна роля в напредъка на нашата мисия, като ни помагате да постигнем важни цели и да окажем по-голямо влияние.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Вие сте основната причина, поради която можем да правим това, което правим! Благодарение на вашата щедрост можем да се заемем с по-големи проекти и да постигнем нови успехи заедно.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Вашата подкрепа е наистина вдъхновяваща! Благодарение на вашия значителен принос, ние можем да разширяваме границите, да внедряваме иновации и да правим значителни стъпки към постигането на нашите цели.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Вие наистина ни помагате да мечтаем за големи неща! Вашата невероятна подкрепа ни дава сили да постигнем необикновени резултати, които оставят траен отпечатък върху всичко, което правим.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Вашата подкрепа ни дава сили да продължаваме напред! Всяка вноска води до промяна – благодарим ви!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Подкрепа на Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird е свободен и с отворен код.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Не показваме реклами.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Не продаваме данните ви.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Ние се финансираме изцяло от потребители като вас.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Присъединете се към нашата мисия да създадем възможно най-доброто преживяване при използването на имейл, което зачита личните данни и може да се персонализира.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Да</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Не сега</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Вашият принос ни помага да се развиваме и да правим значими стъпки напред – благодарим ви!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">Вашият принос е от голямо значение! Вие сте ключът към напредъка на нашата мисия и постигането на резултати.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Вие сте основната причина да можем да правим това, което правим! Вашата щедрост ни помага да постигаме нови успехи.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Вашата подкрепа е вдъхновяваща! Вашият принос ни помага да разширяваме границите и да постигаме целите си.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Вие ни помагате да мечтаем за големи неща! Вашата подкрепа ни дава сили да постигнем невероятни резултати.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Месечно дарение</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Месечно дарение</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Месечно дарение</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Месечно дарение</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Месечно дарение</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Месечно дарение</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="funding_googleplay_contribution_title">Thunderbird Skoazell</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Thunderbird Skoazell</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_list_title">Contribució segura</string>
|
||||
<string name="funding_googleplay_contribution_title">Dóna suport a Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Donació única</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Continua amb el pagament</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Feu una altra contribució impactant</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Dóna suport a Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Mensual</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird està totalment finançat amb les contribucions econòmiques d\'usuaris com tu. Mai mostrem anuncis ni venem les teves dades. Si t\'agrada Thunderbird, si us plau, ajudeu a donar-li suport. No podem fer això sense tu!</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Cap disponible</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Les contribucions no són deduïbles fiscalment com a donacions benèfiques.</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Modifica el pagament mensual</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Visiteu <xliff:g id="link_text">%s</xliff:g> per obtenir més maneres de donar suport al Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Actualment, les contribucions des de l\'aplicació no estan disponibles.</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Mostra més detalls</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Error desconegut</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">La compra ha fallat.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">En aquest moment les contribucions no estan disponibles.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Contribució essencial</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Contribució destacada</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Contribució valuosa</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Contribució important</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Gran contribució</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Contribució excepcional</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">La teva contribució enforteix el desenvolupament del Thunderbird i t\'agraïm de tot cor el teu suport.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Torna-ho a provar</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">El pagament no està disponible en aquests moments</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Ignora l\'error</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">El vostre suport ens fa avançar! Fins i tot les contribucions més petites generen un canvi, i estem molt agraïts de tenir-vos a bord.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Gràcies de tot cor de part de tots nosaltres!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">El teu suport és realment inspirador! Gràcies a la teva substancial contribució, som capaços de superar els límits, innovar i progressar significativament cap als nostres objectius.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Contribució mensual important</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Contribució mensual excepcional</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">La teva contribució brilla! Ets clau per a impulsar la nostra missió i assolir un impacte.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Ets una de les raons principals per les quals podem fer el que fem! La teva generositat ens ajuda a assolir noves fites.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird és gratuït i de codi obert.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">No mostrem anuncis.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">No venem les teves dades.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Ens financem únicament gràcies a usuaris com tu.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Ets una gran raó per la qual podem fer el que fem! Gràcies a la teva generositat, podem prendre projectes més grans i assolir noves fites junts.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">La teva contribució ens ajuda a créixer i a fer passos importants endavant. Moltes gràcies!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Sí</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">La teva contribució realment brilla! Estàs exercint un paper important en l\'avenç del anostra missió, ajudant-nos a assolir fites importants i aconseguir un impacte major.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Realment ens estàs ajudant a somiar en gran! El teu increïble suport ens empodera per a aconseguir l\'extraordinari, deixant un impacte durador en tot el que fem.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Contribució mensual essencial</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Una valiosa contribució mensual</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">El teu suport ens impulsa endavant! Cada contribució crea un canvi - gràcies!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Ens ajudes a somiar en gran! El teu suport ens permet aconseguir coses extraordinàries.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Donar suport a Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">El teu suport és inspirador! La teva contribució ens ajuda a superar els límits i assolir les nostres fites.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Dona suport a la nostra missió de crear la millor experiència de correu electrònic possible que respecta la privacitat i és personalitzable.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Ens estàs ajudant a fer grans coses! Contribuint en aquest nivell, ens estàs ajudant a fer passos significatius cap endavant que ens permetran continuar creixent.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Contribució mensual significativa</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Contribució mensual destacada</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Ara no</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_header_title">Sustene Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Cuntribuzione assicurata</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Dà una volta</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Ogni mese</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Nisuna dispunibule</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Cuntinuà u pagamentu</string>
|
||||
<string name="funding_googleplay_contribution_title">Sustene Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Ora, e cuntribuzioni ùn sò micca dispunibule via l’appiecazione.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Visitate u situ <xliff:g id="link_text">%s</xliff:g> per cunnosce parechje manere di sustene Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Pruvà torna</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Pagamentu indispunibule attualmente</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Mudificà u pagamentu misincu</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Fate un’altra cuntribuzione impurtantissima</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Affissà più d’infurmazioni</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Righjittà u sbagliu</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Sbagliu scunnisciutu</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Fiascu di a cumprera.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Ora, e cuntribuzioni ùn sò micca dispunibule.</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird hè finanziatu sanu sanu da e cuntribuzioni da i nostri utilizatori. Ùn affissemu alcuna publicità è un vindemu mai i vostri dati. S’è Thunderbird vi piace, aiutateci à sustenelu. Senza voi, ùn si pò fà què !</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">E cuntribuzioni ùn ponu micca esse scuntate da l’impositi cum’è e dunazioni.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Di core, vi ringraziemu tantu !</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">A vostra cuntribuzione favurisce u sviluppu di Thunderbird è vi simu assai ricunnuscente di u vostru sustene.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Cuntribuzione essenziale</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Cuntribuzione preziosa</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Cuntribuzione significativa</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Cuntribuzione impurtante</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Cuntribuzione straurdinaria</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Cuntribuzione eccezziunale</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Ci aiutate à fà cose maiò ! Cuntribuiscendu à stu livellu, ci aiutate à piglià misure nutevule chì ci permettenu di cuntinuà à cresce.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">U vostru sustegnu ci permette d’andà più luntanu ! Ancu e cuntribuzioni e più chjuche creanu onde di cambiamentu è vi ringraziemu assai di cuntavvi cù noi.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">A vostra cuntribuzione spampigliuleghja ! Ghjucate un rollu maiò in l’avanzamentu di a nostra missione, aiutenduci à francà tappe impurtante è ottene un impattu più maiò.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Ghjè grazia à voi chì no simu capace di fà ciò chì no femu ! A vostra generusità ci permette d’incaricacci prughjetti più maiò è di francà tappe nove, inseme.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Cuntribuzione misinca impurtante</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">U vostru sustegnu hè una vera stimulazione ! Grazia à a vostra cuntribuzione capitale, pudemu francà i cunfini, innuvà, è fà i passi maiò versu i nostri ogettivi.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Da veru, ci aiutate à sunnià tamantu ! U vostru sustegnu fantasticu ci dà a forza di realizà u straurdinariu, lasciendu un impattu durevule nant’à tuttu ciò chì no femu.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Cuntribuzione misinca essenziale</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Cuntribuzione misinca preziosa</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Cuntribuzione misinca significativa</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Cuntribuzione misinca straurdinaria</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Cuntribuzione misinca eccezziunale</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">U vostru sustegnu ci permette d’andà in avanti !Ogni cuntribuzione permette un cambiamentu, è vi ringraziemu !</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">A vostra cuntribuzione ci aiuta à cresce è à piglià misure nutevule per andà più luntanu. Vi ringraziemu !</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">U vostru sustegnu hè una stimulazione ! A vostra cuntribuzione ci aiuta à francà i cunfini è raghjunghje i nostri ogettivi.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Ghjè grazia à voi chì no pudemu fà ciò chì no femu ! A vostra generusità ci aiuta à francà tappe nove.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">A vostra cuntribuzione spampigliuleghja ! Ghjucate un rollu maiò in l’avanzamentu di a nostra missione è per ottene un impattu.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird un prugramma di rigalu è liberu.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Ùn affissemu alcuna publicità.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Ùn vindemu micca i vostri dati.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Simu finanziatu solu da i nostri utilizatori, cum’è voi.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Ci aiutate à sunnià tamantu ! U vostru sustegnu ci dà a forza di realizà cose straurdinarie.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Micca subitu</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Sì</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Sustene Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Raghjunghjite a nostra missione di creà a più bella esperienza di messaghjeria elettronica, persunalizavule è rispettosa di a vostra vita privata.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_list_title">Bezpečné přispění</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Jednou</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Pokračovat k platbě</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird je financován pouze dary od uživatelů, jako jste vy. Nikdy nezobrazujeme reklamy ani neprodáváme vaše data. Pokud se vám Thunderbird líbí, pomozte jej podpořit. Bez vás to nedokážeme!</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Příspěvky nelze odečíst z daní jako charitativní dary.</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Měsíčně</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Podpořte Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Nedostupné</string>
|
||||
<string name="funding_googleplay_contribution_title">Podpořte Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Upravit měsíční platbu</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Přispějte dalším významným příspěvkem</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Dary v aplikaci nejsou v tuto chvíli dostupné.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Zkusit znovu</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Platba není v tuto chvíli dostupná</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Zobrazit další podrobnosti</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Zavřít chybu</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Výjimečný měsíční dar</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Navštivte <xliff:g id="link_text">%s</xliff:g> pro další způsoby, jak podpořit Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Nákup se nezdařil.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Podstatný dar</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Dary nejsou v tuto chvíli dostupné.</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Neznámá chyba</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Cenný dar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Důležitý dar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Významný dar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Mimořádný dar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Vaše podpora nás posouvá vpřed! I ty nejmenší příspěvky udělají změnu a my jsme vděční za to, že jste s námi.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Výjimečný dar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Pomáháte nám uskutečňovat velké věci! Přispěním na této úrovni nám pomůžete dělat smysluplné kroky vpřed, které nám umožní další růst.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Cenný měsíční dar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Důležitý měsíční dar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Podstatný měsíční dar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Významný měsíční dar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Mimořádný měsíční dar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Díky vám můžeme dělat to, co děláme! Díky vaší štědrosti se můžeme pouštět do větších projektů a společně dosahovat nových milníků.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Vaše podpora je skutečně inspirující! Díky vašemu významnému příspěvku můžeme posouvat hranice, inovovat a významně se přibližovat k našim cílům.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Opravdu nám pomáháte dělat velké věci! Vaše neuvěřitelná podpora nám umožňuje dosahovat mimořádných úspěchů a zanechává trvalý dopad na vše, co děláme.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Váš příspěvek nám pomáhá růst a dělat smysluplné kroky vpřed – děkujeme!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">Váš příspěvek pomáhá! Jste klíčem k rozvoji našeho poslání a dosažení dopadu.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Díky vám můžeme dělat to, co děláme! Vaše štědrost nám pomáhá dosahovat nových milníků.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Vaše podpora je inspirující! Váš příspěvek nám pomáhá posouvat hranice a dosahovat našich cílů.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Připojte se k našemu poslání vytvořit nejlepší možnou přizpůsobitelnou e-mailovou službu respektující soukromí.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Ano</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Teď ne</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Váš příspěvek opravdu pomůže! Hrajete důležitou roli v rozvoji našeho poslání, pomáháte nám dosáhnout důležitých milníků a většího dopadu.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Vaše podpora nás žene kupředu! Každý příspěvek vytváří změnu – děkujeme!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Pomáháte nám dělat velké věci! Vaše podpora nám umožňuje dosahovat mimořádných úspěchů.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Podpořte Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Váš dar podporuje vývoj Thunderbirdu a my jsme za vaši podporu opravdu vděční.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Upřímné poděkování od nás všech!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Jsme financováni výhradně uživateli, jako jste vy.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird je zdarma a open-source.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Nezobrazujeme reklamy.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Neprodáváme vaše data.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_list_title">Sicher spenden</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Thunderbird unterstützen</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Monatlich</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Keine verfügbar</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Monatliche Zahlung ändern</string>
|
||||
<string name="funding_googleplay_contribution_title">Thunderbird unterstützen</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Die Spenden sind nicht als wohltätige Spenden steuerlich absetzbar.</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Weiter zur Zahlung</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Einmalig</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Leiste einen weiteren wirkungsvollen Beitrag</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Wiederholen</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Zahlung derzeit nicht möglich</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Weitere Details anzeigen</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Fehler verwerfen</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Unbekannter Fehler</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Kauf fehlgeschlagen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Maßgebliche Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Außergewöhnliche Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Du hilfst uns, Großes zu erreichen! Indem du einen solchen Spendenbeitrag leistest, hilfst du uns, einen bedeutenden Schritt vorwärts zu machen, damit wir weiter wachsen können.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Du bist ein wichtiger Grund dafür, dass wir tun können, was wir tun! Dank deiner Großzügigkeit können wir größere Projekte in Angriff nehmen und gemeinsam neue Meilensteine erreichen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Deine Unterstützung ist wirklich inspirierend! Dank deines erheblichen Spendenbeitrags sind wir in der Lage, Grenzen zu verschieben, Innovationen voranzutreiben und unseren Zielen ein gutes Stück näher zu kommen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Du hilfst uns wirklich, groß zu träumen! Deine unglaubliche Unterstützung ermöglicht es uns, Außergewöhnliches zu erreichen, und hinterlässt einen nachhaltigen Einfluss auf alles, was wir tun.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Grundlegende monatliche Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Wertvolle monatliche Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Signifikante monatliche Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Maßgebliche monatliche Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Dein Spendenbeitrag hilft uns zu wachsen und sinnvolle Schritte nach vorne zu machen — vielen Dank!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Du bist ein wichtiger Grund dafür, dass wir tun können, was wir tun! Deine Großzügigkeit hilft uns, neue Meilensteine zu erreichen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Du hilfst uns, große Träume zu verwirklichen! Deine Unterstützung befähigt uns, außergewöhnliche Dinge zu erreichen.</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird finanziert sich ausschließlich durch Beiträge von Nutzern wie dir. Wir zeigen keine Werbung und verkaufen deine Daten nicht. Wenn dir Thunderbird gefällt, hilf uns bitte, es zu unterhalten. Ohne dich können wir das nicht tun!</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">In-App-Spenden sind derzeit nicht verfügbar.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Besuche <xliff:g id="link_text">%s</xliff:g> für weitere Möglichkeiten zur Unterstützung von Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Spenden sind derzeit nicht verfügbar.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Grundlegende Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Wertvolle Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Signifikante Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Herausragende Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Deine Unterstützung bringt uns weiter voran! Selbst die kleinsten Spenden bewirken einen Wandel, und wir sind sehr dankbar, dass wir dich an Bord haben.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Dein Spenderbeitrag kann sich wirklich sehen lassen! Du spielst eine wichtige Rolle beim Weiterkommen unserer Mission, hilfst uns, wichtige Meilensteine zu erreichen und eine größere Wirkung zu erzielen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Herausragende monatliche Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Außergewöhnliche monatliche Spende</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Deine Unterstützung bringt uns voran! Jeder Beitrag schafft Veränderung — vielen Dank!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">Dein Spendenbeitag strahlt! Du bist der Schlüssel, um unseren Auftrag voranzubringen und Wirkung zu erzielen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Deine Unterstützung ist inspirierend! Dein Spendenbeitrag hilft uns, Grenzen zu überschreiten und unsere Ziele zu erreichen.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Thunderbird unterstützen</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Ja</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Schließe dich unserer Mission an, die bestmögliche E-Mail-Erfahrung zu schaffen, die den Datenschutz respektiert und anpassbar ist.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Jetzt nicht</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Dein Beitrag fördert die Entwicklung von Thunderbird und wir sind sehr dankbar für deine Unterstützung.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Ein herzliches Dankeschön von uns allen!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Wir zeigen keine Werbung an.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Wir verkaufen deine Daten nicht.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Wir werden ausschließlich von Nutzern wie dir finanziert.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird ist kostenlos und quelloffen.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_header_title">Υποστηρίξτε το Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_title">Υποστηρίξτε το Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Το Thunderbird χρηματοδοτείται εξ ολοκλήρου από συνεισφορές χρηστών όπως εσείς. Δεν προβάλλουμε ποτέ διαφημίσεις ούτε πωλούμε τα δεδομένα σας. Αν απολαμβάνετε το Thunderbird, βοηθήστε μας να το υποστηρίξουμε. Δεν μπορούμε να τα καταφέρουμε χωρίς εσάς!</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Εφάπαξ δωρεά</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Μηνιαία</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Κανένα διαθέσιμο</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Επισκεφθείτε το <xliff:g id="link_text">%s</xliff:g> για περισσότερους τρόπους υποστήριξης του Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Συνέχεια στην πληρωμή</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Η αγορά απέτυχε.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Οι συνεισφορές δεν είναι προς το παρόν διαθέσιμες.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Μας βοηθάτε να πραγματοποιήσουμε σπουδαία πράγματα! Συνεισφέροντας σε αυτό το επίπεδο, μας βοηθάτε να κάνουμε σημαντικά βήματα προς τα εμπρός, επιτρέποντάς μας να συνεχίσουμε να αναπτυσσόμαστε.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Απαραίτητη μηνιαία συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Το Thunderbird είναι δωρεάν και ανοιχτού κώδικα.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Η υποστήριξή σας εμπνέει! Η συνεισφορά σας μας βοηθά να ξεπεράσουμε τα όρια και να επιτύχουμε τους στόχους μας.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Δεν προβάλλουμε διαφημίσεις.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Δεν πωλούμε τα δεδομένα σας.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Χρηματοδοτούμαστε αποκλειστικά από χρήστες όπως εσείς.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Η συνεισφορά σας προάγει την ανάπτυξη του Thunderbird και είμαστε πραγματικά ευγνώμονες για την υποστήριξή σας.</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Οι συνεισφορές δεν εκπίπτουν φορολογικά ως φιλανθρωπικές δωρεές.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Επανάληψη</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Τροποποίηση μηνιαίας πληρωμής</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Κάντε άλλη μια ουσιαστική συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Πληρωμή προς το παρόν μη διαθέσιμη</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Εμφάνιση περισσότερων λεπτομερειών</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Απόρριψη σφάλματος</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Άγνωστο σφάλμα</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Εκτιμώμενη συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Σημαντική συμβολή</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Εξαιρετική συμβολή</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Εξαιρετική συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Η συμβολή σας πραγματικά λάμπει! Παίζετε σημαντικό ρόλο στην προώθηση της αποστολής μας, βοηθώντας μας να φτάσουμε σε σημαντικά ορόσημα και να επιτύχουμε μεγαλύτερο αντίκτυπο.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Εκτιμώμενη μηνιαία συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Σημαντική μηνιαία συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Εξαιρετική μηνιαία συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Φοβερή μηνιαία συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Η υποστήριξή σας μας οδηγεί μπροστά! Κάθε συνεισφορά δημιουργεί αλλαγή - σας ευχαριστούμε!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">Η συνεισφορά σας λάμπει! Είστε το κλειδί για την προώθηση της αποστολής μας και την επίτευξη αντίκτυπου.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Η συνεισφορά σας μας βοηθά να αναπτυχθούμε και να κάνουμε σημαντικά βήματα προς τα εμπρός - σας ευχαριστούμε!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Μας βοηθάτε να κάνουμε μεγάλα όνειρα! Η υποστήριξή σας μας δίνει τη δυνατότητα να πετύχουμε εκπληκτικά πράγματα.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Οι συνεισφορές εντός της εφαρμογής δεν είναι προς το παρόν διαθέσιμες.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Απαραίτητη συμβολή</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Σημαντική συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Σημαντικότερη μηνιαία συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Όχι τώρα</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Η υποστήριξή σας μας κρατάει μπροστά! Ακόμα και οι μικρότερες συνεισφορές δημιουργούν κυματισμούς αλλαγής και είμαστε ευγνώμονες που σας έχουμε μαζί μας.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Συμμετέχετε στην αποστολή μας να δημιουργήσουμε την καλύτερη δυνατή εμπειρία ηλεκτρονικού ταχυδρομείου με σεβασμό στην ιδιωτικότητα και δυνατότητα προσαρμογής.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Ένα ειλικρινές ευχαριστώ από όλους μας!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Ναι</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Ασφαλής συνεισφορά</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Είστε ένας σημαντικός λόγος που είμαστε σε θέση να κάνουμε αυτό που κάνουμε! Χάρη στη γενναιοδωρία σας, μπορούμε να αναλαμβάνουμε μεγαλύτερα έργα και να φτάνουμε μαζί σε νέα ορόσημα.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Μας βοηθάτε πραγματικά να κάνουμε μεγάλα όνειρα! Η απίστευτη υποστήριξή σας μας δίνει τη δυνατότητα να πετύχουμε το εξαιρετικό, αφήνοντας μόνιμο αντίκτυπο σε ό,τι κάνουμε.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Η υποστήριξή σας είναι πραγματικά εμπνευσμένη! Χάρη στην ουσιαστική συνεισφορά σας, είμαστε σε θέση να διευρύνουμε τα όρια, να καινοτομήσουμε και να κάνουμε σημαντικά βήματα προς την επίτευξη των στόχων μας.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Είστε ένας σημαντικός λόγος που μπορούμε να κάνουμε αυτό που κάνουμε! Η γενναιοδωρία σας μας βοηθά να φτάσουμε σε νέα ορόσημα.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Υποστηρίξτε το Thunderbird</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="funding_googleplay_contribution_title">Support Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Support Thunderbird</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="funding_googleplay_contribution_header_title">Subteni Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_title">Subteni Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Ne nun</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Subteni Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Jes</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird se financia en su totalidad con contribuciones de usuarios como tú. Nunca mostramos anuncios ni vendemos tus datos. Si disfrutas de Thunderbird, por favor, ayúdanos a mantenerlo. ¡No podemos hacer esto sin ti!</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Continuar con el pago</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Mensual</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Donación única</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Apoya Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Contribución segura</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Ninguno disponible</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Modifica el pago mensual</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Hacer otra contribución impactante</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Las contribuciones no son fiscalmente deducibles como donaciones benéficas.</string>
|
||||
<string name="funding_googleplay_contribution_title">Apoya Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Reintentar</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Pago no disponible</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Ver más detalles</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Rechazar error</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Error desconocido</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Compra fallida.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Actualmente, las colaboraciones no están disponibles.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Las colaboraciones dentro de la aplicación no están disponibles actualmente.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Visite <xliff:g id="link_text">%s</xliff:g> para conocer más formas de apoyar a Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Gran contribución</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Aporte excepcional</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">¡Tu colaboración realmente brilla! Está desempeñando un papel importante en el avance de nuestra misión, ayudándonos a alcanzar hitos importantes y lograr un mayor impacto.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Una valiosa contribución mensual</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Contribución mensual significativa</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Importante contribución mensual</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Contribución mensual pendiente</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Contribución mensual excepcional</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">¡Su apoyo nos impulsa hacia adelante! ¡Cada contribución crea un cambio -- gracias!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">¡Tu contribución brilla! Eres clave para impulsar nuestra misión y lograr un impacto.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Aportación esencial</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Colaboración valiosa</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Contribución destacada</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Contribución importante</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">¡Su apoyo nos mantiene avanzando! Incluso las contribuciones más pequeñas crean ondas de cambio, y estamos muy agradecidos de tenerlos a bordo.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">¡Nos estás ayudando a hacer grandes cosas! Al colaborar a este nivel, nos estás ayudando a dar pasos significativos hacia adelante que nos permitan seguir creciendo.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">¡Eres una gran razón para que podamos hacer lo que hacemos! Gracias a tu generosidad, podemos tomar proyectos más grandes y alcanzar nuevos hitos juntos.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">¡Su apoyo es verdaderamente inspirador! Gracias a su sustancial contribución, somos capaces de superar los límites, innovar y hacer progresos significativos hacia nuestros objetivos.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">¡Realmente nos estás ayudando a soñar a lo grande! Tu increíble apoyo nos empodera para lograr lo extraordinario, dejando un impacto duradero en todo lo que hacemos.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Contribución mensual esencial</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Su apoyo nos ayuda a crecer y dar pasos importantes hacia adelante. ¡Muchas gracias!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">¡Eres una de las razones principales por las que podemos hacer lo que hacemos! Su generosidad nos ayuda a alcanzar nuevas metas.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">¡Tu apoyo es inspirador! Tu contribución nos ayuda a superar los límites y alcanzar nuestras metas.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">¡Nos ayudas a soñar a lo grande! Tu apoyo nos permite lograr cosas extraordinarias.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Tu contribución promueve el desarrollo de Thunderbird y estamos realmente agradecidos por tu apoyo.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Soporte Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Apoye nuestra misión de crear la mejor experiencia de correo electrónico posible que respete la privacidad y sea personalizable.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Sí</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Ahora no</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">¡Un gracias sincero de parte de todos nosotros!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">No vendemos tus datos.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird es gratuito y de código abierto.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">No mostramos anuncios.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Nos financiamos únicamente gracias a usuarios como tu.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_header_title">Toeta Thunderbirdi</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Turvaline rahaline toetus</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Iga kuu</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Jätka maksega</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Pole saadaval</string>
|
||||
<string name="funding_googleplay_contribution_title">Toeta Thunderbirdi</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Meie rahastamine põhineb terves mahus vaid kasutajate toetustel. Me kunagi ei näita reklaame ega müü sinu andmeid. Kui sulle Thunderbird meeldib, siis palun aita meid. Me ei saaks jätkata ilma sinuta!</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Anneta üks kord</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Toetustel puudub maksuvabastus.</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Anna veel üks mõjus panus</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Muuda igakuist makset</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Rakenduse-sisene annetamise võimalus hetkel puudub.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Meie saidist <xliff:g id="link_text">%s</xliff:g> leiad veel võimalusi Thunderbirdi toetamiseks.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Proovi uuesti</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Maksmisvõimalus pole hetkel saadaval</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Näita lisateavet</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Sulge viga</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Tundmatu viga</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Suur panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Eriti märkimisväärne panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Igakuine väärtuslik panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Igakuine märgatav panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Igakuine suur panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Igakuine eriti märkimisväärne panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Sinu toetus viib meid edasi! Iga toetus loob muutusi - suur tänu!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Sa oled suur põhjus, miks me saame teha seda, mida me teeme! Sinu suuremeelsus aitab meil saavutada uusi verstaposte.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Väärtuslik panus</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Ostutehing ei õnnestunud.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Rahalise toetamise võimalus hetkel puudub.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Märgatav panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Sinu abi aitab meil edasi liikuda! Isegi väikseimad toetused tekitavad muutusi ja me oleme väga tänulikud, et oled meiega koos.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Vajalik panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Väljapaistev panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Sa aitad meil teha suuri asju! Sellisel tasemel panustades aitad meil astuda olulisi samme, mis võimaldavad meil jätkuvalt kasvada.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Sinu toetus paistab tõesti silma! Sa mängid olulist rolli meie missiooni edendamisel, aidates meil saavutada olulisi verstaposte ja saavutada suuremat mõju.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Sa oled suur põhjus, miks me saame teha seda, mida me teeme! Tänu sinu heldusele saame võtta ette suuremaid projekte ja saavutada koos uusi verstaposte.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Sinu toetus aitab meil kasvada ja astuda olulisi samme edasi - suur tänu!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Sinu toetus on inspireeriv! Sinu panus aitab meil ületada piire ja saavutada oma eesmärke.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Sinu toetus on tõeliselt inspireeriv! Tänu sinu märkimisväärsele panusele oleme võimelised laiendama piire, uuendama ja tegema märkimisväärseid edusamme meie eesmärkide saavutamisel.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Igakuine vajalik panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Sa tõesti aitad meil unistada suurelt! Sinu uskumatu toetus annab meile võimaluse saavutada erakordset, jättes püsiva mõju kõigele, mida me teeme.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Igakuine väljapaistev panus</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">Sinu toetus paistab silma! Sa oled meie missiooni edendamisel ja mõju saavutamisel võtmetähtsusega.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Sa aitad meil unistada suurelt! Sinu toetus annab meile võimaluse saavutada erakordseid asju.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Jah</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Mitte praegu</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Toeta Thunderbirdi</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Liitu meie missiooniga parima võimaliku privaatsustaustava ja kohandatava e-postikliendi loomisel.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Sinu toetus otseselt edendab Thunderbirdi arendust ja me oleme tänulikud sinu toe eest.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Siiras tänu sulle meie kõigi poolt!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Me ei näita reklaame.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird on tasuta ja põhineb avatud lähtekoodil.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Me ei müü sinu andmeid.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Meid rahastavad vaid sellised kasutajad, nagu sinagi.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Errore ezezaguna</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Lagundu Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Hilero</string>
|
||||
<string name="funding_googleplay_contribution_title">Lagundu Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Berriro saiatu</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Erakutsi xehetasun gehiago</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Baztertu errorea</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Bai</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Orain ez</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Ez dago ezer eskuragarririk</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Lagundu Thunderbirdi</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird doakoa eta kode irekikoa da.</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Eman behin</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">پرداخت یک باره</string>
|
||||
<string name="funding_googleplay_contribution_header_title">حمایت از تاندربرد</string>
|
||||
<string name="funding_googleplay_contribution_list_title">مشارکت امن</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">ماهانه</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">مشارکتها به عنوان اعانههای خیریه شامل مالیات نمیشوند.</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">ادامه به پرداخت</string>
|
||||
<string name="funding_googleplay_contribution_header_description">تاندربرد کاملاً به دست مشارکتهای مالی کاربرانمان مثل شما، تأمین میشود. ما هرگز تبلیغات نشان نداده یا دادههایتان را نمیفروشیم. لطفاً در حمایت از آن کمک کنید. ما نمی توانیم این کار را بدون شما انجام دهیم!</string>
|
||||
<string name="funding_googleplay_contribution_title">پشتیبانی تاندربرد</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">هیچ کدام موجود نیست</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">یک کمک موثر دیگر داشته باشید</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">پرداخت ماهانه را تغییر دهید</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">شما دلیل بزرگی هستید که ما می توانیم آنچه را که باید، انجام دهیم! به لطف سخاوت شما، ما می توانیم پروژه های بزرگتری را انجام دهیم و با هم به اهداف مهم جدیدی برسیم.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">کمک ماهانه قابل توجه</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">شما واقعاً به ما کمک می کنید رویای بزرگ داشته باشیم! حمایت باورنکردنی شما به ما قدرت میدهد تا به چیزهای خارقالعاده دست پیدا کنیم و تأثیری ماندگار بر هر کاری که انجام میدهیم بر جای بگذاریم.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">کمک ماهانه عمده</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">مشارکت شما به ما کمک میکند رشد کنیم و گامهای معنیداری به جلو برداریم—متشکریم!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">حمایت شما ما را به جلو میراند! هر مشارکتی تغییر ایجاد می کند - متشکریم!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">شما دلیل بزرگی هستید که ما میتوانیم آنچه را که باید، انجام دهیم! سخاوت شما به ما کمک می کند تا به اهداف مهم جدید برسیم.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">تلاش مجدد</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">مشارکت اساسی</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">مشارکت برجسته</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">حمایت شما موجب تداوم پیشرفت ما میشود! حتی کوچکترین مشارکتها موجهایی از تغییر ایجاد میکنند و ما از همراهی شما بسیار سپاسگزاریم.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">شما به ما کمک می کنید تا چیزهای بزرگی اتفاق بیفتد! با مشارکت در این سطح، به ما کمک میکنید گامهای مهمی رو به جلو برداریم تا به رشد خود ادامه دهیم.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">آری</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">اکنون خیر</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">مشارکت درونبرنامهای در حال حاضر در دسترس نیست.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">جهت راههای دیگر حمایت از تاندربرد، از <xliff:g id="link_text">%s</xliff:g> بازدید نمایید.</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">پرداخت در حال حاضر در دسترس نیست</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">نمایش جزییات بیشتر</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">نادیده گرفتن خطا</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">خطای ناشناخته</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">پرداخت ناموفق.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">مشارکت در حال حاضر در دسترس نیست.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">مشارکت ارزشمند</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">مشارکت قابل توجه</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">مشارکت عمده</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">مشارکت استثنایی</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">سهیم شدن شما واقعا میدرخشد! شما نقش مهمی در پیشبرد ماموریت ما ایفا میکنید و به ما کمک میکنید به اهداف مهم خود برسیم و به تأثیر بیشتر دست پیدا کنیم.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">حمایت شما واقعا الهام بخش است! به لطف کمک قابل توجه شما، ما قادریم مرزها را جابجا کنیم، نوآوری کنیم و گام های مهمی را در جهت اهداف خود برداریم.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">کمک ماهانه اساسی</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">کمک ماهانه ارزشمند</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">کمک ماهانه برجسته</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">کمک ماهانه استثنایی</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">سهیم شدن شما می درخشد! شما کلید پیشبرد ماموریت ما و دستیابی به تأثیرگذاری هستید.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">حمایت شما الهام بخش است! مشارکت شما به ما کمک می کند تا مرزها را پشت سر بگذاریم و به اهداف خود برسیم.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">شما به ما کمک می کنید رویای بزرگ داشته باشیم! حمایت شما ما را قادر میسازد تا به چیزهای خارق العادهای دست یابیم.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">حمایت از تاندربرد</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">به ماموریت ما بپیوندید تا بهترین تجربه رایانامه با احترام به حریم خصوصی و قابل شخصیسازی را ایجاد کنید.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">حمایت شما به طور مستقیم، تاندربرد را تقویت میکند و ما واقعا از حمایت شما سپاسگزاریم.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">یک تشکر صمیمانه از طرف همه ما!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">ما آگهی نمایش نمیدهیم.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">ما دادههای شما را نمیفروشیم.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">ما فقط توسط کاربرانی مانند شما تأمین مالی میشویم.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">تاندربرد آزاد و متنباز است.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Jatka maksuun</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Hylkää virhe</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Tuntematon virhe</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Osto epäonnistui.</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Tue Thunderbirdiä</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Kuukausittain</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Muokkaa kuukausittaista maksua</string>
|
||||
<string name="funding_googleplay_contribution_title">Tue Thunderbirdiä</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Auta pitämään Thunderbird elossa</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Yritä uudelleen</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Näytä enemmän tietoja</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Sovelluksen sisäiset lahjoitukset eivät ole tällä hetkellä saatavilla.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Käy osoitteessa <xliff:g id="link_text">%s</xliff:g> nähdäksesi lisää tapoja tukea Thunderbirdiä.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Tue Thunderbirdiä</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Tavoitteemme on tarjota avoimen lähdekoodin sähköpostisovellus, joka on turvallinen, yksityinen ja ilmainen kaikille. Taloudellinen tukesi auttaa työtämme. Lahjoitatko tänään?</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Kyllä</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Ei nyt</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Don unique</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Tous les mois</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Les contributions ne sont pas déductibles fiscalement en tant que dons de bienfaisance.</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Soutenir Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Contribution sécurisée</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Non proposée</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Poursuivre vers le paiement</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Modifier les mensualités</string>
|
||||
<string name="funding_googleplay_contribution_title">Soutenir Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Rendez-vous sur <xliff:g id="link_text">%s</xliff:g> pour découvrir d’autres façons de soutenir Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Réessayer</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Le paiement n’est pas accessible actuellement</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Faites un autre don remarqué</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Afficher plus de détails</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Rejeter l’erreur</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Erreur inconnue</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Échec de l’achat.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Les contributions ne sont pas accessibles actuellement.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Contribution essentielle</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Contribution importante</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Contribution extraordinaire</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Votre contribution se démarque. Vous jouez un rôle important dans l’avancement de notre mission en nous aidant à franchir des étapes importantes, pour un impact croissant.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">C’est en grande partie grâce à vous que nous pouvons faire ce que nous faisons. Votre générosité nous aide à franchir de nouvelles étapes.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Vous nous aidez vraiment à rêver grand. Votre soutien nous permet de réaliser l’extraordinaire.</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird est entièrement financée par les contributions de nos utilisateurs. Nous n’affichons aucune publicité ni ne vendons vos données. Si vous aimez Thunderbird, aidez-nous en la finançant. Votre soutien est essentiel.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Les contributions ne sont actuellement pas proposées dans l’appli.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Contribution appréciable</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Contribution substantielle</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Contribution exceptionnelle</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Votre soutien nous permet de poursuivre notre mission. Même les plus petites contributions ont des répercussions et nous sommes très reconnaissants de vous avoir à bord.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Vous nous aidez à réaliser de grandes choses. En contribuant à ce niveau, vous nous aidez à prendre des mesures significatives qui nous permettent notre croissance.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">C’est en grande partie grâce à vous que nous pouvons faire ce que nous faisons. Votre générosité nous permet d’entreprendre de plus grands projets et de franchir de nouvelles étapes, ensemble.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Votre soutien est une véritable source d’inspiration. Grâce à votre contribution substantielle, nous pouvons repousser les limites, innover et avancer à grands pas vers nos objectifs.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Vous nous aidez vraiment à rêver grand. Votre fantastique soutien nous permet de réaliser l’extraordinaire, en laissant un impact durable sur tout ce que nous accomplissons.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Contribution essentielle mensuelle</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Contribution appréciable mensuelle</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Contribution importante mensuelle</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Votre soutien nous permet d’avancer. Chaque contribution est source de changements. Merci.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Contribution substantielle mensuelle</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Contribution extraordinaire mensuelle</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Contribution exceptionnelle mensuelle</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Votre contribution alimente notre croissance et nous permet de prendre des mesures significatives pour aller de l’avant. Merci.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">Votre contribution se démarque. Vous jouez un rôle essentiel dans la poursuite de notre mission, pour un impact croissant.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Votre soutien est une source d’inspiration. Votre contribution nous aide à repousser les limites et à atteindre nos objectifs.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Soutenir Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Participez à notre mission de créer la meilleure expérience de courriel possible, qui respecte vos données personnelles.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Oui</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Pas maintenant</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Votre contribution financière alimente le développement de Thunderbird et nous sommes sincèrement reconnaissants de votre soutien.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Nous vous remercions tous sincèrement.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird est gratuite (logiciel libre).</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Nous n’affichons pas de publicités.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Nous ne vendons pas vos données.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Nous sommes entièrement financés par des utilisatrices et des utilisateurs tels que vous.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Trochgean nei ôfrekkenjen</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Moanliks</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Bydragen binne net ôflûkber as donaasjes foar goede doelen.</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Moanlikse betelling oanpasse</string>
|
||||
<string name="funding_googleplay_contribution_title">Stypje Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Stypje Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird wurdt folslein finansiere troch bydragen fan ús brûkers as jo. Wy toane jo nea advertinsjes en ferkeapje nea jo gegevens. As jo genietsje fan Thunderbird, stypje it dan. Wy kinne dit net sûnder jo!</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Feilige bydrage</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Donearje ien kear</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Neat beskikber</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Doch noch in bydrage mei impact</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Mear details toane</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Flatermelding slute</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Unbekende flater</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Bûtengewoane bydrage</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Signifikante moanlikse bydrage</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Bûtengewoane moanlikse bydrage</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Betelling op dit stuit beskikber</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Bydragen yn de app binne op dit stuit net beskikber.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Besykje <xliff:g id="link_text">%s</xliff:g> foar mear manieren om Thunderbird te stypjen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Grutte moanlikse bydrage</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Opnij probearje</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Bydragen binne op dit stuit beskikber.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Wurdearre bydrage</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Essinsjele bydrage</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Grutte bydrage</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Signifikante bydrage</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Eksepsjonele bydrage</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Wurdearre moanlikse bydrage</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Jo stipe helpt ús foarút te kommen! Sels de lytste bydragen kinne foar it ferskil soargje, en wy binne tankber jo oan board te hawwen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Essinsjele moanlikse bydrage</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Eksepsjonele moanlikse bydrage</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Jo helpe ús moaie dingen te ferwêzentliken! Troch op dit nivo by te dragen, helpe jo ús wichtige stappen foarút te meitsjen wat ús yn steat stelt fierder te groeien.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Jo bydrage jout glâns! Jo spylje in grutte rol yn de realisaasje fan ús misje, troch te helpen wichtige mylpeallen te berikjen en gruttere impact te krijen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Jo bydrage is echt ynspirearjend! Mei jo substansjele bydrage, kinne wy grinzen ferlizze, ynnovearje en signifikante stappen meitsje nei ús doelen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Jo helpe ús echt grut te dreamen! Jo geweldige stipe fersterket ús it bûtengewoane te berikken, mei in bliuwende impact op alles wat wy dogge.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Jo stipe helpt ús foarút! Elke bydrage liedt ta feroaring – tige tank!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">Jo bydrage jout glâns! Jo binne de kaai om ús misje fierder te bringen en impact te berikjen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Jo helpe ús echt grut te dreamen! Jo stipe fersterket ús it bûtengewoane te berikjen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Jo bydrage is echt ynspirearjend! Mei jo bydrage kinne wy grinzen ferlizze en ús doelen berikje.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Jo binne in grutte reden wêrtroch wy dwaan kinne wat wy dogge! Mei tank oan jo goederjouskens kinne wy gruttere projekten starte en tegearre nije mylpeallen berikje.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Jo binne in grutte reden wêrtroch wy dwaan kinne wat wy dogge! Mei tank oan jo goederjouskens kinne wy nije mylpeallen berikje.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Jo bydrage helpt ús te groeien en wichtige stappen foarút te nimmen – tige tank!</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Bydrage mislearre.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Doch mei oan ús misje om de beste privacy-respektearjende, oanpasbere e-mailûnderfinng mooglik te meitsjen.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Ja</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Stypje Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">No net</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Jo stipe bringt de ûntwikkeling fan Thunderbird fierder en wy binne tankber foar jo stipe.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Wy toane gjin advertinsjes.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Wy ferkeapje jo gegevens net.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Wy wurde allinnich finansiere troch brûkers lykas jo.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Us oprjochte tank oan jo!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird is fergees en iepen boarne.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_title">Tacaigh le Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Athraigh íocaíocht mhíosúil</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Déan cion tairbhe eile</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Tacaigh le Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Ranníocaíocht slán</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Go míosúil</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Tá Thunderbird maoinithe go hiomlán ag ranníocaíochtaí ó úsáideoirí cosúil leatsa. Ní thaispeánaimid fógraí ná ní dhíolaimid do shonraí riamh. Má tá tú ag baint sult as Thunderbird, le do thoil cabhrú leis. Ní féidir linn é seo a dhéanamh gan tú!</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Níl aon cheann ar fáil</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Tabhair uair amháin</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Níl ranníocaíochtaí inasbhainte ó thaobh cánach mar thabhartais charthanachta.</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Lean ar aghaidh chuig an íocaíocht</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Níl ranníocaíochtaí in-aip ar fáil faoi láthair.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Tabhair cuairt ar <xliff:g id="link_text">%s</xliff:g> le haghaidh tuilleadh bealaí chun tacaíocht a thabhairt do Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Earráid anaithnid</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Ranníocaíocht Mhíosúil Suntasach</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Bain triail eile as</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Níl an íocaíocht ar fáil faoi láthair</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Taispeáin tuilleadh sonraí</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Theip ar an gceannach.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Níl ranníocaíochtaí ar fáil faoi láthair.</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Earráid dhíbhe</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Coinníonn do thacaíocht muid ag bogadh ar aghaidh! Cruthaíonn fiú na ranníocaíochtaí is lú ripples an athraithe, agus tá muid chomh buíoch go bhfuil tú ar bord.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Ranníocaíocht Riachtanach</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Ranníocaíocht Mhór</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Ranníocaíocht Shuntasach</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Ranníocaíocht Luachmhar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Ranníocaíocht Mhíosúil Riachtanach</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Ranníocaíocht Mhíosúil Sármhaith</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Tiomáineann do thacaíocht muid ar aghaidh! Cruthaíonn gach ranníocaíocht athrú - go raibh maith agat!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Ranníocaíocht den Scoth</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Ranníocaíocht Eisceachtúil</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Tá tú ag cabhrú linn rudaí iontacha a bhaint amach! Trí rannchuidiú ag an leibhéal seo, tá tú ag cabhrú linn céimeanna suntasacha chun cinn a ghlacadh chun ligean dúinn leanúint ar aghaidh ag fás.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Is iontach an rud é do ranníocaíocht! Tá ról tábhachtach agat i gcur chun cinn ár misean, ag cabhrú linn garspriocanna tábhachtacha a bhaint amach agus tionchar níos mó a bhaint amach.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Is cúis mhór thú go bhfuil muid in ann an méid a dhéanaimid a dhéanamh! A bhuí le do fhlaithiúlacht, is féidir linn tionscadail mhóra a ghlacadh agus garspriocanna nua a bhaint amach le chéile.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Tá tú i ndáiríre ag cabhrú linn aisling mhór! Ligeann do thacaíocht dochreidte dúinn an rud neamhghnách a bhaint amach, rud a fhágann tionchar buan ar gach rud a dhéanaimid.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Ranníocaíocht Mhíosúil Luachmhar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Tá do thacaíocht fíor-spreagtha! A bhuí le do chion suntasach, is féidir linn teorainneacha a bhrú, nuálaíocht a dhéanamh agus dul chun cinn suntasach a dhéanamh i dtreo ár spriocanna.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Mór-Ranníocaíocht Mhíosúil</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Ranníocaíocht Mhíosúil Eisceachtúil</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Cuidíonn do ranníocaíocht linn fás agus céimeanna fiúntacha a ghlacadh chun tosaigh - go raibh maith agat!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">Tá do ranníocaíocht ag taitneamh! Tá tú ríthábhachtach chun ár misean a chur chun cinn agus tionchar a bhaint amach.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Is cúis mhór thú gur féidir linn an méid a dhéanaimid a dhéanamh! Cuidíonn do fhlaithiúlacht linn garspriocanna nua a bhaint amach.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Tá tú ag cabhrú linn aisling mhór! Cuireann do thacaíocht ar ár gcumas rudaí neamhghnácha a bhaint amach.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Tá do thacaíocht spreagúil! Cuidíonn do ranníocaíocht linn teorainneacha a bhrú agus ár spriocanna a bhaint amach.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Tacaigh le Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Tá</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Bí inár misean chun an t-eispéireas ríomhphoist saincheaptha is fearr agus is féidir a urramú do phríobháideacht.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Ní anois</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Cuireann bhur gcuid oibre le forbairt Thunderbird agus táimid fíor bhuíoch as bhur dtacaíocht.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Míle buíochas ó chroí libh go léir!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Tá Thunderbird saor in aisce agus foinse oscailte.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Ní thaispeánaimid fógraí.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Ní dhíolaimid do shonraí.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Tá muid maoinithe ag úsáideoirí cosúil leatsa amháin.</string>
|
||||
</resources>
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_title">Cùm taic ri Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Chan eil Thunderbird a’ faighinn maoineachadh ach na gheibh e de thabhartasan o dhaoine mar thu fhèin. Cha seall sinn sanasachd idir is cha reic sinn an dàta agad uair sam bith. Ma tha Thunderbird a’ còrdadh riut, nach cùm thu taic rinn? Cha dèan sinn seo as d’ aonais!</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Le taic mar seo, is urrainn dhuinn Thunderbird a shìor-leasachadh agus tha sinn fada nad chomain.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Mòran taing uainn uile!</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Tabhartas tèarainte</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Chan urrainn dhut tabhartasan a bheir thu dhuinn a thoirt air falbh o na cìsean agad mar thabhartas do charthannas.</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Air adhart a dhèanamh pàigheadh</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Thoir tabhartas buadhmhor eile</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Seall barrachd fiosrachaidh</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Chan urrainnear pàigheadh an-dràsta fhèin</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Cuir am pàigheadh mìosail air gleus</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Leis seachad a’ mhearachd</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Mearachd neo-aithnichte</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Tabhartas mòr</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Tabhartas air leth</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Chan urrainnear tabhartas a thoirt o bhroinn na h-aplacaid aig an ìre-sa.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Tadhail air <xliff:g id="link_text">%s</xliff:g> airson barrachd dhòighean air an cùm thu taic ri Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Feuch ris a-rithist</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Bun-tabhartas</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Tabhartas glè mhòr</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Cumaidh do thaic a’ doll sinn! Bidh buaidh aig fiù an tabhartas as lugha agus tha sinn cho toilichte gu bheil thu air bhòrd.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Gràinne-mhullaich nan tabhartasan</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Cùm taic ri Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Gach mìos</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Chan eil gin ri fhaighinn</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Dh’fhàillig a cheannach.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Chan urrainnear tabhartas a thoirt an-dràsta fhèin.</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Thoir tabhartas aon turas</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Tabhartas luachmhor</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Tha Thunderbird an-asgaidh ’s tha a chòd fosgailte.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Abair tabhartas! Tha thu air thoiseach mhòran ann a bhith a’ cur ris an iomairt againn ach an ruig sinn clachan-mìle cudromach is buaidh nas motha.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Chan ann an-dràsta</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Is treise sinn do thaic! Le bhith gar cuideachadh aig an ìre seo, ’s urrainn dhuinn ceuman mòra a ghabhail air adhart airson sìor-fhàs a dhèanamh.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Cùm taic ri Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Tha</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Cha seall sinn sanasachd.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Cha reic sinn an dàta agad.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Tha am maoineachadh air fad againn a’ tighinn o luchd-cleachdaidh mar thu fhèin.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_header_title">Támogassa a Thunderbirdöt</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Folytatás a fizetéshez</string>
|
||||
<string name="funding_googleplay_contribution_title">Támogassa a Thunderbirdöt</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">További adományozás</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Havi</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Nem érhető el</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Kiemelkedő havi hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Újra</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Keresse fel a <xliff:g id="link_text">%s</xliff:g> weboldalt a Thunderbird további támogatási módjaiért.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">A támogatása visz minket előre! Még a legkisebb hozzájárulások is számítanak, és nagyra értékeljük, hogy velünk van.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Értékes havi hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Most nem</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Csatlakozzon a küldetésünkhöz, hogy a lehető legjobb, adatvédelmet tiszteletben tartó, testreszabható levelezési élményt biztosítsuk.</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Részletek megjelenítése</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Hiba eltüntetése</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Ismeretlen hiba</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">A fizetés sikertelen.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Jelentős hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Létfontosságú havi hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Jelentős havi hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_header_description">A Thunderbirdöt teljes egészében az Önhöz hasonló felhasználók hozzájárulása finanszírozza. Sosem jelenítünk meg reklámokat, és nem adjuk el az adatait. Ha élvezi a Thunderbird használatát, segítsen a támogatásában. Ön nélkül ezt nem tudnánk megtenni!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">A Thunderbird szabad és nyílt forráskódú.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Hozzájárulása segít a Thunderbird fejlesztésének folytatásában, és nagyon hálásak vagyunk a támogatásért.</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Hálás köszönet mindannyiunktól!</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Biztonságos hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Egyszeri hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">A hozzájárulások nem vonhatók le az adóból jótékonysági adományként.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Az alkalmazáson belüli hozzájárulás jelenleg nem érhető el.</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">A fizetés jelenleg nem érhető el</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Havi összeg módosítása</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">A hozzájárulás jelenleg nem érhető el.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Létfontosságú hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Értékes hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Kiemelkedő hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Nagy értékű hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Kivételes hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Segít a nagy dolgok elérésében! Azzal, hogy ezen a szinten adományoz, segít minket abban, hogy jelentős lépéseket tegyünk a növekedésünk folytatásában.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">A hozzájárulása csak úgy ragyog! Jelentős szerepet játszik a küldetésünkben, segít minket a fontos mérföldkövek és a nagyobb hatás elérésében.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Nagyban hozzájárul ahhoz, hogy azt tehetjük, amit teszünk! Nagylelkűségének köszönhetően nagyobb projekteket vállalhatunk, és együtt új mérföldköveket érhetünk el.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">A támogatása igazán inspiráló! Jelentős hozzájárulásának köszönhetően feszegethetjük a határokat, innoválhatunk, és fontos lépéseket tehetünk a céljaink elérése érdekében.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Valóban segít minket nagyot álmodni! Hihetetlen támogatásával rendkívüli eredményeket érhetünk el, ez tartós hatással bír minden tevékenységünkre.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Kivételes havi hozzájárulás</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">A támogatása visz minket előre! Minden hozzájárulás változást hoz – köszönjük!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Hozzájárulása segít minket abban, hogy növekedjünk, és jelentős lépéseket tegyünk előre – köszönjük!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">A hozzájárulása csak úgy ragyog! Kulcsszerepet játszik a küldetésünkben és hatásunk elérésében.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Nagyban hozzájárul ahhoz, hogy azt tehetjük, amit teszünk! Nagylelkűségének köszönhetően új mérföldköveket érhetünk el.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">A támogatása inspiráló! Hozzájárulásának köszönhetően feszegethetjük a határokat, és elérhetjük a céljainkat.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Segít minket nagyot álmodni! Támogatásával rendkívüli eredményeket érhetünk el.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Támogassa a Thunderbirdöt</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Nem jelenítünk meg hirdetéseket.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Nem adjuk el az adatait.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Kizárólak az Önhöz hasonló felhasználókból finanszírozzuk magunkat.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Igen</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Nagy értékű havi hozzájárulás</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_header_title">Dukung Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Berikan sekali saja</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Kontribusi aman</string>
|
||||
<string name="funding_googleplay_contribution_title">Dukung Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Bulanan</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Tidak tersedia</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Terima kasih atas donasi Anda yang murah hati! Dukungan Anda secara langsung memperkuat Thunderbird, dan kami bersyukur Anda mendampingi kami dalam perjalanan ini.</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">Kontribusi tidak dapat dikurangkan dari pajak sebagai sumbangan amal.</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Kami tidak pernah menayangkan iklan atau menjual data Anda. Kami sepenuhnya didanai oleh kontribusi finansial dari para pengguna kami. Jika Anda menyukai Thunderbird, mohon bantu dukung. Kami tidak dapat melakukan ini tanpa Anda!</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Ulangi</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Kontribusi dalam aplikasi saat ini tidak tersedia.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Kunjungi <xliff:g id="link_text">%s</xliff:g> untuk mengetahui lebih banyak cara mendukung Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Lanjutkan ke pembayaran</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Pembayaran saat ini tidak tersedia</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Ubah pembayaran bulanan</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Kesalahan tidak diketahui</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Kontribusi saat ini tidak tersedia.</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Pembelian gagal.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Kontribusi Penting</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Kontribusi yang Berharga</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Dukungan Anda membuat kami terus maju! Bahkan kontribusi terkecil pun dapat menciptakan riak perubahan, dan kami sangat bersyukur Anda ikut serta.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Kontribusi Signifikan</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Kontribusi Besar</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Kontribusi Luar Biasa</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Anda membantu kami mewujudkan hal-hal hebat! Dengan berkontribusi pada tingkat ini, Anda membantu kami mengambil langkah maju yang berarti sehingga kami dapat terus berkembang.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Kontribusi Anda sungguh cemerlang! Anda memainkan peran utama dalam memajukan misi kami, membantu kami mencapai pencapaian penting dan mencapai dampak yang lebih besar.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Anda benar-benar membantu kami bermimpi besar! Dukungan luar biasa Anda memberdayakan kami untuk mencapai hal luar biasa, meninggalkan dampak abadi pada semua yang kami lakukan.</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Berikan kontribusi lain yang berdampak</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Tampilkan lebih detail</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Singkirkan kesalahan</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Dukungan Anda sungguh menginspirasi! Berkat kontribusi besar Anda, kami mampu mendobrak batasan, berinovasi, dan membuat langkah signifikan menuju tujuan kami.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Kontribusi Luar Biasa</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Anda adalah alasan utama kami dapat melakukan apa yang kami lakukan! Berkat kemurahan hati Anda, kita dapat mengerjakan proyek yang lebih besar dan mencapai pencapaian baru bersama-sama.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Kontribusi Bulanan Penting</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Dukungan Andalah yang membuat kami untuk tetap terus maju. Tiap-tiap kontribusi akan menuai hasilnya—terima kasih, ya!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Kontribusi Andalah yang membantu kami untuk tetap tumbuh dan meniti tiap-tiap langkah—terima kasih, ya!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Sungguh Anda telah membantu kami untuk tetap mengimpikan hal-hal besar. Dukungan Anda meyakinkan kami untuk mencapai hal-hal yang tidak pernah kami sangka sebelumnya.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Kontribusi Utama Bulanan</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Andalah alasan kami hingga dapat melakukan semua ini sekarang. Kedermawanan Anda membantu kami mencapai segala pencapai baru.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Sungguh menginspirasi dukungan Anda! Kontribusi Anda sangat membantu kami mendorong segala pembatas dan mencapai impian kami.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Ya</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Tidak dulu, ya</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Kontribusi Bulanan Berharga</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Mari dukung Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Misi kami adalah untuk menyediakan aplikask surel bersumber terbuka yang aman, privat, sekaligus gratis untuk semua pengguna di seantero dunia. Dukungan dana dari Anda sungguh dapat menyokong proyek ini. Maukah Anda berdonasi sekarang?</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Mensile</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird è finanziato interamente dai contributi di utenti come te. Non mostriamo mai pubblicità né vendiamo i tuoi dati. Se ti piace Thunderbird, ti preghiamo di aiutarci a supportarlo. Non possiamo farcela senza di te!</string>
|
||||
<string name="funding_googleplay_contribution_list_title">Donazione sicura</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">Non disponibile</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Continua per procedere al pagamento</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Modifica il pagamento mensile</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">Dai un altro contributo significativo</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">Pagamento al momento non disponibile</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Mostra maggiori dettagli</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Visita <xliff:g id="link_text">%s</xliff:g> per altre modalità di supporto a Thunderbird.</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">Acquisto non andato a buon fine</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Riprova</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Errore sconosciuto</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">Donazioni al momento non disponibili</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">Le donazioni in-app non sono al momento disponibili.</string>
|
||||
<string name="funding_googleplay_contribution_header_title">Supporta Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_title">Supporta Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Donazione singola</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">Il tuo contributo favorisce lo sviluppo di Thunderbird e ti siamo sinceramente grati per il tuo supporto.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">Il tuo supporto ci fa andare avanti! Anche i contributi più piccoli creano onde di cambiamento e siamo così grati di averti a bordo.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">Ci stai aiutando a realizzare grandi cose! Contribuendo a questo livello, ci stai aiutando a fare passi avanti significativi che ci consentono di continuare a crescere.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">Il tuo contributo è davvero straordinario! Stai giocando un ruolo importante nel far progredire la nostra missione, aiutandoci a raggiungere traguardi importanti e a ottenere un impatto maggiore.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">Il tuo supporto è davvero stimolante! Grazie al tuo contributo sostanziale, siamo in grado di superare i limiti, innovare e fare passi da gigante verso i nostri obiettivi.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">Ci stai davvero aiutando a sognare in grande! Il tuo incredibile supporto ci dà la forza di raggiungere lo straordinario, lasciando un impatto duraturo su tutto ciò che facciamo.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">Siete una delle ragioni principali per cui siamo in grado di fare ciò che facciamo! Grazie alla vostra generosità, possiamo intraprendere progetti più grandi e raggiungere nuovi traguardi insieme.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">Il tuo supporto ci spinge ad andare avanti! Ogni contributo crea un cambiamento: grazie!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">Il tuo contributo brilla! Sei fondamentale per portare avanti la nostra missione e ottenere un impatto.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">Il tuo supporto è fonte di ispirazione! Il tuo contributo ci aiuta a superare i limiti e a raggiungere i nostri obiettivi.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">Siete una grande motivazione per fare ciò che facciamo! La vostra generosità ci aiuta a raggiungere nuovi traguardi.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Supporta Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">Ci stai aiutando a sognare in grande! Il tuo supporto ci dà la forza di realizzare cose straordinarie.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">Unisciti alla nostra missione per creare la migliore esperienza di posta elettronica possibile, personalizzabile e rispettosa della privacy.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Sì</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Non adesso</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">I contributi non sono fiscalmente deducibili in quanto beneficenza.</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Ignora l\'errore</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">Il tuo contributo ci aiuta a crescere e a compiere passi in avanti significativi: grazie!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Contributo prezioso</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Contributo significativo</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Contributo importante</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Contributo mensile prezioso</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Contributo mensile essenziale</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Contributo mensile significativo</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Contributo mensile notevole</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Contributo mensile eccezionale</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Contributo eccezionale</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Contributo notevole</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Contributo mensile importante</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Contributo essenziale</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">Un sincero grazie da tutti noi!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Noi non vendiamo i tuoi dati.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">Siamo finanziati esclusivamente da utenti come te.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Noi non mostriamo pubblicità.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird è libero e open source.</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_header_title">תמוך בת\'אנדרבירד</string>
|
||||
<string name="funding_googleplay_contribution_header_description">אנחנו לעולם לא נציג פרסומות או נמכור את הנתונים שלך. אנחנו ממומנים ע\"י תרומות מהמשתמשים שלנו. אם אתה נהנה מת\'אנדרבירד, אנא עזור לתמוך ביישום. אנחנו לא יכולים לעשות זאת בלעדיך!</string>
|
||||
<string name="funding_googleplay_contribution_list_title">תרומה מאובטחת</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">תן פעם אחת</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">חודשי</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">לא זמין</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">תרומות אינן קבילות להחזר מס.</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">המשך לתשלום</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">שנה תשלום חודשי</string>
|
||||
<string name="funding_googleplay_contribution_title">תמוך בת\'אנדרבירד</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">בצעו תרומה משמעותית נוספת</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">תרומה רצינית</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">התרומה שלך ממש זוהרת! אתה משחק תפקיד גדול בקידום המשימה שלנו, ועוזר לנו להגיע לאבני דרך חשובות ולהצליח לייצר השפעה גדולה יותר.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">תרומה בלתי רגילה</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">תרומה בסיסית</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">התמיכה שלך עוזרת לנו להמשיך קדימה! גם התרומות הקטנות ביותר יוצרות אדוות של שינוי, ואנחנו אסירי תודה שאתה איתנו.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">אתה עוזר לנו לגרום לדברים גדולים לקרות! תרומה בגובה כזה עוזרת לנו לקחת צעדים משמעותיים קדימה ומאפשרת לנו להמשיך לגדול.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">בזכותך אנחנו יכולים לעשות את מה שאנחנו עושים! תודות לנדיבותך, אנחנו יכולים לקחת פרוייקטים גדולים יותר ולהגיע לאבני דרך חדשות ביחד.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">תרומות מתוך היישום לא זמינות כרגע.</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">בקר ב: <xliff:g id="link_text">%s</xliff:g> לדרכים נוספות בהן תוכל לתמוך בת\'אנדרבירד</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">נסה שוב</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">תשלום לא זמין כרגע</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">הצג פרטים נוספים</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">שגיאה לא מוכרת</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">רכישה נכשלה.</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">תרומות לא זמינות כרגע.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">תרומה ערכית</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">תרומה משמעותית</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">תרומה ניכרת</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">תרומתך מעודדת את הפיתוח של Thunderbird ואנו אסירי תודה על תמיכתך.</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">לדחות את השגיאה</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">תודה כנה מכולנו!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">תרומה חודשית מוערכת</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">התמיכה שלכם דוחפת אותנו קדימה! כל תרומה יוצרת שינוי - תודה!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">תרומה חודשית יוצאת דופן</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">התרומה שלך עוזרת לנו לצמוח ולעשות צעדים משמעותיים קדימה - תודה לך!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">אתה סיבה גדולה שאנחנו יכולים לעשות את מה שאנחנו עושים! הנדיבות שלך עוזרת לנו להגיע לאבני דרך חדשות.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">תרומה חודשית מרכזית</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">אתה באמת עוזר לנו לחלום בגדול! התמיכה המדהימה שלך מעצימה אותנו להשיג את יוצא הדופן, ומשאירה השפעה מתמשכת על כל מה שאנחנו עושים.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">תרומה חודשית משמעותית</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">התרומה שלך זורחת! אתה המפתח לקידום המשימה שלנו ולהשגת השפעה.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">התמיכה שלך באמת מעוררת השראה! הודות לתרומתך המשמעותית, אנו מסוגלים לפרוץ גבולות, לחדש ולעשות צעדים משמעותיים לעבר המטרות שלנו.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">תרומה חודשית חיונית</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">תרומה חודשית יוצאת דופן</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird היא אפלקציה חינמי וקוד פתוח.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">אנחנו לא מציגים פרסומות.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">אנחנו לא מוכרים את המידע שלך.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">אנו ממומנים אך ורק על ידי משתמשים כמוך.</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">אתה עוזר לנו לחלום בגדול! תמיכתך מעצימה אותנו להשיג דברים יוצאי דופן.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">תמוך בThunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">הצטרף למשימה שלנו ליצור את חוויית הדוא\"ל הטובה ביותר שמכבדת פרטיות, וניתנת להתאמה אישית.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">לא כרגע</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">התמיכה שלך מעוררת השראה! ועוזרת לנו לפרוץ גבולות ולהשיג את המטרות שלנו.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">כן</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="funding_googleplay_contribution_header_title">Thunderbird を支援する</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">一度だけ</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">毎月</string>
|
||||
<string name="funding_googleplay_contribution_list_title">寄付する</string>
|
||||
<string name="funding_googleplay_contribution_list_disclaimer">税控除の対象となる慈善活動への寄付ではありません。</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">支払いへ進む</string>
|
||||
<string name="funding_googleplay_contribution_header_description">Thunderbird の資金はすべてユーザーから寄付されています。私たちは広告を表示したりあなたのデータを販売したりしません。もし Thunderbird に満足していただけたら、支援にご協力ください。あなたの支援が必要です!</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">毎月の支払いを変更</string>
|
||||
<string name="funding_googleplay_contribution_title">Thunderbird を支援する</string>
|
||||
<string name="funding_googleplay_contribution_list_type_none_available">利用できません</string>
|
||||
<string name="funding_googleplay_contribution_footer_show_contribution_list_button">更なる進化に向けてもう一度貢献する</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_message">Thunderbird を支援するさまざまな方法は <xliff:g id="link_text">%s</xliff:g> で確認できます。</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">再試行</string>
|
||||
<string name="funding_googleplay_contribution_list_empty_title">現在、アプリ内寄付ができません。</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">詳細を表示</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">不明なエラー</string>
|
||||
<string name="funding_googleplay_contribution_error_purchase_failed">課金に失敗しました。</string>
|
||||
<string name="funding_googleplay_contribution_error_service_disconnected">現在、寄付ができません。</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">エラーを無視</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_unavailable_button">現在、支払いができません</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_description">あなたのご支援が私たちの原動力です!あなたの貢献が起こした変化の波に乗って、私たちはあなたと前に進み続けます。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_description">良い変化を起こす支援をありがとうございます!あなたの貢献は成長への確かな一歩を支えています。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_description">私たちがミッションに向け前進し、重要なマイルストーンを達成して変化を生み出すために、あなたの目覚ましい貢献は重要な役割を果たします。</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Thunderbird を支援する</string>
|
||||
<string name="funding_googleplay_contribution_reminder_message">プライバシーを尊重し、メール体験をカスタマイズできるようにするという、私たちのミッションに参加しませんか?</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">はい</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">あとで</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you_message">あなたの貢献が Thunderbird の開発をさらに進めます。あなたの支援に心から感謝します。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_description">あなたの支援は私たちが活動できる大きな理由です!惜しみない援助により、更なるプロジェクトと新たな目標に向けて進めることを心から感謝します。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_description">私たちの夢への大きな貢献をありがとうございます!あなたの素晴らしい支援は果てしない夢に向かう力を与え、私たちの行動すべてに大きな影響を与えました。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_description">あなたの支援に心から感激しています!あなたの重要な貢献により私たちは可能性を広げ、イノベーションを起こし、目標に向けて進めるようになりました。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_description">ありがとうございます!— あなたの貢献が成長と前進への確かな一歩を支えています。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_description">ありがとうございます!— あなたの目覚ましい貢献は、ミッションを達成し変化を生み出すための鍵となります。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_description">ありがとうございます!— あなたの支援は私たちが活動できる大きな理由です。惜しみない貢献により、次の目標に向けて進めます。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_description">ありがとうございます!— あなたの支援に感激しています!あなたの貢献のおかげで可能性が広がり、目標に向かって進めます。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_description">ありがとうございます!— すべての貢献が私たちの原動力です。あなたの支援でプロジェクトが前進します!</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_description">私たちの夢への大きな貢献をありがとうございます!あなたの支援は果てしない夢に向かう力となります。</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xl_title">Outstanding Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_m_title">Significant Monthly Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xl_title">Outstanding Monthly Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xxl_title">Exceptional Monthly Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Essential Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Exceptional Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_l_title">Major Monthly Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Valued Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Major Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Significant Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_xs_title">Essential Monthly Contribution</string>
|
||||
<string name="funding_googleplay_contribution_tfa_recurring_s_title">Valued Monthly Contribution</string>
|
||||
<string name="funding_googleplay_contribution_header_thank_you">あなたに心から感謝します!</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">広告を表示しません。</string>
|
||||
<string name="funding_googleplay_contribution_reminder_claim">私たちの資金はあなたのようなユーザーからの寄付のみです。</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird は無料でオープンソースです。</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">あなたのデータを販売しません。</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="funding_googleplay_contribution_header_title">Thunderbird-ты қолдау</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Ай сайын</string>
|
||||
<string name="funding_googleplay_contribution_title">Thunderbird-ты қолдау</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="funding_googleplay_contribution_header_title">Paremti „Thunderbird“</string>
|
||||
<string name="funding_googleplay_contribution_title">Paremti „Thunderbird“</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="funding_googleplay_contribution_header_title">Støtt Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_list_type_one_time">Gi én gang</string>
|
||||
<string name="funding_googleplay_contribution_reminder_negative_button">Ikke nå</string>
|
||||
<string name="funding_googleplay_contribution_list_error_retry_button">Prøv igjen</string>
|
||||
<string name="funding_googleplay_contribution_footer_payment_button">Fortsett til betaling</string>
|
||||
<string name="funding_googleplay_contribution_list_type_recurring">Månedlig</string>
|
||||
<string name="funding_googleplay_contribution_error_unknown">Ukjent feil</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement">Thunderbird er gratis og har åpen kildekode.</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_1">Vi viser ikke reklamer.</string>
|
||||
<string name="funding_googleplay_contribution_title">Støtt Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_error_show_more">Vis flere detaljer</string>
|
||||
<string name="funding_googleplay_contribution_error_dismiss_button">Avvis feilmeldingen</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xs_title">Essensielt bidrag</string>
|
||||
<string name="funding_googleplay_contribution_reminder_statement_point_2">Vi selger ikke dine data.</string>
|
||||
<string name="funding_googleplay_contribution_footer_manage_button">Endre månedlig betaling</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_m_title">Betydelig bidrag</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_l_title">Stort bidrag</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_xxl_title">Eksepsjonelt bidrag</string>
|
||||
<string name="funding_googleplay_contribution_tfa_onetime_s_title">Verdsatt bidrag</string>
|
||||
<string name="funding_googleplay_contribution_reminder_title">Støtt Thunderbird</string>
|
||||
<string name="funding_googleplay_contribution_reminder_positive_button">Ja</string>
|
||||
</resources>
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue