From bf3088ad0b4da7dbc4f2084e4974c3ad29719e9b Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Thu, 20 Feb 2020 08:50:19 -0600 Subject: [PATCH] Migrate tasker list notification to androidx prefs --- .../tasks/injection/FragmentComponent.java | 3 + .../locale/bundle/ListNotificationBundle.java | 1 - .../AbstractFragmentPluginPreference.kt | 81 ++++++++++ ...tractFragmentPluginPreferenceActivity.java | 132 ---------------- .../ui/activity/TaskerSettingsActivity.java | 141 ------------------ .../ui/activity/TaskerSettingsActivity.kt | 40 +++++ .../fragments/TaskerListNotification.kt | 99 ++++++++++++ app/src/main/res/xml/preferences_tasker.xml | 2 +- 8 files changed, 224 insertions(+), 275 deletions(-) create mode 100644 app/src/main/java/org/tasks/locale/ui/activity/AbstractFragmentPluginPreference.kt delete mode 100644 app/src/main/java/org/tasks/locale/ui/activity/AbstractFragmentPluginPreferenceActivity.java delete mode 100755 app/src/main/java/org/tasks/locale/ui/activity/TaskerSettingsActivity.java create mode 100644 app/src/main/java/org/tasks/locale/ui/activity/TaskerSettingsActivity.kt create mode 100644 app/src/main/java/org/tasks/preferences/fragments/TaskerListNotification.kt diff --git a/app/src/main/java/org/tasks/injection/FragmentComponent.java b/app/src/main/java/org/tasks/injection/FragmentComponent.java index 0dba62edd..de9e30b01 100644 --- a/app/src/main/java/org/tasks/injection/FragmentComponent.java +++ b/app/src/main/java/org/tasks/injection/FragmentComponent.java @@ -15,6 +15,7 @@ import org.tasks.fragments.CommentBarFragment; import org.tasks.preferences.fragments.DashClock; import org.tasks.preferences.fragments.HelpAndFeedback; import org.tasks.preferences.fragments.ScrollableWidget; +import org.tasks.preferences.fragments.TaskerListNotification; import org.tasks.ui.CalendarControlSet; import org.tasks.ui.DeadlineControlSet; import org.tasks.ui.DescriptionControlSet; @@ -71,4 +72,6 @@ public interface FragmentComponent { void inject(@NotNull ScrollableWidget scrollableWidget); void inject(@NotNull DashClock dashClock); + + void inject(@NotNull TaskerListNotification taskerListNotification); } diff --git a/app/src/main/java/org/tasks/locale/bundle/ListNotificationBundle.java b/app/src/main/java/org/tasks/locale/bundle/ListNotificationBundle.java index 08a08d32c..f15088d18 100755 --- a/app/src/main/java/org/tasks/locale/bundle/ListNotificationBundle.java +++ b/app/src/main/java/org/tasks/locale/bundle/ListNotificationBundle.java @@ -9,7 +9,6 @@ import timber.log.Timber; public final class ListNotificationBundle { public static final String BUNDLE_EXTRA_STRING_FILTER = "org.tasks.locale.STRING_FILTER"; - public static final String BUNDLE_EXTRA_PREVIOUS_BUNDLE = "org.tasks.locale.PREVIOUS_BUNDLE"; private static final String BUNDLE_EXTRA_INT_VERSION_CODE = "org.tasks.locale.INT_VERSION_CODE"; private ListNotificationBundle() {} diff --git a/app/src/main/java/org/tasks/locale/ui/activity/AbstractFragmentPluginPreference.kt b/app/src/main/java/org/tasks/locale/ui/activity/AbstractFragmentPluginPreference.kt new file mode 100644 index 000000000..5d4a510af --- /dev/null +++ b/app/src/main/java/org/tasks/locale/ui/activity/AbstractFragmentPluginPreference.kt @@ -0,0 +1,81 @@ +package org.tasks.locale.ui.activity + +import android.content.Intent +import android.os.Bundle +import org.tasks.preferences.BasePreferences +import timber.log.Timber + +abstract class AbstractFragmentPluginPreference : BasePreferences() { + + companion object { + fun isLocalePluginIntent(intent: Intent): Boolean { + val action = intent.action + return com.twofortyfouram.locale.api.Intent.ACTION_EDIT_CONDITION == action + || com.twofortyfouram.locale.api.Intent.ACTION_EDIT_SETTING == action + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + if (isLocalePluginIntent(intent)) { + Timber.d( + "Creating Activity with Intent=%s, savedInstanceState=%s, EXTRA_BUNDLE=%s", + intent, savedInstanceState, getPreviousBundle()) + } + } + + override fun finish() { + if (isLocalePluginIntent(intent)) { + if (!isCancelled()) { + val resultBundle = getResultBundle() + if (null != resultBundle) { + val blurb = getResultBlurb(resultBundle) + val result = Bundle() + result.putBundle(com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE, resultBundle) + result.putString(com.twofortyfouram.locale.api.Intent.EXTRA_STRING_BLURB, blurb) + setResult(RESULT_OK, Intent().putExtras(result)) + } + } + } + super.finish() + } + + /** + * @return The [EXTRA_BUNDLE][com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE] that was + * previously saved to the host and subsequently passed back to this Activity for further + * editing. Internally, this method relies on [.isBundleValid]. If the bundle + * exists but is not valid, this method will return null. + */ + protected fun getPreviousBundle(): Bundle? { + val bundle = intent.getBundleExtra(com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE) + if (null != bundle) { + if (isBundleValid(bundle)) { + return bundle + } + } + return null + } + + /** + * Validates the Bundle, to ensure that a malicious application isn't attempting to pass an + * invalid Bundle. + * + * @param bundle The plug-in's Bundle previously returned by the edit Activity. `bundle` + * should not be mutated by this method. + * @return true if `bundle` is valid for the plug-in. + */ + protected abstract fun isBundleValid(bundle: Bundle?): Boolean + + /** @return Bundle for the plug-in or `null` if a valid Bundle cannot be generated. + */ + protected abstract fun getResultBundle(): Bundle? + + /** + * @param bundle Valid bundle for the component. + * @return Blurb for `bundle`. + */ + protected abstract fun getResultBlurb(bundle: Bundle?): String? + + protected abstract fun isCancelled(): Boolean +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/locale/ui/activity/AbstractFragmentPluginPreferenceActivity.java b/app/src/main/java/org/tasks/locale/ui/activity/AbstractFragmentPluginPreferenceActivity.java deleted file mode 100644 index da3d8e88e..000000000 --- a/app/src/main/java/org/tasks/locale/ui/activity/AbstractFragmentPluginPreferenceActivity.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.tasks.locale.ui.activity; - -import android.content.Intent; -import android.os.Bundle; -import org.tasks.injection.InjectingPreferenceActivity; -import timber.log.Timber; - -public abstract class AbstractFragmentPluginPreferenceActivity extends InjectingPreferenceActivity { - - boolean mIsCancelled = false; - - /* package */ - private static boolean isLocalePluginIntent(final Intent intent) { - final String action = intent.getAction(); - - return com.twofortyfouram.locale.api.Intent.ACTION_EDIT_CONDITION.equals(action) - || com.twofortyfouram.locale.api.Intent.ACTION_EDIT_SETTING.equals(action); - } - - @Override - public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (isLocalePluginIntent(getIntent())) { - final Bundle previousBundle = getPreviousBundle(); - - Timber.d( - "Creating Activity with Intent=%s, savedInstanceState=%s, EXTRA_BUNDLE=%s", - getIntent(), savedInstanceState, previousBundle); // $NON-NLS-1$ - } - } - - @Override - protected void onPostCreate(final Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - - if (isLocalePluginIntent(getIntent())) { - if (null == savedInstanceState) { - final Bundle previousBundle = getPreviousBundle(); - final String previousBlurb = getPreviousBlurb(); - if (null != previousBundle && null != previousBlurb) { - onPostCreateWithPreviousResult(previousBundle, previousBlurb); - } - } - } - } - - @Override - public void finish() { - if (isLocalePluginIntent(getIntent())) { - if (!mIsCancelled) { - final Bundle resultBundle = getResultBundle(); - - if (null != resultBundle) { - String blurb = getResultBlurb(resultBundle); - Bundle result = new Bundle(); - result.putBundle(com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE, resultBundle); - result.putString(com.twofortyfouram.locale.api.Intent.EXTRA_STRING_BLURB, blurb); - mergeResults(result); - } - } - } - super.finish(); - } - - /** - * @return The {@link com.twofortyfouram.locale.api.Intent#EXTRA_BUNDLE EXTRA_BUNDLE} that was - * previously saved to the host and subsequently passed back to this Activity for further - * editing. Internally, this method relies on {@link #isBundleValid(Bundle)}. If the bundle - * exists but is not valid, this method will return null. - */ - private Bundle getPreviousBundle() { - final Bundle bundle = - getIntent().getBundleExtra(com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE); - - if (null != bundle) { - if (isBundleValid(bundle)) { - return bundle; - } - } - - return null; - } - - /** - * @return The {@link com.twofortyfouram.locale.api.Intent#EXTRA_STRING_BLURB EXTRA_STRING_BLURB} - * that was previously saved to the host and subsequently passed back to this Activity for - * further editing. - */ - private String getPreviousBlurb() { - return getIntent().getStringExtra(com.twofortyfouram.locale.api.Intent.EXTRA_STRING_BLURB); - } - - /** - * Validates the Bundle, to ensure that a malicious application isn't attempting to pass an - * invalid Bundle. - * - * @param bundle The plug-in's Bundle previously returned by the edit Activity. {@code bundle} - * should not be mutated by this method. - * @return true if {@code bundle} is valid for the plug-in. - */ - protected abstract boolean isBundleValid(final Bundle bundle); - - /** - * Plug-in Activity lifecycle callback to allow the Activity to restore state for editing a - * previously saved plug-in instance. This callback will occur during the onPostCreate() phase of - * the Activity lifecycle. - * - *

{@code bundle} will have been validated by {@link #isBundleValid(Bundle)} prior to this - * method being called. If {@link #isBundleValid(Bundle)} returned false, then this method will - * not be called. This helps ensure that plug-in Activity subclasses only have to worry about - * bundle validation once, in the {@link #isBundleValid(Bundle)} method. - * - *

Note this callback only occurs the first time the Activity is created, so it will not be - * called when the Activity is recreated (e.g. {@code savedInstanceState != null}) such as after a - * configuration change like a screen rotation. - * - * @param previousBundle Previous bundle that the Activity saved. - * @param previousBlurb Previous blurb that the Activity saved - */ - protected abstract void onPostCreateWithPreviousResult( - final Bundle previousBundle, final String previousBlurb); - - /** @return Bundle for the plug-in or {@code null} if a valid Bundle cannot be generated. */ - protected abstract Bundle getResultBundle(); - - /** - * @param bundle Valid bundle for the component. - * @return Blurb for {@code bundle}. - */ - protected abstract String getResultBlurb(final Bundle bundle); -} diff --git a/app/src/main/java/org/tasks/locale/ui/activity/TaskerSettingsActivity.java b/app/src/main/java/org/tasks/locale/ui/activity/TaskerSettingsActivity.java deleted file mode 100755 index d60b6281b..000000000 --- a/app/src/main/java/org/tasks/locale/ui/activity/TaskerSettingsActivity.java +++ /dev/null @@ -1,141 +0,0 @@ -package org.tasks.locale.ui.activity; - -import android.content.Intent; -import android.os.Bundle; -import android.view.MenuItem; -import androidx.appcompat.widget.Toolbar; -import com.todoroo.astrid.api.Filter; -import javax.inject.Inject; -import org.tasks.R; -import org.tasks.activities.FilterSelectionActivity; -import org.tasks.billing.BillingClient; -import org.tasks.billing.Inventory; -import org.tasks.billing.PurchaseActivity; -import org.tasks.injection.ActivityComponent; -import org.tasks.locale.bundle.ListNotificationBundle; -import org.tasks.preferences.DefaultFilterProvider; - -public final class TaskerSettingsActivity extends AbstractFragmentPluginPreferenceActivity - implements Toolbar.OnMenuItemClickListener { - - private static final int REQUEST_SELECT_FILTER = 10124; - private static final int REQUEST_SUBSCRIPTION = 10125; - private static final String EXTRA_FILTER = "extra_filter"; - - @Inject DefaultFilterProvider defaultFilterProvider; - @Inject BillingClient billingClient; - @Inject Inventory inventory; - - private Bundle previousBundle; - private Filter filter; - - @Override - public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - addPreferencesFromResource(R.xml.preferences_tasker); - - if (savedInstanceState != null) { - previousBundle = - savedInstanceState.getParcelable(ListNotificationBundle.BUNDLE_EXTRA_PREVIOUS_BUNDLE); - filter = savedInstanceState.getParcelable(EXTRA_FILTER); - } else { - filter = defaultFilterProvider.getDefaultFilter(); - } - - findPreference(R.string.filter) - .setOnPreferenceClickListener( - preference -> { - Intent intent = - new Intent(TaskerSettingsActivity.this, FilterSelectionActivity.class); - intent.putExtra(FilterSelectionActivity.EXTRA_FILTER, filter); - intent.putExtra(FilterSelectionActivity.EXTRA_RETURN_FILTER, true); - startActivityForResult(intent, REQUEST_SELECT_FILTER); - return false; - }); - - refreshPreferences(); - - if (!inventory.purchasedTasker()) { - startActivityForResult(new Intent(this, PurchaseActivity.class), REQUEST_SUBSCRIPTION); - } - } - - @Override - public void onPostCreateWithPreviousResult( - final Bundle previousBundle, final String previousBlurb) { - this.previousBundle = previousBundle; - this.filter = - defaultFilterProvider.getFilterFromPreference( - ListNotificationBundle.getFilter(previousBundle)); - refreshPreferences(); - } - - @Override - public boolean isBundleValid(final Bundle bundle) { - return ListNotificationBundle.isBundleValid(bundle); - } - - @Override - protected Bundle getResultBundle() { - return ListNotificationBundle.generateBundle( - defaultFilterProvider.getFilterPreferenceValue(filter)); - } - - @Override - public String getResultBlurb(final Bundle bundle) { - return filter.listingTitle; - } - - private void cancel() { - mIsCancelled = true; - finish(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == REQUEST_SELECT_FILTER) { - if (resultCode == RESULT_OK) { - filter = data.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER); - refreshPreferences(); - } - } else if (requestCode == REQUEST_SUBSCRIPTION) { - if (!inventory.purchasedTasker()) { - cancel(); - } - } else { - super.onActivityResult(requestCode, resultCode, data); - } - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putParcelable(ListNotificationBundle.BUNDLE_EXTRA_PREVIOUS_BUNDLE, previousBundle); - outState.putParcelable(EXTRA_FILTER, filter); - } - - private void refreshPreferences() { - findPreference(getString(R.string.filter)).setSummary(filter.listingTitle); - } - - @Override - public void inject(ActivityComponent component) { - component.inject(this); - } - - @Override - protected String getHelpUrl() { - return "http://tasks.org/help/tasker"; - } - - @Override - public boolean onMenuItemClick(MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_save: - finish(); - return true; - } - return super.onMenuItemClick(item); - } -} diff --git a/app/src/main/java/org/tasks/locale/ui/activity/TaskerSettingsActivity.kt b/app/src/main/java/org/tasks/locale/ui/activity/TaskerSettingsActivity.kt new file mode 100644 index 000000000..8b8a1644f --- /dev/null +++ b/app/src/main/java/org/tasks/locale/ui/activity/TaskerSettingsActivity.kt @@ -0,0 +1,40 @@ +package org.tasks.locale.ui.activity + +import android.os.Bundle +import org.tasks.R +import org.tasks.injection.ActivityComponent +import org.tasks.locale.bundle.ListNotificationBundle +import org.tasks.preferences.fragments.TaskerListNotification +import org.tasks.preferences.fragments.TaskerListNotification.Companion.newTaskerListNotification + +class TaskerSettingsActivity : AbstractFragmentPluginPreference() { + + var filter: String? = null + + override fun onCreate(savedInstanceState: Bundle?) { + if (isLocalePluginIntent(intent)) { + val previousBundle = getPreviousBundle() + if (isBundleValid(previousBundle)) { + filter = ListNotificationBundle.getFilter(previousBundle) + } + } + + super.onCreate(savedInstanceState) + } + + override fun isBundleValid(bundle: Bundle?) = ListNotificationBundle.isBundleValid(bundle) + + override fun getResultBundle() = getFragment().getBundle() + + override fun getResultBlurb(bundle: Bundle?) = getFragment().getResultBlurb() + + override fun isCancelled() = getFragment().cancelled + + override fun getRootTitle() = R.string.tasker_list_notification + + override fun getRootPreference() = newTaskerListNotification(filter) + + override fun inject(component: ActivityComponent) = component.inject(this) + + private fun getFragment() = supportFragmentManager.findFragmentById(R.id.settings) as TaskerListNotification +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/preferences/fragments/TaskerListNotification.kt b/app/src/main/java/org/tasks/preferences/fragments/TaskerListNotification.kt new file mode 100644 index 000000000..e4e7cad10 --- /dev/null +++ b/app/src/main/java/org/tasks/preferences/fragments/TaskerListNotification.kt @@ -0,0 +1,99 @@ +package org.tasks.preferences.fragments + +import android.app.Activity.RESULT_OK +import android.content.Intent +import android.os.Bundle +import com.todoroo.astrid.api.Filter +import org.tasks.R +import org.tasks.activities.FilterSelectionActivity +import org.tasks.billing.Inventory +import org.tasks.billing.PurchaseActivity +import org.tasks.injection.FragmentComponent +import org.tasks.injection.InjectingPreferenceFragment +import org.tasks.locale.bundle.ListNotificationBundle +import org.tasks.preferences.DefaultFilterProvider +import javax.inject.Inject + +const val EXTRA_FILTER = "extra_filter" +private const val REQUEST_SELECT_FILTER = 10124 +private const val REQUEST_SUBSCRIPTION = 10125 + +class TaskerListNotification : InjectingPreferenceFragment() { + + companion object { + fun newTaskerListNotification(filter: String?): TaskerListNotification { + val fragment = TaskerListNotification() + val args = Bundle() + args.putString(EXTRA_FILTER, filter) + fragment.arguments = args + return fragment + } + } + + @Inject lateinit var defaultFilterProvider: DefaultFilterProvider + @Inject lateinit var inventory: Inventory + + var filter: Filter? = null + var cancelled: Boolean = false + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.preferences_tasker, rootKey) + + filter = if (savedInstanceState == null) { + defaultFilterProvider.getFilterFromPreference(arguments?.getString(EXTRA_FILTER)) + } else { + savedInstanceState.getParcelable(EXTRA_FILTER) + } + + refreshPreferences() + + findPreference(R.string.filter).setOnPreferenceClickListener { + val intent = Intent(context, FilterSelectionActivity::class.java) + intent.putExtra(FilterSelectionActivity.EXTRA_FILTER, filter) + intent.putExtra(FilterSelectionActivity.EXTRA_RETURN_FILTER, true) + startActivityForResult(intent, REQUEST_SELECT_FILTER) + false + } + + if (!inventory.purchasedTasker()) { + startActivityForResult(Intent(context, PurchaseActivity::class.java), REQUEST_SUBSCRIPTION) + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + if (requestCode == REQUEST_SELECT_FILTER) { + if (resultCode == RESULT_OK) { + filter = data!!.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER) + refreshPreferences() + } + } else if (requestCode == REQUEST_SUBSCRIPTION) { + if (!inventory.purchasedTasker()) { + cancelled = true + activity!!.finish() + } + } else { + super.onActivityResult(requestCode, resultCode, data) + } + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + + outState.putParcelable(EXTRA_FILTER, filter) + } + + private fun refreshPreferences() { + findPreference(R.string.filter).summary = filter?.listingTitle + } + + fun getResultBlurb(): String? { + return filter?.listingTitle + } + + fun getBundle(): Bundle { + return ListNotificationBundle.generateBundle( + defaultFilterProvider.getFilterPreferenceValue(filter)) + } + + override fun inject(component: FragmentComponent) = component.inject(this) +} \ No newline at end of file diff --git a/app/src/main/res/xml/preferences_tasker.xml b/app/src/main/res/xml/preferences_tasker.xml index 23be7b62b..0d66511b5 100644 --- a/app/src/main/res/xml/preferences_tasker.xml +++ b/app/src/main/res/xml/preferences_tasker.xml @@ -1,6 +1,6 @@ - \ No newline at end of file