mirror of https://github.com/tasks/tasks
Migrate settings to androidx preferences
parent
bf3088ad0b
commit
00b57e1af7
@ -1,79 +0,0 @@
|
||||
package org.tasks.preferences;
|
||||
|
||||
import static com.google.common.primitives.Ints.asList;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import androidx.annotation.StringRes;
|
||||
import at.bitfire.cert4android.CustomCertManager;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.billing.BillingClient;
|
||||
import org.tasks.billing.Inventory;
|
||||
import org.tasks.injection.ActivityComponent;
|
||||
import org.tasks.injection.InjectingPreferenceActivity;
|
||||
import org.tasks.ui.Toaster;
|
||||
|
||||
public class DebugPreferences extends InjectingPreferenceActivity {
|
||||
|
||||
@Inject Inventory inventory;
|
||||
@Inject BillingClient billingClient;
|
||||
@Inject Toaster toaster;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences_debug);
|
||||
|
||||
for (int pref :
|
||||
asList(
|
||||
R.string.p_leakcanary,
|
||||
R.string.p_flipper,
|
||||
R.string.p_strict_mode_vm,
|
||||
R.string.p_strict_mode_thread)) {
|
||||
findPreference(pref)
|
||||
.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
showRestartDialog();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
findPreference(R.string.debug_reset_ssl)
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
CustomCertManager.Companion.resetCertificates(this);
|
||||
toaster.longToast("SSL certificates reset");
|
||||
return false;
|
||||
});
|
||||
|
||||
setupIap(R.string.debug_themes, Inventory.SKU_THEMES);
|
||||
setupIap(R.string.debug_tasker, Inventory.SKU_TASKER);
|
||||
setupIap(R.string.debug_dashclock, Inventory.SKU_DASHCLOCK);
|
||||
}
|
||||
|
||||
private void setupIap(@StringRes int prefId, String sku) {
|
||||
Preference preference = findPreference(prefId);
|
||||
if (inventory.getPurchase(sku) == null) {
|
||||
preference.setTitle(getString(R.string.debug_purchase, sku));
|
||||
preference.setOnPreferenceClickListener(
|
||||
p -> {
|
||||
billingClient.initiatePurchaseFlow(DebugPreferences.this, sku, "inapp" /*SkuType.INAPP*/, null);
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
preference.setTitle(getString(R.string.debug_consume, sku));
|
||||
preference.setOnPreferenceClickListener(
|
||||
p -> {
|
||||
billingClient.consume(sku);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package org.tasks.preferences.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.preference.Preference
|
||||
import at.bitfire.cert4android.CustomCertManager.Companion.resetCertificates
|
||||
import com.android.billingclient.api.BillingClient.SkuType
|
||||
import com.google.common.primitives.Ints
|
||||
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 org.tasks.ui.Toaster
|
||||
import javax.inject.Inject
|
||||
|
||||
class Debug : InjectingPreferenceFragment() {
|
||||
|
||||
@Inject lateinit var inventory: Inventory
|
||||
@Inject lateinit var billingClient: BillingClient
|
||||
@Inject lateinit var toaster: Toaster
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences_debug, rootKey)
|
||||
|
||||
for (pref in Ints.asList(
|
||||
R.string.p_leakcanary,
|
||||
R.string.p_flipper,
|
||||
R.string.p_strict_mode_vm,
|
||||
R.string.p_strict_mode_thread)) findPreference(pref)
|
||||
.setOnPreferenceChangeListener { _: Preference?, _: Any? ->
|
||||
showRestartDialog()
|
||||
true
|
||||
}
|
||||
|
||||
findPreference(R.string.debug_reset_ssl).setOnPreferenceClickListener {
|
||||
resetCertificates(context!!)
|
||||
toaster.longToast("SSL certificates reset")
|
||||
false
|
||||
}
|
||||
|
||||
setupIap(R.string.debug_themes, Inventory.SKU_THEMES)
|
||||
setupIap(R.string.debug_tasker, Inventory.SKU_TASKER)
|
||||
setupIap(R.string.debug_dashclock, Inventory.SKU_DASHCLOCK)
|
||||
}
|
||||
|
||||
private fun setupIap(@StringRes prefId: Int, sku: String) {
|
||||
val preference: Preference = findPreference(prefId)
|
||||
if (inventory.getPurchase(sku) == null) {
|
||||
preference.title = getString(R.string.debug_purchase, sku)
|
||||
preference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
billingClient.initiatePurchaseFlow(activity, sku, SkuType.INAPP, null)
|
||||
false
|
||||
}
|
||||
} else {
|
||||
preference.title = getString(R.string.debug_consume, sku)
|
||||
preference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
billingClient.consume(sku)
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun inject(component: FragmentComponent) = component.inject(this)
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.core;
|
||||
|
||||
import static org.tasks.PermissionUtil.verifyPermissions;
|
||||
import static org.tasks.activities.RemoteListNativePicker.newRemoteListNativePicker;
|
||||
import static org.tasks.dialogs.NativeSeekBarDialog.newSeekBarDialog;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.todoroo.astrid.api.CaldavFilter;
|
||||
import com.todoroo.astrid.api.Filter;
|
||||
import com.todoroo.astrid.api.GtasksFilter;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.activities.CalendarSelectionActivity;
|
||||
import org.tasks.calendars.AndroidCalendar;
|
||||
import org.tasks.calendars.CalendarProvider;
|
||||
import org.tasks.dialogs.DialogBuilder;
|
||||
import org.tasks.dialogs.NativeSeekBarDialog;
|
||||
import org.tasks.gtasks.RemoteListSelectionHandler;
|
||||
import org.tasks.injection.ActivityComponent;
|
||||
import org.tasks.injection.InjectingPreferenceActivity;
|
||||
import org.tasks.locale.Locale;
|
||||
import org.tasks.preferences.ActivityPermissionRequestor;
|
||||
import org.tasks.preferences.DefaultFilterProvider;
|
||||
import org.tasks.preferences.Device;
|
||||
import org.tasks.preferences.PermissionRequestor;
|
||||
import org.tasks.preferences.Preferences;
|
||||
import org.tasks.sync.AddAccountDialog;
|
||||
|
||||
public class DefaultsPreferences extends InjectingPreferenceActivity
|
||||
implements RemoteListSelectionHandler, NativeSeekBarDialog.SeekBarCallback {
|
||||
|
||||
private static final String FRAG_TAG_REMOTE_LIST_SELECTION = "frag_tag_remote_list_selection";
|
||||
private static final String FRAG_TAG_RADIUS_PICKER = "frag_tag_radius_picker";
|
||||
|
||||
private static final int REQUEST_CALENDAR_SELECTION = 10412;
|
||||
|
||||
@Inject Preferences preferences;
|
||||
@Inject CalendarProvider calendarProvider;
|
||||
@Inject ActivityPermissionRequestor permissionRequester;
|
||||
@Inject DefaultFilterProvider defaultFilterProvider;
|
||||
@Inject Locale locale;
|
||||
@Inject Device device;
|
||||
@Inject DialogBuilder dialogBuilder;
|
||||
|
||||
private Preference defaultCalendarPref;
|
||||
private Preference defaultRadiusPref;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences_defaults);
|
||||
|
||||
defaultCalendarPref = findPreference(getString(R.string.gcal_p_default));
|
||||
defaultCalendarPref.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
if (permissionRequester.requestCalendarPermissions()) {
|
||||
startCalendarSelectionActivity();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
String defaultCalendarName = getDefaultCalendarName();
|
||||
defaultCalendarPref.setSummary(
|
||||
defaultCalendarName == null
|
||||
? getString(R.string.dont_add_to_calendar)
|
||||
: defaultCalendarName);
|
||||
|
||||
findPreference(R.string.p_default_remote_list)
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
newRemoteListNativePicker(defaultFilterProvider.getDefaultRemoteList())
|
||||
.show(getFragmentManager(), FRAG_TAG_REMOTE_LIST_SELECTION);
|
||||
return false;
|
||||
});
|
||||
updateRemoteListSummary();
|
||||
defaultRadiusPref = findPreference(R.string.p_default_location_radius);
|
||||
defaultRadiusPref.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
newSeekBarDialog(
|
||||
R.layout.dialog_radius_seekbar,
|
||||
75,
|
||||
1000,
|
||||
preferences.getInt(R.string.p_default_location_radius, 250),
|
||||
0)
|
||||
.show(getFragmentManager(), FRAG_TAG_RADIUS_PICKER);
|
||||
return false;
|
||||
});
|
||||
updateRadius();
|
||||
|
||||
requires(device.supportsGeofences(), R.string.p_default_location_reminder_key);
|
||||
}
|
||||
|
||||
private void startCalendarSelectionActivity() {
|
||||
Intent intent = new Intent(DefaultsPreferences.this, CalendarSelectionActivity.class);
|
||||
intent.putExtra(CalendarSelectionActivity.EXTRA_CALENDAR_NAME, getDefaultCalendarName());
|
||||
startActivityForResult(intent, REQUEST_CALENDAR_SELECTION);
|
||||
}
|
||||
|
||||
private String getDefaultCalendarName() {
|
||||
AndroidCalendar calendar =
|
||||
calendarProvider.getCalendar(preferences.getStringValue(R.string.gcal_p_default));
|
||||
return calendar == null ? null : calendar.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(
|
||||
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if (requestCode == PermissionRequestor.REQUEST_CALENDAR) {
|
||||
if (verifyPermissions(grantResults)) {
|
||||
startCalendarSelectionActivity();
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_CALENDAR_SELECTION && resultCode == RESULT_OK) {
|
||||
preferences.setString(
|
||||
R.string.gcal_p_default,
|
||||
data.getStringExtra(CalendarSelectionActivity.EXTRA_CALENDAR_ID));
|
||||
defaultCalendarPref.setSummary(
|
||||
data.getStringExtra(CalendarSelectionActivity.EXTRA_CALENDAR_NAME));
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAccount() {
|
||||
AddAccountDialog.showAddAccountDialog(this, dialogBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectedList(Filter list) {
|
||||
if (list == null) {
|
||||
preferences.setString(R.string.p_default_remote_list, null);
|
||||
} else if (list instanceof GtasksFilter || list instanceof CaldavFilter) {
|
||||
defaultFilterProvider.setDefaultRemoteList(list);
|
||||
} else {
|
||||
throw new RuntimeException("Unhandled filter type");
|
||||
}
|
||||
updateRemoteListSummary();
|
||||
}
|
||||
|
||||
private void updateRemoteListSummary() {
|
||||
Filter defaultFilter = defaultFilterProvider.getDefaultRemoteList();
|
||||
findPreference(R.string.p_default_remote_list)
|
||||
.setSummary(
|
||||
defaultFilter == null ? getString(R.string.dont_sync) : defaultFilter.listingTitle);
|
||||
}
|
||||
|
||||
private void updateRadius() {
|
||||
String radius =
|
||||
locale.formatNumber(preferences.getInt(R.string.p_default_location_radius, 250));
|
||||
defaultRadiusPref.setSummary(getString(R.string.location_radius_meters, radius));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueSelected(int radius, int requestCode) {
|
||||
preferences.setInt(R.string.p_default_location_radius, radius);
|
||||
updateRadius();
|
||||
}
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.core;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.StringRes;
|
||||
import com.todoroo.astrid.dao.Database;
|
||||
import com.todoroo.astrid.dao.TaskDao;
|
||||
import com.todoroo.astrid.service.TaskDeleter;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.util.concurrent.Callable;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.calendars.CalendarEventProvider;
|
||||
import org.tasks.dialogs.DialogBuilder;
|
||||
import org.tasks.injection.ActivityComponent;
|
||||
import org.tasks.injection.InjectingPreferenceActivity;
|
||||
import org.tasks.preferences.Preferences;
|
||||
import org.tasks.ui.Toaster;
|
||||
|
||||
public class OldTaskPreferences extends InjectingPreferenceActivity {
|
||||
|
||||
@Inject DialogBuilder dialogBuilder;
|
||||
@Inject Preferences preferences;
|
||||
@Inject Database database;
|
||||
@Inject TaskDao taskDao;
|
||||
@Inject CalendarEventProvider calendarEventProvider;
|
||||
@Inject TaskDeleter taskDeleter;
|
||||
@Inject Toaster toaster;
|
||||
|
||||
private CompositeDisposable disposables;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences_oldtasks);
|
||||
|
||||
findPreference(getString(R.string.EPr_manage_purge_deleted))
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
purgeDeletedTasks();
|
||||
return false;
|
||||
});
|
||||
|
||||
findPreference(getString(R.string.EPr_manage_delete_completed_gcal))
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
deleteCompletedEvents();
|
||||
return false;
|
||||
});
|
||||
|
||||
findPreference(getString(R.string.EPr_manage_delete_all_gcal))
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
deleteAllCalendarEvents();
|
||||
return false;
|
||||
});
|
||||
|
||||
findPreference(getString(R.string.EPr_reset_preferences))
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
resetPreferences();
|
||||
return false;
|
||||
});
|
||||
|
||||
findPreference(getString(R.string.EPr_delete_task_data))
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
deleteTaskData();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private void purgeDeletedTasks() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.EPr_manage_purge_deleted_message)
|
||||
.setPositiveButton(
|
||||
android.R.string.ok,
|
||||
(dialog, which) ->
|
||||
performAction(
|
||||
R.string.EPr_manage_purge_deleted_status, () -> taskDeleter.purgeDeleted()))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void deleteCompletedEvents() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.EPr_manage_delete_completed_gcal_message)
|
||||
.setPositiveButton(
|
||||
android.R.string.ok,
|
||||
(dialog, which) ->
|
||||
performAction(
|
||||
R.string.EPr_manage_delete_completed_gcal_status,
|
||||
() -> {
|
||||
calendarEventProvider.deleteEvents(taskDao.getCompletedCalendarEvents());
|
||||
return taskDao.clearCompletedCalendarEvents();
|
||||
}))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void deleteAllCalendarEvents() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.EPr_manage_delete_all_gcal_message)
|
||||
.setPositiveButton(
|
||||
android.R.string.ok,
|
||||
(dialog, which) ->
|
||||
performAction(
|
||||
R.string.EPr_manage_delete_all_gcal_status,
|
||||
() -> {
|
||||
calendarEventProvider.deleteEvents(taskDao.getAllCalendarEvents());
|
||||
return taskDao.clearAllCalendarEvents();
|
||||
}))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void performAction(@StringRes int message, Callable<Integer> callable) {
|
||||
disposables.add(
|
||||
Single.fromCallable(callable)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(c -> toaster.longToastUnformatted(message, c)));
|
||||
}
|
||||
|
||||
private void resetPreferences() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.EPr_reset_preferences_warning)
|
||||
.setPositiveButton(
|
||||
R.string.EPr_reset_preferences,
|
||||
(dialog, which) -> {
|
||||
preferences.reset();
|
||||
System.exit(0);
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void deleteTaskData() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.EPr_delete_task_data_warning)
|
||||
.setPositiveButton(
|
||||
R.string.EPr_delete_task_data,
|
||||
(dialog, which) -> {
|
||||
deleteDatabase(database.getName());
|
||||
System.exit(0);
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
disposables = new CompositeDisposable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
disposables.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -1,220 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.reminders;
|
||||
|
||||
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastMarshmallow;
|
||||
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastOreo;
|
||||
import static com.todoroo.andlib.utility.AndroidUtilities.preOreo;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
import android.media.Ringtone;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.Settings;
|
||||
import com.todoroo.astrid.api.Filter;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.LocalBroadcastManager;
|
||||
import org.tasks.R;
|
||||
import org.tasks.activities.FilterSelectionActivity;
|
||||
import org.tasks.activities.TimePickerActivity;
|
||||
import org.tasks.injection.ActivityComponent;
|
||||
import org.tasks.injection.InjectingPreferenceActivity;
|
||||
import org.tasks.preferences.DefaultFilterProvider;
|
||||
import org.tasks.receivers.ShortcutBadger;
|
||||
import org.tasks.scheduling.NotificationSchedulerIntentService;
|
||||
import org.tasks.time.DateTime;
|
||||
import org.tasks.ui.TimePreference;
|
||||
|
||||
public class ReminderPreferences extends InjectingPreferenceActivity {
|
||||
|
||||
private static final int REQUEST_QUIET_START = 10001;
|
||||
private static final int REQUEST_QUIET_END = 10002;
|
||||
private static final int REQUEST_DEFAULT_REMIND = 10003;
|
||||
private static final int REQUEST_BADGE_LIST = 10004;
|
||||
|
||||
@Inject DefaultFilterProvider defaultFilterProvider;
|
||||
@Inject LocalBroadcastManager localBroadcastManager;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences_reminders);
|
||||
|
||||
rescheduleNotificationsOnChange(
|
||||
R.string.p_rmd_time,
|
||||
R.string.p_rmd_enable_quiet,
|
||||
R.string.p_rmd_quietStart,
|
||||
R.string.p_rmd_quietEnd,
|
||||
R.string.p_rmd_persistent);
|
||||
|
||||
initializeRingtonePreference();
|
||||
initializeTimePreference(getDefaultRemindTimePreference(), REQUEST_DEFAULT_REMIND);
|
||||
initializeTimePreference(getQuietStartPreference(), REQUEST_QUIET_START);
|
||||
initializeTimePreference(getQuietEndPreference(), REQUEST_QUIET_END);
|
||||
|
||||
findPreference(R.string.notification_channel_settings)
|
||||
.setOnPreferenceClickListener(this::openNotificationChannelSettings);
|
||||
findPreference(R.string.battery_optimization_settings)
|
||||
.setOnPreferenceClickListener(this::openBatteryOptimizationSettings);
|
||||
|
||||
findPreference(R.string.p_bundle_notifications)
|
||||
.setOnPreferenceChangeListener(
|
||||
(preference, o) -> {
|
||||
NotificationSchedulerIntentService.enqueueWork(this, true);
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference(R.string.p_badges_enabled)
|
||||
.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
if (newValue != null) {
|
||||
if ((boolean) newValue) {
|
||||
showRestartDialog();
|
||||
} else {
|
||||
ShortcutBadger.removeCount(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
Preference badgePreference = findPreference(getString(R.string.p_badge_list));
|
||||
Filter filter = defaultFilterProvider.getBadgeFilter();
|
||||
badgePreference.setSummary(filter.listingTitle);
|
||||
badgePreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
Intent intent = new Intent(ReminderPreferences.this, FilterSelectionActivity.class);
|
||||
intent.putExtra(
|
||||
FilterSelectionActivity.EXTRA_FILTER, defaultFilterProvider.getBadgeFilter());
|
||||
intent.putExtra(FilterSelectionActivity.EXTRA_RETURN_FILTER, true);
|
||||
startActivityForResult(intent, REQUEST_BADGE_LIST);
|
||||
return true;
|
||||
});
|
||||
|
||||
requires(atLeastOreo(), R.string.notification_channel_settings);
|
||||
requires(atLeastMarshmallow(), R.string.battery_optimization_settings);
|
||||
requires(
|
||||
preOreo(), R.string.p_rmd_ringtone, R.string.p_rmd_vibrate, R.string.p_led_notification);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
private boolean openNotificationChannelSettings(Preference ignored) {
|
||||
Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
|
||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, ReminderPreferences.this.getPackageName());
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
private boolean openBatteryOptimizationSettings(Preference ignored) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void rescheduleNotificationsOnChange(int... resIds) {
|
||||
for (int resId : resIds) {
|
||||
findPreference(getString(resId))
|
||||
.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
NotificationSchedulerIntentService.enqueueWork(this, false);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeTimePreference(final TimePreference preference, final int requestCode) {
|
||||
preference.setOnPreferenceClickListener(
|
||||
ignored -> {
|
||||
final DateTime current = new DateTime().withMillisOfDay(preference.getMillisOfDay());
|
||||
Intent intent = new Intent(ReminderPreferences.this, TimePickerActivity.class);
|
||||
intent.putExtra(TimePickerActivity.EXTRA_TIMESTAMP, current.getMillis());
|
||||
startActivityForResult(intent, requestCode);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void initializeRingtonePreference() {
|
||||
Preference.OnPreferenceChangeListener ringtoneChangedListener =
|
||||
(preference, value) -> {
|
||||
if ("".equals(value)) {
|
||||
preference.setSummary(R.string.silent);
|
||||
} else {
|
||||
Ringtone ringtone =
|
||||
RingtoneManager.getRingtone(
|
||||
ReminderPreferences.this,
|
||||
value == null
|
||||
? Settings.System.DEFAULT_NOTIFICATION_URI
|
||||
: Uri.parse((String) value));
|
||||
preference.setSummary(
|
||||
ringtone == null ? "" : ringtone.getTitle(ReminderPreferences.this));
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
String ringtoneKey = getString(R.string.p_rmd_ringtone);
|
||||
Preference ringtonePreference = findPreference(ringtoneKey);
|
||||
ringtonePreference.setOnPreferenceChangeListener(ringtoneChangedListener);
|
||||
ringtoneChangedListener.onPreferenceChange(
|
||||
ringtonePreference,
|
||||
PreferenceManager.getDefaultSharedPreferences(this).getString(ringtoneKey, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_QUIET_START) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
getQuietStartPreference().handleTimePickerActivityIntent(data);
|
||||
}
|
||||
} else if (requestCode == REQUEST_QUIET_END) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
getQuietEndPreference().handleTimePickerActivityIntent(data);
|
||||
}
|
||||
} else if (requestCode == REQUEST_DEFAULT_REMIND) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
getDefaultRemindTimePreference().handleTimePickerActivityIntent(data);
|
||||
}
|
||||
} else if (requestCode == REQUEST_BADGE_LIST) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
Filter filter = data.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER);
|
||||
defaultFilterProvider.setBadgeFilter(filter);
|
||||
findPreference(getString(R.string.p_badge_list)).setSummary(filter.listingTitle);
|
||||
localBroadcastManager.broadcastRefresh();
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
private TimePreference getQuietStartPreference() {
|
||||
return getTimePreference(R.string.p_rmd_quietStart);
|
||||
}
|
||||
|
||||
private TimePreference getQuietEndPreference() {
|
||||
return getTimePreference(R.string.p_rmd_quietEnd);
|
||||
}
|
||||
|
||||
private TimePreference getDefaultRemindTimePreference() {
|
||||
return getTimePreference(R.string.p_rmd_time);
|
||||
}
|
||||
|
||||
private TimePreference getTimePreference(int resId) {
|
||||
return (TimePreference) findPreference(getString(resId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
public class MultilineCheckboxPreference extends CheckBoxPreference {
|
||||
|
||||
public MultilineCheckboxPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(View view) {
|
||||
super.onBindView(view);
|
||||
MultilineHelper.makeMultiline(view);
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.ui;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
class MultilineHelper {
|
||||
|
||||
static void makeMultiline(View view) {
|
||||
if (view instanceof ViewGroup) {
|
||||
|
||||
ViewGroup grp = (ViewGroup) view;
|
||||
|
||||
for (int index = 0; index < grp.getChildCount(); index++) {
|
||||
makeMultiline(grp.getChildAt(index));
|
||||
}
|
||||
} else if (view instanceof TextView) {
|
||||
TextView t = (TextView) view;
|
||||
t.setSingleLine(false);
|
||||
t.setEllipsize(null);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import org.tasks.locale.Locale;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class MultilineListPreference extends ListPreference {
|
||||
|
||||
public MultilineListPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(View view) {
|
||||
try {
|
||||
super.onBindView(view);
|
||||
} catch (Exception e) {
|
||||
// happens on 4.0 emulators
|
||||
Timber.e(e);
|
||||
}
|
||||
MultilineHelper.makeMultiline(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showDialog(Bundle state) {
|
||||
super.showDialog(state);
|
||||
Locale.getInstance(getContext()).applyDirectionality(getDialog());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String value) {
|
||||
super.setValue(value);
|
||||
setSummary(getEntry());
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
public class MultilinePreference extends Preference {
|
||||
|
||||
public MultilinePreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(View view) {
|
||||
super.onBindView(view);
|
||||
MultilineHelper.makeMultiline(view);
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package org.tasks.activities;
|
||||
|
||||
import static org.tasks.activities.RemoteListSupportPicker.createDialog;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import com.todoroo.astrid.adapter.FilterAdapter;
|
||||
import com.todoroo.astrid.api.Filter;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.dialogs.DialogBuilder;
|
||||
import org.tasks.filters.FilterProvider;
|
||||
import org.tasks.gtasks.RemoteListSelectionHandler;
|
||||
import org.tasks.injection.InjectingNativeDialogFragment;
|
||||
import org.tasks.injection.NativeDialogFragmentComponent;
|
||||
import org.tasks.sync.SyncAdapters;
|
||||
|
||||
public class RemoteListNativePicker extends InjectingNativeDialogFragment {
|
||||
|
||||
private static final String EXTRA_SELECTED = "extra_selected";
|
||||
|
||||
@Inject DialogBuilder dialogBuilder;
|
||||
@Inject FilterAdapter filterAdapter;
|
||||
@Inject FilterProvider filterProvider;
|
||||
@Inject SyncAdapters syncAdapters;
|
||||
private RemoteListSelectionHandler handler;
|
||||
private CompositeDisposable disposables;
|
||||
|
||||
public static RemoteListNativePicker newRemoteListNativePicker(Filter selected) {
|
||||
RemoteListNativePicker dialog = new RemoteListNativePicker();
|
||||
Bundle arguments = new Bundle();
|
||||
if (selected != null) {
|
||||
arguments.putParcelable(EXTRA_SELECTED, selected);
|
||||
}
|
||||
dialog.setArguments(arguments);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
filterAdapter.restore(savedInstanceState);
|
||||
}
|
||||
|
||||
return createDialog(filterAdapter, dialogBuilder, syncAdapters, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
Filter selected = getArguments().getParcelable(EXTRA_SELECTED);
|
||||
|
||||
disposables =
|
||||
new CompositeDisposable(
|
||||
Single.fromCallable(filterProvider::getRemoteListPickerItems)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(items -> filterAdapter.setData(items, selected, 0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
disposables.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
handler = (RemoteListSelectionHandler) activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
filterAdapter.save(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(NativeDialogFragmentComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
package org.tasks.dialogs;
|
||||
|
||||
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastMarshmallow;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.DatePickerDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.widget.DatePicker;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.injection.ForActivity;
|
||||
import org.tasks.injection.InjectingNativeDialogFragment;
|
||||
import org.tasks.injection.NativeDialogFragmentComponent;
|
||||
import org.tasks.preferences.Preferences;
|
||||
import org.tasks.themes.Theme;
|
||||
import org.tasks.time.DateTime;
|
||||
|
||||
public class NativeDatePickerDialog extends InjectingNativeDialogFragment
|
||||
implements DatePickerDialog.OnDateSetListener {
|
||||
|
||||
private static final String EXTRA_YEAR = "extra_year";
|
||||
private static final String EXTRA_MONTH = "extra_month";
|
||||
private static final String EXTRA_DAY = "extra_day";
|
||||
@Inject @ForActivity Context context;
|
||||
@Inject Theme theme;
|
||||
@Inject Preferences preferences;
|
||||
private NativeDatePickerDialogCallback callback;
|
||||
|
||||
public static NativeDatePickerDialog newNativeDatePickerDialog(DateTime initial) {
|
||||
NativeDatePickerDialog dialog = new NativeDatePickerDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(EXTRA_YEAR, initial.getYear());
|
||||
args.putInt(EXTRA_MONTH, initial.getMonthOfYear() - 1);
|
||||
args.putInt(EXTRA_DAY, initial.getDayOfMonth());
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Bundle args = getArguments();
|
||||
DatePickerDialog datePickerDialog =
|
||||
new DatePickerDialog(
|
||||
theme.wrap(context),
|
||||
this,
|
||||
args.getInt(EXTRA_YEAR),
|
||||
args.getInt(EXTRA_MONTH),
|
||||
args.getInt(EXTRA_DAY));
|
||||
int firstDayOfWeek = preferences.getFirstDayOfWeek();
|
||||
if (firstDayOfWeek >= 1 && firstDayOfWeek <= 7 && atLeastMarshmallow()) {
|
||||
datePickerDialog.getDatePicker().setFirstDayOfWeek(firstDayOfWeek);
|
||||
}
|
||||
datePickerDialog.setTitle("");
|
||||
return datePickerDialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDateSet(DatePicker datePicker, int year, int month, int day) {
|
||||
callback.onDateSet(year, month, day);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
|
||||
callback.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
callback = (NativeDatePickerDialogCallback) activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(NativeDialogFragmentComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
public interface NativeDatePickerDialogCallback {
|
||||
|
||||
void cancel();
|
||||
|
||||
void onDateSet(int year, int month, int day);
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
package org.tasks.dialogs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import com.rey.material.widget.Slider;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.injection.InjectingNativeDialogFragment;
|
||||
import org.tasks.injection.NativeDialogFragmentComponent;
|
||||
import org.tasks.locale.Locale;
|
||||
import org.tasks.themes.Theme;
|
||||
|
||||
public class NativeSeekBarDialog extends InjectingNativeDialogFragment {
|
||||
|
||||
private static final String EXTRA_LAYOUT = "extra_layout";
|
||||
private static final String EXTRA_INITIAL_VALUE = "extra_initial_value";
|
||||
private static final String EXTRA_MIN = "extra_min";
|
||||
private static final String EXTRA_MAX = "extra_max";
|
||||
private static final String EXTRA_REQUEST_CODE = "extra_request_code";
|
||||
|
||||
@BindView(R.id.slider)
|
||||
Slider slider;
|
||||
|
||||
@BindView(R.id.min)
|
||||
TextView min;
|
||||
|
||||
@BindView(R.id.max)
|
||||
TextView max;
|
||||
|
||||
@Inject DialogBuilder dialogBuilder;
|
||||
@Inject Theme theme;
|
||||
@Inject Locale locale;
|
||||
private int requestCode;
|
||||
private SeekBarCallback callback;
|
||||
|
||||
public static NativeSeekBarDialog newSeekBarDialog(
|
||||
int layout, int min, int max, int initial, int requestCode) {
|
||||
NativeSeekBarDialog dialog = new NativeSeekBarDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(EXTRA_LAYOUT, layout);
|
||||
args.putInt(EXTRA_MIN, min);
|
||||
args.putInt(EXTRA_MAX, max);
|
||||
args.putInt(EXTRA_INITIAL_VALUE, initial);
|
||||
args.putInt(EXTRA_REQUEST_CODE, requestCode);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Bundle arguments = getArguments();
|
||||
requestCode = arguments.getInt(EXTRA_REQUEST_CODE);
|
||||
int initial =
|
||||
savedInstanceState == null
|
||||
? arguments.getInt(EXTRA_INITIAL_VALUE)
|
||||
: savedInstanceState.getInt(EXTRA_INITIAL_VALUE);
|
||||
int layout = arguments.getInt(EXTRA_LAYOUT);
|
||||
|
||||
LayoutInflater layoutInflater = theme.getLayoutInflater(getActivity());
|
||||
View view = layoutInflater.inflate(layout, null);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
slider.setValueDescriptionProvider(value -> locale.formatNumber(value));
|
||||
slider.setValueRange(arguments.getInt(EXTRA_MIN), arguments.getInt(EXTRA_MAX), false);
|
||||
slider.setValue(initial, true);
|
||||
min.setText(locale.formatNumber(slider.getMinValue()));
|
||||
max.setText(locale.formatNumber(slider.getMaxValue()));
|
||||
return dialogBuilder
|
||||
.newDialog()
|
||||
.setView(view)
|
||||
.setPositiveButton(
|
||||
android.R.string.ok,
|
||||
(dialogInterface, i) -> callback.valueSelected(slider.getValue(), requestCode))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
callback = (SeekBarCallback) activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putInt(EXTRA_INITIAL_VALUE, slider.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(NativeDialogFragmentComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
public interface SeekBarCallback {
|
||||
|
||||
void valueSelected(int value, int requestCode);
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
package org.tasks.dialogs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.TimePickerDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.widget.TimePicker;
|
||||
import com.todoroo.andlib.utility.DateUtilities;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.injection.InjectingNativeDialogFragment;
|
||||
import org.tasks.injection.NativeDialogFragmentComponent;
|
||||
import org.tasks.themes.Theme;
|
||||
import org.tasks.time.DateTime;
|
||||
|
||||
public class NativeTimePickerDialog extends InjectingNativeDialogFragment
|
||||
implements TimePickerDialog.OnTimeSetListener {
|
||||
|
||||
private static final String EXTRA_HOUR = "extra_hour";
|
||||
private static final String EXTRA_MINUTE = "extra_minute";
|
||||
@Inject Theme theme;
|
||||
private NativeTimePickerDialogCallback callback;
|
||||
|
||||
public static NativeTimePickerDialog newNativeTimePickerDialog(DateTime initial) {
|
||||
NativeTimePickerDialog dialog = new NativeTimePickerDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(EXTRA_HOUR, initial.getHourOfDay());
|
||||
args.putInt(EXTRA_MINUTE, initial.getMinuteOfHour());
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Bundle args = getArguments();
|
||||
Context context = getActivity();
|
||||
theme.applyToContext(context);
|
||||
TimePickerDialog timePickerDialog =
|
||||
new TimePickerDialog(
|
||||
context,
|
||||
this,
|
||||
args.getInt(EXTRA_HOUR),
|
||||
args.getInt(EXTRA_MINUTE),
|
||||
DateUtilities.is24HourFormat(context));
|
||||
timePickerDialog.setTitle("");
|
||||
return timePickerDialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
|
||||
callback.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeSet(TimePicker timePicker, int hour, int minute) {
|
||||
callback.onTimeSet(hour, minute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
callback = (NativeTimePickerDialogCallback) activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void inject(NativeDialogFragmentComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
public interface NativeTimePickerDialogCallback {
|
||||
|
||||
void cancel();
|
||||
|
||||
void onTimeSet(int hour, int minute);
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package org.tasks.injection;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
|
||||
public abstract class InjectingNativeDialogFragment extends DialogFragment {
|
||||
|
||||
private boolean injected;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
|
||||
if (!injected) {
|
||||
inject(
|
||||
((InjectingActivity) activity).getComponent().plus(new NativeDialogFragmentModule(this)));
|
||||
injected = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
// https://code.google.com/p/android/issues/detail?id=17423
|
||||
Dialog dialog = getDialog();
|
||||
if (dialog != null && getRetainInstance()) {
|
||||
dialog.setDismissMessage(null);
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
protected abstract void inject(NativeDialogFragmentComponent component);
|
||||
}
|
@ -1,215 +0,0 @@
|
||||
package org.tasks.injection;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.appcompat.widget.Toolbar.OnMenuItemClickListener;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import com.jakewharton.processphoenix.ProcessPhoenix;
|
||||
import com.todoroo.astrid.activity.MainActivity;
|
||||
import com.todoroo.astrid.api.Filter;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.dialogs.DialogBuilder;
|
||||
import org.tasks.locale.Locale;
|
||||
import org.tasks.preferences.AppCompatPreferenceActivity;
|
||||
import org.tasks.preferences.Device;
|
||||
import org.tasks.themes.Theme;
|
||||
import org.tasks.ui.MenuColorizer;
|
||||
import timber.log.Timber;
|
||||
|
||||
public abstract class InjectingPreferenceActivity extends AppCompatPreferenceActivity
|
||||
implements InjectingActivity, OnMenuItemClickListener {
|
||||
|
||||
public static final String EXTRA_RESTART = "extra_restart";
|
||||
private static final String EXTRA_BUNDLE = "extra_bundle";
|
||||
|
||||
@Inject DialogBuilder dialogBuilder;
|
||||
@Inject Device device;
|
||||
|
||||
private ActivityComponent activityComponent;
|
||||
private Bundle result;
|
||||
|
||||
protected InjectingPreferenceActivity() {
|
||||
Locale.getInstance(this).applyOverrideConfiguration(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
activityComponent =
|
||||
((InjectingApplication) getApplication()).getComponent().plus(new ActivityModule(this));
|
||||
inject(activityComponent);
|
||||
|
||||
Theme theme = activityComponent.getTheme();
|
||||
|
||||
theme.applyThemeAndStatusBarColor(this, getDelegate());
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
result = savedInstanceState == null ? new Bundle() : savedInstanceState.getBundle(EXTRA_BUNDLE);
|
||||
|
||||
ViewGroup root = findViewById(android.R.id.content);
|
||||
View content = root.getChildAt(0);
|
||||
LinearLayout toolbarContainer =
|
||||
(LinearLayout) View.inflate(this, R.layout.activity_prefs, null);
|
||||
|
||||
root.removeAllViews();
|
||||
toolbarContainer.addView(content);
|
||||
root.addView(toolbarContainer);
|
||||
|
||||
Toolbar toolbar = toolbarContainer.findViewById(R.id.toolbar);
|
||||
try {
|
||||
ComponentName componentName = new ComponentName(this, getClass());
|
||||
ActivityInfo activityInfo = getPackageManager().getActivityInfo(componentName, 0);
|
||||
toolbar.setTitle(activityInfo.labelRes);
|
||||
} catch (Exception e) {
|
||||
Timber.e(e);
|
||||
toolbar.setTitle(getTitle());
|
||||
}
|
||||
toolbar.setNavigationIcon(
|
||||
ContextCompat.getDrawable(this, R.drawable.ic_outline_arrow_back_24px));
|
||||
toolbar.setNavigationOnClickListener(v -> finish());
|
||||
toolbar.inflateMenu(R.menu.menu_preferences);
|
||||
toolbar.setOnMenuItemClickListener(this);
|
||||
MenuColorizer.colorToolbar(this, toolbar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityComponent getComponent() {
|
||||
return activityComponent;
|
||||
}
|
||||
|
||||
protected void requires(int prefGroup, boolean passesCheck, int... resIds) {
|
||||
if (!passesCheck) {
|
||||
remove((PreferenceCategory) findPreference(getString(prefGroup)), resIds);
|
||||
}
|
||||
}
|
||||
|
||||
protected void requires(boolean passesCheck, int... resIds) {
|
||||
if (!passesCheck) {
|
||||
remove(resIds);
|
||||
}
|
||||
}
|
||||
|
||||
protected void remove(int... resIds) {
|
||||
//noinspection deprecation
|
||||
remove(getPreferenceScreen(), resIds);
|
||||
}
|
||||
|
||||
private void remove(PreferenceGroup preferenceGroup, int[] resIds) {
|
||||
for (int resId : resIds) {
|
||||
preferenceGroup.removePreference(findPreference(resId));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation", "EmptyMethod"})
|
||||
@Override
|
||||
public void addPreferencesFromResource(int preferencesResId) {
|
||||
super.addPreferencesFromResource(preferencesResId);
|
||||
}
|
||||
|
||||
protected Preference findPreference(int resId) {
|
||||
return findPreference(getString(resId));
|
||||
}
|
||||
|
||||
protected Preference findPreference(String key) {
|
||||
//noinspection deprecation
|
||||
return super.findPreference(key);
|
||||
}
|
||||
|
||||
protected void showRestartDialog() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.restart_required)
|
||||
.setPositiveButton(
|
||||
R.string.restart_now,
|
||||
(dialogInterface, i) -> {
|
||||
Intent nextIntent = new Intent(InjectingPreferenceActivity.this, MainActivity.class);
|
||||
nextIntent.putExtra(MainActivity.OPEN_FILTER, (Filter) null);
|
||||
ProcessPhoenix.triggerRebirth(InjectingPreferenceActivity.this, nextIntent);
|
||||
})
|
||||
.setNegativeButton(R.string.restart_later, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_contact:
|
||||
emailSupport();
|
||||
return true;
|
||||
case R.id.menu_help:
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getHelpUrl())));
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putBundle(EXTRA_BUNDLE, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
Intent data = new Intent();
|
||||
data.putExtras(result);
|
||||
setResult(RESULT_OK, data);
|
||||
super.finish();
|
||||
}
|
||||
|
||||
protected void restart() {
|
||||
Intent intent = getIntent();
|
||||
finish();
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
protected void emailSupport() {
|
||||
startActivity(
|
||||
new Intent(
|
||||
Intent.ACTION_SENDTO,
|
||||
Uri.fromParts("mailto", "Alex <" + getString(R.string.support_email) + ">", null))
|
||||
.putExtra(Intent.EXTRA_SUBJECT, "Tasks Feedback")
|
||||
.putExtra(Intent.EXTRA_TEXT, device.getDebugInfo()));
|
||||
}
|
||||
|
||||
protected String getHelpUrl() {
|
||||
return "http://tasks.org/help";
|
||||
}
|
||||
|
||||
protected void forceRestart() {
|
||||
result.putBoolean(EXTRA_RESTART, true);
|
||||
}
|
||||
|
||||
protected void mergeResults(Bundle bundle) {
|
||||
result.putAll(bundle);
|
||||
}
|
||||
|
||||
protected void setExtraOnChange(final String extra, final int... resIds) {
|
||||
for (int resId : resIds) {
|
||||
setExtraOnChange(resId, extra);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setExtraOnChange(final int resId, final String extra) {
|
||||
findPreference(getString(resId))
|
||||
.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
result.putBoolean(extra, true);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package org.tasks.injection;
|
||||
|
||||
import dagger.Subcomponent;
|
||||
import org.tasks.activities.RemoteListNativePicker;
|
||||
import org.tasks.dialogs.ExportTasksDialog;
|
||||
import org.tasks.dialogs.ImportTasksDialog;
|
||||
import org.tasks.dialogs.NativeDatePickerDialog;
|
||||
import org.tasks.dialogs.NativeSeekBarDialog;
|
||||
import org.tasks.dialogs.NativeTimePickerDialog;
|
||||
import org.tasks.locale.LocalePickerDialog;
|
||||
|
||||
@Subcomponent(modules = NativeDialogFragmentModule.class)
|
||||
public interface NativeDialogFragmentComponent {
|
||||
|
||||
void inject(RemoteListNativePicker remoteListNativePicker);
|
||||
|
||||
void inject(LocalePickerDialog localePickerDialog);
|
||||
|
||||
void inject(NativeDatePickerDialog nativeDatePickerDialog);
|
||||
|
||||
void inject(NativeTimePickerDialog nativeTimePickerDialog);
|
||||
|
||||
void inject(NativeSeekBarDialog nativeSeekBarDialog);
|
||||
|
||||
void inject(ExportTasksDialog exportTasksDialog);
|
||||
|
||||
void inject(ImportTasksDialog importTasksDialog);
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package org.tasks.injection;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.DialogFragment;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class NativeDialogFragmentModule {
|
||||
|
||||
private final DialogFragment dialogFragment;
|
||||
|
||||
public NativeDialogFragmentModule(DialogFragment dialogFragment) {
|
||||
this.dialogFragment = dialogFragment;
|
||||
}
|
||||
|
||||
@Provides
|
||||
public Activity getActivity() {
|
||||
return dialogFragment.getActivity();
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
package org.tasks.preferences;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
|
||||
/**
|
||||
* A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls
|
||||
* to be used with AppCompat.
|
||||
*
|
||||
* <p>This technique can be used with an {@link android.app.Activity} class, not just {@link
|
||||
* android.preference.PreferenceActivity}.
|
||||
*/
|
||||
public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
|
||||
|
||||
private AppCompatDelegate mDelegate;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
getDelegate().installViewFactory();
|
||||
getDelegate().onCreate(savedInstanceState);
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
getDelegate().onPostCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public MenuInflater getMenuInflater() {
|
||||
return getDelegate().getMenuInflater();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(@LayoutRes int layoutResID) {
|
||||
getDelegate().setContentView(layoutResID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View view) {
|
||||
getDelegate().setContentView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View view, ViewGroup.LayoutParams params) {
|
||||
getDelegate().setContentView(view, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addContentView(View view, ViewGroup.LayoutParams params) {
|
||||
getDelegate().addContentView(view, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostResume() {
|
||||
super.onPostResume();
|
||||
getDelegate().onPostResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTitleChanged(CharSequence title, int color) {
|
||||
super.onTitleChanged(title, color);
|
||||
getDelegate().setTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
getDelegate().onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
getDelegate().onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
getDelegate().onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateOptionsMenu() {
|
||||
getDelegate().invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
protected AppCompatDelegate getDelegate() {
|
||||
if (mDelegate == null) {
|
||||
mDelegate = AppCompatDelegate.create(this, null);
|
||||
}
|
||||
return mDelegate;
|
||||
}
|
||||
}
|
@ -1,724 +0,0 @@
|
||||
package org.tasks.preferences;
|
||||
|
||||
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastJellybeanMR1;
|
||||
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastLollipop;
|
||||
import static com.todoroo.andlib.utility.DateUtilities.now;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.tasks.PermissionUtil.verifyPermissions;
|
||||
import static org.tasks.dialogs.ExportTasksDialog.newExportTasksDialog;
|
||||
import static org.tasks.dialogs.ImportTasksDialog.newImportTasksDialog;
|
||||
import static org.tasks.dialogs.NativeSeekBarDialog.newSeekBarDialog;
|
||||
import static org.tasks.files.FileHelper.newFilePickerIntent;
|
||||
import static org.tasks.files.FileHelper.uri2String;
|
||||
import static org.tasks.locale.LocalePickerDialog.newLocalePickerDialog;
|
||||
import static org.tasks.themes.ThemeColor.LAUNCHERS;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import com.google.common.base.Strings;
|
||||
import com.todoroo.astrid.activity.BeastModePreferences;
|
||||
import com.todoroo.astrid.api.Filter;
|
||||
import com.todoroo.astrid.core.OldTaskPreferences;
|
||||
import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity;
|
||||
import com.todoroo.astrid.reminders.ReminderPreferences;
|
||||
import com.todoroo.astrid.service.TaskDeleter;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.BuildConfig;
|
||||
import org.tasks.LocalBroadcastManager;
|
||||
import org.tasks.R;
|
||||
import org.tasks.activities.ColorPickerActivity;
|
||||
import org.tasks.activities.ColorPickerActivity.ColorPalette;
|
||||
import org.tasks.activities.FilterSelectionActivity;
|
||||
import org.tasks.billing.Inventory;
|
||||
import org.tasks.caldav.CaldavAccountSettingsActivity;
|
||||
import org.tasks.data.CaldavAccount;
|
||||
import org.tasks.data.CaldavDao;
|
||||
import org.tasks.data.GoogleTaskAccount;
|
||||
import org.tasks.data.GoogleTaskListDao;
|
||||
import org.tasks.dialogs.DialogBuilder;
|
||||
import org.tasks.dialogs.NativeSeekBarDialog;
|
||||
import org.tasks.drive.DriveLoginActivity;
|
||||
import org.tasks.etesync.EteSyncAccountSettingsActivity;
|
||||
import org.tasks.files.FileHelper;
|
||||
import org.tasks.gtasks.GoogleAccountManager;
|
||||
import org.tasks.gtasks.PlayServices;
|
||||
import org.tasks.injection.ActivityComponent;
|
||||
import org.tasks.injection.InjectingPreferenceActivity;
|
||||
import org.tasks.jobs.WorkManager;
|
||||
import org.tasks.locale.Locale;
|
||||
import org.tasks.locale.LocalePickerDialog;
|
||||
import org.tasks.sync.AddAccountDialog;
|
||||
import org.tasks.themes.ThemeAccent;
|
||||
import org.tasks.themes.ThemeBase;
|
||||
import org.tasks.themes.ThemeCache;
|
||||
import org.tasks.themes.ThemeColor;
|
||||
import org.tasks.ui.SingleCheckedArrayAdapter;
|
||||
import org.tasks.ui.Toaster;
|
||||
|
||||
public class BasicPreferences extends InjectingPreferenceActivity
|
||||
implements LocalePickerDialog.LocaleSelectionHandler, NativeSeekBarDialog.SeekBarCallback {
|
||||
|
||||
private static final String FRAG_TAG_LOCALE_PICKER = "frag_tag_locale_picker";
|
||||
private static final String FRAG_TAG_IMPORT_TASKS = "frag_tag_import_tasks";
|
||||
private static final String FRAG_TAG_EXPORT_TASKS = "frag_tag_export_tasks";
|
||||
private static final String FRAG_TAG_ROW_PADDING_SEEKBAR = "frag_tag_row_padding_seekbar";
|
||||
private static final String FRAG_TAG_FONT_SIZE_SEEKBAR = "frag_tag_font_size_seekbar";
|
||||
private static final int RC_PREFS = 10001;
|
||||
private static final int REQUEST_THEME_PICKER = 10002;
|
||||
private static final int REQUEST_COLOR_PICKER = 10003;
|
||||
private static final int REQUEST_ACCENT_PICKER = 10004;
|
||||
private static final int REQUEST_CODE_BACKUP_DIR = 10005;
|
||||
private static final int REQUEST_PICKER = 10006;
|
||||
private static final int REQUEST_LAUNCHER_PICKER = 10007;
|
||||
private static final int REQUEST_DRIVE_BACKUP = 10008;
|
||||
private static final int REQUEST_DEFAULT_LIST = 10009;
|
||||
private static final int REQUEST_ROW_PADDING = 10010;
|
||||
private static final int REQUEST_FONT_SIZE = 10011;
|
||||
private static final int REQUEST_CUSTOMIZE = 10012;
|
||||
public static final int REQUEST_CALDAV_SETTINGS = 10013;
|
||||
public static final int REQUEST_GOOGLE_TASKS = 10014;
|
||||
|
||||
@Inject Preferences preferences;
|
||||
@Inject ThemeBase themeBase;
|
||||
@Inject ThemeColor themeColor;
|
||||
@Inject ThemeAccent themeAccent;
|
||||
@Inject DialogBuilder dialogBuilder;
|
||||
@Inject Locale locale;
|
||||
@Inject ThemeCache themeCache;
|
||||
@Inject Inventory inventory;
|
||||
@Inject PlayServices playServices;
|
||||
@Inject Toaster toaster;
|
||||
@Inject ActivityPermissionRequestor permissionRequestor;
|
||||
@Inject GoogleAccountManager googleAccountManager;
|
||||
@Inject DefaultFilterProvider defaultFilterProvider;
|
||||
@Inject LocalBroadcastManager localBroadcastManager;
|
||||
@Inject WorkManager workManager;
|
||||
@Inject GoogleTaskListDao googleTaskListDao;
|
||||
@Inject CaldavDao caldavDao;
|
||||
@Inject TaskDeleter taskDeleter;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
|
||||
setExtraOnChange(
|
||||
EXTRA_RESTART,
|
||||
R.string.p_fontSize,
|
||||
R.string.p_rowPadding,
|
||||
R.string.p_fullTaskTitle,
|
||||
R.string.p_show_description,
|
||||
R.string.p_show_full_description,
|
||||
R.string.p_linkify_task_list,
|
||||
R.string.p_show_list_indicators);
|
||||
|
||||
findPreference(R.string.p_show_subtasks)
|
||||
.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
forceRestart();
|
||||
localBroadcastManager.broadcastRefresh();
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference(R.string.customize_edit_screen)
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
startActivityForResult(
|
||||
new Intent(BasicPreferences.this, BeastModePreferences.class),
|
||||
REQUEST_CUSTOMIZE);
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference(R.string.p_fontSize)
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
newSeekBarDialog(
|
||||
R.layout.dialog_font_size_seekbar,
|
||||
10,
|
||||
48,
|
||||
preferences.getFontSize(),
|
||||
REQUEST_FONT_SIZE)
|
||||
.show(getFragmentManager(), FRAG_TAG_FONT_SIZE_SEEKBAR);
|
||||
return false;
|
||||
});
|
||||
updateFontSize();
|
||||
|
||||
findPreference(R.string.p_rowPadding)
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
newSeekBarDialog(
|
||||
R.layout.dialog_font_size_seekbar,
|
||||
0,
|
||||
16,
|
||||
preferences.getRowPadding(),
|
||||
REQUEST_ROW_PADDING)
|
||||
.show(getFragmentManager(), FRAG_TAG_ROW_PADDING_SEEKBAR);
|
||||
return false;
|
||||
});
|
||||
updateRowPadding();
|
||||
Preference defaultList = findPreference(getString(R.string.p_default_list));
|
||||
Filter filter = defaultFilterProvider.getDefaultFilter();
|
||||
defaultList.setSummary(filter.listingTitle);
|
||||
defaultList.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
Intent intent = new Intent(BasicPreferences.this, FilterSelectionActivity.class);
|
||||
intent.putExtra(
|
||||
FilterSelectionActivity.EXTRA_FILTER, defaultFilterProvider.getDefaultFilter());
|
||||
intent.putExtra(FilterSelectionActivity.EXTRA_RETURN_FILTER, true);
|
||||
startActivityForResult(intent, REQUEST_DEFAULT_LIST);
|
||||
return true;
|
||||
});
|
||||
|
||||
setupActivity(R.string.notifications, ReminderPreferences.class);
|
||||
setupActivity(R.string.EPr_manage_header, OldTaskPreferences.class);
|
||||
setupActivity(R.string.debug, DebugPreferences.class);
|
||||
|
||||
Preference themePreference = findPreference(getString(R.string.p_theme));
|
||||
themePreference.setSummary(themeBase.getName());
|
||||
themePreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
Intent intent = new Intent(BasicPreferences.this, ColorPickerActivity.class);
|
||||
intent.putExtra(ColorPickerActivity.EXTRA_PALETTE, ColorPalette.THEMES);
|
||||
startActivityForResult(intent, REQUEST_THEME_PICKER);
|
||||
return false;
|
||||
});
|
||||
Preference colorPreference = findPreference(getString(R.string.p_theme_color));
|
||||
colorPreference.setSummary(themeColor.getName());
|
||||
colorPreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
Intent intent = new Intent(BasicPreferences.this, ColorPickerActivity.class);
|
||||
intent.putExtra(ColorPickerActivity.EXTRA_PALETTE, ColorPalette.COLORS);
|
||||
startActivityForResult(intent, REQUEST_COLOR_PICKER);
|
||||
return false;
|
||||
});
|
||||
Preference accentPreference = findPreference(getString(R.string.p_theme_accent));
|
||||
accentPreference.setSummary(themeAccent.getName());
|
||||
accentPreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
Intent intent = new Intent(BasicPreferences.this, ColorPickerActivity.class);
|
||||
intent.putExtra(ColorPickerActivity.EXTRA_PALETTE, ColorPalette.ACCENTS);
|
||||
startActivityForResult(intent, REQUEST_ACCENT_PICKER);
|
||||
return false;
|
||||
});
|
||||
Preference launcherPreference = findPreference(getString(R.string.p_theme_launcher));
|
||||
ThemeColor launcherColor =
|
||||
themeCache.getThemeColor(preferences.getInt(R.string.p_theme_launcher, 7));
|
||||
launcherPreference.setSummary(launcherColor.getName());
|
||||
launcherPreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
Intent intent = new Intent(BasicPreferences.this, ColorPickerActivity.class);
|
||||
intent.putExtra(ColorPickerActivity.EXTRA_PALETTE, ColorPalette.LAUNCHER);
|
||||
startActivityForResult(intent, REQUEST_LAUNCHER_PICKER);
|
||||
return false;
|
||||
});
|
||||
Preference languagePreference = findPreference(getString(R.string.p_language));
|
||||
updateLocale();
|
||||
languagePreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
newLocalePickerDialog().show(getFragmentManager(), FRAG_TAG_LOCALE_PICKER);
|
||||
return false;
|
||||
});
|
||||
findPreference(getString(R.string.p_layout_direction))
|
||||
.setOnPreferenceChangeListener(
|
||||
(preference, o) -> {
|
||||
int newValue = Integer.parseInt((String) o);
|
||||
if (locale.getDirectionality()
|
||||
!= locale.withDirectionality(newValue).getDirectionality()) {
|
||||
showRestartDialog();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference(R.string.backup_BAc_import)
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
startActivityForResult(
|
||||
newFilePickerIntent(BasicPreferences.this, preferences.getBackupDirectory()),
|
||||
REQUEST_PICKER);
|
||||
return false;
|
||||
});
|
||||
|
||||
findPreference(R.string.backup_BAc_export)
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
newExportTasksDialog().show(getFragmentManager(), FRAG_TAG_EXPORT_TASKS);
|
||||
return false;
|
||||
});
|
||||
|
||||
initializeBackupDirectory();
|
||||
|
||||
CheckBoxPreference googleDriveBackup =
|
||||
(CheckBoxPreference) findPreference(R.string.p_google_drive_backup);
|
||||
googleDriveBackup.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
if (newValue == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((Boolean) newValue) {
|
||||
if (permissionRequestor.requestAccountPermissions()) {
|
||||
requestGoogleDriveLogin();
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
preference.setSummary(null);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
findPreference(getString(R.string.p_background_sync_unmetered_only))
|
||||
.setOnPreferenceChangeListener(
|
||||
(preference, o) -> {
|
||||
workManager.updateBackgroundSync(null, null, (Boolean) o);
|
||||
return true;
|
||||
});
|
||||
findPreference(getString(R.string.p_background_sync))
|
||||
.setOnPreferenceChangeListener(
|
||||
(preference, o) -> {
|
||||
workManager.updateBackgroundSync(null, (Boolean) o, null);
|
||||
return true;
|
||||
});
|
||||
CheckBoxPreference positionHack =
|
||||
(CheckBoxPreference) findPreference(R.string.google_tasks_position_hack);
|
||||
positionHack.setChecked(preferences.isPositionHackEnabled());
|
||||
positionHack.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
if (newValue == null) {
|
||||
return false;
|
||||
}
|
||||
preferences.setLong(
|
||||
R.string.p_google_tasks_position_hack, ((Boolean) newValue) ? now() : 0);
|
||||
return true;
|
||||
});
|
||||
findPreference(R.string.add_account)
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
AddAccountDialog.showAddAccountDialog(BasicPreferences.this, dialogBuilder);
|
||||
return false;
|
||||
});
|
||||
|
||||
requires(
|
||||
R.string.settings_localization,
|
||||
atLeastJellybeanMR1(),
|
||||
R.string.p_language,
|
||||
R.string.p_layout_direction);
|
||||
|
||||
requires(R.string.task_list_options, atLeastLollipop(), R.string.p_show_subtasks);
|
||||
|
||||
requires(BuildConfig.DEBUG, R.string.debug);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
if (!BuildConfig.FLAVOR.equals("googleplay")) {
|
||||
removeGroup(R.string.TEA_control_location);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeGroup(int key) {
|
||||
Preference preference = findPreference(key);
|
||||
if (preference != null) {
|
||||
((PreferenceScreen) findPreference(R.string.preference_screen)).removePreference(preference);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
CheckBoxPreference googleDriveBackup =
|
||||
(CheckBoxPreference) findPreference(R.string.p_google_drive_backup);
|
||||
String account = preferences.getStringValue(R.string.p_google_drive_backup_account);
|
||||
if (preferences.getBoolean(R.string.p_google_drive_backup, false)
|
||||
&& googleAccountManager.canAccessAccount(account)) {
|
||||
googleDriveBackup.setChecked(true);
|
||||
googleDriveBackup.setSummary(account);
|
||||
} else {
|
||||
googleDriveBackup.setChecked(false);
|
||||
}
|
||||
googleDriveBackup.setChecked(preferences.getBoolean(R.string.p_google_drive_backup, false));
|
||||
|
||||
PreferenceCategory synchronizationPreferences =
|
||||
(PreferenceCategory) findPreference(R.string.synchronization);
|
||||
synchronizationPreferences.removeAll();
|
||||
|
||||
boolean hasGoogleAccounts = addGoogleTasksAccounts(synchronizationPreferences);
|
||||
boolean hasCaldavAccounts = addCaldavAccounts(synchronizationPreferences);
|
||||
if (!hasGoogleAccounts) {
|
||||
removeGroup(R.string.gtasks_GPr_header);
|
||||
}
|
||||
if (!(hasGoogleAccounts || hasCaldavAccounts)) {
|
||||
removeGroup(R.string.sync_SPr_interval_title);
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
if (!BuildConfig.FLAVOR.equals("googleplay")) {
|
||||
return;
|
||||
}
|
||||
List<String> choices =
|
||||
asList(getString(R.string.map_provider_mapbox), getString(R.string.map_provider_google));
|
||||
SingleCheckedArrayAdapter singleCheckedArrayAdapter =
|
||||
new SingleCheckedArrayAdapter(this, choices, themeAccent);
|
||||
Preference mapProviderPreference = findPreference(R.string.p_map_provider);
|
||||
mapProviderPreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setSingleChoiceItems(
|
||||
singleCheckedArrayAdapter,
|
||||
getMapProvider(),
|
||||
(dialog, which) -> {
|
||||
if (which == 1) {
|
||||
if (!playServices.refreshAndCheck()) {
|
||||
playServices.resolve(this);
|
||||
dialog.dismiss();
|
||||
return;
|
||||
}
|
||||
}
|
||||
preferences.setInt(R.string.p_map_provider, which);
|
||||
mapProviderPreference.setSummary(choices.get(which));
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.showThemedListView();
|
||||
return false;
|
||||
});
|
||||
int mapProvider = getMapProvider();
|
||||
mapProviderPreference.setSummary(
|
||||
mapProvider == -1 ? getString(R.string.none) : choices.get(mapProvider));
|
||||
|
||||
Preference placeProviderPreference = findPreference(R.string.p_place_provider);
|
||||
placeProviderPreference.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setSingleChoiceItems(
|
||||
singleCheckedArrayAdapter,
|
||||
getPlaceProvider(),
|
||||
(dialog, which) -> {
|
||||
if (which == 1) {
|
||||
if (!playServices.refreshAndCheck()) {
|
||||
playServices.resolve(this);
|
||||
dialog.dismiss();
|
||||
return;
|
||||
}
|
||||
if (!inventory.hasPro()) {
|
||||
toaster.longToast(R.string.requires_pro_subscription);
|
||||
dialog.dismiss();
|
||||
return;
|
||||
}
|
||||
}
|
||||
preferences.setInt(R.string.p_place_provider, which);
|
||||
placeProviderPreference.setSummary(choices.get(which));
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.showThemedListView();
|
||||
return false;
|
||||
});
|
||||
int placeProvider = getPlaceProvider();
|
||||
placeProviderPreference.setSummary(choices.get(placeProvider));
|
||||
}
|
||||
|
||||
private boolean addGoogleTasksAccounts(PreferenceCategory category) {
|
||||
List<GoogleTaskAccount> accounts = googleTaskListDao.getAccounts();
|
||||
for (GoogleTaskAccount googleTaskAccount : accounts) {
|
||||
String account = googleTaskAccount.getAccount();
|
||||
Preference preference = new Preference(this);
|
||||
preference.setTitle(account);
|
||||
String error = googleTaskAccount.getError();
|
||||
if (Strings.isNullOrEmpty(error)) {
|
||||
preference.setSummary(R.string.gtasks_GPr_header);
|
||||
} else {
|
||||
preference.setSummary(error);
|
||||
}
|
||||
preference.setOnPreferenceClickListener(
|
||||
p -> {
|
||||
dialogBuilder
|
||||
.newDialog(account)
|
||||
.setItems(
|
||||
asList(getString(R.string.reinitialize_account), getString(R.string.logout)),
|
||||
(dialog, which) -> {
|
||||
if (which == 0) {
|
||||
startActivityForResult(
|
||||
new Intent(this, GtasksLoginActivity.class),
|
||||
BasicPreferences.REQUEST_GOOGLE_TASKS);
|
||||
} else {
|
||||
logoutConfirmation(googleTaskAccount);
|
||||
}
|
||||
})
|
||||
.showThemedListView();
|
||||
return false;
|
||||
});
|
||||
category.addPreference(preference);
|
||||
}
|
||||
return !accounts.isEmpty();
|
||||
}
|
||||
|
||||
private boolean addCaldavAccounts(PreferenceCategory category) {
|
||||
List<CaldavAccount> accounts = caldavDao.getAccounts();
|
||||
for (CaldavAccount account : accounts) {
|
||||
Preference preference = new Preference(this);
|
||||
preference.setTitle(account.getName());
|
||||
String error = account.getError();
|
||||
if (Strings.isNullOrEmpty(error)) {
|
||||
preference.setSummary(
|
||||
account.isCaldavAccount() ? R.string.caldav : R.string.etesync);
|
||||
} else {
|
||||
preference.setSummary(error);
|
||||
}
|
||||
preference.setOnPreferenceClickListener(
|
||||
p -> {
|
||||
Intent intent =
|
||||
new Intent(
|
||||
this,
|
||||
account.isCaldavAccount()
|
||||
? CaldavAccountSettingsActivity.class
|
||||
: EteSyncAccountSettingsActivity.class);
|
||||
intent.putExtra(CaldavAccountSettingsActivity.EXTRA_CALDAV_DATA, account);
|
||||
startActivityForResult(intent, REQUEST_CALDAV_SETTINGS);
|
||||
return false;
|
||||
});
|
||||
category.addPreference(preference);
|
||||
}
|
||||
return !accounts.isEmpty();
|
||||
}
|
||||
|
||||
private void logoutConfirmation(GoogleTaskAccount account) {
|
||||
String name = account.getAccount();
|
||||
AlertDialog alertDialog =
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.logout_warning, name)
|
||||
.setPositiveButton(
|
||||
R.string.logout,
|
||||
(dialog, which) -> {
|
||||
taskDeleter.delete(account);
|
||||
restart();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create();
|
||||
alertDialog.setCanceledOnTouchOutside(false);
|
||||
alertDialog.setCancelable(false);
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
private int getPlaceProvider() {
|
||||
return playServices.isPlayServicesAvailable() && inventory.hasPro()
|
||||
? preferences.getInt(R.string.p_place_provider, 0)
|
||||
: 0;
|
||||
}
|
||||
|
||||
private int getMapProvider() {
|
||||
return playServices.isPlayServicesAvailable()
|
||||
? preferences.getInt(R.string.p_map_provider, 0)
|
||||
: 0;
|
||||
}
|
||||
|
||||
private void requestGoogleDriveLogin() {
|
||||
startActivityForResult(new Intent(this, DriveLoginActivity.class), REQUEST_DRIVE_BACKUP);
|
||||
}
|
||||
|
||||
private void setupActivity(int key, final Class<?> target) {
|
||||
findPreference(getString(key))
|
||||
.setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
startActivityForResult(new Intent(BasicPreferences.this, target), RC_PREFS);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(
|
||||
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if (requestCode == PermissionRequestor.REQUEST_GOOGLE_ACCOUNTS) {
|
||||
if (verifyPermissions(grantResults)) {
|
||||
requestGoogleDriveLogin();
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_THEME_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
int index = data.getIntExtra(ColorPickerActivity.EXTRA_THEME_INDEX, 0);
|
||||
preferences.setInt(R.string.p_theme, index);
|
||||
themeCache.getThemeBase(index).setDefaultNightMode();
|
||||
forceRestart();
|
||||
recreate();
|
||||
}
|
||||
} else if (requestCode == REQUEST_COLOR_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
int index = data.getIntExtra(ColorPickerActivity.EXTRA_THEME_INDEX, 0);
|
||||
preferences.setInt(R.string.p_theme_color, index);
|
||||
forceRestart();
|
||||
recreate();
|
||||
}
|
||||
} else if (requestCode == REQUEST_ACCENT_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
int index = data.getIntExtra(ColorPickerActivity.EXTRA_THEME_INDEX, 0);
|
||||
preferences.setInt(R.string.p_theme_accent, index);
|
||||
forceRestart();
|
||||
recreate();
|
||||
}
|
||||
} else if (requestCode == REQUEST_LAUNCHER_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
int index = data.getIntExtra(ColorPickerActivity.EXTRA_THEME_INDEX, 0);
|
||||
setLauncherIcon(index);
|
||||
preferences.setInt(R.string.p_theme_launcher, index);
|
||||
recreate();
|
||||
}
|
||||
} else if (requestCode == RC_PREFS) {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
mergeResults(data.getExtras());
|
||||
}
|
||||
} else if (requestCode == REQUEST_CODE_BACKUP_DIR) {
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
Uri uri = data.getData();
|
||||
if (atLeastLollipop()) {
|
||||
getContentResolver()
|
||||
.takePersistableUriPermission(
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
}
|
||||
preferences.setUri(R.string.p_backup_dir, uri);
|
||||
updateBackupDirectory();
|
||||
}
|
||||
} else if (requestCode == REQUEST_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
Uri uri = data.getData();
|
||||
String extension = FileHelper.getExtension(this, uri);
|
||||
if (!("json".equalsIgnoreCase(extension) || "xml".equalsIgnoreCase(extension))) {
|
||||
toaster.longToast(R.string.invalid_backup_file);
|
||||
} else {
|
||||
newImportTasksDialog(uri, extension).show(getFragmentManager(), FRAG_TAG_IMPORT_TASKS);
|
||||
forceRestart();
|
||||
}
|
||||
}
|
||||
} else if (requestCode == REQUEST_DRIVE_BACKUP) {
|
||||
boolean success = resultCode == RESULT_OK;
|
||||
((CheckBoxPreference) findPreference(R.string.p_google_drive_backup)).setChecked(success);
|
||||
if (!success && data != null) {
|
||||
toaster.longToast(data.getStringExtra(GtasksLoginActivity.EXTRA_ERROR));
|
||||
}
|
||||
} else if (requestCode == REQUEST_DEFAULT_LIST) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
Filter filter = data.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER);
|
||||
defaultFilterProvider.setDefaultFilter(filter);
|
||||
findPreference(getString(R.string.p_default_list)).setSummary(filter.listingTitle);
|
||||
localBroadcastManager.broadcastRefresh();
|
||||
}
|
||||
} else if (requestCode == REQUEST_CUSTOMIZE) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
forceRestart();
|
||||
}
|
||||
} else if (requestCode == REQUEST_CALDAV_SETTINGS) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
workManager.updateBackgroundSync();
|
||||
restart();
|
||||
}
|
||||
} else if (requestCode == REQUEST_GOOGLE_TASKS) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
workManager.updateBackgroundSync();
|
||||
restart();
|
||||
} else if (data != null) {
|
||||
toaster.longToast(data.getStringExtra(GtasksLoginActivity.EXTRA_ERROR));
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocaleSelected(Locale newValue) {
|
||||
String override = newValue.getLanguageOverride();
|
||||
if (Strings.isNullOrEmpty(override)) {
|
||||
preferences.remove(R.string.p_language);
|
||||
} else {
|
||||
preferences.setString(R.string.p_language, override);
|
||||
}
|
||||
updateLocale();
|
||||
if (!locale.equals(newValue)) {
|
||||
showRestartDialog();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLocale() {
|
||||
Preference languagePreference = findPreference(getString(R.string.p_language));
|
||||
String preference = preferences.getStringValue(R.string.p_language);
|
||||
languagePreference.setSummary(locale.withLanguage(preference).getDisplayName());
|
||||
}
|
||||
|
||||
private void initializeBackupDirectory() {
|
||||
findPreference(getString(R.string.p_backup_dir))
|
||||
.setOnPreferenceClickListener(
|
||||
p -> {
|
||||
FileHelper.newDirectoryPicker(
|
||||
this, REQUEST_CODE_BACKUP_DIR, preferences.getBackupDirectory());
|
||||
return false;
|
||||
});
|
||||
updateBackupDirectory();
|
||||
}
|
||||
|
||||
private void updateBackupDirectory() {
|
||||
findPreference(getString(R.string.p_backup_dir))
|
||||
.setSummary(uri2String(preferences.getBackupDirectory()));
|
||||
}
|
||||
|
||||
private void setLauncherIcon(int index) {
|
||||
PackageManager packageManager = getPackageManager();
|
||||
for (int i = 0; i < LAUNCHERS.length; i++) {
|
||||
ComponentName componentName =
|
||||
new ComponentName(this, "com.todoroo.astrid.activity.TaskListActivity" + LAUNCHERS[i]);
|
||||
packageManager.setComponentEnabledSetting(
|
||||
componentName,
|
||||
index == i
|
||||
? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|
||||
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFontSize() {
|
||||
findPreference(R.string.p_fontSize).setSummary(locale.formatNumber(preferences.getFontSize()));
|
||||
}
|
||||
|
||||
private void updateRowPadding() {
|
||||
findPreference(R.string.p_rowPadding)
|
||||
.setSummary(locale.formatNumber(preferences.getRowPadding()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueSelected(int value, int requestCode) {
|
||||
int resId = 0;
|
||||
if (requestCode == REQUEST_ROW_PADDING) {
|
||||
preferences.setInt(R.string.p_rowPadding, value);
|
||||
updateRowPadding();
|
||||
resId = R.string.p_rowPadding;
|
||||
} else if (requestCode == REQUEST_FONT_SIZE) {
|
||||
preferences.setInt(R.string.p_fontSize, value);
|
||||
updateFontSize();
|
||||
resId = R.string.p_fontSize;
|
||||
}
|
||||
if (resId > 0) {
|
||||
forceRestart();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
package org.tasks.preferences;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.widget.Toast;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.activities.TimePickerActivity;
|
||||
import org.tasks.injection.ActivityComponent;
|
||||
import org.tasks.injection.InjectingPreferenceActivity;
|
||||
import org.tasks.locale.Locale;
|
||||
import org.tasks.time.DateTime;
|
||||
import org.tasks.ui.TimePreference;
|
||||
import org.threeten.bp.DayOfWeek;
|
||||
import org.threeten.bp.format.TextStyle;
|
||||
|
||||
public class DateTimePreferences extends InjectingPreferenceActivity
|
||||
implements Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final int REQUEST_MORNING = 10001;
|
||||
private static final int REQUEST_AFTERNOON = 10002;
|
||||
private static final int REQUEST_EVENING = 10003;
|
||||
private static final int REQUEST_NIGHT = 10004;
|
||||
|
||||
@Inject Locale locale;
|
||||
@Inject Preferences preferences;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences_date_time);
|
||||
|
||||
ListPreference startOfWeekPreference = getStartOfWeekPreference();
|
||||
startOfWeekPreference.setEntries(getWeekdayEntries());
|
||||
startOfWeekPreference.setOnPreferenceChangeListener(this);
|
||||
|
||||
initializeTimePreference(getMorningPreference(), REQUEST_MORNING);
|
||||
initializeTimePreference(getAfternoonPreference(), REQUEST_AFTERNOON);
|
||||
initializeTimePreference(getEveningPreference(), REQUEST_EVENING);
|
||||
initializeTimePreference(getNightPreference(), REQUEST_NIGHT);
|
||||
|
||||
updateStartOfWeek(preferences.getStringValue(R.string.p_start_of_week));
|
||||
}
|
||||
|
||||
private String[] getWeekdayEntries() {
|
||||
return new String[] {
|
||||
getString(R.string.use_locale_default),
|
||||
getWeekdayDisplayName(DayOfWeek.SUNDAY),
|
||||
getWeekdayDisplayName(DayOfWeek.MONDAY)
|
||||
};
|
||||
}
|
||||
|
||||
private String getWeekdayDisplayName(DayOfWeek dayOfWeek) {
|
||||
return dayOfWeek.getDisplayName(TextStyle.FULL, locale.getLocale());
|
||||
}
|
||||
|
||||
private TimePreference getMorningPreference() {
|
||||
return getTimePreference(R.string.p_date_shortcut_morning);
|
||||
}
|
||||
|
||||
private TimePreference getAfternoonPreference() {
|
||||
return getTimePreference(R.string.p_date_shortcut_afternoon);
|
||||
}
|
||||
|
||||
private TimePreference getEveningPreference() {
|
||||
return getTimePreference(R.string.p_date_shortcut_evening);
|
||||
}
|
||||
|
||||
private TimePreference getNightPreference() {
|
||||
return getTimePreference(R.string.p_date_shortcut_night);
|
||||
}
|
||||
|
||||
private TimePreference getTimePreference(int resId) {
|
||||
return (TimePreference) findPreference(getString(resId));
|
||||
}
|
||||
|
||||
private void initializeTimePreference(final TimePreference preference, final int requestCode) {
|
||||
preference.setOnPreferenceChangeListener(this);
|
||||
preference.setOnPreferenceClickListener(
|
||||
ignored -> {
|
||||
final DateTime current = new DateTime().withMillisOfDay(preference.getMillisOfDay());
|
||||
Intent intent = new Intent(DateTimePreferences.this, TimePickerActivity.class);
|
||||
intent.putExtra(TimePickerActivity.EXTRA_TIMESTAMP, current.getMillis());
|
||||
startActivityForResult(intent, requestCode);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_MORNING:
|
||||
getMorningPreference().handleTimePickerActivityIntent(data);
|
||||
return;
|
||||
case REQUEST_AFTERNOON:
|
||||
getAfternoonPreference().handleTimePickerActivityIntent(data);
|
||||
return;
|
||||
case REQUEST_EVENING:
|
||||
getEveningPreference().handleTimePickerActivityIntent(data);
|
||||
return;
|
||||
case REQUEST_NIGHT:
|
||||
getNightPreference().handleTimePickerActivityIntent(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (preference.equals(getStartOfWeekPreference())) {
|
||||
updateStartOfWeek(newValue.toString());
|
||||
} else {
|
||||
int millisOfDay = (int) newValue;
|
||||
|
||||
if (preference.equals(getMorningPreference())) {
|
||||
if (millisOfDay >= getAfternoonPreference().getMillisOfDay()) {
|
||||
mustComeBefore(R.string.date_shortcut_morning, R.string.date_shortcut_afternoon);
|
||||
return false;
|
||||
}
|
||||
} else if (preference.equals(getAfternoonPreference())) {
|
||||
if (millisOfDay <= getMorningPreference().getMillisOfDay()) {
|
||||
mustComeAfter(R.string.date_shortcut_afternoon, R.string.date_shortcut_morning);
|
||||
return false;
|
||||
} else if (millisOfDay >= getEveningPreference().getMillisOfDay()) {
|
||||
mustComeBefore(R.string.date_shortcut_afternoon, R.string.date_shortcut_evening);
|
||||
return false;
|
||||
}
|
||||
} else if (preference.equals(getEveningPreference())) {
|
||||
if (millisOfDay <= getAfternoonPreference().getMillisOfDay()) {
|
||||
mustComeAfter(R.string.date_shortcut_evening, R.string.date_shortcut_afternoon);
|
||||
return false;
|
||||
} else if (millisOfDay >= getNightPreference().getMillisOfDay()) {
|
||||
mustComeBefore(R.string.date_shortcut_evening, R.string.date_shortcut_night);
|
||||
return false;
|
||||
}
|
||||
} else if (preference.equals(getNightPreference())) {
|
||||
if (millisOfDay <= getEveningPreference().getMillisOfDay()) {
|
||||
mustComeAfter(R.string.date_shortcut_night, R.string.date_shortcut_evening);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void mustComeBefore(int settingResId, int relativeResId) {
|
||||
invalidSetting(R.string.date_shortcut_must_come_before, settingResId, relativeResId);
|
||||
}
|
||||
|
||||
private void mustComeAfter(int settingResId, int relativeResId) {
|
||||
invalidSetting(R.string.date_shortcut_must_come_after, settingResId, relativeResId);
|
||||
}
|
||||
|
||||
private void invalidSetting(int errorResId, int settingResId, int relativeResId) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
getString(errorResId, getString(settingResId), getString(relativeResId)),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void updateStartOfWeek(String value) {
|
||||
ListPreference preference = getStartOfWeekPreference();
|
||||
int index = preference.findIndexOfValue(value);
|
||||
String summary = getWeekdayEntries()[index];
|
||||
preference.setSummary(summary);
|
||||
}
|
||||
|
||||
private ListPreference getStartOfWeekPreference() {
|
||||
return (ListPreference) findPreference(R.string.p_start_of_week);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package org.tasks.preferences
|
||||
|
||||
import android.content.Intent
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import org.tasks.R
|
||||
import org.tasks.injection.ActivityComponent
|
||||
import org.tasks.preferences.fragments.MainSettingsFragment
|
||||
|
||||
class MainPreferences : BasePreferences(), Toolbar.OnMenuItemClickListener {
|
||||
|
||||
override fun setupMenu() {
|
||||
toolbar.inflateMenu(R.menu.menu_preferences)
|
||||
toolbar.setOnMenuItemClickListener(this)
|
||||
}
|
||||
|
||||
override fun getRootTitle() = R.string.TLA_menu_settings
|
||||
|
||||
override fun getRootPreference() = MainSettingsFragment()
|
||||
|
||||
override fun inject(component: ActivityComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem?): Boolean {
|
||||
return if (item?.itemId == R.id.menu_help_and_feedback) {
|
||||
startActivity(Intent(this, HelpAndFeedback::class.java))
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package org.tasks.preferences
|
||||
|
||||
import org.tasks.R
|
||||
import org.tasks.injection.ActivityComponent
|
||||
import org.tasks.preferences.fragments.Advanced
|
||||
import org.tasks.preferences.fragments.HelpAndFeedback
|
||||
import org.tasks.preferences.fragments.Notifications
|
||||
|
||||
class ManageSpaceActivity : BasePreferences() {
|
||||
|
||||
override fun getRootTitle() = R.string.preferences_advanced
|
||||
|
||||
override fun getRootPreference() = Advanced()
|
||||
|
||||
override fun inject(component: ActivityComponent) = component.inject(this)
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
package org.tasks.preferences;
|
||||
|
||||
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastLollipop;
|
||||
import static org.tasks.PermissionUtil.verifyPermissions;
|
||||
import static org.tasks.files.FileHelper.uri2String;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.todoroo.astrid.voice.VoiceOutputAssistant;
|
||||
import javax.inject.Inject;
|
||||
import org.tasks.R;
|
||||
import org.tasks.files.FileHelper;
|
||||
import org.tasks.injection.ActivityComponent;
|
||||
import org.tasks.injection.InjectingPreferenceActivity;
|
||||
import org.tasks.scheduling.CalendarNotificationIntentService;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class MiscellaneousPreferences extends InjectingPreferenceActivity {
|
||||
|
||||
private static final int REQUEST_CODE_FILES_DIR = 2;
|
||||
private static final int REQUEST_CODE_TTS_CHECK = 2534;
|
||||
|
||||
@Inject Preferences preferences;
|
||||
@Inject VoiceOutputAssistant voiceOutputAssistant;
|
||||
@Inject ActivityPermissionRequestor permissionRequestor;
|
||||
@Inject PermissionChecker permissionChecker;
|
||||
|
||||
private CheckBoxPreference calendarReminderPreference;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.preferences_misc);
|
||||
|
||||
calendarReminderPreference =
|
||||
(CheckBoxPreference) findPreference(getString(R.string.p_calendar_reminders));
|
||||
|
||||
initializeAttachmentDirectoryPreference();
|
||||
initializeCalendarReminderPreference();
|
||||
initializeVoiceReminderPreference();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_CODE_FILES_DIR) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
Uri uri = data.getData();
|
||||
if (atLeastLollipop()) {
|
||||
getContentResolver()
|
||||
.takePersistableUriPermission(
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
}
|
||||
preferences.setUri(R.string.p_attachment_dir, uri);
|
||||
updateAttachmentDirectory();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (requestCode == REQUEST_CODE_TTS_CHECK) {
|
||||
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
|
||||
// success, create the TTS instance
|
||||
voiceOutputAssistant.initTTS();
|
||||
} else {
|
||||
// missing data, install it
|
||||
Intent installIntent = new Intent();
|
||||
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
|
||||
startActivity(installIntent);
|
||||
}
|
||||
}
|
||||
} catch (VerifyError e) {
|
||||
// unavailable
|
||||
Timber.e(e);
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
voiceOutputAssistant.shutdown();
|
||||
}
|
||||
|
||||
private void initializeAttachmentDirectoryPreference() {
|
||||
findPreference(getString(R.string.p_attachment_dir))
|
||||
.setOnPreferenceClickListener(
|
||||
p -> {
|
||||
FileHelper.newDirectoryPicker(
|
||||
this, REQUEST_CODE_FILES_DIR, preferences.getAttachmentsDirectory());
|
||||
return false;
|
||||
});
|
||||
updateAttachmentDirectory();
|
||||
}
|
||||
|
||||
private void updateAttachmentDirectory() {
|
||||
findPreference(getString(R.string.p_attachment_dir))
|
||||
.setSummary(uri2String(preferences.getAttachmentsDirectory()));
|
||||
}
|
||||
|
||||
private void initializeCalendarReminderPreference() {
|
||||
CheckBoxPreference calendarReminderPreference =
|
||||
(CheckBoxPreference) findPreference(getString(R.string.p_calendar_reminders));
|
||||
calendarReminderPreference.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
if (newValue == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(Boolean) newValue) {
|
||||
return true;
|
||||
}
|
||||
if (permissionRequestor.requestCalendarPermissions()) {
|
||||
CalendarNotificationIntentService.enqueueWork(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
calendarReminderPreference.setChecked(
|
||||
calendarReminderPreference.isChecked() && permissionChecker.canAccessCalendars());
|
||||
}
|
||||
|
||||
private void initializeVoiceReminderPreference() {
|
||||
findPreference(getString(R.string.p_voiceRemindersEnabled))
|
||||
.setOnPreferenceChangeListener(
|
||||
(preference, newValue) -> {
|
||||
boolean enabled = (boolean) newValue;
|
||||
try {
|
||||
if (enabled && !voiceOutputAssistant.isTTSInitialized()) {
|
||||
Intent checkIntent = new Intent();
|
||||
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
|
||||
startActivityForResult(checkIntent, REQUEST_CODE_TTS_CHECK);
|
||||
} else if (!enabled && voiceOutputAssistant.isTTSInitialized()) {
|
||||
voiceOutputAssistant.shutdown();
|
||||
}
|
||||
} catch (VerifyError e) {
|
||||
Timber.e(e);
|
||||
preference.setEnabled(false);
|
||||
preferences.setBoolean(preference.getKey(), false);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(
|
||||
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if (requestCode == PermissionRequestor.REQUEST_CALENDAR) {
|
||||
if (verifyPermissions(grantResults)) {
|
||||
calendarReminderPreference.setChecked(true);
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inject(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package org.tasks.preferences
|
||||
|
||||
import org.tasks.R
|
||||
import org.tasks.injection.ActivityComponent
|
||||
import org.tasks.preferences.fragments.HelpAndFeedback
|
||||
import org.tasks.preferences.fragments.Notifications
|
||||
|
||||
class NotificationPreferences : BasePreferences() {
|
||||
|
||||
override fun getRootTitle() = R.string.notifications
|
||||
|
||||
override fun getRootPreference() = Notifications()
|
||||
|
||||
override fun inject(component: ActivityComponent) = component.inject(this)
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package org.tasks.preferences
|
||||
|
||||
import org.tasks.R
|
||||
import org.tasks.injection.ActivityComponent
|
||||
import org.tasks.preferences.fragments.Synchronization
|
||||
|
||||
class SyncPreferences : BasePreferences() {
|
||||
|
||||
override fun getRootTitle() = R.string.synchronization
|
||||
|
||||
override fun getRootPreference() = Synchronization()
|
||||
|
||||
override fun inject(component: ActivityComponent) = component.inject(this)
|
||||
}
|
@ -0,0 +1,234 @@
|
||||
package org.tasks.preferences.fragments
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import com.todoroo.andlib.utility.AndroidUtilities
|
||||
import com.todoroo.astrid.dao.Database
|
||||
import com.todoroo.astrid.dao.TaskDao
|
||||
import com.todoroo.astrid.service.TaskDeleter
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.tasks.PermissionUtil
|
||||
import org.tasks.R
|
||||
import org.tasks.calendars.CalendarEventProvider
|
||||
import org.tasks.files.FileHelper
|
||||
import org.tasks.injection.FragmentComponent
|
||||
import org.tasks.injection.InjectingPreferenceFragment
|
||||
import org.tasks.preferences.FragmentPermissionRequestor
|
||||
import org.tasks.preferences.PermissionChecker
|
||||
import org.tasks.preferences.PermissionRequestor
|
||||
import org.tasks.preferences.Preferences
|
||||
import org.tasks.scheduling.CalendarNotificationIntentService
|
||||
import org.tasks.ui.Toaster
|
||||
import java.util.concurrent.Callable
|
||||
import javax.inject.Inject
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
private const val REQUEST_CODE_FILES_DIR = 10000
|
||||
|
||||
class Advanced : InjectingPreferenceFragment() {
|
||||
|
||||
@Inject lateinit var preferences: Preferences
|
||||
@Inject lateinit var database: Database
|
||||
@Inject lateinit var taskDao: TaskDao
|
||||
@Inject lateinit var calendarEventProvider: CalendarEventProvider
|
||||
@Inject lateinit var taskDeleter: TaskDeleter
|
||||
@Inject lateinit var toaster: Toaster
|
||||
@Inject lateinit var permissionRequester: FragmentPermissionRequestor
|
||||
@Inject lateinit var permissionChecker: PermissionChecker
|
||||
|
||||
private lateinit var disposables: CompositeDisposable
|
||||
private lateinit var calendarReminderPreference: SwitchPreferenceCompat
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences_advanced, rootKey)
|
||||
|
||||
findPreference(R.string.EPr_manage_purge_deleted)
|
||||
.setOnPreferenceClickListener {
|
||||
purgeDeletedTasks()
|
||||
false
|
||||
}
|
||||
|
||||
findPreference(R.string.EPr_manage_delete_completed_gcal)
|
||||
.setOnPreferenceClickListener {
|
||||
deleteCompletedEvents()
|
||||
false
|
||||
}
|
||||
|
||||
findPreference(R.string.EPr_manage_delete_all_gcal)
|
||||
.setOnPreferenceClickListener {
|
||||
deleteAllCalendarEvents()
|
||||
false
|
||||
}
|
||||
|
||||
findPreference(R.string.EPr_reset_preferences)
|
||||
.setOnPreferenceClickListener {
|
||||
resetPreferences()
|
||||
false
|
||||
}
|
||||
|
||||
findPreference(R.string.EPr_delete_task_data)
|
||||
.setOnPreferenceClickListener {
|
||||
deleteTaskData()
|
||||
false
|
||||
}
|
||||
|
||||
findPreference(R.string.p_attachment_dir)
|
||||
.setOnPreferenceClickListener {
|
||||
FileHelper.newDirectoryPicker(this, REQUEST_CODE_FILES_DIR, preferences.attachmentsDirectory)
|
||||
false
|
||||
}
|
||||
updateAttachmentDirectory()
|
||||
|
||||
calendarReminderPreference = findPreference(R.string.p_calendar_reminders) as SwitchPreferenceCompat
|
||||
initializeCalendarReminderPreference()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == REQUEST_CODE_FILES_DIR) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
val uri = data!!.data!!
|
||||
if (AndroidUtilities.atLeastLollipop()) {
|
||||
context!!.contentResolver
|
||||
.takePersistableUriPermission(
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
}
|
||||
preferences.setUri(R.string.p_attachment_dir, uri)
|
||||
updateAttachmentDirectory()
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int, permissions: Array<String?>, grantResults: IntArray) {
|
||||
if (requestCode == PermissionRequestor.REQUEST_CALENDAR) {
|
||||
if (PermissionUtil.verifyPermissions(grantResults)) {
|
||||
calendarReminderPreference.isChecked = true
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
disposables = CompositeDisposable()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
|
||||
disposables.dispose()
|
||||
}
|
||||
|
||||
private fun initializeCalendarReminderPreference() {
|
||||
calendarReminderPreference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
if (newValue == null) {
|
||||
false
|
||||
} else if (!(newValue as Boolean)) {
|
||||
true
|
||||
} else if (permissionRequester.requestCalendarPermissions()) {
|
||||
CalendarNotificationIntentService.enqueueWork(context)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
calendarReminderPreference.isChecked = calendarReminderPreference.isChecked && permissionChecker.canAccessCalendars()
|
||||
}
|
||||
|
||||
private fun updateAttachmentDirectory() {
|
||||
findPreference(R.string.p_attachment_dir).summary =
|
||||
FileHelper.uri2String(preferences.attachmentsDirectory)
|
||||
}
|
||||
|
||||
private fun purgeDeletedTasks() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.EPr_manage_purge_deleted_message)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
performAction(
|
||||
R.string.EPr_manage_purge_deleted_status, Callable { taskDeleter.purgeDeleted() })
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun deleteCompletedEvents() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.EPr_manage_delete_completed_gcal_message)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
performAction(
|
||||
R.string.EPr_manage_delete_completed_gcal_status,
|
||||
Callable {
|
||||
calendarEventProvider.deleteEvents(taskDao.completedCalendarEvents)
|
||||
taskDao.clearCompletedCalendarEvents()
|
||||
})
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun deleteAllCalendarEvents() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.EPr_manage_delete_all_gcal_message)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
performAction(
|
||||
R.string.EPr_manage_delete_all_gcal_status,
|
||||
Callable {
|
||||
calendarEventProvider.deleteEvents(taskDao.allCalendarEvents)
|
||||
taskDao.clearAllCalendarEvents()
|
||||
})
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun performAction(@StringRes message: Int, callable: Callable<Int>) {
|
||||
disposables.add(
|
||||
Single.fromCallable(callable)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { c: Int? -> toaster.longToastUnformatted(message, c!!) })
|
||||
}
|
||||
|
||||
private fun resetPreferences() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.EPr_reset_preferences_warning)
|
||||
.setPositiveButton(R.string.EPr_reset_preferences) { _, _ ->
|
||||
preferences.reset()
|
||||
exitProcess(0)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun deleteTaskData() {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.EPr_delete_task_data_warning)
|
||||
.setPositiveButton(R.string.EPr_delete_task_data) { _, _ ->
|
||||
context!!.deleteDatabase(database.name)
|
||||
exitProcess(0)
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun inject(component: FragmentComponent) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
package org.tasks.preferences.fragments
|
||||
|
||||
import android.app.Activity.RESULT_OK
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import com.todoroo.andlib.utility.AndroidUtilities
|
||||
import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity
|
||||
import org.tasks.PermissionUtil
|
||||
import org.tasks.R
|
||||
import org.tasks.dialogs.ExportTasksDialog
|
||||
import org.tasks.dialogs.ImportTasksDialog
|
||||
import org.tasks.drive.DriveLoginActivity
|
||||
import org.tasks.files.FileHelper
|
||||
import org.tasks.gtasks.GoogleAccountManager
|
||||
import org.tasks.injection.FragmentComponent
|
||||
import org.tasks.injection.InjectingPreferenceFragment
|
||||
import org.tasks.preferences.FragmentPermissionRequestor
|
||||
import org.tasks.preferences.PermissionRequestor
|
||||
import org.tasks.preferences.Preferences
|
||||
import org.tasks.ui.Toaster
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val REQUEST_CODE_BACKUP_DIR = 10001
|
||||
private const val REQUEST_DRIVE_BACKUP = 10002
|
||||
private const val REQUEST_PICKER = 10003
|
||||
private const val FRAG_TAG_EXPORT_TASKS = "frag_tag_export_tasks"
|
||||
private const val FRAG_TAG_IMPORT_TASKS = "frag_tag_import_tasks"
|
||||
|
||||
class Backups : InjectingPreferenceFragment() {
|
||||
|
||||
@Inject lateinit var preferences: Preferences
|
||||
@Inject lateinit var permissionRequestor: FragmentPermissionRequestor
|
||||
@Inject lateinit var toaster: Toaster
|
||||
@Inject lateinit var googleAccountManager: GoogleAccountManager
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences_backups, rootKey)
|
||||
|
||||
initializeBackupDirectory()
|
||||
|
||||
findPreference(R.string.backup_BAc_import)
|
||||
.setOnPreferenceClickListener {
|
||||
startActivityForResult(
|
||||
FileHelper.newFilePickerIntent(activity, preferences.backupDirectory),
|
||||
REQUEST_PICKER)
|
||||
false
|
||||
}
|
||||
|
||||
findPreference(R.string.backup_BAc_export)
|
||||
.setOnPreferenceClickListener {
|
||||
ExportTasksDialog.newExportTasksDialog()
|
||||
.show(fragmentManager!!, FRAG_TAG_EXPORT_TASKS)
|
||||
false
|
||||
}
|
||||
|
||||
val googleDriveBackup = findPreference(R.string.p_google_drive_backup) as SwitchPreferenceCompat
|
||||
googleDriveBackup.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference: Preference, newValue: Any? ->
|
||||
when {
|
||||
newValue == null -> {
|
||||
false
|
||||
}
|
||||
newValue as Boolean -> {
|
||||
if (permissionRequestor.requestAccountPermissions()) {
|
||||
requestGoogleDriveLogin()
|
||||
}
|
||||
false
|
||||
}
|
||||
else -> {
|
||||
preference.summary = null
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
val googleDriveBackup = findPreference(R.string.p_google_drive_backup) as SwitchPreferenceCompat
|
||||
val account = preferences.getStringValue(R.string.p_google_drive_backup_account)
|
||||
if (preferences.getBoolean(R.string.p_google_drive_backup, false)
|
||||
&& googleAccountManager.canAccessAccount(account)) {
|
||||
googleDriveBackup.isChecked = true
|
||||
googleDriveBackup.summary = account
|
||||
} else {
|
||||
googleDriveBackup.isChecked = false
|
||||
googleDriveBackup.summary = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
if (requestCode == PermissionRequestor.REQUEST_GOOGLE_ACCOUNTS) {
|
||||
if (PermissionUtil.verifyPermissions(grantResults)) {
|
||||
requestGoogleDriveLogin()
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == REQUEST_CODE_BACKUP_DIR) {
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
val uri = data.data!!
|
||||
if (AndroidUtilities.atLeastLollipop()) {
|
||||
context?.contentResolver
|
||||
?.takePersistableUriPermission(
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
}
|
||||
preferences.setUri(R.string.p_backup_dir, uri)
|
||||
updateBackupDirectory()
|
||||
}
|
||||
} else if (requestCode == REQUEST_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
val uri = data!!.data
|
||||
val extension = FileHelper.getExtension(activity, uri)
|
||||
if (!("json".equals(extension, ignoreCase = true) || "xml".equals(extension, ignoreCase = true))) {
|
||||
toaster.longToast(R.string.invalid_backup_file)
|
||||
} else {
|
||||
ImportTasksDialog.newImportTasksDialog(uri, extension).show(fragmentManager!!, FRAG_TAG_IMPORT_TASKS)
|
||||
}
|
||||
}
|
||||
} else if (requestCode == REQUEST_DRIVE_BACKUP) {
|
||||
val success = resultCode == RESULT_OK
|
||||
(findPreference(R.string.p_google_drive_backup) as SwitchPreferenceCompat).isChecked = success
|
||||
if (!success && data != null) {
|
||||
toaster.longToast(data.getStringExtra(GtasksLoginActivity.EXTRA_ERROR))
|
||||
}
|
||||
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestGoogleDriveLogin() {
|
||||
startActivityForResult(Intent(context, DriveLoginActivity::class.java), REQUEST_DRIVE_BACKUP)
|
||||
}
|
||||
|
||||
private fun initializeBackupDirectory() {
|
||||
findPreference(R.string.p_backup_dir)
|
||||
.setOnPreferenceClickListener {
|
||||
FileHelper.newDirectoryPicker(
|
||||
this, REQUEST_CODE_BACKUP_DIR, preferences.backupDirectory)
|
||||
false
|
||||
}
|
||||
updateBackupDirectory()
|
||||
}
|
||||
|
||||
private fun updateBackupDirectory() {
|
||||
findPreference(R.string.p_backup_dir).summary = FileHelper.uri2String(preferences.backupDirectory)
|
||||
}
|
||||
|
||||
override fun inject(component: FragmentComponent) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,431 @@
|
||||
package org.tasks.preferences.fragments
|
||||
|
||||
import android.app.Activity.RESULT_OK
|
||||
import android.content.ComponentName
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import com.google.common.base.Strings
|
||||
import com.todoroo.andlib.utility.AndroidUtilities.atLeastJellybeanMR1
|
||||
import com.todoroo.andlib.utility.AndroidUtilities.atLeastLollipop
|
||||
import com.todoroo.astrid.api.Filter
|
||||
import org.tasks.BuildConfig
|
||||
import org.tasks.LocalBroadcastManager
|
||||
import org.tasks.R
|
||||
import org.tasks.activities.ColorPickerActivity
|
||||
import org.tasks.activities.ColorPickerActivity.ColorPalette.*
|
||||
import org.tasks.activities.FilterSelectionActivity
|
||||
import org.tasks.activities.TimePickerActivity
|
||||
import org.tasks.billing.Inventory
|
||||
import org.tasks.gtasks.PlayServices
|
||||
import org.tasks.injection.FragmentComponent
|
||||
import org.tasks.injection.InjectingPreferenceFragment
|
||||
import org.tasks.locale.Locale
|
||||
import org.tasks.locale.LocalePickerDialog
|
||||
import org.tasks.preferences.DefaultFilterProvider
|
||||
import org.tasks.preferences.Preferences
|
||||
import org.tasks.themes.ThemeAccent
|
||||
import org.tasks.themes.ThemeBase
|
||||
import org.tasks.themes.ThemeCache
|
||||
import org.tasks.themes.ThemeColor
|
||||
import org.tasks.time.DateTime
|
||||
import org.tasks.ui.SingleCheckedArrayAdapter
|
||||
import org.tasks.ui.TimePreference
|
||||
import org.tasks.ui.Toaster
|
||||
import org.threeten.bp.DayOfWeek
|
||||
import org.threeten.bp.format.TextStyle
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val REQUEST_THEME_PICKER = 10001
|
||||
private const val REQUEST_COLOR_PICKER = 10002
|
||||
private const val REQUEST_ACCENT_PICKER = 10003
|
||||
private const val REQUEST_LAUNCHER_PICKER = 10004
|
||||
private const val REQUEST_DEFAULT_LIST = 10005
|
||||
private const val REQUEST_LOCALE = 10006
|
||||
private const val REQUEST_MORNING = 10007
|
||||
private const val REQUEST_AFTERNOON = 10008
|
||||
private const val REQUEST_EVENING = 10009
|
||||
private const val REQUEST_NIGHT = 10010
|
||||
private const val FRAG_TAG_LOCALE_PICKER = "frag_tag_locale_picker"
|
||||
|
||||
class LookAndFeel : InjectingPreferenceFragment(), Preference.OnPreferenceChangeListener {
|
||||
|
||||
@Inject lateinit var themeCache: ThemeCache
|
||||
@Inject lateinit var themeBase: ThemeBase
|
||||
@Inject lateinit var themeColor: ThemeColor
|
||||
@Inject lateinit var themeAccent: ThemeAccent
|
||||
@Inject lateinit var preferences: Preferences
|
||||
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
|
||||
@Inject lateinit var locale: Locale
|
||||
@Inject lateinit var defaultFilterProvider: DefaultFilterProvider
|
||||
@Inject lateinit var playServices: PlayServices
|
||||
@Inject lateinit var inventory: Inventory
|
||||
@Inject lateinit var toaster: Toaster
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences_look_and_feel, rootKey)
|
||||
|
||||
setupColorPreference(R.string.p_theme, themeBase.name, THEMES, REQUEST_THEME_PICKER)
|
||||
setupColorPreference(R.string.p_theme_color, themeColor.name, COLORS, REQUEST_COLOR_PICKER)
|
||||
setupColorPreference(R.string.p_theme_accent, themeAccent.name, ACCENTS, REQUEST_ACCENT_PICKER)
|
||||
updateLauncherPreference()
|
||||
|
||||
findPreference(R.string.p_show_subtasks)
|
||||
.setOnPreferenceChangeListener { _: Preference?, _: Any? ->
|
||||
localBroadcastManager.broadcastRefresh()
|
||||
true
|
||||
}
|
||||
|
||||
val defaultList = findPreference(R.string.p_default_list)
|
||||
val filter: Filter = defaultFilterProvider.defaultFilter
|
||||
defaultList.summary = filter.listingTitle
|
||||
defaultList.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
val intent = Intent(context, FilterSelectionActivity::class.java)
|
||||
intent.putExtra(FilterSelectionActivity.EXTRA_FILTER, defaultFilterProvider.defaultFilter)
|
||||
intent.putExtra(FilterSelectionActivity.EXTRA_RETURN_FILTER, true)
|
||||
startActivityForResult(intent, REQUEST_DEFAULT_LIST)
|
||||
true
|
||||
}
|
||||
|
||||
val languagePreference = findPreference(R.string.p_language)
|
||||
updateLocale()
|
||||
languagePreference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
val dialog = LocalePickerDialog.newLocalePickerDialog()
|
||||
dialog.setTargetFragment(this, REQUEST_LOCALE)
|
||||
dialog.show(fragmentManager!!, FRAG_TAG_LOCALE_PICKER)
|
||||
false
|
||||
}
|
||||
findPreference(R.string.p_layout_direction)
|
||||
.setOnPreferenceChangeListener { _: Preference?, o: Any ->
|
||||
val newValue: Int = o as Int
|
||||
if (locale.directionality
|
||||
!= locale.withDirectionality(newValue).directionality) {
|
||||
showRestartDialog()
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
val startOfWeekPreference: ListPreference = getStartOfWeekPreference()
|
||||
startOfWeekPreference.entries = getWeekdayEntries()
|
||||
startOfWeekPreference.onPreferenceChangeListener = this
|
||||
|
||||
initializeTimePreference(getMorningPreference(), REQUEST_MORNING)
|
||||
initializeTimePreference(getAfternoonPreference(), REQUEST_AFTERNOON)
|
||||
initializeTimePreference(getEveningPreference(), REQUEST_EVENING)
|
||||
initializeTimePreference(getNightPreference(), REQUEST_NIGHT)
|
||||
|
||||
updateStartOfWeek(preferences.getStringValue(R.string.p_start_of_week)!!)
|
||||
|
||||
requires(R.string.task_list_options, atLeastLollipop(), R.string.p_show_subtasks)
|
||||
|
||||
requires(R.string.settings_localization,
|
||||
atLeastJellybeanMR1(),
|
||||
R.string.p_language,
|
||||
R.string.p_layout_direction)
|
||||
|
||||
@Suppress("ConstantConditionIf")
|
||||
if (BuildConfig.FLAVOR != "googleplay") {
|
||||
removeGroup(R.string.TEA_control_location)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
@Suppress("ConstantConditionIf")
|
||||
if (BuildConfig.FLAVOR == "googleplay") {
|
||||
setupLocationPickers()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateLauncherPreference() =
|
||||
setupColorPreference(
|
||||
R.string.p_theme_launcher,
|
||||
themeCache.getThemeColor(preferences.getInt(R.string.p_theme_launcher, 7)).name,
|
||||
LAUNCHER,
|
||||
REQUEST_LAUNCHER_PICKER)
|
||||
|
||||
private fun setupLocationPickers() {
|
||||
val choices = listOf(getString(R.string.map_provider_mapbox), getString(R.string.map_provider_google))
|
||||
val singleCheckedArrayAdapter = SingleCheckedArrayAdapter(context!!, choices, themeAccent)
|
||||
val mapProviderPreference = findPreference(R.string.p_map_provider)
|
||||
mapProviderPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setSingleChoiceItems(
|
||||
singleCheckedArrayAdapter,
|
||||
getMapProvider()
|
||||
) { dialog: DialogInterface, which: Int ->
|
||||
if (which == 1) {
|
||||
if (!playServices.refreshAndCheck()) {
|
||||
playServices.resolve(activity)
|
||||
dialog.dismiss()
|
||||
return@setSingleChoiceItems
|
||||
}
|
||||
}
|
||||
preferences.setInt(R.string.p_map_provider, which)
|
||||
mapProviderPreference.summary = choices[which]
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.showThemedListView()
|
||||
false
|
||||
}
|
||||
val mapProvider: Int = getMapProvider()
|
||||
mapProviderPreference.summary = if (mapProvider == -1) getString(R.string.none) else choices[mapProvider]
|
||||
|
||||
val placeProviderPreference = findPreference(R.string.p_place_provider)
|
||||
placeProviderPreference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
dialogBuilder
|
||||
.newDialog()
|
||||
.setSingleChoiceItems(
|
||||
singleCheckedArrayAdapter,
|
||||
getPlaceProvider()
|
||||
) { dialog: DialogInterface, which: Int ->
|
||||
if (which == 1) {
|
||||
if (!playServices.refreshAndCheck()) {
|
||||
playServices.resolve(activity)
|
||||
dialog.dismiss()
|
||||
return@setSingleChoiceItems
|
||||
}
|
||||
if (!inventory.hasPro()) {
|
||||
toaster.longToast(R.string.requires_pro_subscription)
|
||||
dialog.dismiss()
|
||||
return@setSingleChoiceItems
|
||||
}
|
||||
}
|
||||
preferences.setInt(R.string.p_place_provider, which)
|
||||
placeProviderPreference.summary = choices[which]
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.showThemedListView()
|
||||
false
|
||||
}
|
||||
val placeProvider: Int = getPlaceProvider()
|
||||
placeProviderPreference.summary = choices[placeProvider]
|
||||
}
|
||||
|
||||
private fun getPlaceProvider(): Int {
|
||||
return if (playServices.isPlayServicesAvailable && inventory.hasPro()) preferences.getInt(R.string.p_place_provider, 0) else 0
|
||||
}
|
||||
|
||||
private fun getMapProvider(): Int {
|
||||
return if (playServices.isPlayServicesAvailable) preferences.getInt(R.string.p_map_provider, 0) else 0
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == REQUEST_THEME_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
val index = data!!.getIntExtra(ColorPickerActivity.EXTRA_THEME_INDEX, 0)
|
||||
preferences.setInt(R.string.p_theme, index)
|
||||
Handler().post {
|
||||
themeCache.getThemeBase(index).setDefaultNightMode()
|
||||
recreate()
|
||||
}
|
||||
}
|
||||
} else if (requestCode == REQUEST_COLOR_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
val index = data!!.getIntExtra(ColorPickerActivity.EXTRA_THEME_INDEX, 0)
|
||||
preferences.setInt(R.string.p_theme_color, index)
|
||||
recreate()
|
||||
}
|
||||
} else if (requestCode == REQUEST_ACCENT_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
val index = data!!.getIntExtra(ColorPickerActivity.EXTRA_THEME_INDEX, 0)
|
||||
preferences.setInt(R.string.p_theme_accent, index)
|
||||
recreate()
|
||||
}
|
||||
} else if (requestCode == REQUEST_LAUNCHER_PICKER) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
val index = data!!.getIntExtra(ColorPickerActivity.EXTRA_THEME_INDEX, 0)
|
||||
setLauncherIcon(index)
|
||||
preferences.setInt(R.string.p_theme_launcher, index)
|
||||
updateLauncherPreference()
|
||||
}
|
||||
} else if (requestCode == REQUEST_DEFAULT_LIST) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
val filter: Filter = data!!.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER)!!
|
||||
defaultFilterProvider.defaultFilter = filter
|
||||
findPreference(R.string.p_default_list).summary = filter.listingTitle
|
||||
localBroadcastManager.broadcastRefresh()
|
||||
}
|
||||
} else if (requestCode == REQUEST_LOCALE) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
val newValue: Locale = data!!.getSerializableExtra(LocalePickerDialog.EXTRA_LOCALE) as Locale
|
||||
val override: String? = newValue.languageOverride
|
||||
if (Strings.isNullOrEmpty(override)) {
|
||||
preferences.remove(R.string.p_language)
|
||||
} else {
|
||||
preferences.setString(R.string.p_language, override)
|
||||
}
|
||||
updateLocale()
|
||||
if (locale != newValue) {
|
||||
showRestartDialog()
|
||||
}
|
||||
}
|
||||
} else if (requestCode == REQUEST_MORNING) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
getMorningPreference().handleTimePickerActivityIntent(data)
|
||||
}
|
||||
} else if (requestCode == REQUEST_AFTERNOON) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
getAfternoonPreference().handleTimePickerActivityIntent(data)
|
||||
}
|
||||
} else if (requestCode == REQUEST_EVENING) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
getEveningPreference().handleTimePickerActivityIntent(data)
|
||||
}
|
||||
} else if (requestCode == REQUEST_NIGHT) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
getNightPreference().handleTimePickerActivityIntent(data)
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateLocale() {
|
||||
val languagePreference = findPreference(R.string.p_language)
|
||||
val preference = preferences.getStringValue(R.string.p_language)
|
||||
languagePreference.summary = locale.withLanguage(preference).displayName
|
||||
}
|
||||
|
||||
private fun setLauncherIcon(index: Int) {
|
||||
val packageManager: PackageManager? = context?.packageManager
|
||||
for (i in ThemeColor.LAUNCHERS.indices) {
|
||||
val componentName = ComponentName(context!!, "com.todoroo.astrid.activity.TaskListActivity" + ThemeColor.LAUNCHERS[i])
|
||||
packageManager?.setComponentEnabledSetting(
|
||||
componentName,
|
||||
if (index == i) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
||||
PackageManager.DONT_KILL_APP)
|
||||
}
|
||||
}
|
||||
|
||||
override fun inject(component: FragmentComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
private fun setupColorPreference(@StringRes prefId: Int, summary: String, palette: ColorPickerActivity.ColorPalette, requestCode: Int) {
|
||||
val themePref: Preference = findPreference(prefId)
|
||||
themePref.summary = summary
|
||||
themePref.setOnPreferenceClickListener {
|
||||
val intent = Intent(context, ColorPickerActivity::class.java)
|
||||
intent.putExtra(ColorPickerActivity.EXTRA_PALETTE, palette)
|
||||
startActivityForResult(intent, requestCode)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeTimePreference(preference: TimePreference, requestCode: Int) {
|
||||
preference.onPreferenceChangeListener = this
|
||||
preference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
val current = DateTime().withMillisOfDay(preference.millisOfDay)
|
||||
val intent = Intent(context, TimePickerActivity::class.java)
|
||||
intent.putExtra(TimePickerActivity.EXTRA_TIMESTAMP, current.millis)
|
||||
startActivityForResult(intent, requestCode)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreferenceChange(preference: Preference?, newValue: Any?): Boolean {
|
||||
if (preference == getStartOfWeekPreference()) {
|
||||
updateStartOfWeek(newValue.toString())
|
||||
} else {
|
||||
val millisOfDay = newValue as Int
|
||||
if (preference == getMorningPreference()) {
|
||||
if (millisOfDay >= getAfternoonPreference().millisOfDay) {
|
||||
mustComeBefore(R.string.date_shortcut_morning, R.string.date_shortcut_afternoon)
|
||||
return false
|
||||
}
|
||||
} else if (preference == getAfternoonPreference()) {
|
||||
if (millisOfDay <= getMorningPreference().millisOfDay) {
|
||||
mustComeAfter(R.string.date_shortcut_afternoon, R.string.date_shortcut_morning)
|
||||
return false
|
||||
} else if (millisOfDay >= getEveningPreference().millisOfDay) {
|
||||
mustComeBefore(R.string.date_shortcut_afternoon, R.string.date_shortcut_evening)
|
||||
return false
|
||||
}
|
||||
} else if (preference == getEveningPreference()) {
|
||||
if (millisOfDay <= getAfternoonPreference().millisOfDay) {
|
||||
mustComeAfter(R.string.date_shortcut_evening, R.string.date_shortcut_afternoon)
|
||||
return false
|
||||
} else if (millisOfDay >= getNightPreference().millisOfDay) {
|
||||
mustComeBefore(R.string.date_shortcut_evening, R.string.date_shortcut_night)
|
||||
return false
|
||||
}
|
||||
} else if (preference == getNightPreference()) {
|
||||
if (millisOfDay <= getEveningPreference().millisOfDay) {
|
||||
mustComeAfter(R.string.date_shortcut_night, R.string.date_shortcut_evening)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun mustComeBefore(settingResId: Int, relativeResId: Int) {
|
||||
invalidSetting(R.string.date_shortcut_must_come_before, settingResId, relativeResId)
|
||||
}
|
||||
|
||||
private fun mustComeAfter(settingResId: Int, relativeResId: Int) {
|
||||
invalidSetting(R.string.date_shortcut_must_come_after, settingResId, relativeResId)
|
||||
}
|
||||
|
||||
private fun invalidSetting(errorResId: Int, settingResId: Int, relativeResId: Int) {
|
||||
Toast.makeText(
|
||||
context,
|
||||
getString(errorResId, getString(settingResId), getString(relativeResId)),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun updateStartOfWeek(value: String) {
|
||||
val preference = getStartOfWeekPreference()
|
||||
val index = preference.findIndexOfValue(value)
|
||||
val summary: String? = getWeekdayEntries()?.get(index)
|
||||
preference.summary = summary
|
||||
}
|
||||
|
||||
private fun getStartOfWeekPreference(): ListPreference {
|
||||
return findPreference(R.string.p_start_of_week) as ListPreference
|
||||
}
|
||||
|
||||
private fun getWeekdayDisplayName(dayOfWeek: DayOfWeek): String {
|
||||
return dayOfWeek.getDisplayName(TextStyle.FULL, locale.locale)
|
||||
}
|
||||
|
||||
private fun getMorningPreference(): TimePreference {
|
||||
return getTimePreference(R.string.p_date_shortcut_morning)
|
||||
}
|
||||
|
||||
private fun getAfternoonPreference(): TimePreference {
|
||||
return getTimePreference(R.string.p_date_shortcut_afternoon)
|
||||
}
|
||||
|
||||
private fun getEveningPreference(): TimePreference {
|
||||
return getTimePreference(R.string.p_date_shortcut_evening)
|
||||
}
|
||||
|
||||
private fun getNightPreference(): TimePreference {
|
||||
return getTimePreference(R.string.p_date_shortcut_night)
|
||||
}
|
||||
|
||||
private fun getTimePreference(resId: Int): TimePreference {
|
||||
return findPreference(resId) as TimePreference
|
||||
}
|
||||
|
||||
private fun getWeekdayEntries(): Array<String?>? {
|
||||
return arrayOf(
|
||||
getString(R.string.use_locale_default),
|
||||
getWeekdayDisplayName(DayOfWeek.SUNDAY),
|
||||
getWeekdayDisplayName(DayOfWeek.MONDAY)
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package org.tasks.preferences.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import org.tasks.BuildConfig
|
||||
import org.tasks.R
|
||||
import org.tasks.injection.FragmentComponent
|
||||
import org.tasks.injection.InjectingPreferenceFragment
|
||||
|
||||
class MainSettingsFragment : InjectingPreferenceFragment() {
|
||||
override fun inject(component: FragmentComponent) = component.inject(this)
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences, rootKey)
|
||||
|
||||
requires(BuildConfig.DEBUG, R.string.debug)
|
||||
}
|
||||
}
|
@ -0,0 +1,270 @@
|
||||
package org.tasks.preferences.fragments
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Activity.RESULT_OK
|
||||
import android.content.Intent
|
||||
import android.media.RingtoneManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.speech.tts.TextToSpeech
|
||||
import androidx.preference.Preference
|
||||
import com.todoroo.andlib.utility.AndroidUtilities
|
||||
import com.todoroo.astrid.api.Filter
|
||||
import com.todoroo.astrid.voice.VoiceOutputAssistant
|
||||
import org.tasks.LocalBroadcastManager
|
||||
import org.tasks.R
|
||||
import org.tasks.activities.FilterSelectionActivity
|
||||
import org.tasks.activities.TimePickerActivity
|
||||
import org.tasks.injection.FragmentComponent
|
||||
import org.tasks.injection.InjectingPreferenceFragment
|
||||
import org.tasks.preferences.DefaultFilterProvider
|
||||
import org.tasks.preferences.Preferences
|
||||
import org.tasks.receivers.ShortcutBadger
|
||||
import org.tasks.scheduling.NotificationSchedulerIntentService
|
||||
import org.tasks.time.DateTime
|
||||
import org.tasks.ui.TimePreference
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val REQUEST_QUIET_START = 10001
|
||||
private const val REQUEST_QUIET_END = 10002
|
||||
private const val REQUEST_DEFAULT_REMIND = 10003
|
||||
private const val REQUEST_BADGE_LIST = 10004
|
||||
private const val REQUEST_CODE_ALERT_RINGTONE = 10005
|
||||
private const val REQUEST_CODE_TTS_CHECK = 10006
|
||||
|
||||
class Notifications : InjectingPreferenceFragment() {
|
||||
|
||||
@Inject lateinit var preferences: Preferences
|
||||
@Inject lateinit var defaultFilterProvider: DefaultFilterProvider
|
||||
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
|
||||
@Inject lateinit var voiceOutputAssistant: VoiceOutputAssistant
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences_notifications, rootKey)
|
||||
|
||||
rescheduleNotificationsOnChange(
|
||||
R.string.p_rmd_time,
|
||||
R.string.p_rmd_enable_quiet,
|
||||
R.string.p_rmd_quietStart,
|
||||
R.string.p_rmd_quietEnd,
|
||||
R.string.p_rmd_persistent)
|
||||
|
||||
initializeRingtonePreference()
|
||||
initializeTimePreference(getDefaultRemindTimePreference()!!, REQUEST_DEFAULT_REMIND)
|
||||
initializeTimePreference(getQuietStartPreference()!!, REQUEST_QUIET_START)
|
||||
initializeTimePreference(getQuietEndPreference()!!, REQUEST_QUIET_END)
|
||||
|
||||
findPreference(R.string.notification_channel_settings)
|
||||
.setOnPreferenceClickListener(::openNotificationChannelSettings)
|
||||
findPreference(R.string.battery_optimization_settings)
|
||||
.setOnPreferenceClickListener(::openBatteryOptimizationSettings)
|
||||
|
||||
findPreference(R.string.p_bundle_notifications)
|
||||
.setOnPreferenceChangeListener { _: Preference?, _: Any? ->
|
||||
NotificationSchedulerIntentService.enqueueWork(context, true)
|
||||
true
|
||||
}
|
||||
|
||||
findPreference(R.string.p_badges_enabled)
|
||||
.setOnPreferenceChangeListener { _: Preference?, newValue: Any? ->
|
||||
if (newValue != null) {
|
||||
if (newValue as Boolean) {
|
||||
showRestartDialog()
|
||||
} else {
|
||||
ShortcutBadger.removeCount(context)
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
val badgePreference: Preference = findPreference(R.string.p_badge_list)
|
||||
val filter = defaultFilterProvider.badgeFilter
|
||||
badgePreference.summary = filter.listingTitle
|
||||
badgePreference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
val intent = Intent(context, FilterSelectionActivity::class.java)
|
||||
intent.putExtra(
|
||||
FilterSelectionActivity.EXTRA_FILTER, defaultFilterProvider.badgeFilter)
|
||||
intent.putExtra(FilterSelectionActivity.EXTRA_RETURN_FILTER, true)
|
||||
startActivityForResult(intent, REQUEST_BADGE_LIST)
|
||||
true
|
||||
}
|
||||
|
||||
findPreference(R.string.p_voiceRemindersEnabled)
|
||||
.setOnPreferenceChangeListener { preference: Preference, newValue: Any ->
|
||||
val enabled = newValue as Boolean
|
||||
try {
|
||||
if (enabled && !voiceOutputAssistant.isTTSInitialized) {
|
||||
val checkIntent = Intent()
|
||||
checkIntent.action = TextToSpeech.Engine.ACTION_CHECK_TTS_DATA
|
||||
startActivityForResult(checkIntent, REQUEST_CODE_TTS_CHECK)
|
||||
} else if (!enabled && voiceOutputAssistant.isTTSInitialized) {
|
||||
voiceOutputAssistant.shutdown()
|
||||
}
|
||||
} catch (e: VerifyError) {
|
||||
Timber.e(e)
|
||||
preference.isEnabled = false
|
||||
preferences.setBoolean(preference.key, false)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
requires(AndroidUtilities.atLeastOreo(), R.string.notification_channel_settings)
|
||||
requires(AndroidUtilities.atLeastMarshmallow(), R.string.battery_optimization_settings)
|
||||
requires(
|
||||
AndroidUtilities.preOreo(), R.string.p_rmd_ringtone, R.string.p_rmd_vibrate, R.string.p_led_notification)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
voiceOutputAssistant.shutdown()
|
||||
}
|
||||
|
||||
override fun inject(component: FragmentComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
private fun rescheduleNotificationsOnChange(vararg resIds: Int) {
|
||||
for (resId in resIds) {
|
||||
findPreference(resId)
|
||||
.setOnPreferenceChangeListener { _: Preference?, _: Any? ->
|
||||
NotificationSchedulerIntentService.enqueueWork(context, false)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
|
||||
return if (preference!!.key == getString(R.string.p_rmd_ringtone)) {
|
||||
val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER)
|
||||
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION)
|
||||
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true)
|
||||
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true)
|
||||
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, Settings.System.DEFAULT_NOTIFICATION_URI)
|
||||
val existingValue: String? = preferences.getStringValue(R.string.p_rmd_ringtone)
|
||||
if (existingValue != null) {
|
||||
if (existingValue.isEmpty()) {
|
||||
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, null as Uri?)
|
||||
} else {
|
||||
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Uri.parse(existingValue))
|
||||
}
|
||||
} else {
|
||||
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, Settings.System.DEFAULT_NOTIFICATION_URI)
|
||||
}
|
||||
startActivityForResult(intent, REQUEST_CODE_ALERT_RINGTONE)
|
||||
true
|
||||
} else {
|
||||
super.onPreferenceTreeClick(preference)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getQuietStartPreference(): TimePreference? {
|
||||
return getTimePreference(R.string.p_rmd_quietStart)
|
||||
}
|
||||
|
||||
private fun getQuietEndPreference(): TimePreference? {
|
||||
return getTimePreference(R.string.p_rmd_quietEnd)
|
||||
}
|
||||
|
||||
private fun getDefaultRemindTimePreference(): TimePreference? {
|
||||
return getTimePreference(R.string.p_rmd_time)
|
||||
}
|
||||
|
||||
private fun getTimePreference(resId: Int): TimePreference? {
|
||||
return findPreference(getString(resId)) as TimePreference?
|
||||
}
|
||||
|
||||
private fun initializeTimePreference(preference: TimePreference, requestCode: Int) {
|
||||
preference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
val current = DateTime().withMillisOfDay(preference.millisOfDay)
|
||||
val intent = Intent(context, TimePickerActivity::class.java)
|
||||
intent.putExtra(TimePickerActivity.EXTRA_TIMESTAMP, current.millis)
|
||||
startActivityForResult(intent, requestCode)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeRingtonePreference() {
|
||||
val ringtoneChangedListener = Preference.OnPreferenceChangeListener { preference: Preference, value: Any? ->
|
||||
if ("" == value) {
|
||||
preference.setSummary(R.string.silent)
|
||||
} else {
|
||||
val ringtone = RingtoneManager.getRingtone(
|
||||
context,
|
||||
if (value == null) Settings.System.DEFAULT_NOTIFICATION_URI else Uri.parse(value as String?))
|
||||
preference.summary = if (ringtone == null) "" else ringtone.getTitle(context)
|
||||
}
|
||||
true
|
||||
}
|
||||
val ringtoneKey = R.string.p_rmd_ringtone
|
||||
val ringtonePreference: Preference = findPreference(ringtoneKey)
|
||||
ringtonePreference.onPreferenceChangeListener = ringtoneChangedListener
|
||||
ringtoneChangedListener.onPreferenceChange(
|
||||
ringtonePreference,
|
||||
preferences.getStringValue(ringtoneKey))
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
private fun openNotificationChannelSettings(@Suppress("UNUSED_PARAMETER") ignored: Preference): Boolean {
|
||||
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
|
||||
intent.putExtra(Settings.EXTRA_APP_PACKAGE, activity!!.packageName)
|
||||
startActivity(intent)
|
||||
return true
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
private fun openBatteryOptimizationSettings(@Suppress("UNUSED_PARAMETER") ignored: Preference): Boolean {
|
||||
val intent = Intent()
|
||||
intent.action = Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
|
||||
startActivity(intent)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == REQUEST_CODE_ALERT_RINGTONE) {
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
val ringtone: Uri? = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI)
|
||||
if (ringtone != null) {
|
||||
preferences.setString(R.string.p_rmd_ringtone, ringtone.toString())
|
||||
} else {
|
||||
preferences.setString(R.string.p_rmd_ringtone, "")
|
||||
}
|
||||
initializeRingtonePreference()
|
||||
}
|
||||
} else if (requestCode == REQUEST_QUIET_START) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
getQuietStartPreference()!!.handleTimePickerActivityIntent(data)
|
||||
}
|
||||
} else if (requestCode == REQUEST_QUIET_END) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
getQuietEndPreference()!!.handleTimePickerActivityIntent(data)
|
||||
}
|
||||
} else if (requestCode == REQUEST_DEFAULT_REMIND) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
getDefaultRemindTimePreference()!!.handleTimePickerActivityIntent(data)
|
||||
}
|
||||
} else if (requestCode == REQUEST_BADGE_LIST) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
val filter: Filter = data!!.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER)!!
|
||||
defaultFilterProvider.badgeFilter = filter
|
||||
findPreference(R.string.p_badge_list).summary = filter.listingTitle
|
||||
localBroadcastManager.broadcastRefresh()
|
||||
}
|
||||
} else if (requestCode == REQUEST_CODE_TTS_CHECK) {
|
||||
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) { // success, create the TTS instance
|
||||
voiceOutputAssistant.initTTS()
|
||||
} else { // missing data, install it
|
||||
val installIntent = Intent()
|
||||
installIntent.action = TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA
|
||||
startActivity(installIntent)
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
package org.tasks.preferences.fragments
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceCategory
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import com.google.common.base.Strings
|
||||
import com.todoroo.andlib.utility.DateUtilities
|
||||
import com.todoroo.astrid.gtasks.auth.GtasksLoginActivity
|
||||
import com.todoroo.astrid.service.TaskDeleter
|
||||
import org.tasks.R
|
||||
import org.tasks.caldav.CaldavAccountSettingsActivity
|
||||
import org.tasks.data.CaldavAccount
|
||||
import org.tasks.data.CaldavDao
|
||||
import org.tasks.data.GoogleTaskAccount
|
||||
import org.tasks.data.GoogleTaskListDao
|
||||
import org.tasks.etesync.EteSyncAccountSettingsActivity
|
||||
import org.tasks.injection.FragmentComponent
|
||||
import org.tasks.injection.InjectingPreferenceFragment
|
||||
import org.tasks.jobs.WorkManager
|
||||
import org.tasks.preferences.Preferences
|
||||
import org.tasks.sync.AddAccountDialog
|
||||
import org.tasks.ui.Toaster
|
||||
import javax.inject.Inject
|
||||
|
||||
const val REQUEST_CALDAV_SETTINGS = 10013
|
||||
const val REQUEST_GOOGLE_TASKS = 10014
|
||||
|
||||
class Synchronization : InjectingPreferenceFragment() {
|
||||
|
||||
@Inject lateinit var workManager: WorkManager
|
||||
@Inject lateinit var preferences: Preferences
|
||||
@Inject lateinit var toaster: Toaster
|
||||
@Inject lateinit var caldavDao: CaldavDao
|
||||
@Inject lateinit var googleTaskListDao: GoogleTaskListDao
|
||||
@Inject lateinit var taskDeleter: TaskDeleter
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences_synchronization, rootKey)
|
||||
|
||||
findPreference(R.string.p_background_sync_unmetered_only)
|
||||
.setOnPreferenceChangeListener { _: Preference?, o: Any? ->
|
||||
workManager.updateBackgroundSync(null, null, o as Boolean?)
|
||||
true
|
||||
}
|
||||
findPreference(R.string.p_background_sync)
|
||||
.setOnPreferenceChangeListener { _: Preference?, o: Any? ->
|
||||
workManager.updateBackgroundSync(null, o as Boolean?, null)
|
||||
true
|
||||
}
|
||||
|
||||
val positionHack = findPreference(R.string.google_tasks_position_hack) as SwitchPreferenceCompat
|
||||
positionHack.isChecked = preferences.isPositionHackEnabled
|
||||
positionHack.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any? ->
|
||||
if (newValue == null) {
|
||||
false
|
||||
} else {
|
||||
preferences.setLong(
|
||||
R.string.p_google_tasks_position_hack, if (newValue as Boolean) DateUtilities.now() else 0)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
findPreference(R.string.add_account)
|
||||
.setOnPreferenceClickListener {
|
||||
AddAccountDialog.showAddAccountDialog(activity, dialogBuilder)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
refresh()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == REQUEST_CALDAV_SETTINGS) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
workManager.updateBackgroundSync()
|
||||
}
|
||||
} else if (requestCode == REQUEST_GOOGLE_TASKS) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
workManager.updateBackgroundSync()
|
||||
} else if (data != null) {
|
||||
toaster.longToast(data.getStringExtra(GtasksLoginActivity.EXTRA_ERROR))
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addGoogleTasksAccounts(category: PreferenceCategory): Boolean {
|
||||
val accounts: List<GoogleTaskAccount> = googleTaskListDao.accounts
|
||||
for (googleTaskAccount in accounts) {
|
||||
val account = googleTaskAccount.account
|
||||
val preference = Preference(context)
|
||||
preference.title = account
|
||||
val error = googleTaskAccount.error
|
||||
if (Strings.isNullOrEmpty(error)) {
|
||||
preference.setSummary(R.string.gtasks_GPr_header)
|
||||
} else {
|
||||
preference.summary = error
|
||||
}
|
||||
preference.setOnPreferenceClickListener {
|
||||
dialogBuilder
|
||||
.newDialog(account)
|
||||
.setItems(listOf(getString(R.string.reinitialize_account), getString(R.string.logout))) { _, which ->
|
||||
if (which == 0) {
|
||||
startActivityForResult(
|
||||
Intent(context, GtasksLoginActivity::class.java),
|
||||
REQUEST_GOOGLE_TASKS)
|
||||
} else {
|
||||
logoutConfirmation(googleTaskAccount)
|
||||
}
|
||||
}
|
||||
.showThemedListView()
|
||||
false
|
||||
}
|
||||
category.addPreference(preference)
|
||||
}
|
||||
return accounts.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun addCaldavAccounts(category: PreferenceCategory): Boolean {
|
||||
val accounts: List<CaldavAccount> = caldavDao.accounts
|
||||
for (account in accounts) {
|
||||
val preference = Preference(context)
|
||||
preference.title = account.name
|
||||
val error = account.error
|
||||
if (Strings.isNullOrEmpty(error)) {
|
||||
preference.setSummary(
|
||||
if (account.isCaldavAccount) R.string.caldav else R.string.etesync)
|
||||
} else {
|
||||
preference.summary = error
|
||||
}
|
||||
preference.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
val intent = Intent(
|
||||
context,
|
||||
if (account.isCaldavAccount) CaldavAccountSettingsActivity::class.java
|
||||
else EteSyncAccountSettingsActivity::class.java)
|
||||
intent.putExtra(CaldavAccountSettingsActivity.EXTRA_CALDAV_DATA, account)
|
||||
startActivityForResult(intent, REQUEST_CALDAV_SETTINGS)
|
||||
false
|
||||
}
|
||||
category.addPreference(preference)
|
||||
}
|
||||
return accounts.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun logoutConfirmation(account: GoogleTaskAccount) {
|
||||
val name = account.account
|
||||
val alertDialog = dialogBuilder
|
||||
.newDialog()
|
||||
.setMessage(R.string.logout_warning, name)
|
||||
.setPositiveButton(R.string.logout) { _, _ ->
|
||||
taskDeleter.delete(account)
|
||||
refresh()
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
alertDialog.setCanceledOnTouchOutside(false)
|
||||
alertDialog.setCancelable(false)
|
||||
alertDialog.show()
|
||||
}
|
||||
|
||||
private fun refresh() {
|
||||
val synchronizationPreferences = findPreference(R.string.accounts) as PreferenceCategory
|
||||
synchronizationPreferences.removeAll()
|
||||
|
||||
val hasGoogleAccounts: Boolean = addGoogleTasksAccounts(synchronizationPreferences)
|
||||
val hasCaldavAccounts = addCaldavAccounts(synchronizationPreferences)
|
||||
findPreference(R.string.gtasks_GPr_header).isVisible = hasGoogleAccounts
|
||||
findPreference(R.string.accounts).isVisible = hasGoogleAccounts || hasCaldavAccounts
|
||||
findPreference(R.string.sync_SPr_interval_title).isVisible = hasGoogleAccounts || hasCaldavAccounts
|
||||
}
|
||||
|
||||
override fun inject(component: FragmentComponent) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package org.tasks.preferences.fragments
|
||||
|
||||
import android.app.Activity.RESULT_OK
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.preference.Preference
|
||||
import com.todoroo.astrid.api.CaldavFilter
|
||||
import com.todoroo.astrid.api.Filter
|
||||
import com.todoroo.astrid.api.GtasksFilter
|
||||
import org.tasks.PermissionUtil
|
||||
import org.tasks.R
|
||||
import org.tasks.activities.CalendarSelectionActivity
|
||||
import org.tasks.activities.RemoteListPicker
|
||||
import org.tasks.calendars.CalendarProvider
|
||||
import org.tasks.injection.FragmentComponent
|
||||
import org.tasks.injection.InjectingPreferenceFragment
|
||||
import org.tasks.preferences.DefaultFilterProvider
|
||||
import org.tasks.preferences.FragmentPermissionRequestor
|
||||
import org.tasks.preferences.PermissionRequestor
|
||||
import org.tasks.preferences.Preferences
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val FRAG_TAG_REMOTE_LIST_SELECTION = "frag_tag_remote_list_selection"
|
||||
private const val REQUEST_REMOTE_LIST = 10010
|
||||
private const val REQUEST_CALENDAR_SELECTION = 10011
|
||||
|
||||
class TaskDefaults : InjectingPreferenceFragment() {
|
||||
|
||||
@Inject lateinit var permissionRequester: FragmentPermissionRequestor
|
||||
@Inject lateinit var defaultFilterProvider: DefaultFilterProvider
|
||||
@Inject lateinit var preferences: Preferences
|
||||
@Inject lateinit var calendarProvider: CalendarProvider
|
||||
|
||||
private lateinit var defaultCalendarPref: Preference
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences_task_defaults, rootKey)
|
||||
|
||||
defaultCalendarPref = findPreference(R.string.gcal_p_default)
|
||||
defaultCalendarPref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
if (permissionRequester.requestCalendarPermissions()) {
|
||||
startCalendarSelectionActivity()
|
||||
}
|
||||
false
|
||||
}
|
||||
val defaultCalendarName: String? = getDefaultCalendarName()
|
||||
defaultCalendarPref.summary = defaultCalendarName
|
||||
?: getString(R.string.dont_add_to_calendar)
|
||||
|
||||
findPreference(R.string.p_default_remote_list)
|
||||
.setOnPreferenceClickListener {
|
||||
RemoteListPicker.newRemoteListSupportPicker(defaultFilterProvider.defaultRemoteList, this, REQUEST_REMOTE_LIST)
|
||||
.show(fragmentManager!!, FRAG_TAG_REMOTE_LIST_SELECTION)
|
||||
false
|
||||
}
|
||||
updateRemoteListSummary()
|
||||
|
||||
requires(device.supportsGeofences(), R.string.p_default_location_reminder_key)
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
if (requestCode == PermissionRequestor.REQUEST_CALENDAR) {
|
||||
if (PermissionUtil.verifyPermissions(grantResults)) {
|
||||
startCalendarSelectionActivity()
|
||||
}
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == REQUEST_REMOTE_LIST) {
|
||||
val list: Filter? = data!!.getParcelableExtra(RemoteListPicker.EXTRA_SELECTED_FILTER)
|
||||
if (list == null) {
|
||||
preferences.setString(R.string.p_default_remote_list, null)
|
||||
} else if (list is GtasksFilter || list is CaldavFilter) {
|
||||
defaultFilterProvider.defaultRemoteList = list
|
||||
} else {
|
||||
throw RuntimeException("Unhandled filter type")
|
||||
}
|
||||
updateRemoteListSummary()
|
||||
} else if (requestCode == REQUEST_CALENDAR_SELECTION) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
preferences.setString(
|
||||
R.string.gcal_p_default,
|
||||
data!!.getStringExtra(CalendarSelectionActivity.EXTRA_CALENDAR_ID))
|
||||
defaultCalendarPref.summary = data.getStringExtra(CalendarSelectionActivity.EXTRA_CALENDAR_NAME)
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDefaultCalendarName(): String? {
|
||||
val calendarId = preferences.getStringValue(R.string.gcal_p_default)
|
||||
return calendarProvider.getCalendar(calendarId)?.name
|
||||
}
|
||||
|
||||
private fun startCalendarSelectionActivity() {
|
||||
val intent = Intent(context, CalendarSelectionActivity::class.java)
|
||||
intent.putExtra(CalendarSelectionActivity.EXTRA_CALENDAR_NAME, getDefaultCalendarName())
|
||||
startActivityForResult(intent, REQUEST_CALENDAR_SELECTION)
|
||||
}
|
||||
|
||||
private fun updateRemoteListSummary() {
|
||||
val defaultFilter = defaultFilterProvider.defaultRemoteList
|
||||
findPreference(R.string.p_default_remote_list).summary =
|
||||
if (defaultFilter == null) getString(R.string.dont_sync)
|
||||
else defaultFilter.listingTitle
|
||||
}
|
||||
|
||||
override fun inject(component: FragmentComponent) {
|
||||
component.inject(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M19,19H5V5h7V3H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2v7zM14,3v2h3.59l-9.83,9.83 1.41,1.41L19,6.41V10h2V3h-7z"/>
|
||||
</vector>
|
@ -0,0 +1,5 @@
|
||||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M14.06,9.02l0.92,0.92L5.92,19L5,19v-0.92l9.06,-9.06M17.66,3c-0.25,0 -0.51,0.1 -0.7,0.29l-1.83,1.83 3.75,3.75 1.83,-1.83c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.2,-0.2 -0.45,-0.29 -0.71,-0.29zM14.06,6.19L3,17.25L3,21h3.75L17.81,9.94l-3.75,-3.75z"/>
|
||||
</vector>
|
@ -0,0 +1,5 @@
|
||||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||
</vector>
|
@ -0,0 +1,9 @@
|
||||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,22C6.49,22 2,17.51 2,12S6.49,2 12,2s10,4.04 10,9c0,3.31 -2.69,6 -6,6h-1.77c-0.28,0 -0.5,0.22 -0.5,0.5 0,0.12 0.05,0.23 0.13,0.33 0.41,0.47 0.64,1.06 0.64,1.67 0,1.38 -1.12,2.5 -2.5,2.5zM12,4c-4.41,0 -8,3.59 -8,8s3.59,8 8,8c0.28,0 0.5,-0.22 0.5,-0.5 0,-0.16 -0.08,-0.28 -0.14,-0.35 -0.41,-0.46 -0.63,-1.05 -0.63,-1.65 0,-1.38 1.12,-2.5 2.5,-2.5L16,15c2.21,0 4,-1.79 4,-4 0,-3.86 -3.59,-7 -8,-7z"/>
|
||||
<path android:fillColor="#FF000000" android:pathData="M6.5,11.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
|
||||
<path android:fillColor="#FF000000" android:pathData="M9.5,7.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
|
||||
<path android:fillColor="#FF000000" android:pathData="M14.5,7.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
|
||||
<path android:fillColor="#FF000000" android:pathData="M17.5,11.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
|
||||
</vector>
|
@ -0,0 +1,5 @@
|
||||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M18,4v16L6,20L6,8.83L10.83,4L18,4m0,-2h-8L4,8v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,4c0,-1.1 -0.9,-2 -2,-2zM9,7h2v4L9,11zM12,7h2v4h-2zM15,7h2v4h-2z"/>
|
||||
</vector>
|
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/toolbar"/>
|
||||
|
||||
</LinearLayout>
|
@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.rey.material.widget.Slider xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/slider"
|
||||
style="@style/Material.Widget.Slider.Discrete"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/keyline_first"
|
||||
android:paddingEnd="@dimen/keyline_first"
|
||||
android:paddingLeft="@dimen/keyline_first"
|
||||
android:paddingRight="@dimen/keyline_first"
|
||||
android:gravity="center"
|
||||
android:minHeight="?attr/listPreferredItemHeight"
|
||||
app:sl_discreteMode="true"
|
||||
app:sl_stepValue="2"
|
||||
app:sl_travelAnimDuration="100"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/min"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@id/slider"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingStart="@dimen/keyline_first"
|
||||
android:paddingEnd="@dimen/keyline_first"
|
||||
android:paddingLeft="@dimen/keyline_first"
|
||||
android:paddingRight="@dimen/keyline_first"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/max"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/slider"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingStart="@dimen/keyline_first"
|
||||
android:paddingEnd="@dimen/keyline_first"
|
||||
android:paddingLeft="@dimen/keyline_first"
|
||||
android:paddingRight="@dimen/keyline_first"/>
|
||||
|
||||
</RelativeLayout>
|
@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.rey.material.widget.Slider xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/slider"
|
||||
style="@style/Material.Widget.Slider.Discrete"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/keyline_first"
|
||||
android:paddingEnd="@dimen/keyline_first"
|
||||
android:paddingLeft="@dimen/keyline_first"
|
||||
android:paddingRight="@dimen/keyline_first"
|
||||
android:gravity="center"
|
||||
android:minHeight="?attr/listPreferredItemHeight"
|
||||
app:sl_discreteMode="true"
|
||||
app:sl_stepValue="5"
|
||||
app:sl_travelAnimDuration="100"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/min"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@id/slider"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingStart="@dimen/keyline_first"
|
||||
android:paddingEnd="@dimen/keyline_first"
|
||||
android:paddingLeft="@dimen/keyline_first"
|
||||
android:paddingRight="@dimen/keyline_first"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/max"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/slider"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingStart="@dimen/keyline_first"
|
||||
android:paddingEnd="@dimen/keyline_first"
|
||||
android:paddingLeft="@dimen/keyline_first"
|
||||
android:paddingRight="@dimen/keyline_first"/>
|
||||
|
||||
</RelativeLayout>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue