From 7ece10726f7ee6f1bcf4aaf3b5545a92708ed479 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Thu, 28 Sep 2017 14:11:32 -0500 Subject: [PATCH] Populate recurrence picker with existing settings --- .../java/com/todoroo/astrid/data/Task.java | 6 +- .../astrid/repeats/RepeatControlSet.java | 297 ++++++------------ .../tasks/repeats/CustomRecurrenceDialog.java | 149 +++++---- .../main/java/org/tasks/time/DateTime.java | 15 + 4 files changed, 219 insertions(+), 248 deletions(-) diff --git a/app/src/main/java/com/todoroo/astrid/data/Task.java b/app/src/main/java/com/todoroo/astrid/data/Task.java index 933a3747a..13c40c132 100644 --- a/app/src/main/java/com/todoroo/astrid/data/Task.java +++ b/app/src/main/java/com/todoroo/astrid/data/Task.java @@ -386,7 +386,11 @@ public class Task extends RemoteModel { } public String sanitizedRecurrence() { - return getRecurrence().replaceAll("BYDAY=;", "").replaceAll(";?FROM=[^;]*", ""); //$NON-NLS-1$//$NON-NLS-2$ + return getRecurrenceWithoutFrom().replaceAll("BYDAY=;", ""); //$NON-NLS-1$//$NON-NLS-2$ + } + + public String getRecurrenceWithoutFrom() { + return getRecurrence().replaceAll(";?FROM=[^;]*", ""); } /** diff --git a/app/src/main/java/com/todoroo/astrid/repeats/RepeatControlSet.java b/app/src/main/java/com/todoroo/astrid/repeats/RepeatControlSet.java index 8e0d757d6..adf595737 100644 --- a/app/src/main/java/com/todoroo/astrid/repeats/RepeatControlSet.java +++ b/app/src/main/java/com/todoroo/astrid/repeats/RepeatControlSet.java @@ -24,7 +24,6 @@ import android.widget.TextView; import com.google.common.base.Joiner; import com.google.common.base.Strings; -import com.google.common.primitives.Booleans; import com.google.ical.values.Frequency; import com.google.ical.values.RRule; import com.google.ical.values.Weekday; @@ -49,7 +48,6 @@ import java.text.DateFormatSymbols; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Calendar; import java.util.List; import javax.inject.Inject; @@ -57,11 +55,15 @@ import javax.inject.Inject; import butterknife.BindView; import butterknife.OnClick; import butterknife.OnItemSelected; -import timber.log.Timber; import static android.support.v4.content.ContextCompat.getColor; -import static com.google.common.collect.Iterables.any; import static com.google.common.collect.Lists.newArrayList; +import static com.google.ical.values.Frequency.DAILY; +import static com.google.ical.values.Frequency.HOURLY; +import static com.google.ical.values.Frequency.MINUTELY; +import static com.google.ical.values.Frequency.MONTHLY; +import static com.google.ical.values.Frequency.WEEKLY; +import static com.google.ical.values.Frequency.YEARLY; import static org.tasks.repeats.CustomRecurrenceDialog.newCustomRecurrenceDialog; /** @@ -74,15 +76,12 @@ public class RepeatControlSet extends TaskEditControlFragment implements CustomRecurrenceDialog.CustomRecurrenceCallback { public static final int TAG = R.string.TEA_ctrl_repeat_pref; + public static final List WEEKDAYS = Arrays.asList(Weekday.values()); private static final String FRAG_TAG_CUSTOM_RECURRENCE = "frag_tag_custom_recurrence"; @Override - public void onSelected(int frequency, int interval, long repeatUntilValue, boolean[] isChecked) { - doRepeat = true; - this.interval = interval; - this.frequency = frequency; - this.repeatUntilValue = repeatUntilValue; - this.isChecked = isChecked; + public void onSelected(RRule rrule) { + this.rrule = rrule; refreshDisplayView(); } @@ -91,23 +90,10 @@ public class RepeatControlSet extends TaskEditControlFragment } private static final String EXTRA_RECURRENCE = "extra_recurrence"; - private static final String EXTRA_REPEAT_UNTIL = "extra_repeat_until"; private static final String EXTRA_REPEAT_AFTER_COMPLETION = "extra_repeat_after_completion"; - // --- spinner constants - - public static final int FREQUENCY_MINUTES = 0; - public static final int FREQUENCY_HOURS = 1; - public static final int FREQUENCY_DAYS = 2; - public static final int FREQUENCY_WEEKS = 3; - public static final int FREQUENCY_MONTHS = 4; - public static final int FREQUENCY_YEARS = 5; - - public static final int TYPE_DUE_DATE = 0; - public static final int TYPE_COMPLETION_DATE = 1; - - //private final CheckBox enabled; - private boolean doRepeat = false; + public static final int TYPE_DUE_DATE = 1; + public static final int TYPE_COMPLETION_DATE = 2; @Inject DialogBuilder dialogBuilder; @Inject Preferences preferences; @@ -119,12 +105,7 @@ public class RepeatControlSet extends TaskEditControlFragment @BindView(R.id.repeatType) Spinner typeSpinner; @BindView(R.id.repeatTypeContainer) LinearLayout repeatTypeContainer; - private String recurrence; - private int interval; - private int frequency; - private long repeatUntilValue; - private boolean[] isChecked; - private final Weekday[] weekdays = new Weekday[7]; + private RRule rrule; private final List repeatTypes = new ArrayList<>(); private HiddenTopArrayAdapter typeAdapter; @@ -137,8 +118,16 @@ public class RepeatControlSet extends TaskEditControlFragment public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); if (savedInstanceState != null) { - recurrence = savedInstanceState.getString(EXTRA_RECURRENCE); - repeatUntilValue = savedInstanceState.getLong(EXTRA_REPEAT_UNTIL); + String recurrence = savedInstanceState.getString(EXTRA_RECURRENCE); + if (Strings.isNullOrEmpty(recurrence)) { + rrule = null; + } else { + try { + rrule = new RRule(recurrence); + } catch (ParseException e) { + rrule = null; + } + } repeatAfterCompletion = savedInstanceState.getBoolean(EXTRA_REPEAT_AFTER_COMPLETION); } @@ -165,60 +154,12 @@ public class RepeatControlSet extends TaskEditControlFragment typeSpinner.setAdapter(typeAdapter); typeSpinner.setSelection(repeatAfterCompletion ? TYPE_COMPLETION_DATE : TYPE_DUE_DATE); - Calendar calendar = Calendar.getInstance(); - calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek()); - for(int i = 0; i < 7; i++) { - int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); - weekdays[i] = Weekday.values()[dayOfWeek - 1]; - calendar.add(Calendar.DATE, 1); - } - - doRepeat = !Strings.isNullOrEmpty(recurrence); - if (doRepeat) { - try { - RRule rrule = new RRule(recurrence); - interval = rrule.getInterval(); - isChecked = new boolean[7]; - for (WeekdayNum day : rrule.getByDay()) { - for (int i = 0 ; i < 7 ; i++) { - if (weekdays[i].equals(day.wday)) { - isChecked[i] = true; - } - } - } - switch (rrule.getFreq()) { - case DAILY: - frequency = FREQUENCY_DAYS; - break; - case WEEKLY: - frequency = FREQUENCY_WEEKS; - break; - case MONTHLY: - frequency = FREQUENCY_MONTHS; - break; - case HOURLY: - frequency = FREQUENCY_HOURS; - break; - case MINUTELY: - frequency = FREQUENCY_MINUTES; - break; - case YEARLY: - frequency = FREQUENCY_YEARS; - break; - - } - } catch (ParseException e) { - recurrence = ""; - Timber.e(e, e.getMessage()); - } - - } refreshDisplayView(); return view; } @OnItemSelected(R.id.repeatType) - public void onRepeatTypeChanged(Spinner spinner, int position) { + public void onRepeatTypeChanged(int position) { repeatAfterCompletion = position == TYPE_COMPLETION_DATE; repeatTypes.set(0, repeatAfterCompletion ? repeatTypes.get(2) : repeatTypes.get(1)); typeAdapter.notifyDataSetChanged(); @@ -228,8 +169,7 @@ public class RepeatControlSet extends TaskEditControlFragment public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - outState.putString(EXTRA_RECURRENCE, getRecurrence()); - outState.putLong(EXTRA_REPEAT_UNTIL, repeatUntilValue); + outState.putString(EXTRA_RECURRENCE, rrule == null ? "" : rrule.toIcal()); outState.putBoolean(EXTRA_REPEAT_AFTER_COMPLETION, repeatAfterCompletion); } @@ -246,14 +186,15 @@ public class RepeatControlSet extends TaskEditControlFragment } private boolean isCustomValue() { - if (!doRepeat) { + if (rrule == null) { return false; } - return frequency == FREQUENCY_WEEKS && any(Booleans.asList(isChecked), b -> b) || - frequency == FREQUENCY_HOURS || - frequency == FREQUENCY_MINUTES || - repeatUntilValue != 0 || - interval != 1; + Frequency frequency = rrule.getFreq(); + return frequency == WEEKLY && !rrule.getByDay().isEmpty() || + frequency == HOURLY || + frequency == MINUTELY || + rrule.getUntil() != null || + rrule.getInterval() != 1; } @OnClick(R.id.display_row_edit) @@ -264,21 +205,21 @@ public class RepeatControlSet extends TaskEditControlFragment if (customPicked) { adapter.insert(getRepeatString(), 0); adapter.setChecked(0); - } else if (!doRepeat) { + } else if (rrule == null) { adapter.setChecked(0); } else { int selected; - switch(frequency) { - case FREQUENCY_DAYS: + switch (rrule.getFreq()) { + case DAILY: selected = 1; break; - case FREQUENCY_WEEKS: + case WEEKLY: selected = 2; break; - case FREQUENCY_MONTHS: + case MONTHLY: selected = 3; break; - case FREQUENCY_YEARS: + case YEARLY: selected = 4; break; default: @@ -296,35 +237,33 @@ public class RepeatControlSet extends TaskEditControlFragment i--; } if (i == 0) { - doRepeat = false; + rrule = null; } else if (i == 5) { - newCustomRecurrenceDialog(this) + newCustomRecurrenceDialog(this, rrule) .show(getFragmentManager(), FRAG_TAG_CUSTOM_RECURRENCE); return; } else { - doRepeat = true; + rrule = new RRule(); + rrule.setInterval(1); repeatAfterCompletion = false; - interval = 1; - repeatUntilValue = 0; switch (i) { case 1: - frequency = FREQUENCY_DAYS; + rrule.setFreq(DAILY); break; case 2: - frequency = FREQUENCY_WEEKS; - isChecked = new boolean[7]; + rrule.setFreq(WEEKLY); break; case 3: - frequency = FREQUENCY_MONTHS; + rrule.setFreq(MONTHLY); break; case 4: - frequency = FREQUENCY_YEARS; + rrule.setFreq(YEARLY); break; } } - callback.repeatChanged(doRepeat); + callback.repeatChanged(rrule != null); refreshDisplayView(); }) @@ -350,24 +289,38 @@ public class RepeatControlSet extends TaskEditControlFragment @Override public void initialize(boolean isNewTask, Task task) { repeatAfterCompletion = task.repeatAfterCompletion(); - recurrence = task.sanitizedRecurrence(); - repeatUntilValue = task.getRepeatUntil(); + try { + rrule = new RRule(task.getRecurrenceWithoutFrom()); + rrule.setUntil(new DateTime(task.getRepeatUntil()).toDateValue()); + } catch (ParseException e) { + rrule = null; + } } @Override public boolean hasChanges(Task original) { - return !getRecurrenceValue().equals(original.getRecurrence()) || repeatUntilValue != original.getRepeatUntil(); + return !getRecurrenceValue().equals(original.getRecurrence()) || + original.getRepeatUntil() != (rrule == null ? 0 : DateTime.from(rrule.getUntil()).getMillis()); } @Override public void apply(Task task) { + task.setRepeatUntil(rrule == null ? 0 : DateTime.from(rrule.getUntil()).getMillis()); task.setRecurrence(getRecurrenceValue()); - task.setRepeatUntil(repeatUntilValue); } private String getRecurrenceValue() { - String result = getRecurrence(); - + if (rrule == null) { + return ""; + } + RRule copy; + try { + copy = new RRule(rrule.toIcal()); + } catch (ParseException e) { + return ""; + } + copy.setUntil(null); + String result = copy.toIcal(); if (repeatAfterCompletion && !TextUtils.isEmpty(result)) { result += ";FROM=COMPLETION"; //$NON-NLS-1$ } @@ -375,90 +328,50 @@ public class RepeatControlSet extends TaskEditControlFragment return result; } - private String getRecurrence() { - String result; - if(!doRepeat) { - result = ""; //$NON-NLS-1$ - } else { - RRule rrule = new RRule(); - rrule.setInterval(interval); - switch(frequency) { - case FREQUENCY_DAYS: - rrule.setFreq(Frequency.DAILY); - break; - case FREQUENCY_WEEKS: { - rrule.setFreq(Frequency.WEEKLY); - - ArrayList days = new ArrayList<>(); - for (int i = 0 ; i < isChecked.length ; i++) { - if (isChecked[i]) { - days.add(new WeekdayNum(0, weekdays[i])); - } - } - rrule.setByDay(days); - break; - } - case FREQUENCY_MONTHS: - rrule.setFreq(Frequency.MONTHLY); - break; - case FREQUENCY_HOURS: - rrule.setFreq(Frequency.HOURLY); - break; - case FREQUENCY_MINUTES: - rrule.setFreq(Frequency.MINUTELY); - break; - case FREQUENCY_YEARS: - rrule.setFreq(Frequency.YEARLY); - break; - } - - result = rrule.toIcal(); - } - - return result; - } - private void refreshDisplayView() { - if (doRepeat) { - displayView.setText(getRepeatString()); - displayView.setTextColor(getColor(context, R.color.text_primary)); - repeatTypeContainer.setVisibility(View.VISIBLE); - } else { + if (rrule == null) { displayView.setText(R.string.repeat_option_does_not_repeat); displayView.setTextColor(getColor(context, R.color.text_tertiary)); repeatTypeContainer.setVisibility(View.GONE); + } else { + displayView.setText(getRepeatString()); + displayView.setTextColor(getColor(context, R.color.text_primary)); + repeatTypeContainer.setVisibility(View.VISIBLE); } } private String getRepeatString() { + int interval = rrule.getInterval(); + Frequency frequency = rrule.getFreq(); + DateTime repeatUntil = rrule.getUntil() == null ? null : DateTime.from(rrule.getUntil()); if (interval == 1) { String frequencyString = getString(getSingleFrequencyResource(frequency)); - if (frequency == FREQUENCY_WEEKS && any(Booleans.asList(isChecked), b -> b)) { + if (frequency == WEEKLY && !rrule.getByDay().isEmpty()) { String dayString = getDayString(); - if (repeatUntilValue > 0) { - return getString(R.string.repeats_single_on_until, frequencyString, dayString, DateUtilities.getLongDateString(new DateTime(repeatUntilValue))); - } else { + if (repeatUntil == null) { return getString(R.string.repeats_single_on, frequencyString, dayString); + } else { + return getString(R.string.repeats_single_on_until, frequencyString, dayString, DateUtilities.getLongDateString(repeatUntil)); } - } else if (repeatUntilValue > 0) { - return getString(R.string.repeats_single_until, frequencyString, DateUtilities.getLongDateString(new DateTime(repeatUntilValue))); - } else { + } else if (repeatUntil == null) { return getString(R.string.repeats_single, frequencyString); + } else { + return getString(R.string.repeats_single_until, frequencyString, DateUtilities.getLongDateString(repeatUntil)); } } else { int plural = getFrequencyPlural(frequency); String frequencyPlural = getResources().getQuantityString(plural, interval, interval); - if (frequency == FREQUENCY_WEEKS && any(Booleans.asList(isChecked), b -> b)) { + if (frequency == WEEKLY && !rrule.getByDay().isEmpty()) { String dayString = getDayString(); - if (repeatUntilValue > 0) { - return getString(R.string.repeats_plural_on_until, frequencyPlural, dayString, DateUtilities.getLongDateString(new DateTime(repeatUntilValue))); - } else { + if (repeatUntil == null) { return getString(R.string.repeats_plural_on, frequencyPlural, dayString); + } else { + return getString(R.string.repeats_plural_on_until, frequencyPlural, dayString, DateUtilities.getLongDateString(repeatUntil)); } - } else if (repeatUntilValue > 0) { - return getString(R.string.repeats_plural_until, frequencyPlural, DateUtilities.getLongDateString(new DateTime(repeatUntilValue))); - } else { + } else if (repeatUntil == null) { return getString(R.string.repeats_plural, frequencyPlural); + } else { + return getString(R.string.repeats_plural_until, frequencyPlural, DateUtilities.getLongDateString(repeatUntil)); } } } @@ -467,46 +380,44 @@ public class RepeatControlSet extends TaskEditControlFragment DateFormatSymbols dfs = new DateFormatSymbols(locale.getLocale()); String[] shortWeekdays = dfs.getShortWeekdays(); List days = new ArrayList<>(); - for (int i = 0 ; i < 7 ; i++) { - if (isChecked[i]) { - days.add(shortWeekdays[i + 1]); - } + for (WeekdayNum weekday : rrule.getByDay()) { + days.add(shortWeekdays[WEEKDAYS.indexOf(weekday.wday) + 1]); } return Joiner.on(getString(R.string.list_separator_with_space)).join(days); } - private int getSingleFrequencyResource(int frequency) { + private int getSingleFrequencyResource(Frequency frequency) { switch (frequency) { - case FREQUENCY_MINUTES: + case MINUTELY: return R.string.repeats_minutely; - case FREQUENCY_HOURS: + case HOURLY: return R.string.repeats_hourly; - case FREQUENCY_DAYS: + case DAILY: return R.string.repeats_daily; - case FREQUENCY_WEEKS: + case WEEKLY: return R.string.repeats_weekly; - case FREQUENCY_MONTHS: + case MONTHLY: return R.string.repeats_monthly; - case FREQUENCY_YEARS: + case YEARLY: return R.string.repeats_yearly; default: throw new RuntimeException("Invalid frequency: " + frequency); } } - private int getFrequencyPlural(int frequency) { + private int getFrequencyPlural(Frequency frequency) { switch (frequency) { - case FREQUENCY_MINUTES: + case MINUTELY: return R.plurals.repeat_n_minutes; - case FREQUENCY_HOURS: + case HOURLY: return R.plurals.repeat_n_hours; - case FREQUENCY_DAYS: + case DAILY: return R.plurals.repeat_n_days; - case FREQUENCY_WEEKS: + case WEEKLY: return R.plurals.repeat_n_weeks; - case FREQUENCY_MONTHS: + case MONTHLY: return R.plurals.repeat_n_months; - case FREQUENCY_YEARS: + case YEARLY: return R.plurals.repeat_n_years; default: throw new RuntimeException("Invalid frequency: " + frequency); diff --git a/app/src/main/java/org/tasks/repeats/CustomRecurrenceDialog.java b/app/src/main/java/org/tasks/repeats/CustomRecurrenceDialog.java index 4a2779ea7..f0cd09cb5 100644 --- a/app/src/main/java/org/tasks/repeats/CustomRecurrenceDialog.java +++ b/app/src/main/java/org/tasks/repeats/CustomRecurrenceDialog.java @@ -19,9 +19,12 @@ import android.widget.TextView; import com.appeaser.sublimepickerlibrary.drawables.CheckableDrawable; import com.appeaser.sublimepickerlibrary.recurrencepicker.WeekButton; +import com.google.common.base.Strings; +import com.google.ical.values.Frequency; +import com.google.ical.values.RRule; +import com.google.ical.values.WeekdayNum; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.data.Task; -import com.todoroo.astrid.repeats.RepeatControlSet; import org.tasks.R; import org.tasks.activities.DatePickerActivity; @@ -36,8 +39,10 @@ import org.tasks.themes.ThemeAccent; import org.tasks.time.DateTime; import java.text.DateFormatSymbols; +import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; import java.util.List; import javax.inject.Inject; @@ -46,29 +51,39 @@ import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnItemSelected; import butterknife.OnTextChanged; +import timber.log.Timber; import static android.support.v4.content.ContextCompat.getColor; -import static com.todoroo.astrid.repeats.RepeatControlSet.FREQUENCY_DAYS; -import static com.todoroo.astrid.repeats.RepeatControlSet.FREQUENCY_HOURS; -import static com.todoroo.astrid.repeats.RepeatControlSet.FREQUENCY_MINUTES; -import static com.todoroo.astrid.repeats.RepeatControlSet.FREQUENCY_MONTHS; -import static com.todoroo.astrid.repeats.RepeatControlSet.FREQUENCY_WEEKS; -import static com.todoroo.astrid.repeats.RepeatControlSet.FREQUENCY_YEARS; -import static com.todoroo.astrid.repeats.RepeatControlSet.TYPE_COMPLETION_DATE; +import static com.google.ical.values.Frequency.DAILY; +import static com.google.ical.values.Frequency.HOURLY; +import static com.google.ical.values.Frequency.MINUTELY; +import static com.google.ical.values.Frequency.MONTHLY; +import static com.google.ical.values.Frequency.WEEKLY; +import static com.google.ical.values.Frequency.YEARLY; +import static com.todoroo.astrid.repeats.RepeatControlSet.WEEKDAYS; +import static java.util.Arrays.asList; import static org.tasks.date.DateTimeUtils.newDateTime; public class CustomRecurrenceDialog extends InjectingDialogFragment { - public static CustomRecurrenceDialog newCustomRecurrenceDialog(Fragment target) { + public static CustomRecurrenceDialog newCustomRecurrenceDialog(Fragment target, RRule rrule) { CustomRecurrenceDialog dialog = new CustomRecurrenceDialog(); dialog.setTargetFragment(target, 0); + Bundle arguments = new Bundle(); + if (rrule != null) { + arguments.putString(EXTRA_RRULE, rrule.toIcal()); + } + dialog.setArguments(arguments); return dialog; } public interface CustomRecurrenceCallback { - void onSelected(int frequency, int interval, long repeatUntilValue, boolean[] isChecked); + void onSelected(RRule rrule); } + private static final List FREQUENCIES = asList(MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY); + + private static final String EXTRA_RRULE = "extra_rrule"; private static final int REQUEST_PICK_DATE = 505; @Inject @ForActivity Context context; @@ -93,11 +108,8 @@ public class CustomRecurrenceDialog extends InjectingDialogFragment { private ArrayAdapter repeatUntilAdapter; private final List repeatUntilOptions = new ArrayList<>(); - private final boolean[] isChecked = new boolean[7]; - private int frequency; - private int interval; - private long repeatUntilValue; + private RRule rrule; @NonNull @Override @@ -105,23 +117,33 @@ public class CustomRecurrenceDialog extends InjectingDialogFragment { LayoutInflater inflater = LayoutInflater.from(getActivity()); View dialogView = inflater.inflate(R.layout.control_set_repeat, null); + Bundle arguments = getArguments(); + String rule = arguments.getString(EXTRA_RRULE); + if (!Strings.isNullOrEmpty(rule)) { + try { + rrule = new RRule(rule); + } catch (Exception ignored) { + } + } + if (rrule == null) { + rrule = new RRule(); + rrule.setInterval(1); + rrule.setFreq(WEEKLY); + } + ButterKnife.bind(this, dialogView); ArrayAdapter frequencyAdapter = ArrayAdapter.createFromResource(context, R.array.repeat_frequency, R.layout.frequency_item); frequencyAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); frequencySpinner.setAdapter(frequencyAdapter); - frequencySpinner.setSelection(3); - intervalEditText.setText(locale.formatNumber(1)); - intervalEditText.setSelectAllOnFocus(true); - intervalEditText.selectAll(); + frequencySpinner.setSelection(FREQUENCIES.indexOf(rrule.getFreq())); + + intervalEditText.setText(locale.formatNumber(rrule.getInterval())); repeatUntilAdapter = new ArrayAdapter<>(context, R.layout.simple_spinner_item, repeatUntilOptions); repeatUntilAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); repeatUntilSpinner.setAdapter(repeatUntilAdapter); - - setInterval(1, true); - - setRepeatUntilValue(repeatUntilValue); + updateRepeatUntilOptions(); WeekButton[] weekButtons = new WeekButton[] { day1, day2, day3, day4, day5, day6, day7 }; int expandedWidthHeight = getResources() @@ -137,32 +159,55 @@ public class CustomRecurrenceDialog extends InjectingDialogFragment { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek()); String[] shortWeekdays = dfs.getShortWeekdays(); + for(int i = 0; i < 7; i++) { - final int index = i; - WeekButton weekButton = weekButtons[index]; - int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); - String text = shortWeekdays[dayOfWeek]; + String text = shortWeekdays[calendar.get(Calendar.DAY_OF_WEEK)]; + WeekdayNum weekdayNum = new WeekdayNum(0, WEEKDAYS.get(i)); + WeekButton weekButton = weekButtons[i]; weekButton.setBackgroundDrawable(new CheckableDrawable(accent.getAccentColor(), false, expandedWidthHeight)); weekButton.setTextColor(weekButtonUnselectedTextColor); weekButton.setTextOff(text); weekButton.setTextOn(text); weekButton.setText(text); - weekButton.setOnCheckedChangeListener((compoundButton, b) -> CustomRecurrenceDialog.this.isChecked[index] = b); + if (rrule.getByDay().contains(weekdayNum)) { + weekButton.setChecked(true); + } + weekButton.setOnCheckedChangeListener((compoundButton, b) -> { + List days = rrule.getByDay(); + if (b) { + days.add(weekdayNum); + } else { + days.remove(weekdayNum); + } + }); calendar.add(Calendar.DATE, 1); } return dialogBuilder.newDialog() .setView(dialogView) - .setPositiveButton(android.R.string.ok, (dialog12, which) -> - ((CustomRecurrenceCallback) getTargetFragment()) - .onSelected(frequency, interval, repeatUntilValue, isChecked)) + .setPositiveButton(android.R.string.ok, (dialog12, which) -> { + if (rrule.getFreq() != WEEKLY) { + rrule.setByDay(Collections.emptyList()); + } + ((CustomRecurrenceCallback) getTargetFragment()).onSelected(rrule); + }) .setNegativeButton(android.R.string.cancel, null) .setOnCancelListener(DialogInterface::dismiss) .show(); } + private void setFrequency(Frequency frequency) { + rrule.setFreq(frequency); + int weekVisibility = frequency == WEEKLY ? View.VISIBLE : View.GONE; + weekGroup1.setVisibility(weekVisibility); + if (weekGroup2 != null) { + weekGroup2.setVisibility(weekVisibility); + } + updateIntervalTextView(); + } + private void setInterval(int interval, boolean updateEditText) { - this.interval = interval; + rrule.setInterval(interval); if (updateEditText) { intervalEditText.setText(locale.formatNumber(interval)); } @@ -171,31 +216,31 @@ public class CustomRecurrenceDialog extends InjectingDialogFragment { private void updateIntervalTextView() { int resource = getFrequencyPlural(); - String quantityString = getResources().getQuantityString(resource, interval); + String quantityString = getResources().getQuantityString(resource, rrule.getInterval()); intervalTextView.setText(quantityString); } private int getFrequencyPlural() { - switch (frequency) { - case FREQUENCY_MINUTES: + switch (rrule.getFreq()) { + case MINUTELY: return R.plurals.repeat_minutes; - case FREQUENCY_HOURS: + case HOURLY: return R.plurals.repeat_hours; - case FREQUENCY_DAYS: + case DAILY: return R.plurals.repeat_days; - case FREQUENCY_WEEKS: + case WEEKLY: return R.plurals.repeat_weeks; - case FREQUENCY_MONTHS: + case MONTHLY: return R.plurals.repeat_months; - case FREQUENCY_YEARS: + case YEARLY: return R.plurals.repeat_years; default: - throw new RuntimeException("Invalid frequency: " + frequency); + throw new RuntimeException("Invalid frequency: " + rrule.getFreq()); } } @OnItemSelected(R.id.repeat_until) - public void onRepeatUntilChanged(Spinner spinner, int position) { + public void onRepeatUntilChanged(int position) { if (repeatUntilOptions.size() == 2) { if (position == 0) { setRepeatUntilValue(0); @@ -212,14 +257,8 @@ public class CustomRecurrenceDialog extends InjectingDialogFragment { } @OnItemSelected(R.id.frequency) - public void onFrequencyChanged(Spinner spinner, int position) { - int weekVisibility = position == RepeatControlSet.FREQUENCY_WEEKS ? View.VISIBLE : View.GONE; - weekGroup1.setVisibility(weekVisibility); - if (weekGroup2 != null) { - weekGroup2.setVisibility(weekVisibility); - } - frequency = position; - updateIntervalTextView(); + public void onFrequencyChanged(int position) { + setFrequency(FREQUENCIES.get(position)); } @OnTextChanged(R.id.repeatValue) @@ -236,20 +275,22 @@ public class CustomRecurrenceDialog extends InjectingDialogFragment { } private void setRepeatUntilValue(long newValue) { - repeatUntilValue = newValue; + rrule.setUntil(new DateTime(newValue).toDateValue()); updateRepeatUntilOptions(); } private void repeatUntilClick() { Intent intent = new Intent(context, DatePickerActivity.class); - intent.putExtra(DatePickerActivity.EXTRA_TIMESTAMP, repeatUntilValue > 0 ? repeatUntilValue : 0L); + long repeatUntil = DateTime.from(rrule.getUntil()).getMillis(); + intent.putExtra(DatePickerActivity.EXTRA_TIMESTAMP, repeatUntil > 0 ? repeatUntil : 0L); startActivityForResult(intent, REQUEST_PICK_DATE); } private void updateRepeatUntilOptions() { repeatUntilOptions.clear(); - if (repeatUntilValue > 0) { - repeatUntilOptions.add(getString(R.string.repeat_until, getDisplayString(context, repeatUntilValue))); + long repeatUntil = DateTime.from(rrule.getUntil()).getMillis(); + if (repeatUntil > 0) { + repeatUntilOptions.add(getString(R.string.repeat_until, getDisplayString(context, repeatUntil))); } repeatUntilOptions.add(getString(R.string.repeat_forever)); repeatUntilOptions.add(getString(R.string.repeat_until, "").trim()); @@ -263,7 +304,7 @@ public class CustomRecurrenceDialog extends InjectingDialogFragment { if (resultCode == Activity.RESULT_OK) { setRepeatUntilValue(data.getLongExtra(DatePickerActivity.EXTRA_TIMESTAMP, 0L)); } else { - setRepeatUntilValue(repeatUntilValue); + setRepeatUntilValue(DateTime.from(rrule.getUntil()).getMillis()); } } super.onActivityResult(requestCode, resultCode, data); diff --git a/app/src/main/java/org/tasks/time/DateTime.java b/app/src/main/java/org/tasks/time/DateTime.java index 0177dcf41..3c876df1a 100644 --- a/app/src/main/java/org/tasks/time/DateTime.java +++ b/app/src/main/java/org/tasks/time/DateTime.java @@ -1,5 +1,8 @@ package org.tasks.time; +import com.google.ical.values.DateValue; +import com.google.ical.values.DateValueImpl; + import org.tasks.locale.Locale; import java.text.SimpleDateFormat; @@ -19,6 +22,12 @@ public class DateTime { private final TimeZone timeZone; private final long timestamp; + public static DateTime from(DateValue dateValue) { + return dateValue == null + ? new DateTime(0) + : new DateTime(dateValue.year(), dateValue.month(), dateValue.day()); + } + public DateTime(int year, int month, int day) { this(year, month, day, 0, 0, 0, 0); } @@ -268,6 +277,12 @@ public class DateTime { return calendar; } + public DateValue toDateValue() { + return timestamp == 0 + ? null + : new DateValueImpl(getYear(), getMonthOfYear(), getDayOfMonth()); + } + @Override public boolean equals(Object o) { if (this == o) return true;