mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
402 lines
14 KiB
Java
402 lines
14 KiB
Java
/**
|
|
* Copyright (c) 2012 Todoroo Inc
|
|
*
|
|
* See the file "LICENSE" for the full license governing this code.
|
|
*/
|
|
package com.todoroo.astrid.ui;
|
|
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.View.OnClickListener;
|
|
import android.view.ViewGroup;
|
|
import android.widget.AdapterView;
|
|
import android.widget.ArrayAdapter;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.Spinner;
|
|
import android.widget.TextView;
|
|
|
|
import com.todoroo.andlib.data.Callback;
|
|
import com.todoroo.andlib.utility.DateUtilities;
|
|
import com.todoroo.astrid.activity.TaskEditFragment;
|
|
import com.todoroo.astrid.alarms.AlarmFields;
|
|
import com.todoroo.astrid.alarms.AlarmService;
|
|
import com.todoroo.astrid.data.Metadata;
|
|
import com.todoroo.astrid.data.Task;
|
|
import com.todoroo.astrid.helper.TaskEditControlSetBase;
|
|
|
|
import org.joda.time.DateTime;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.tasks.R;
|
|
import org.tasks.dialogs.DateAndTimePickerDialog;
|
|
import org.tasks.dialogs.LocationPickerDialog;
|
|
import org.tasks.location.Geofence;
|
|
import org.tasks.location.GeofenceService;
|
|
import org.tasks.location.OnLocationPickedHandler;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Date;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
import static org.tasks.date.DateTimeUtils.newDateTime;
|
|
|
|
/**
|
|
* Control set dealing with reminder settings
|
|
*
|
|
* @author Tim Su <tim@todoroo.com>
|
|
*
|
|
*/
|
|
public class ReminderControlSet extends TaskEditControlSetBase implements AdapterView.OnItemSelectedListener {
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(ReminderControlSet.class);
|
|
private static final String FRAG_TAG_LOCATION_PICKER = "frag_tag_location_picker";
|
|
|
|
private Spinner mode;
|
|
private Spinner addSpinner;
|
|
private TextView modeDisplay;
|
|
|
|
private RandomReminderControlSet randomControlSet;
|
|
private LinearLayout alertContainer;
|
|
private boolean whenDue;
|
|
private boolean whenOverdue;
|
|
private AlarmService alarmService;
|
|
private GeofenceService geofenceService;
|
|
private TaskEditFragment taskEditFragment;
|
|
private List<String> spinnerOptions = new ArrayList<>();
|
|
private ArrayAdapter<String> remindAdapter;
|
|
|
|
|
|
public ReminderControlSet(AlarmService alarmService, GeofenceService geofenceService, TaskEditFragment taskEditFragment) {
|
|
super(taskEditFragment.getActivity(), R.layout.control_set_reminders);
|
|
this.alarmService = alarmService;
|
|
this.geofenceService = geofenceService;
|
|
this.taskEditFragment = taskEditFragment;
|
|
}
|
|
|
|
public int getValue() {
|
|
int value = 0;
|
|
if(whenDue) {
|
|
value |= Task.NOTIFY_AT_DEADLINE;
|
|
}
|
|
if(whenOverdue) {
|
|
value |= Task.NOTIFY_AFTER_DEADLINE;
|
|
}
|
|
|
|
value &= ~(Task.NOTIFY_MODE_FIVE | Task.NOTIFY_MODE_NONSTOP);
|
|
if(mode.getSelectedItemPosition() == 2) {
|
|
value |= Task.NOTIFY_MODE_NONSTOP;
|
|
} else if(mode.getSelectedItemPosition() == 1) {
|
|
value |= Task.NOTIFY_MODE_FIVE;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
private void addNewAlarm() {
|
|
pickNewAlarm(newDateTime().withMillisOfDay(0), new DateAndTimePickerDialog.OnDateTimePicked() {
|
|
@Override
|
|
public void onDateTimePicked(DateTime dateTime) {
|
|
addAlarmRow(dateTime.getMillis());
|
|
}
|
|
});
|
|
}
|
|
|
|
private void pickNewAlarm(DateTime initial, DateAndTimePickerDialog.OnDateTimePicked onDateTimePicked) {
|
|
DateAndTimePickerDialog.dateAndTimePickerDialog(taskEditFragment.getFragmentManager(),
|
|
taskEditFragment.getActivity(), initial, onDateTimePicked, null);
|
|
}
|
|
|
|
private void addAlarmRow(final Long timestamp) {
|
|
final View alertItem = addAlarmRow(getDisplayString(timestamp), timestamp, null);
|
|
TextView display = (TextView) alertItem.findViewById(R.id.alarm_string);
|
|
display.setOnClickListener(new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
pickNewAlarm(newDateTime(timestamp), new DateAndTimePickerDialog.OnDateTimePicked() {
|
|
@Override
|
|
public void onDateTimePicked(DateTime dateTime) {
|
|
long millis = dateTime.getMillis();
|
|
addAlarmRow(alertItem, getDisplayString(millis), millis, null);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
public void addGeolocationReminder(final Geofence geofence) {
|
|
View alertItem = addAlarmRow(geofence.getName(), null, new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
}
|
|
});
|
|
alertItem.setTag(geofence);
|
|
}
|
|
|
|
private View addAlarmRow(String text, Long timestamp, final OnClickListener onRemove) {
|
|
final View alertItem = LayoutInflater.from(activity).inflate(R.layout.alarm_edit_row, null);
|
|
alertContainer.addView(alertItem);
|
|
addAlarmRow(alertItem, text, timestamp, onRemove);
|
|
return alertItem;
|
|
}
|
|
|
|
private void addAlarmRow(final View alertItem, String text, Long timestamp, final View.OnClickListener onRemove) {
|
|
alertItem.setTag(timestamp);
|
|
TextView display = (TextView) alertItem.findViewById(R.id.alarm_string);
|
|
display.setText(text);
|
|
alertItem.findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
alertContainer.removeView(alertItem);
|
|
if (onRemove != null) {
|
|
onRemove.onClick(v);
|
|
}
|
|
updateSpinner();
|
|
}
|
|
});
|
|
updateSpinner();
|
|
}
|
|
|
|
private void updateSpinner() {
|
|
addSpinner.setSelection(0);
|
|
spinnerOptions.clear();
|
|
spinnerOptions.add("");
|
|
if (!whenDue) {
|
|
spinnerOptions.add(taskEditFragment.getString(R.string.when_due));
|
|
}
|
|
if (!whenOverdue) {
|
|
spinnerOptions.add(taskEditFragment.getString(R.string.when_overdue));
|
|
}
|
|
if (randomControlSet == null) {
|
|
spinnerOptions.add(taskEditFragment.getString(R.string.randomly));
|
|
}
|
|
if (taskEditFragment.getResources().getBoolean(R.bool.location_enabled)) {
|
|
spinnerOptions.add(taskEditFragment.getString(R.string.pick_a_location));
|
|
}
|
|
spinnerOptions.add(taskEditFragment.getString(R.string.pick_a_date_and_time));
|
|
remindAdapter.notifyDataSetChanged();
|
|
}
|
|
|
|
@Override
|
|
protected void afterInflate() {
|
|
alertContainer = (LinearLayout) getView().findViewById(R.id.alert_container);
|
|
getView().findViewById(R.id.alarms_add).setOnClickListener(new OnClickListener() {
|
|
@Override
|
|
public void onClick(View arg0) {
|
|
if (spinnerOptions.size() == 2) {
|
|
addNewAlarm();
|
|
} else {
|
|
addSpinner.performClick();
|
|
}
|
|
}
|
|
});
|
|
addSpinner = (Spinner) getView().findViewById(R.id.alarms_add_spinner);
|
|
addSpinner.setOnItemSelectedListener(ReminderControlSet.this);
|
|
remindAdapter = new ArrayAdapter<String>(activity, R.layout.simple_spinner_item, spinnerOptions) {
|
|
@Override
|
|
public View getDropDownView(int position, View convertView, ViewGroup parent) {
|
|
View v;
|
|
|
|
// If this is the initial dummy entry, make it hidden
|
|
if (position == 0) {
|
|
TextView tv = new TextView(getContext());
|
|
tv.setHeight(0);
|
|
tv.setVisibility(View.GONE);
|
|
v = tv;
|
|
}
|
|
else {
|
|
// Pass convertView as null to prevent reuse of special case views
|
|
v = super.getDropDownView(position, null, parent);
|
|
}
|
|
|
|
// Hide scroll bar because it appears sometimes unnecessarily, this does not prevent scrolling
|
|
parent.setVerticalScrollBarEnabled(false);
|
|
return v;
|
|
}
|
|
};
|
|
addSpinner.setAdapter(remindAdapter);
|
|
remindAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
modeDisplay = (TextView) getView().findViewById(R.id.reminder_alarm_display);
|
|
mode = (Spinner) getView().findViewById(R.id.reminder_alarm);
|
|
modeDisplay.setOnClickListener(new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
mode.performClick();
|
|
}
|
|
});
|
|
|
|
String[] list = new String[] {
|
|
activity.getString(R.string.ring_once),
|
|
activity.getString(R.string.ring_five_times),
|
|
activity.getString(R.string.ring_nonstop),
|
|
};
|
|
final ArrayAdapter<String> modeAdapter = new ArrayAdapter<>(
|
|
activity, android.R.layout.simple_spinner_item, list);
|
|
modeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
mode.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
|
|
|
@Override
|
|
public void onItemSelected(AdapterView<?> parent, View view,
|
|
int position, long id) {
|
|
modeDisplay.setText(modeAdapter.getItem(position));
|
|
}
|
|
|
|
@Override
|
|
public void onNothingSelected(AdapterView<?> parent) {
|
|
// TODO Auto-generated method stub
|
|
|
|
}
|
|
});
|
|
activity.runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
mode.setAdapter(modeAdapter);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
protected void readFromTaskOnInitialize() {
|
|
setValue(model.getReminderFlags());
|
|
|
|
alertContainer.removeAllViews();
|
|
if (whenDue) {
|
|
addDue();
|
|
}
|
|
if (whenOverdue) {
|
|
addOverdue();
|
|
}
|
|
if (model.hasRandomReminder()) {
|
|
addRandomReminder();
|
|
}
|
|
alarmService.getAlarms(model.getId(), new Callback<Metadata>() {
|
|
@Override
|
|
public void apply(Metadata entry) {
|
|
addAlarmRow(entry.getValue(AlarmFields.TIME));
|
|
}
|
|
});
|
|
for (Geofence geofence : geofenceService.getGeofences(model.getId())) {
|
|
addGeolocationReminder(geofence);
|
|
}
|
|
updateSpinner();
|
|
}
|
|
|
|
private void addDue() {
|
|
whenDue = true;
|
|
addAlarmRow(taskEditFragment.getString(R.string.when_due), null, new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
whenDue = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
private void addOverdue() {
|
|
whenOverdue = true;
|
|
addAlarmRow(taskEditFragment.getString(R.string.when_overdue), null, new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
whenOverdue = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
private void addRandomReminder() {
|
|
View alarmRow = addAlarmRow(taskEditFragment.getString(R.string.randomly_once), null, new OnClickListener() {
|
|
@Override
|
|
public void onClick(View v) {
|
|
randomControlSet = null;
|
|
}
|
|
});
|
|
randomControlSet = new RandomReminderControlSet(activity, alarmRow);
|
|
randomControlSet.readFromTaskOnInitialize(model);
|
|
}
|
|
|
|
private void setValue(int flags) {
|
|
whenDue = (flags & Task.NOTIFY_AT_DEADLINE) > 0;
|
|
whenOverdue = (flags & Task.NOTIFY_AFTER_DEADLINE) > 0;
|
|
|
|
if((flags & Task.NOTIFY_MODE_NONSTOP) > 0) {
|
|
mode.setSelection(2);
|
|
} else if((flags & Task.NOTIFY_MODE_FIVE) > 0) {
|
|
mode.setSelection(1);
|
|
} else {
|
|
mode.setSelection(0);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void writeToModelAfterInitialized(Task task) {
|
|
task.setReminderFlags(getValue());
|
|
|
|
task.setReminderPeriod(randomControlSet == null ? 0L : randomControlSet.getReminderPeriod());
|
|
|
|
Set<Long> alarms = new LinkedHashSet<>();
|
|
Set<Geofence> geofences = new LinkedHashSet<>();
|
|
|
|
for(int i = 0; i < alertContainer.getChildCount(); i++) {
|
|
Object tag = alertContainer.getChildAt(i).getTag();
|
|
//noinspection StatementWithEmptyBody
|
|
if (tag == null) {
|
|
} else if (tag instanceof Long) {
|
|
alarms.add((Long) tag);
|
|
} else if (tag instanceof Geofence) {
|
|
geofences.add((Geofence) tag);
|
|
} else {
|
|
log.error("Unexpected tag: {}", tag);
|
|
}
|
|
}
|
|
|
|
if(alarmService.synchronizeAlarms(task.getId(), alarms)) {
|
|
task.setModificationDate(DateUtilities.now());
|
|
}
|
|
if (geofenceService.synchronizeGeofences(task.getId(), geofences)) {
|
|
task.setModificationDate(DateUtilities.now());
|
|
}
|
|
}
|
|
|
|
private String getDisplayString(long forDate) {
|
|
DateTime dateTime = newDateTime(forDate);
|
|
Date d = dateTime.toDate();
|
|
return (dateTime.getYear() == newDateTime().getYear()
|
|
? DateUtilities.getLongDateStringHideYear(d)
|
|
: DateUtilities.getLongDateString(d)) +
|
|
", " + DateUtilities.getTimeString(activity, d);
|
|
}
|
|
|
|
@Override
|
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
|
log.info("onItemSelected({}, {}, {}, {})", parent, view, position, id);
|
|
String selected = spinnerOptions.get(position);
|
|
if (selected.equals(taskEditFragment.getString(R.string.when_due))) {
|
|
addDue();
|
|
} else if(selected.equals(taskEditFragment.getString(R.string.when_overdue))) {
|
|
addOverdue();
|
|
} else if (selected.equals(taskEditFragment.getString(R.string.randomly))) {
|
|
addRandomReminder();
|
|
} else if (selected.equals(taskEditFragment.getString(R.string.pick_a_date_and_time))) {
|
|
addNewAlarm();
|
|
} else if (selected.equals(taskEditFragment.getString(R.string.pick_a_location))) {
|
|
new LocationPickerDialog(new OnLocationPickedHandler() {
|
|
@Override
|
|
public void onLocationPicked(Geofence geofence) {
|
|
addGeolocationReminder(geofence);
|
|
}
|
|
}).show(taskEditFragment.getChildFragmentManager(), FRAG_TAG_LOCATION_PICKER);
|
|
}
|
|
if (position != 0) {
|
|
updateSpinner();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onNothingSelected(AdapterView<?> parent) {
|
|
}
|
|
|
|
@Override
|
|
public int getIcon() {
|
|
return R.attr.ic_action_bell;
|
|
}
|
|
}
|