diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e51965ebe..c673d7faa 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -180,6 +180,7 @@ dependencies { implementation("androidx.annotation:annotation:1.1.0") implementation("androidx.constraintlayout:constraintlayout:2.0.0-beta4") implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0") + implementation("androidx.preference:preference:1.1.0") implementation("com.jakewharton.timber:timber:4.7.1") implementation("com.jakewharton.threetenabp:threetenabp:1.2.1") implementation("com.google.guava:guava:27.1-android") diff --git a/app/licenses.yml b/app/licenses.yml index f6e43887f..6c1f7d94a 100644 --- a/app/licenses.yml +++ b/app/licenses.yml @@ -829,3 +829,9 @@ license: Bouncy Castle Licence licenseUrl: http://www.bouncycastle.org/licence.html url: http://rtyley.github.io/spongycastle/ +- artifact: androidx.preference:preference:+ + name: AndroidX Preference + copyrightHolder: Android Open Source Project + license: The Apache Software License, Version 2.0 + licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt + url: https://developer.android.com/jetpack/androidx diff --git a/app/src/debug/res/values/keys.xml b/app/src/debug/res/values/keys.xml index 36bf6f2dc..99967f7f4 100644 --- a/app/src/debug/res/values/keys.xml +++ b/app/src/debug/res/values/keys.xml @@ -1,6 +1,7 @@ Tasks Debug + org.tasks.debug AEdPqrEAAAAImTf5DbfspggWrU9h06685ONycpUVwJj1JwawQQ Strict mode - Thread Strict mode - VM diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dfc7007f7..f59113fc9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -574,6 +574,10 @@ android:name=".etesync.EncryptionSettingsActivity" android:theme="@style/Tasks" /> + + + val nextIntent = Intent(context, MainActivity::class.java) + nextIntent.putExtra(MainActivity.OPEN_FILTER, null as Filter?) + ProcessPhoenix.triggerRebirth(context, nextIntent) + } + .setNegativeButton(R.string.restart_later, null) + .show() + } + + protected fun requires(@StringRes prefGroup: Int, check: Boolean, vararg resIds: Int) { + if (!check) { + remove(findPreference(prefGroup) as PreferenceGroup, resIds) + } + } + + protected fun remove(vararg resIds: Int) { + remove(preferenceScreen, resIds) + } + + private fun remove(preferenceGroup: PreferenceGroup, resIds: IntArray) { + for (resId in resIds) { + preferenceGroup.removePreference(findPreference(resId)) + } + } + + protected fun recreate() { + activity!!.recreate() + } + + protected fun findPreference(@StringRes prefId: Int): Preference { + return findPreference(getString(prefId))!! + } + + protected abstract fun inject(component: FragmentComponent) +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/preferences/BasicPreferences.java b/app/src/main/java/org/tasks/preferences/BasicPreferences.java index e4045c92e..8daad0717 100644 --- a/app/src/main/java/org/tasks/preferences/BasicPreferences.java +++ b/app/src/main/java/org/tasks/preferences/BasicPreferences.java @@ -43,9 +43,7 @@ import org.tasks.activities.FilterSelectionActivity; import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracking; import org.tasks.analytics.Tracking.Events; -import org.tasks.billing.BillingClient; import org.tasks.billing.Inventory; -import org.tasks.billing.PurchaseActivity; import org.tasks.caldav.CaldavAccountSettingsActivity; import org.tasks.data.CaldavAccount; import org.tasks.data.CaldavDao; @@ -107,7 +105,6 @@ public class BasicPreferences extends InjectingPreferenceActivity @Inject Toaster toaster; @Inject ActivityPermissionRequestor permissionRequestor; @Inject GoogleAccountManager googleAccountManager; - @Inject BillingClient billingClient; @Inject DefaultFilterProvider defaultFilterProvider; @Inject LocalBroadcastManager localBroadcastManager; @Inject WorkManager workManager; @@ -248,12 +245,6 @@ public class BasicPreferences extends InjectingPreferenceActivity } return true; }); - findPreference(getString(R.string.p_collect_statistics)) - .setOnPreferenceChangeListener( - (preference, newValue) -> { - showRestartDialog(); - return true; - }); findPreference(R.string.backup_BAc_import) .setOnPreferenceClickListener( @@ -292,45 +283,6 @@ public class BasicPreferences extends InjectingPreferenceActivity } }); - findPreference(R.string.contact_developer) - .setOnPreferenceClickListener( - preference -> { - emailSupport(); - return false; - }); - - findPreference(R.string.third_party_licenses) - .setOnPreferenceClickListener( - preference -> { - startActivity(new Intent(this, AttributionActivity.class)); - return false; - }); - - findPreference(R.string.rate_tasks) - .setOnPreferenceClickListener( - preference -> { - startActivity( - new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.market_url)))); - return false; - }); - - Preference upgradeToPro = findPreference(R.string.upgrade_to_pro); - upgradeToPro.setOnPreferenceClickListener( - p -> { - startActivity(new Intent(this, PurchaseActivity.class)); - return false; - }); - if (inventory.hasPro()) { - upgradeToPro.setTitle(R.string.manage_subscription); - upgradeToPro.setSummary(R.string.manage_subscription_summary); - } - - findPreference(R.string.refresh_purchases).setOnPreferenceClickListener( - preference -> { - billingClient.queryPurchases(); - return false; - }); - findPreference(getString(R.string.p_background_sync_unmetered_only)) .setOnPreferenceChangeListener( (preference, o) -> { @@ -362,9 +314,6 @@ public class BasicPreferences extends InjectingPreferenceActivity return false; }); - findPreference(R.string.changelog) - .setSummary(getString(R.string.version_string, BuildConfig.VERSION_NAME)); - requires( R.string.settings_localization, atLeastJellybeanMR1(), @@ -375,17 +324,6 @@ public class BasicPreferences extends InjectingPreferenceActivity requires(BuildConfig.DEBUG, R.string.debug); - //noinspection ConstantConditions - if (BuildConfig.FLAVOR.equals("generic")) { - requires( - R.string.about, - false, - R.string.rate_tasks, - R.string.upgrade_to_pro, - R.string.refresh_purchases); - requires(R.string.privacy, false, R.string.p_collect_statistics); - } - //noinspection ConstantConditions if (!BuildConfig.FLAVOR.equals("googleplay")) { removeGroup(R.string.TEA_control_location); diff --git a/app/src/main/java/org/tasks/preferences/HelpAndFeedback.kt b/app/src/main/java/org/tasks/preferences/HelpAndFeedback.kt new file mode 100644 index 000000000..e18e54a8a --- /dev/null +++ b/app/src/main/java/org/tasks/preferences/HelpAndFeedback.kt @@ -0,0 +1,81 @@ +package org.tasks.preferences + +import android.os.Bundle +import androidx.appcompat.widget.Toolbar +import androidx.core.content.ContextCompat +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat +import org.tasks.R +import org.tasks.databinding.ActivityPreferencesBinding +import org.tasks.injection.ActivityComponent +import org.tasks.injection.ThemedInjectingAppCompatActivity +import org.tasks.preferences.fragments.HelpAndFeedback +import org.tasks.ui.MenuColorizer + +private const val EXTRA_TITLE = "extra_title" + +class HelpAndFeedback : ThemedInjectingAppCompatActivity(), + PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { + + lateinit var toolbar: Toolbar + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val binding = ActivityPreferencesBinding.inflate(layoutInflater) + setContentView(binding.root) + toolbar = binding.toolbar.toolbar + if (savedInstanceState == null) { + supportFragmentManager + .beginTransaction() + .replace(R.id.settings, HelpAndFeedback()) + .commit() + toolbar.title = getString(R.string.help_and_feedback) + } else { + toolbar.title = savedInstanceState.getCharSequence(EXTRA_TITLE) + } + supportFragmentManager.addOnBackStackChangedListener { + if (supportFragmentManager.backStackEntryCount == 0) { + toolbar.title = getString(R.string.help_and_feedback) + } + } + toolbar.navigationIcon = ContextCompat.getDrawable(this, R.drawable.ic_outline_arrow_back_24px); + toolbar.setNavigationOnClickListener { onBackPressed() } + MenuColorizer.colorToolbar(this, toolbar) + } + + override fun inject(component: ActivityComponent) { + component.inject(this) + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + outState.putCharSequence(EXTRA_TITLE, toolbar.title) + } + + override fun onSupportNavigateUp(): Boolean { + if (supportFragmentManager.popBackStackImmediate()) { + return true + } + return super.onSupportNavigateUp() + } + + override fun onPreferenceStartFragment( + caller: PreferenceFragmentCompat, + pref: Preference + ): Boolean { + val args = pref.extras + val fragment = supportFragmentManager.fragmentFactory.instantiate( + classLoader, + pref.fragment + ).apply { + arguments = args + setTargetFragment(caller, 0) + } + supportFragmentManager.beginTransaction() + .replace(R.id.settings, fragment) + .addToBackStack(null) + .commit() + toolbar.title = pref.title + return true + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/preferences/fragments/HelpAndFeedback.kt b/app/src/main/java/org/tasks/preferences/fragments/HelpAndFeedback.kt new file mode 100644 index 000000000..68909d113 --- /dev/null +++ b/app/src/main/java/org/tasks/preferences/fragments/HelpAndFeedback.kt @@ -0,0 +1,64 @@ +package org.tasks.preferences.fragments + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import org.tasks.BuildConfig +import org.tasks.R +import org.tasks.billing.BillingClient +import org.tasks.billing.Inventory +import org.tasks.injection.FragmentComponent +import org.tasks.injection.InjectingPreferenceFragment +import javax.inject.Inject + +class HelpAndFeedback : InjectingPreferenceFragment() { + + @Inject lateinit var billingClient: BillingClient + @Inject lateinit var inventory: Inventory + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.help_and_feedback, rootKey) + + findPreference(R.string.changelog).summary = getString(R.string.version_string, BuildConfig.VERSION_NAME) + + findPreference(R.string.contact_developer) + .setOnPreferenceClickListener { + val uri = Uri.fromParts("mailto", "Alex <" + getString(R.string.support_email) + ">", null) + val intent = Intent(Intent.ACTION_SENDTO, uri) + .putExtra(Intent.EXTRA_SUBJECT, "Tasks Feedback") + .putExtra(Intent.EXTRA_TEXT, device.debugInfo) + startActivity(intent) + false + } + + findPreference(R.string.refresh_purchases) + .setOnPreferenceClickListener { + billingClient.queryPurchases() + false + } + + findPreference(R.string.p_collect_statistics) + .setOnPreferenceClickListener { + showRestartDialog() + true + } + + if (inventory.hasPro()) { + val findPreference = findPreference(R.string.upgrade_to_pro) + findPreference.title = getString(R.string.manage_subscription) + findPreference.summary = getString(R.string.manage_subscription_summary) + } + + @Suppress("ConstantConditionIf") + if (BuildConfig.FLAVOR == "generic") { + remove(R.string.p_collect_statistics, + R.string.rate_tasks, + R.string.upgrade_to_pro, + R.string.refresh_purchases) + } + } + + override fun inject(component: FragmentComponent) { + component.inject(this); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/themes/CustomIcons.kt b/app/src/main/java/org/tasks/themes/CustomIcons.kt index 135132d5f..51ed7d482 100644 --- a/app/src/main/java/org/tasks/themes/CustomIcons.kt +++ b/app/src/main/java/org/tasks/themes/CustomIcons.kt @@ -152,7 +152,11 @@ object CustomIcons { 1115 to R.drawable.ic_outline_scanner_24px, 1116 to R.drawable.ic_outline_router_24px, 1117 to R.drawable.ic_outline_watch_24px, - 1118 to R.drawable.ic_outline_videogame_asset_24px + 1118 to R.drawable.ic_outline_videogame_asset_24px, + 1119 to R.drawable.ic_cached_24px, + 1120 to R.drawable.ic_octocat, + 1121 to R.drawable.ic_outline_perm_identity_24px, + 1122 to R.drawable.ic_track_changes_24px ) @kotlin.jvm.JvmStatic diff --git a/app/src/main/res/drawable/ic_cached_24px.xml b/app/src/main/res/drawable/ic_cached_24px.xml new file mode 100644 index 000000000..1f361b4c4 --- /dev/null +++ b/app/src/main/res/drawable/ic_cached_24px.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_octocat.xml b/app/src/main/res/drawable/ic_octocat.xml new file mode 100644 index 000000000..863680d33 --- /dev/null +++ b/app/src/main/res/drawable/ic_octocat.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_perm_identity_24px.xml b/app/src/main/res/drawable/ic_outline_perm_identity_24px.xml new file mode 100644 index 000000000..972af9cf1 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_perm_identity_24px.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_track_changes_24px.xml b/app/src/main/res/drawable/ic_track_changes_24px.xml new file mode 100644 index 000000000..8092efc53 --- /dev/null +++ b/app/src/main/res/drawable/ic_track_changes_24px.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_preferences.xml b/app/src/main/res/layout/activity_preferences.xml new file mode 100644 index 000000000..a022a0822 --- /dev/null +++ b/app/src/main/res/layout/activity_preferences.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3de05e03a..0d3cfcca3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -496,6 +496,7 @@ File %1$s contained %2$s.\n\n Create task List notification Help + Help & feedback Home set not found Connection failed Only on unmetered connections @@ -578,4 +579,5 @@ File %1$s contained %2$s.\n\n Requires an account with a CalDAV service provider or a self-hosted server. Find a service provider by visiting tasks.org/caldav Requires an account with EteSync.com or a self-hosted server Choose an encryption password. Do not forget your password, it cannot be recovered! + Documentation diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 8e6faf96f..962366668 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,6 +1,8 @@ - +