diff --git a/app/src/googleplay/java/org/tasks/billing/Purchase.kt b/app/src/googleplay/java/org/tasks/billing/Purchase.kt
index 2aef951ca..8bd7e73e9 100644
--- a/app/src/googleplay/java/org/tasks/billing/Purchase.kt
+++ b/app/src/googleplay/java/org/tasks/billing/Purchase.kt
@@ -48,6 +48,6 @@ class Purchase(private val purchase: Purchase) {
}
companion object {
- private val PATTERN = Pattern.compile("^(annual|monthly)_([0-1][0-9]|499)$")
+ private val PATTERN = Pattern.compile("^(annual|monthly)_([0-3][0-9]|499)$")
}
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d7f0fd4e7..1994bd33a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -532,10 +532,6 @@
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="adjustResize"/>
-
-
this.onButtonChecked(group!!, id, checked) }
-
- val toolbar = binding.toolbar.toolbar
- toolbar.setNavigationIcon(R.drawable.ic_outline_arrow_back_24px)
- toolbar.setNavigationContentDescription(R.string.back)
- toolbar.setNavigationOnClickListener { finish() }
- toolbar.setTitle(R.string.upgrade_to_pro)
- toolbar.inflateMenu(R.menu.menu_purchase_activity)
- toolbar.setOnMenuItemClickListener(this)
-
- themeColor.apply(toolbar)
-
- setWaitScreen(true)
- }
-
- @SuppressLint("DefaultLocale")
- @OnClick(R.id.subscribe)
- fun subscribe() {
- if (currentSubscriptionSelected() && currentSubscription?.isCanceled == true) {
- billingClient.initiatePurchaseFlow(
- this, currentSubscription!!.sku, BillingClientImpl.TYPE_SUBS, null)
- } else {
- billingClient.initiatePurchaseFlow(this, String.format("%s_%02d", if (isMonthly()) "monthly" else "annual", adapter.selected),
- BillingClientImpl.TYPE_SUBS,
- currentSubscription?.sku)
- }
- billingClient.addPurchaseCallback(this)
- }
-
- private fun onButtonChecked(group: MaterialButtonToggleGroup, id: Int, checked: Boolean) {
- if (id == R.id.button_monthly) {
- if (!checked && group.checkedButtonId != R.id.button_annually) {
- group.check(R.id.button_monthly)
- }
- } else {
- if (!checked && group.checkedButtonId != R.id.button_monthly) {
- group.check(R.id.button_annually)
- }
- }
- updateSubscribeButton()
- }
-
- override fun onSaveInstanceState(outState: Bundle) {
- super.onSaveInstanceState(outState)
- outState.putBoolean(EXTRA_MONTHLY, isMonthly())
- outState.putInt(EXTRA_PRICE, adapter.selected)
- }
-
- private fun isMonthly() = binding.buttons.checkedButtonId == R.id.button_monthly
-
- private fun setWaitScreen(isWaitScreen: Boolean) {
- Timber.d("setWaitScreen(%s)", isWaitScreen)
- binding.recyclerView.visibility = if (isWaitScreen) View.GONE else View.VISIBLE
- binding.buttons.visibility = if (isWaitScreen) View.GONE else View.VISIBLE
- binding.subscribe.visibility = if (isWaitScreen) View.GONE else View.VISIBLE
- binding.screenWait.visibility = if (isWaitScreen) View.VISIBLE else View.GONE
- }
-
- override fun onStart() {
- super.onStart()
- localBroadcastManager.registerPurchaseReceiver(purchaseReceiver)
- billingClient.queryPurchases()
- }
-
- override fun onStop() {
- super.onStop()
- localBroadcastManager.unregisterReceiver(purchaseReceiver)
- }
-
- private fun setup() {
- currentSubscription = inventory.subscription
- if (adapter.selected == 0) {
- adapter.selected = currentSubscription?.subscriptionPrice ?: 3
- if (currentSubscription != null) {
- binding.buttons.check(if (currentSubscription?.isMonthly == true) R.id.button_monthly else R.id.button_annually)
- }
- }
- binding.unsubscribe.visibility = if (currentSubscription == null || currentSubscription?.isCanceled == true) View.GONE else View.VISIBLE
- updateSubscribeButton()
- setWaitScreen(false)
- adapter.submitList((1..15).toList())
- binding.recyclerView.layoutManager = IconLayoutManager(this)
- binding.recyclerView.adapter = adapter
- }
-
- private fun updateSubscribeButton() {
- binding.subscribe.isEnabled = true
- if (currentSubscription == null) {
- binding.subscribe.setText(R.string.button_subscribe)
- } else if (currentSubscriptionSelected()) {
- if (currentSubscription!!.isCanceled) {
- binding.subscribe.setText(R.string.button_restore_subscription)
- } else {
- binding.subscribe.setText(R.string.button_current_subscription)
- binding.subscribe.isEnabled = false
- }
- } else {
- binding.subscribe.setText(if (isUpgrade()) R.string.button_upgrade else R.string.button_downgrade)
- }
- }
-
- private fun currentSubscriptionSelected() =
- currentSubscription != null
- && isMonthly() == currentSubscription!!.isMonthly
- && adapter.selected == currentSubscription!!.subscriptionPrice
-
- private fun isUpgrade() = if (isMonthly() == currentSubscription!!.isMonthly) {
- currentSubscription!!.subscriptionPrice!! < adapter.selected
- } else {
- isMonthly()
- }
-
- private fun onPriceChanged(price: Int) {
- adapter.selected = price
- updateSubscribeButton()
- }
-
- @OnClick(R.id.unsubscribe)
- fun manageSubscription() {
- startActivity(
- Intent(
- Intent.ACTION_VIEW,
- Uri.parse(getString(R.string.manage_subscription_url, currentSubscription!!.sku))))
- }
-
- override fun onPurchasesUpdated(success: Boolean) {
- if (success) {
- finish()
- }
- }
-
- override fun onMenuItemClick(item: MenuItem?): Boolean {
- return if (item?.itemId == R.id.menu_more_info) {
- startActivity(
- Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.subscription_help_url))))
- true
- } else {
- false
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/tasks/billing/PurchaseAdapter.java b/app/src/main/java/org/tasks/billing/PurchaseAdapter.java
deleted file mode 100644
index baf287319..000000000
--- a/app/src/main/java/org/tasks/billing/PurchaseAdapter.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.tasks.billing;
-
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.DiffUtil.ItemCallback;
-import androidx.recyclerview.widget.ListAdapter;
-import org.tasks.Callback;
-import org.tasks.R;
-import org.tasks.locale.Locale;
-import org.tasks.themes.Theme;
-
-public class PurchaseAdapter extends ListAdapter {
-
- private final Context context;
- private final Theme theme;
- private final Locale locale;
- private final Callback onPriceChanged;
- private int selected;
-
- PurchaseAdapter(Context context, Theme theme, Locale locale, Callback onPriceChanged) {
- super(new DiffCallback());
- this.context = context;
- this.theme = theme;
- this.locale = locale;
- this.onPriceChanged = onPriceChanged;
- }
-
- public int getSelected() {
- return selected;
- }
-
- public void setSelected(int price) {
- int previous = selected;
- this.selected = price;
- notifyItemChanged(previous - 1, null);
- notifyItemChanged(price - 1, null);
- }
-
- @NonNull
- @Override
- public PurchaseHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View view =
- theme.getLayoutInflater(context).inflate(R.layout.dialog_purchase_cell, parent, false);
- return new PurchaseHolder(view, onPriceChanged, locale);
- }
-
- @Override
- public void onBindViewHolder(@NonNull PurchaseHolder holder, int position) {
- int price = position + 1;
- holder.bind(price, price == selected);
- }
-
- private static class DiffCallback extends ItemCallback {
- @Override
- public boolean areItemsTheSame(@NonNull Integer oldItem, @NonNull Integer newItem) {
- return oldItem.equals(newItem);
- }
-
- @Override
- public boolean areContentsTheSame(@NonNull Integer oldItem, @NonNull Integer newItem) {
- return true;
- }
- }
-}
diff --git a/app/src/main/java/org/tasks/billing/PurchaseDialog.kt b/app/src/main/java/org/tasks/billing/PurchaseDialog.kt
new file mode 100644
index 000000000..a5f1e150f
--- /dev/null
+++ b/app/src/main/java/org/tasks/billing/PurchaseDialog.kt
@@ -0,0 +1,250 @@
+package org.tasks.billing
+
+import android.app.Activity.RESULT_OK
+import android.app.Dialog
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.text.method.LinkMovementMethod
+import androidx.core.view.isVisible
+import androidx.fragment.app.DialogFragment
+import androidx.fragment.app.Fragment
+import butterknife.ButterKnife
+import butterknife.OnClick
+import com.google.android.material.slider.Slider
+import dagger.hilt.android.AndroidEntryPoint
+import io.noties.markwon.Markwon
+import io.noties.markwon.ext.strikethrough.StrikethroughPlugin
+import org.tasks.LocalBroadcastManager
+import org.tasks.R
+import org.tasks.databinding.ActivityPurchaseBinding
+import org.tasks.dialogs.DialogBuilder
+import org.tasks.locale.Locale
+import org.tasks.themes.Theme
+import timber.log.Timber
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class PurchaseDialog : DialogFragment(), OnPurchasesUpdated {
+
+ private val purchaseReceiver: BroadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ setup()
+ }
+ }
+
+ @Inject lateinit var tasksTheme: Theme
+ @Inject lateinit var inventory: Inventory
+ @Inject lateinit var dialogBuilder: DialogBuilder
+ @Inject lateinit var billingClient: BillingClient
+ @Inject lateinit var localBroadcastManager: LocalBroadcastManager
+ @Inject lateinit var locale: Locale
+
+ private lateinit var binding: ActivityPurchaseBinding
+ private lateinit var markwon: Markwon
+
+ private var currentSubscription: Purchase? = null
+ private var priceChanged = false
+ private var nameYourPrice = false
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ binding = ActivityPurchaseBinding.inflate(layoutInflater)
+ ButterKnife.bind(this, binding.root)
+
+ if (savedInstanceState != null) {
+ binding.slider.value = savedInstanceState.getFloat(EXTRA_PRICE)
+ priceChanged = savedInstanceState.getBoolean(EXTRA_PRICE_CHANGED)
+ nameYourPrice = savedInstanceState.getBoolean(EXTRA_NAME_YOUR_PRICE)
+ }
+
+ binding.slider.addOnChangeListener(this::onPriceChanged)
+ binding.slider.setLabelFormatter {
+ "$${it - .01}"
+ }
+ binding.text.movementMethod = LinkMovementMethod.getInstance()
+
+ markwon = Markwon.builder(requireContext())
+ .usePlugin(StrikethroughPlugin.create())
+ .build()
+
+ setWaitScreen(true)
+
+ return dialogBuilder.newDialog()
+ .setView(binding.root)
+ .show()
+ }
+
+ private fun updateText() {
+ var benefits = "### ${getString(R.string.upgrade_header)}"
+ if (nameYourPrice) {
+ benefits += """
+---
+#### ~~${getString(R.string.upgrade_sync_with_tasks)}~~
+"""
+ } else {
+ benefits += """
+---
+#### [${getString(R.string.upgrade_sync_with_tasks)} (BETA)](https://tasks.org/sync)
+* **${getString(R.string.upgrade_no_platform_lock_in)}** — ${getString(R.string.upgrade_open_internet_standards)}
+* **${getString(R.string.upgrade_customer)}** — ${getString(R.string.upgrade_privacy)}
+* ${getString(R.string.upgrade_coming_soon)}
+"""
+ }
+ benefits += """
+---
+#### ${getString(R.string.upgrade_synchronization)}
+* [${getString(R.string.davx5)}](https://tasks.org/docs/davx5.html)
+* [${getString(R.string.caldav)}](https://tasks.org/docs/caldav_intro.html)
+* [${getString(R.string.upgrade_etesync)}](https://tasks.org/docs/etesync_intro.html)
+* ${getString(R.string.upgrade_google_tasks)}
+---
+#### ${getString(R.string.upgrade_additional_features)}
+* ${getString(R.string.upgrade_themes)}
+* ${getString(R.string.upgrade_google_places)}
+* [${getString(R.string.upgrade_tasker)}](https://tasks.org/docs/tasker.html)
+---
+* ${getString(R.string.upgrade_free_trial)}
+* **${getString(R.string.upgrade_downgrade)}** — ${getString(R.string.upgrade_balance)}
+* **${getString(R.string.upgrade_cancel)}** — ${getString(R.string.upgrade_benefits_retained)}
+"""
+
+ binding.text.text = markwon.toMarkdown(benefits)
+ }
+
+ @OnClick(R.id.pay_annually)
+ fun subscribeAnnually() {
+ initiatePurchase(false, 30)
+ }
+
+ @OnClick(R.id.pay_monthly)
+ fun subscribeMonthly() {
+ initiatePurchase(true, 3)
+ }
+
+ private fun initiatePurchase(isMonthly: Boolean, price: Int) {
+ val newSku = String.format("%s_%02d", if (isMonthly) "monthly" else "annual", price)
+ billingClient.initiatePurchaseFlow(
+ requireActivity(),
+ newSku,
+ BillingClientImpl.TYPE_SUBS,
+ currentSubscription?.sku?.takeIf { it != newSku })
+ billingClient.addPurchaseCallback(this)
+ }
+
+ @OnClick(R.id.pay_other)
+ fun nameYourPrice() {
+ nameYourPrice = !nameYourPrice
+ setWaitScreen(false)
+ binding.scroll.scrollTo(0, 0)
+ updateSubscribeButton()
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ outState.putFloat(EXTRA_PRICE, binding.slider.value)
+ outState.putBoolean(EXTRA_PRICE_CHANGED, priceChanged)
+ outState.putBoolean(EXTRA_NAME_YOUR_PRICE, nameYourPrice)
+ }
+
+ private fun setWaitScreen(isWaitScreen: Boolean) {
+ Timber.d("setWaitScreen(%s)", isWaitScreen)
+ binding.slider.isVisible = !isWaitScreen && nameYourPrice
+ binding.payOther.isVisible = !isWaitScreen
+ binding.payOther.setText(if (nameYourPrice) R.string.back else R.string.more_options)
+ binding.tasksOrgButtonPanel.isVisible = !isWaitScreen
+ binding.screenWait.isVisible = isWaitScreen
+ updateText()
+ }
+
+ override fun onStart() {
+ super.onStart()
+ localBroadcastManager.registerPurchaseReceiver(purchaseReceiver)
+ billingClient.queryPurchases()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ localBroadcastManager.unregisterReceiver(purchaseReceiver)
+ }
+
+ private fun setup() {
+ currentSubscription = inventory.subscription
+ if (!priceChanged) {
+ binding.slider.value =
+ currentSubscription
+ ?.subscriptionPrice
+ ?.coerceAtMost(25)
+ ?.toFloat() ?: 10f
+ }
+ updateSubscribeButton()
+ setWaitScreen(false)
+ }
+
+ private fun updateSubscribeButton() {
+ val sliderValue = binding.slider.value.toInt()
+ val annualPrice = if (nameYourPrice) sliderValue else 30
+ val monthlyPrice = if (nameYourPrice) sliderValue else 3
+ val constrained = resources.getBoolean(R.bool.width_constrained)
+ binding.payAnnually.let {
+ it.isEnabled = true
+ it.text = getString(
+ if (constrained) R.string.price_per_year_abbreviated else R.string.price_per_year,
+ annualPrice - .01
+ )
+ it.setOnClickListener {
+ initiatePurchase(false, if (nameYourPrice) sliderValue else 30)
+ }
+ }
+ binding.payMonthly.let {
+ it.isEnabled = true
+ it.text = getString(
+ if (constrained) R.string.price_per_month_abbreviated else R.string.price_per_month,
+ monthlyPrice - .01
+ )
+ it.setOnClickListener {
+ initiatePurchase(true, if (nameYourPrice) sliderValue else 3)
+ }
+ it.isVisible = !nameYourPrice || sliderValue < 3
+ }
+ currentSubscription?.let {
+ binding.payMonthly.isEnabled =
+ it.isCanceled || !it.isMonthly || monthlyPrice != it.subscriptionPrice
+ binding.payAnnually.isEnabled =
+ it.isCanceled || it.isMonthly || annualPrice != it.subscriptionPrice
+ }
+ }
+
+ private fun onPriceChanged(slider: Slider, value: Float, fromUser: Boolean) {
+ if (fromUser) {
+ priceChanged = true
+ }
+ updateSubscribeButton()
+ }
+
+ override fun onPurchasesUpdated(success: Boolean) {
+ if (success) {
+ dismiss()
+ targetFragment?.onActivityResult(targetRequestCode, RESULT_OK, null)
+ }
+ }
+
+ companion object {
+ private const val EXTRA_PRICE = "extra_price"
+ private const val EXTRA_PRICE_CHANGED = "extra_price_changed"
+ private const val EXTRA_NAME_YOUR_PRICE = "extra_name_your_price"
+ @JvmStatic
+ val FRAG_TAG_PURCHASE_DIALOG = "frag_tag_purchase_dialog"
+
+ @JvmStatic
+ fun newPurchaseDialog(): PurchaseDialog {
+ return PurchaseDialog()
+ }
+
+ fun newPurchaseDialog(target: Fragment, rc: Int): PurchaseDialog {
+ val dialog = PurchaseDialog()
+ dialog.setTargetFragment(target, rc)
+ return dialog
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/tasks/billing/PurchaseHolder.java b/app/src/main/java/org/tasks/billing/PurchaseHolder.java
deleted file mode 100644
index 936a5510a..000000000
--- a/app/src/main/java/org/tasks/billing/PurchaseHolder.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.tasks.billing;
-
-import android.view.View;
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import butterknife.OnClick;
-import com.google.android.material.button.MaterialButton;
-import org.tasks.Callback;
-import org.tasks.R;
-import org.tasks.locale.Locale;
-
-public class PurchaseHolder extends RecyclerView.ViewHolder {
-
- private final Callback onClick;
- private final Locale locale;
-
- @BindView(R.id.price)
- MaterialButton button;
-
- private int price;
-
- PurchaseHolder(@NonNull View view, Callback onClick, Locale locale) {
- super(view);
- this.locale = locale;
-
- ButterKnife.bind(this, view);
-
- this.onClick = onClick;
- }
-
- @OnClick(R.id.price)
- void onClick() {
- onClick.call(price);
- }
-
- public void bind(int price, boolean selected) {
- this.price = price;
- button.setText(String.format("$%s", locale.formatNumber(price)));
- button.setChecked(selected);
- }
-}
diff --git a/app/src/main/java/org/tasks/caldav/BaseCaldavAccountSettingsActivity.kt b/app/src/main/java/org/tasks/caldav/BaseCaldavAccountSettingsActivity.kt
index c3a8d087d..d844d005e 100644
--- a/app/src/main/java/org/tasks/caldav/BaseCaldavAccountSettingsActivity.kt
+++ b/app/src/main/java/org/tasks/caldav/BaseCaldavAccountSettingsActivity.kt
@@ -25,7 +25,8 @@ import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.analytics.Firebase
import org.tasks.billing.Inventory
-import org.tasks.billing.PurchaseActivity
+import org.tasks.billing.PurchaseDialog.Companion.FRAG_TAG_PURCHASE_DIALOG
+import org.tasks.billing.PurchaseDialog.Companion.newPurchaseDialog
import org.tasks.data.CaldavAccount
import org.tasks.data.CaldavDao
import org.tasks.databinding.ActivityCaldavAccountSettingsBinding
@@ -97,7 +98,7 @@ abstract class BaseCaldavAccountSettingsActivity : ThemedInjectingAppCompatActiv
newSnackbar(getString(R.string.this_feature_requires_a_subscription))
.setDuration(BaseTransientBottomBar.LENGTH_INDEFINITE)
.setAction(R.string.button_subscribe) {
- startActivity(Intent(this, PurchaseActivity::class.java))
+ newPurchaseDialog().show(supportFragmentManager, FRAG_TAG_PURCHASE_DIALOG)
}
.show()
}
diff --git a/app/src/main/java/org/tasks/dialogs/ColorPalettePicker.kt b/app/src/main/java/org/tasks/dialogs/ColorPalettePicker.kt
index 782eb070e..22f20b943 100644
--- a/app/src/main/java/org/tasks/dialogs/ColorPalettePicker.kt
+++ b/app/src/main/java/org/tasks/dialogs/ColorPalettePicker.kt
@@ -16,7 +16,8 @@ import butterknife.ButterKnife
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
import org.tasks.billing.Inventory
-import org.tasks.billing.PurchaseActivity
+import org.tasks.billing.PurchaseDialog.Companion.FRAG_TAG_PURCHASE_DIALOG
+import org.tasks.billing.PurchaseDialog.Companion.newPurchaseDialog
import org.tasks.dialogs.ColorPickerAdapter.Palette
import org.tasks.dialogs.ColorWheelPicker.Companion.newColorWheel
import org.tasks.themes.ColorProvider
@@ -107,7 +108,7 @@ class ColorPalettePicker : DialogFragment() {
builder.setNegativeButton(R.string.cancel, null)
} else {
builder.setPositiveButton(R.string.button_subscribe) { _: DialogInterface?, _: Int ->
- context?.startActivity(Intent(requireContext(), PurchaseActivity::class.java))
+ newPurchaseDialog().show(parentFragmentManager, FRAG_TAG_PURCHASE_DIALOG)
}
}
return builder.show()
diff --git a/app/src/main/java/org/tasks/dialogs/ColorWheelPicker.kt b/app/src/main/java/org/tasks/dialogs/ColorWheelPicker.kt
index ae3d74563..f782d4028 100644
--- a/app/src/main/java/org/tasks/dialogs/ColorWheelPicker.kt
+++ b/app/src/main/java/org/tasks/dialogs/ColorWheelPicker.kt
@@ -15,17 +15,16 @@ import com.flask.colorpicker.builder.ColorPickerDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
import org.tasks.billing.Inventory
-import org.tasks.billing.PurchaseActivity
-import org.tasks.ui.NavigationDrawerFragment.Companion.REQUEST_PURCHASE
+import org.tasks.billing.PurchaseDialog.Companion.FRAG_TAG_PURCHASE_DIALOG
+import org.tasks.billing.PurchaseDialog.Companion.newPurchaseDialog
import javax.inject.Inject
-private const val REQUEST_PURCHASE = 10010
-
@AndroidEntryPoint
class ColorWheelPicker : DialogFragment() {
companion object {
const val EXTRA_SELECTED = "extra_selected"
+ private const val REQUEST_PURCHASE = 10010
fun newColorWheel(target: Fragment?, rc: Int, selected: Int): ColorWheelPicker {
val args = Bundle()
@@ -66,7 +65,8 @@ class ColorWheelPicker : DialogFragment() {
if (inventory.purchasedThemes()) {
deliverSelection()
} else {
- startActivityForResult(Intent(activity, PurchaseActivity::class.java), REQUEST_PURCHASE)
+ newPurchaseDialog(this, REQUEST_PURCHASE)
+ .show(parentFragmentManager, FRAG_TAG_PURCHASE_DIALOG)
}
}
.setNegativeButton(R.string.cancel, null)
@@ -86,7 +86,7 @@ class ColorWheelPicker : DialogFragment() {
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- if (requestCode == org.tasks.dialogs.REQUEST_PURCHASE) {
+ if (requestCode == REQUEST_PURCHASE) {
if (inventory.hasPro) {
deliverSelection()
} else {
diff --git a/app/src/main/java/org/tasks/dialogs/IconPickerDialog.java b/app/src/main/java/org/tasks/dialogs/IconPickerDialog.java
index b9099e22a..3ae7613a7 100644
--- a/app/src/main/java/org/tasks/dialogs/IconPickerDialog.java
+++ b/app/src/main/java/org/tasks/dialogs/IconPickerDialog.java
@@ -1,9 +1,10 @@
package org.tasks.dialogs;
+import static org.tasks.billing.PurchaseDialog.newPurchaseDialog;
+
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
-import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -17,7 +18,7 @@ import dagger.hilt.android.AndroidEntryPoint;
import javax.inject.Inject;
import org.tasks.R;
import org.tasks.billing.Inventory;
-import org.tasks.billing.PurchaseActivity;
+import org.tasks.billing.PurchaseDialog;
import org.tasks.themes.CustomIcons;
@AndroidEntryPoint
@@ -64,7 +65,8 @@ public class IconPickerDialog extends DialogFragment {
if (!inventory.getHasPro()) {
builder.setPositiveButton(
R.string.button_subscribe,
- (dialog, which) -> context.startActivity(new Intent(context, PurchaseActivity.class)));
+ (dialog, which) -> newPurchaseDialog()
+ .show(getParentFragmentManager(), PurchaseDialog.getFRAG_TAG_PURCHASE_DIALOG()));
}
return builder.show();
}
diff --git a/app/src/main/java/org/tasks/dialogs/WhatsNewDialog.kt b/app/src/main/java/org/tasks/dialogs/WhatsNewDialog.kt
index 412a06b80..b4a3be46d 100644
--- a/app/src/main/java/org/tasks/dialogs/WhatsNewDialog.kt
+++ b/app/src/main/java/org/tasks/dialogs/WhatsNewDialog.kt
@@ -18,7 +18,8 @@ import org.tasks.BuildConfig
import org.tasks.R
import org.tasks.analytics.Firebase
import org.tasks.billing.Inventory
-import org.tasks.billing.PurchaseActivity
+import org.tasks.billing.PurchaseDialog.Companion.FRAG_TAG_PURCHASE_DIALOG
+import org.tasks.billing.PurchaseDialog.Companion.newPurchaseDialog
import org.tasks.preferences.Preferences
import javax.inject.Inject
@@ -88,7 +89,7 @@ class WhatsNewDialog : DialogFragment() {
private fun onSubscribeClick() {
logClick(true)
dismiss()
- startActivity(Intent(context, PurchaseActivity::class.java))
+ newPurchaseDialog().show(parentFragmentManager, FRAG_TAG_PURCHASE_DIALOG)
}
private fun onRateClick() {
diff --git a/app/src/main/java/org/tasks/filters/FilterProvider.kt b/app/src/main/java/org/tasks/filters/FilterProvider.kt
index 2f4d772c6..2caf37d03 100644
--- a/app/src/main/java/org/tasks/filters/FilterProvider.kt
+++ b/app/src/main/java/org/tasks/filters/FilterProvider.kt
@@ -177,7 +177,7 @@ class FilterProvider @Inject constructor(
}
.plusIf(!inventory.hasPro) {
NavigationDrawerAction(
- context.getString(R.string.name_your_price),
+ context.getString(R.string.upgrade_to_pro),
R.drawable.ic_outline_attach_money_24px,
NavigationDrawerFragment.REQUEST_PURCHASE)
}
diff --git a/app/src/main/java/org/tasks/locale/ui/activity/TaskerCreateTaskActivity.java b/app/src/main/java/org/tasks/locale/ui/activity/TaskerCreateTaskActivity.java
index e95a1b90b..ddb2d5157 100755
--- a/app/src/main/java/org/tasks/locale/ui/activity/TaskerCreateTaskActivity.java
+++ b/app/src/main/java/org/tasks/locale/ui/activity/TaskerCreateTaskActivity.java
@@ -1,5 +1,7 @@
package org.tasks.locale.ui.activity;
+import static org.tasks.billing.PurchaseDialog.newPurchaseDialog;
+
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -11,7 +13,7 @@ import net.dinglisch.android.tasker.TaskerPlugin;
import org.tasks.LocalBroadcastManager;
import org.tasks.R;
import org.tasks.billing.Inventory;
-import org.tasks.billing.PurchaseActivity;
+import org.tasks.billing.PurchaseDialog;
import org.tasks.databinding.ActivityTaskerCreateBinding;
import org.tasks.locale.bundle.TaskCreationBundle;
@@ -53,7 +55,8 @@ public final class TaskerCreateTaskActivity extends AbstractFragmentPluginAppCom
}
private void showPurchaseDialog() {
- startActivity(new Intent(this, PurchaseActivity.class));
+ newPurchaseDialog()
+ .show(getSupportFragmentManager(), PurchaseDialog.getFRAG_TAG_PURCHASE_DIALOG());
}
@Override
diff --git a/app/src/main/java/org/tasks/preferences/fragments/HelpAndFeedback.kt b/app/src/main/java/org/tasks/preferences/fragments/HelpAndFeedback.kt
index e1d51ded5..30578a066 100644
--- a/app/src/main/java/org/tasks/preferences/fragments/HelpAndFeedback.kt
+++ b/app/src/main/java/org/tasks/preferences/fragments/HelpAndFeedback.kt
@@ -9,6 +9,8 @@ import org.tasks.BuildConfig
import org.tasks.R
import org.tasks.billing.BillingClient
import org.tasks.billing.Inventory
+import org.tasks.billing.PurchaseDialog.Companion.FRAG_TAG_PURCHASE_DIALOG
+import org.tasks.billing.PurchaseDialog.Companion.newPurchaseDialog
import org.tasks.dialogs.WhatsNewDialog
import org.tasks.injection.InjectingPreferenceFragment
import javax.inject.Inject
@@ -60,12 +62,28 @@ class HelpAndFeedback : InjectingPreferenceFragment() {
true
}
+ findPreference(R.string.button_unsubscribe).setOnPreferenceClickListener {
+ inventory.subscription?.let {
+ startActivity(
+ Intent(
+ Intent.ACTION_VIEW,
+ Uri.parse(getString(R.string.manage_subscription_url, it.sku))))
+ }
+ false
+ }
+
+ findPreference(R.string.upgrade_to_pro).setOnPreferenceClickListener {
+ newPurchaseDialog().show(parentFragmentManager, FRAG_TAG_PURCHASE_DIALOG)
+ false
+ }
+
@Suppress("ConstantConditionIf")
if (BuildConfig.FLAVOR == "generic") {
remove(
R.string.p_collect_statistics,
R.string.rate_tasks,
R.string.upgrade_to_pro,
+ R.string.button_unsubscribe,
R.string.refresh_purchases
)
}
@@ -75,11 +93,12 @@ class HelpAndFeedback : InjectingPreferenceFragment() {
super.onResume()
if (BuildConfig.FLAVOR != "generic") {
- val findPreference = findPreference(R.string.upgrade_to_pro)
- if (inventory.hasPro) {
- findPreference.title = getString(R.string.manage_subscription)
- findPreference.summary = getString(R.string.manage_subscription_summary)
- }
+ findPreference(R.string.upgrade_to_pro).title = getString(if (inventory.hasPro) {
+ R.string.manage_subscription
+ } else {
+ R.string.upgrade_to_pro
+ })
+ findPreference(R.string.button_unsubscribe).isEnabled = inventory.subscription != null
}
}
diff --git a/app/src/main/java/org/tasks/preferences/fragments/LookAndFeel.kt b/app/src/main/java/org/tasks/preferences/fragments/LookAndFeel.kt
index 4227d40cf..26282da0d 100644
--- a/app/src/main/java/org/tasks/preferences/fragments/LookAndFeel.kt
+++ b/app/src/main/java/org/tasks/preferences/fragments/LookAndFeel.kt
@@ -21,7 +21,8 @@ import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.activities.FilterSelectionActivity
import org.tasks.billing.Inventory
-import org.tasks.billing.PurchaseActivity
+import org.tasks.billing.PurchaseDialog.Companion.FRAG_TAG_PURCHASE_DIALOG
+import org.tasks.billing.PurchaseDialog.Companion.newPurchaseDialog
import org.tasks.dialogs.ColorPalettePicker
import org.tasks.dialogs.ColorPalettePicker.Companion.newColorPalette
import org.tasks.dialogs.ColorPickerAdapter
@@ -242,10 +243,8 @@ class LookAndFeel : InjectingPreferenceFragment() {
if (inventory.purchasedThemes() || ThemeBase(index).isFree) {
setBaseTheme(index)
} else {
- startActivityForResult(
- Intent(context, PurchaseActivity::class.java),
- REQUEST_PURCHASE
- )
+ newPurchaseDialog(this, REQUEST_PURCHASE)
+ .show(parentFragmentManager, FRAG_TAG_PURCHASE_DIALOG)
}
} else {
setBaseTheme(index)
diff --git a/app/src/main/java/org/tasks/preferences/fragments/TaskerListNotification.kt b/app/src/main/java/org/tasks/preferences/fragments/TaskerListNotification.kt
index 8dd77fef2..c1fd0c525 100644
--- a/app/src/main/java/org/tasks/preferences/fragments/TaskerListNotification.kt
+++ b/app/src/main/java/org/tasks/preferences/fragments/TaskerListNotification.kt
@@ -8,7 +8,8 @@ import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R
import org.tasks.activities.FilterSelectionActivity
import org.tasks.billing.Inventory
-import org.tasks.billing.PurchaseActivity
+import org.tasks.billing.PurchaseDialog.Companion.FRAG_TAG_PURCHASE_DIALOG
+import org.tasks.billing.PurchaseDialog.Companion.newPurchaseDialog
import org.tasks.injection.InjectingPreferenceFragment
import org.tasks.locale.bundle.ListNotificationBundle
import org.tasks.preferences.DefaultFilterProvider
@@ -57,10 +58,8 @@ class TaskerListNotification : InjectingPreferenceFragment() {
}
if (!inventory.purchasedTasker()) {
- startActivityForResult(
- Intent(context, PurchaseActivity::class.java),
- REQUEST_SUBSCRIPTION
- )
+ newPurchaseDialog(this, REQUEST_SUBSCRIPTION)
+ .show(parentFragmentManager, FRAG_TAG_PURCHASE_DIALOG)
}
}
diff --git a/app/src/main/java/org/tasks/ui/NavigationDrawerFragment.kt b/app/src/main/java/org/tasks/ui/NavigationDrawerFragment.kt
index 3fd68a8f7..2c70a9f33 100644
--- a/app/src/main/java/org/tasks/ui/NavigationDrawerFragment.kt
+++ b/app/src/main/java/org/tasks/ui/NavigationDrawerFragment.kt
@@ -24,7 +24,8 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.tasks.LocalBroadcastManager
import org.tasks.R
-import org.tasks.billing.PurchaseActivity
+import org.tasks.billing.PurchaseDialog.Companion.FRAG_TAG_PURCHASE_DIALOG
+import org.tasks.billing.PurchaseDialog.Companion.newPurchaseDialog
import org.tasks.data.TaskDao
import org.tasks.dialogs.NewFilterDialog.Companion.newFilterDialog
import org.tasks.filters.FilterProvider
@@ -83,7 +84,8 @@ class NavigationDrawerFragment : Fragment() {
activity?.startActivity(TaskIntents.getTaskListIntent(activity, item))
} else if (item is NavigationDrawerAction) {
when (item.requestCode) {
- REQUEST_PURCHASE -> startActivity(Intent(context, PurchaseActivity::class.java))
+ REQUEST_PURCHASE ->
+ newPurchaseDialog().show(parentFragmentManager, FRAG_TAG_PURCHASE_DIALOG)
REQUEST_DONATE -> startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://tasks.org/donate")))
REQUEST_NEW_FILTER -> newFilterDialog().show(parentFragmentManager, FRAG_TAG_NEW_FILTER)
else -> activity?.startActivityForResult(item.intent, item.requestCode)
diff --git a/app/src/main/res/layout/activity_purchase.xml b/app/src/main/res/layout/activity_purchase.xml
index af9a528a4..1c3be039f 100644
--- a/app/src/main/res/layout/activity_purchase.xml
+++ b/app/src/main/res/layout/activity_purchase.xml
@@ -1,127 +1,110 @@
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:lineSpacingMultiplier="1.2"
+ android:textSize="16sp"
+ android:padding="@dimen/keyline_second"/>
+
-
+
-
+
+
+
-
+
+
+
+ tools:text="$2.99/year"
+ app:layout_constraintEnd_toStartOf="@+id/pay_monthly"
+ app:layout_constraintHorizontal_chainStyle="packed"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_chainStyle="packed" />
+ tools:text="$2.99/month"
+ android:layout_marginStart="@dimen/keyline_first"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@id/pay_annually"
+ app:layout_constraintTop_toTopOf="parent" />
+ android:text="@string/more_options"
+ android:textColor="@color/text_secondary"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/pay_annually"
+ tools:text="@string/back"/>
-
+
-
-
+
+
+
diff --git a/app/src/main/res/menu/menu_purchase_activity.xml b/app/src/main/res/menu/menu_purchase_activity.xml
deleted file mode 100644
index 3b4d83d66..000000000
--- a/app/src/main/res/menu/menu_purchase_activity.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml
index d13508413..03b06719b 100644
--- a/app/src/main/res/values-cs/strings.xml
+++ b/app/src/main/res/values-cs/strings.xml
@@ -450,7 +450,6 @@
O aplikaci
Aplikace Tasks je svobodný software s otevřeným zdrojovým kódem licencovaný pod GNU General Public License v3.0
Ikona
- Zvýšit, snížit nebo zrušit vaše předplatné
Aktuální předplatné
Obnovit předplatné
Snížit předplatné
@@ -493,7 +492,6 @@
Verze %s
Neplatný soubor zálohy
Nové úkoly na vrchu
- Zaplať kolik chceš
Měsíčně
Ročně
Dovolit serveru plánovat opakující se úkoly
@@ -591,9 +589,6 @@
Při spuštění
Seznamy
Přidat filtr
- Před zahájení používání bezplatné zkušební verze vyberte níže jakoukoli cenu předplatného. Můžete jej kdykoli zrušit.
- Strávil jsem tisíce hodin prací na Tasks a bezplatně zveřejňuji veškerý zdrojový kód online. Za účelem podpory mé práce některé funkce vyžadují předplatné
- Ahoj! Jmenuji se Alex. Jsem nezávislý vývojář Tasks
Více barev
Neplatné uživatelské jméno nebo heslo
Synchronizujte své úkoly pomocí aplikace DAVx⁵
diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml
index fc9085126..6d6aec4dd 100644
--- a/app/src/main/res/values-da/strings.xml
+++ b/app/src/main/res/values-da/strings.xml
@@ -170,9 +170,6 @@
Boble-stil
Tilbage
Din støtte betydet meget for mig, tak!
- Vælg hvilken som helst abonnementspris herunder for at begynde din gratis prøveperiode. Du kan til enhver tid opsige abonnementet
- Jeg har brugt tusindvis af arbejdstimer på Tasks, og jeg udgiver hele kildekoden gratis online. For at støtte mit arbejde kræver nogle funktioner et abonnement
- Hej! Jeg hedder Alex. Jeg er den selvstændige udvikler bag Tasks
Farvehjul
Ugyldigt brugernavn eller kodeord
Ringetone, vibrér og mere
@@ -205,7 +202,6 @@
Lad serveren planlægge gentagne opgaver
Årligt
Månedligt
- Betal, hvad du vil
Nye opgaver øverst
Ugyldig sikkerhedskopi-fil
Version %s
@@ -413,7 +409,6 @@
Nedgrader abonnement
Opgrader til pro
Opdater køb
- Opgrader, nedgrader eller opsig dit abonnement
Administrer abonnement
hver %1$s i %2$s
hver %1$s i %2$s
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 7c9865505..ea19973a6 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -471,13 +471,11 @@
Version %s
Fehler: %s
Symbol
- Abonnement hoch-/herabstufen oder kündigen
Aktuelles Abonnement
Abonnement wiederherstellen
Abonnement herabstufen
Abonnement hochstufen
Abonnement kündigen
- Nennen Sie Ihren Preis
monatlich
jährlich
Manuelle Sortierung
@@ -528,9 +526,6 @@
Klingelton, Vibration und mehr
Ungültiger Benutzername oder Passwort
Farbkreis
- Hallo! Mein Name ist Alex. Ich bin der unabhängige Entwickler hinter Tasks
- Ich habe Tausende von Stunden mit der Arbeit an Tasks verbracht und veröffentliche den gesamten Quellcode kostenlos online. Um meine Arbeit zu unterstützen, erfordern einige Funktionen ein Abonnement
- Wählen Sie unten einen beliebigen Abonnementpreis aus, um Ihre kostenlose Testversion zu starten. Sie können jederzeit kündigen
Ihre Unterstützung bedeutet mir sehr viel, danke!
Zurück
Stil der Marken
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 3e7372924..f55c54366 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -471,13 +471,11 @@
Error : %s
", "
Icono
- Actualizar, rebajar o cancelar su suscripción
Suscripción actual
Restaurar la suscripción
Suscripción de degradación
Suscripción de actualización
Cancelar la suscripción
- Escoger tu precio
Mensualmente
Anualmente
Mi orden
@@ -527,9 +525,6 @@
Nombre de usuario o contraseña inválidos
El sistema por defecto
Rueda de colores
- ¡Hola! Me llamo Alex. Soy el desarrollador independiente detrás de Tasks
- He pasado miles de horas trabajando en Tareas, y publico todo el código fuente en línea de forma gratuita. Para apoyar mi trabajo, algunas características requieren una suscripción
- Elija cualquier precio de suscripción a continuación para iniciar su prueba gratuita. Puede cancelar en cualquier momento
Su apoyo significa mucho para mí, ¡gracias!
Volver
Estilo de chip
diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml
index 10a75f451..7df4f4398 100644
--- a/app/src/main/res/values-eu/strings.xml
+++ b/app/src/main/res/values-eu/strings.xml
@@ -470,13 +470,11 @@
Baliogabeko babes-kopia fitxategia
Zeregin berriak goialdean
Ikonoa
- Handiagotu, txikiagotu edo ezeztatu zure harpidetza
Uneko harpidetza
Berrezarri harpidetza
Txikiagotu harpidetza
Handiagotu harpidetza
Ezeztatu harpidetza
- Jarri zuk prezioa
Hilero
Urtero
Errorea: %s
@@ -527,9 +525,6 @@
Erabiltzaile-izen edo pasahitz okerra
Sisteman lehenetsia
Kolore-gurpila
- Kaixo! Nire izana Alex da. Ni naiz Tasks aplikazioaren garatzaile independentea
- Milaka ordu eman ditut Tsks aplikazioan lanean, eta kode guztia argitaratzen dut doan. Nire lana babesteko ezaugarri batzuk harpidetza eskatzen dute
- Hautatu azpiko harpidetza salneurri bat zure doako proba hasteko. Nahi duzunean eten dezakezu
Zure babesa asko da niretzat, eskerrik asko!
Atzera
Txip estiloa
diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml
index 7d5a3d07f..d21896d0d 100644
--- a/app/src/main/res/values-fi/strings.xml
+++ b/app/src/main/res/values-fi/strings.xml
@@ -442,7 +442,6 @@
Anna palvelimen ajoittaa toistuvia tehtäviä
Vuosittain
Kuukausittain
- Nimeä hintasi
Uudet tehtävät huipulla
Epäsopiva varmuuskopiotiedosto
Versio %s
@@ -545,7 +544,6 @@
Uusi tehtävä
Dashclock-laajennus
Päivitä pro versioon
- Valitse mikä tahansa alla olevista tilaus vaihtoehdoista aloittaaksesi vapaan kokeilun. Voit keskeyttää milloin haluat
Vaatii tilin Etesync.com :ssa tai itsehallinnoidun serverin
Ei tärkeyttä
Normaali tärkeys
@@ -580,8 +578,6 @@
Sulje automaattisesti kun valitaan tehtävä listalta
Paikka asetukset
Paikat
- Olen käyttänyt tuhansia tunteja työskennellen Task ohjelman parissa, ja julkaisen koko lähdekoodin netissä ilmaiseksi. Työni tueksi joidenkin ohjelman ominaisuuksien käyttö vaatii tilauksen
- Moi! Nimeni on Alex. Olen itsenäinen ohjelmistontekijä Task ohjelman takana
Ongelmien ratkaisu
Näytä ilmoitukset puettavassa laitteessasi
Puettavan laitteen ilmoitukset
@@ -593,7 +589,6 @@
Kirjaudu ulos %s\? Kaikki tälle tilille tallennetut tiedot poistetaan laitteeltasi
Alenna tilaustasi
Päivitä ostoksesi
- Päivitä, alenna tai keskeytä tilauksesi
Vain rajoittamattomalla yhteydellä
Piilotettu
Otsikon alle
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 74e02b039..789fa83dc 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -465,13 +465,11 @@
", "
Version %s
Icône
- Augmentez, diminuez ou annulez votre abonnement
Abonnement actuel
Restaurer l\'abonnement
Diminuer l\'abonnement
Augmenter l\'abonnement
Annuler l\'abonnement
- Donnez votre prix
Chaque mois
Chaque année
Erreur : %s
@@ -522,9 +520,6 @@
Nom d\'utilisateur ou mot de passe invalide
Défaut du système
Palette de couleurs
- Salut ! Je m\'appelle Alex. Je suis le développeur indépendant à l\'origine de Tasks
- J\'ai passé des milliers d\'heures à travailler sur Tasks, et je publie gratuitement tout le code source en ligne. Afin de soutenir mon travail, certaines fonctionnalités nécessitent un abonnement
- Choisissez l\'un des prix d\'abonnement ci-dessous pour commencer votre essai gratuit. Vous pouvez annuler à tout moment
Votre soutien est très important pour moi, merci !
Retour
Style de puce
diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml
index 5bd6ced29..9bc1311fa 100644
--- a/app/src/main/res/values-hu/strings.xml
+++ b/app/src/main/res/values-hu/strings.xml
@@ -468,13 +468,11 @@
%s m
", "
Ikon
- Előfizetés upgrade-je, downgrade-je vagy lemondása
Jelenlegi előfizetés
Előfizetés visszaállítása
Előfizetés downgrade-je
Előfizetés upgrade-je
Előfizetés lemondása
- Nevezd meg az árat
Havi
Éves
Egyéni sorrend
@@ -525,9 +523,6 @@
Hibás felhasználónév vagy jelszó
Alapértelmezett
Színkör
- Szia! Alexnek hívnak. Én vagyok a Tasks mögött álló független fejlesztő
- Több ezer órát dolgoztam a Tasks appon, és a teljes forráskódot ingyenesen elérhetővé tettem. A munkám támogatása érdekében néhány funkció eléréséhez előfizetés szükséges
- Az ingyenes próbaidőszak megkezdéséhez válassz a lenti előfizetési díjakból. Bármikor lemondhatod az előfizetést
A támogatásod sokat jelent nekem, köszönöm!
Vissza
Jelölő stílusa
diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml
index 174d053ba..dd3996c6c 100644
--- a/app/src/main/res/values-id/strings.xml
+++ b/app/src/main/res/values-id/strings.xml
@@ -358,7 +358,6 @@
Hanya pada koneksi tak terbatas
Tingkatkan ke pro
Kelola langganan
- Tingkatkan, turunkan, atau batalkan langganan anda
Segarkan pembelian
Langganan
Langganan saat ini
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index b986bf3d0..ec5a0f911 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -491,9 +491,6 @@
Contornato
Indietro
Il tuo supporto significa molto per me, grazie!
- Scegli, di seguito, un qualunque piano di abbonamento per iniziare la prova gratuita. Puoi annullarla in qualsiasi momento
- Ho dedicato a Tasks migliaia di ore di lavoro, pubblicando tutto il codice sorgente online, gratuitamente. Per supportare il mio lavoro alcune funzioni richiedono un abbonamento
- Ciao! Mi chiamo Alex. Sono lo sviluppatore, indipendente, di Tasks
Cerchio cromatico
Nome utente o password non validi
Suoneria, vibrazione ed altro
@@ -517,12 +514,10 @@
Inserisci il nome dell\'etichetta
Inserisci titolo
Comprimi attività secondarie
- Fai tu il prezzo
Licenze di terze parti
Questa funzione richiede un abbonamento
Annulla abbonamento
Ripristina abbonamento
- Passa alla versione premium, a quella base o cancella il tuo abbonamento
Abbonamento attuale
Aiuto & feedback
URL
diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml
index 6720745d8..ece201d9e 100644
--- a/app/src/main/res/values-iw/strings.xml
+++ b/app/src/main/res/values-iw/strings.xml
@@ -500,13 +500,11 @@
משימות חדשות בראש הרשימה
", "
סמל
- שדרוג, שנמוך או ביטול המינוי
מינוי נוכחי
שחזור מינוי
שנמוך מינוי
שדרוג מינוי
ביטול מינוי
- מה המחיר שלך
חודשי
שנתי
מיקומים
@@ -614,9 +612,6 @@
גישה מלאה למסד הנתונים של Tasks
איפוס אופן הסידור
התמיכה שלך יקרה ללבי, תודה רבה לך!
- נא לבחור את מחיר ההרשמה להלן כדי להתחיל בהתנסות חינמית. ניתן לבטל אותה בכל עת
- השקעתי אלפי שעות בעבודה על Tasks ואני מפרסם את כל קוד המקור באינטרנט בחינם. כדי לתמוך בעבודה שלי חלק מהתכונות דורשות הרשמה
- היי! אני אלכס, המתכנת העצמאי שמאחורי Tasks
שם המשתמש או הססמה שגויים
צלצול, סוגי רטט ועוד
השבתת שיפורי סוללה
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index 7090e34ae..c49a27c89 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -465,13 +465,11 @@
URL
", "
アイコン
- サブスクリプションのアップグレード、ダウングレード、またはキャンセル
現在のサブスクリプション
サブスクリプションの復元
サブスクリプションのダウングレード
サブスクリプションのアップグレード
サブスクリプションのキャンセル
- 価格の名前
毎月
毎年
\ No newline at end of file
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 6193fd945..52b63274b 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -467,13 +467,11 @@
부적합한 백업 파일
새 할일을 가장 위로
아이콘
- 업그레이드, 다운그레이드, 구독 취소
현재 구독
구독 복원
구독 다운그레이드
구독 업그레이드
구독 취소
- 구독 금액 정하기
매월
매년
순서 직접 정렬
@@ -519,7 +517,6 @@
네비게이션 서랍
위치 설정
위치
- 안녕하세요! Tasks의 1인 개발자 알렉스입니다
다크 테마 사용 시 채도를 낮춥니다
다크 테마 사용 시 채도를 낮추지 않습니다
저채도 색상
@@ -528,9 +525,7 @@
칩
배경색 채움
칩 스타일
- 저는 Tasks 개발에 엄청나게 많은 시간을 쏟고 있으며, 모든 소스코드를 웹에 무상으로 공개하고 있습니다. 저의 작업을 후원하기 위해 일부 기능은 구독이 필요합니다
당신의 후원은 저에게 큰 힘이 됩니다. 감사합니다!
- 무료 체험을 시작하려면 아래에서 구독 금액을 선택하세요. 언제라도 구독을 취소하실 수 있습니다
색상환
유효하지 않은 사용자명과 비밀번호
신호음, 진동 등
diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml
index 8c45ae723..1f40b0e38 100644
--- a/app/src/main/res/values-nb/strings.xml
+++ b/app/src/main/res/values-nb/strings.xml
@@ -470,13 +470,11 @@
Ugyldig sikkerhetskopifil
Nye gjøremål øverst
Ikon
- Oppgrader, nedgrader eller avbryt ditt abonnement
Nåværende abonnement
Gjenopprett abonnement
Nedgrader abonnement
Oppgrader abonnement
Avbryt abonnement
- Betal det du vil
Månedlig
Årlig
Feil: %s
@@ -576,11 +574,8 @@
Flis
Omrisset
Flisstil
- Jeg har brukt tusenvis av timer på å jobbe med Tasks, og jeg offentliggjør all kildekoden på nettet gratis. For å støtte mitt arbeid krever noen funksjoner et abonnement
- Hei, jeg heter Alex. Jeg er den uavhengige utvikleren bak Tasks
Krever en konto med en CalDAV-tjenestetilbyder, eller en selvdrevet tjener. Finn en tjenestetilbyder ved å besøke tasks.org/caldav
Fylt
- Velg en vilkårlig pris nedenfor for å starte din gratisperiode. Du kan avbryte når som helst.
Vis merknader på din ikledbare
Ikledbare merknader
Boolsk logikkboks 4
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index 676ac1b9d..b971d477c 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -460,13 +460,11 @@
Filters
Filter
Accent
- Aanmelden, afmelden of annuleer je aanmelding
Huidige abonnement
Abonnement herstellen
Terugdraaien abonnement
Abonnement upgraden
Abonnement annuleren
- Bepaal je prijs
Maandelijks
Jaarlijks
Later
@@ -522,9 +520,6 @@
Ongeldige gebruikersnaam of wachtwoord
Systeeminstelling
Kleurenwiel
- Hoi! Mijn naam is Alex. Ik ben de onafhankelijke ontwikkelaar achter Tasks.
- Ik heb duizenden uren aan Tasks gewerkt, en ik publiceer de volledige broncode gratis online. Om mijn werk te steunen vereisen sommige functies een abonnement.
- Kies hierbeneden een abonnementsprijs om je gratis proefperiode te starten. Je kunt het altijd annuleren.
Je steun betekent veel voor me, bedankt!
Terug
Fiche-stijl
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index e4a0983cf..b04e2d0ac 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -481,13 +481,11 @@
Nieprawidłowy plik kopii zapasowej
Nowe zadania na górze
Ikona
- Podwyższyć, obniżyć poziom albo anulować subskrypcję
Aktualna subskrypcja
Przywróć subskrypcję
Obniżyć poziom subskrypcji
Podwyższyć poziom subskrypcji
Anuluj subskrypcję
- Nazwij swoją cenę
Miesięczne
Rocznie
Ręczne
@@ -538,9 +536,6 @@
Nieprawidłowa nazwa użytkownika lub hasło
Domyślny systemowy
Paleta
- Cześć! Mam na imię Alex. Jestem niezależnym deweloperem stojącym za Tasks
- Spędziłem tysiące godzin pracując nad Tasks i publikuję cały kod źródłowy online za darmo. Aby wesprzeć moją pracę, niektóre funkcję wymagają subskrypcji
- Wybierz dowolną cenę subskrypcji poniżej, aby rozpocząć bezpłatny okres próbny. Możesz zrezygnować w każdej chwili
Twoje wsparcie wiele dla mnie znaczy, dziękuję!
Wstecz
Styl chipa
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 4f9b10960..7c5c8cdc3 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -490,9 +490,6 @@
Estilo de notificação
Voltar
Seu suporte significa muito para mim, obrigado!
- Escolha qualquer preço de subscrição abaixo para começar seu teste grátis. Você poderá cancelar a qualquer momento
- Eu investi centenas de horas trabalhando no Tasks, e eu publico todo o código fonte online de graça. Para apoiar meu trabalho, algumas funcionalidades precisam de um plano de subscrição
- Olá! Meu nome é Alex e eu sou o desenvolvedor independente por trás do Tasks
Roda de cores
Nome de usuário ou senha inválido
Toque, vibrações e mais
@@ -526,7 +523,6 @@
Permita que o servidor agende tarefas recorrentes
Anualmente
Mensalmente
- Dê seu valor
Novas tarefas ao topo
Arquivo de restauro inválido
Versão %s
@@ -539,7 +535,6 @@
Rebaixar plano
Recuperar plano
Plano atual
- Atualizar, rebaixar ou cancelar o seu plano
Ajuda e Comentários
", "
Erro: %s
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index bfcee6eb8..a368dcfe7 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -553,9 +553,6 @@
Estilo de notificação
Voltar
Seu suporte significa muito para mim, obrigado!
- Escolha qualquer preço de assinatura abaixo para começar seu teste grátis. Poderá cancelar a qualquer momento
- Eu investi centenas de horas a trabalhar no Tasks e publico todo o código-fonte online de graça. Para apoiar meu trabalho, algumas funcionalidades precisam de uma assinatura
- Olá! O meu nome é Alex e sou o programador independente por trás do Tasks
Roda de cores
Predefinição do Sistema
Nome de utilizador ou palavra-passe inválido
@@ -602,10 +599,8 @@
Temporareamente mostrar tarefas quando completas
Permita que o servidor agende tarefas recorrentes
Minha ordem
- Dê o seu valor
Atualizar assinatura
Rebaixar assinatura
- Atualizar, rebaixar ou cancelar a sua assinatura
Não foi possível conectar
%s m
Sincronize a suas tarefas com a app DAVx⁵
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index e6e5df856..f3ea4dec3 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -482,12 +482,10 @@
Текущая подписка
Восстановить подписку
Отменить подписку
- Назовите свою цену
URL
Ошибка: %s
", "
Генерация уведомлений
- Повысить, понизить уровень подписки или отменить ее
Понизить уровень подписки
Повысить уровень подписки
Ручная сортировка
@@ -543,9 +541,6 @@
Неверное имя пользователя или пароль
Системная по умолчанию
Палитра
- Привет! Меня зовут Алекс. Я - независимый разработчик, стоящий за программой Tasks
- Я потратил тысячи часов, работая над Tasks, и я публикую весь исходный код онлайн, бесплатно. Для того, чтобы поддержать мою работу, некоторые функциональности требуют подписки
- Выберите любую сумму подписки для того, чтобы начать Ваш бесплатный пробный период. Вы можете отказаться в любой момент
Ваша поддержка много значит для меня, спасибо!
Назад
Стиль индикаторов списков
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index f880e674a..28746fe67 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -465,13 +465,11 @@
Ogiltig säkerhetskopia
Nya uppgifter överst
Ikon
- Uppgradera, nedgradera eller Avbryt prenumerationen
Hantera prenumerationer
Återställ prenumeration
Nedgradera prenumeration
Uppgradera prenumerationen
Avbryt prenumeration
- Namnge ditt pris
Månadsvis
Årligen
Min ordning
diff --git a/app/src/main/res/values-sw384dp/bools.xml b/app/src/main/res/values-sw384dp/bools.xml
new file mode 100644
index 000000000..78e6eef0e
--- /dev/null
+++ b/app/src/main/res/values-sw384dp/bools.xml
@@ -0,0 +1,4 @@
+
+
+ false
+
\ No newline at end of file
diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml
index bd342456f..fdcbd1909 100644
--- a/app/src/main/res/values-ta/strings.xml
+++ b/app/src/main/res/values-ta/strings.xml
@@ -243,9 +243,6 @@
கோடிட்டுக் காட்டப்பட்டுள்ளது
சிப் பாணி
மீண்டும்
- உங்கள் இலவச சோதனையைத் தொடங்க கீழே உள்ள எந்த சந்தா விலையையும் தேர்வு செய்யவும். நீங்கள் எந்த நேரத்திலும் ரத்து செய்யலாம்
- நான் பணிகளில் ஆயிரக்கணக்கான மணிநேரங்களை செலவிட்டேன், மேலும் மூலக் குறியீடு அனைத்தையும் ஆன்லைனில் இலவசமாக வெளியிடுகிறேன். எனது பணியை ஆதரிக்க சில அம்சங்களுக்கு சந்தா தேவை
- வணக்கம்! என் பெயர் அலெக்ஸ். பணிகளுக்குப் பின்னால் உள்ள சுயாதீன டெவலப்பர் நான்
வண்ண சக்கரம்
தவறான பயனர்பெயர் அல்லது கடவுச்சொல்
ரிங்டோன், அதிர்வுகள் மற்றும் பல
@@ -278,7 +275,6 @@
தொடர்ச்சியான பணிகளை சேவையாக அட்டவணைப்படுத்தட்டும்
ஆண்டு
மாதாந்திர
- உங்கள் விலைக்கு பெயரிடுங்கள்
மேலே புதிய பணிகள்
தவறான காப்பு கோப்பு
பதிப்பு %s
@@ -321,7 +317,6 @@
தற்போதைய சந்தா
பதிவு
வாங்குதல்களைப் புதுப்பிக்கவும்
- உங்கள் சந்தாவை மேம்படுத்தவும், தரமிறக்கவும் அல்லது ரத்து செய்யவும்
சந்தாவை நிர்வகிக்கவும்
சார்புக்கு மேம்படுத்தவும்
அளவிடப்படாத இணைப்புகளில் மட்டுமே
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index ba01e0649..0f7d3a893 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -471,13 +471,11 @@
Hata: %s
", "
Simge
- Aboneliğinizi yükseltin, alçaltın veya iptal edin
Geçerli abonelik
Aboneliği geri getir
Aboneliği alçalt
Aboneliği yükselt
Aboneliği iptal et
- Fiyat belirleyin
Aylık
Yıllık
Düzenim
@@ -527,9 +525,6 @@
Geçersiz kullanıcı adı veya parola
Sistem öntanımlısı
Renk tekeri
- Hey! Ben Alex. Tasks\'ın arkasındaki bağımsız geliştiriciyim
- Binlerce saatimi Tasks\'ta çalışarak geçirdim, kaynak kodun tümünü çevrim içi olarak ücretsiz yayımladım. Çalışmamı desteklemek için bazı özellikler abonelik gerektirir
- Ücretsiz denemenizi başlatmak için aşağıdan herhangi abonelik bedelini seçin. İstediğinizde iptal edebilirsiniz
Desteğiniz çok şey ifade ediyor, teşekkürler!
Geri
Yonga biçimi
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 4193167e1..260fe7e94 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -508,7 +508,6 @@
Google Tasks
Відновити підписку
Поточна підписка
- Змініть або скасуйте підписку
Підтвердіть пароль шифрування
Пароль шифрування
Потрібний пароль шифрування
@@ -532,7 +531,6 @@
Згорнути підзавдання
Розгорнути підзавдання
Дозволити серверу встановлювати регулярні завдання
- Назвіть свою ціну
Щорічно
Щомісячно
Ця функція потребує підписки
@@ -562,9 +560,6 @@
Стиль індикаторів списків
Назад
Ваша підтримка багато означає для мене. Дякую!
- Оберіть будь-яку вартість підписки знизу, щоб розпочати безоплатний пробний період. Його можна скасувати будь-коли
- Я витратив тисячі годин, працюючи над Tasks, і я публікую весь код онлайн безоплатно. Щоб підтримати мою роботу, деякі функції потребують підписки
- Привіт! Моє ім\'я Алекс. Я - незалежний розробник Tasks
Палітра
Невірне ім\'я користувача або пароль
Мелодія, вібрація та інше
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index c8fee8678..9c1643216 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -460,13 +460,11 @@
无效的备份文件
新任务显示在顶部
图标
- 升级,降级或取消您的订阅
当前订阅
恢复订阅
降级订阅
升级订阅
取消订阅
- 您愿意支付多少费用
每月
每年
", "
@@ -518,9 +516,6 @@
无效的用户名或密码
系统默认
给滚轮着色
- 你好!我叫Alex,是Tasks背后的独立开发者
- 我已经花了数千个小时用于开发Tasks,并且在网上免费发布了所有源代码。 为了支持我的工作,某些功能需要订阅
- 选择下方任意订阅价格即可开始免费试用。 你可以随时取消
您的支持对我很重要,谢谢!
返回
流式布局样式
diff --git a/app/src/main/res/values/bools.xml b/app/src/main/res/values/bools.xml
index 94074fd18..ab08ecd63 100644
--- a/app/src/main/res/values/bools.xml
+++ b/app/src/main/res/values/bools.xml
@@ -4,4 +4,5 @@
false
false
false
+ true
\ No newline at end of file
diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml
index 15b7da07f..9272ab9a8 100644
--- a/app/src/main/res/values/keys.xml
+++ b/app/src/main/res/values/keys.xml
@@ -7,6 +7,7 @@
org.tasks
org.tasks.opentasks
AEdPqrEAAAAI49v5bBusi_bq1bgLBB1LIsepNV0eBrFkQrBZkw
+ 1006257750459-3jt0e32kbqgug7hkluqe26d5mbno92no.apps.googleusercontent.com
@string/ok
@string/cancel
Tasks Shortcut
@@ -17,6 +18,27 @@
https://api.etesync.com
https://tasks.org/sync
+
+ Subscribe to unlock additional features and support open source software!
+ Sync with Tasks.org
+ No platform lock-in
+ Tasks.org is based on open internet standards
+ You are the customer
+ Tasks.org does not monetize you or your data
+ Many new features coming soon!
+ Sync with third-party or self-hosted servers
+ End-to-end encryption with EteSync
+ Multiple Google Task accounts
+ Additional features
+ Unlock all themes, colors, and icons
+ Improved location search with Google Places
+ Tasker plugins
+ New subscribers receive a 7-day free trial
+ Upgrade or downgrade at any time
+ Your remaining balance will apply to your new subscription
+ Cancel at any time
+ benefits are retained until the end of your billing period
+
date_shortcut_morning
date_shortcut_afternoon
date_shortcut_evening
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2fa8493ed..f57656be8 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -489,8 +489,7 @@ File %1$s contained %2$s.\n\n
Could not connect
Only on unmetered connections
Upgrade to pro
- Manage subscription
- Upgrade, downgrade, or cancel your subscription
+ Modify subscription
Refresh purchases
Subscribe
Current subscription
@@ -534,7 +533,7 @@ File %1$s contained %2$s.\n\n
Version %s
Invalid backup file
New tasks on top
- Name your price
+ More options
Monthly
Yearly
Let server schedule recurring tasks
@@ -569,9 +568,6 @@ File %1$s contained %2$s.\n\n
Ringtone, vibrations, and more
Invalid username or password
Color wheel
- Hi! My name is Alex. I am the independent developer behind Tasks
- I have spent thousands of hours working on Tasks, and I publish all of the source code online for free. In order to support my work some features require a subscription
- Choose any subscription price below to start your free trial. You may cancel at any time
Your support means a lot to me, thank you!
Back
Chip style
@@ -658,4 +654,8 @@ File %1$s contained %2$s.\n\n
Delete this comment?
Has subtasks
Is subtask
+ $%s/year
+ $%s/yr
+ $%s/month
+ $%s/mo
diff --git a/app/src/main/res/xml/help_and_feedback.xml b/app/src/main/res/xml/help_and_feedback.xml
index 0fa878cb9..af3ce7da8 100644
--- a/app/src/main/res/xml/help_and_feedback.xml
+++ b/app/src/main/res/xml/help_and_feedback.xml
@@ -51,11 +51,11 @@
android:key="@string/upgrade_to_pro"
android:title="@string/upgrade_to_pro"
app:allowDividerAbove="true"
- app:icon="@drawable/ic_outline_attach_money_24px">
-
-
+ app:icon="@drawable/ic_outline_attach_money_24px" />
+
+