mirror of https://github.com/tasks/tasks
Fixed some warnings, pulled out repeat completion listener into it's own
class, now handling "repeat after complete date", and cloning task. Needs a unit test of course (of course!)pull/14/head
parent
a3ce02e073
commit
21ea97ed34
@ -0,0 +1,99 @@
|
|||||||
|
package com.todoroo.astrid.repeats;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import com.google.ical.iter.RecurrenceIterator;
|
||||||
|
import com.google.ical.iter.RecurrenceIteratorFactory;
|
||||||
|
import com.google.ical.values.DateTimeValueImpl;
|
||||||
|
import com.google.ical.values.DateValue;
|
||||||
|
import com.google.ical.values.DateValueImpl;
|
||||||
|
import com.todoroo.andlib.service.Autowired;
|
||||||
|
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||||
|
import com.todoroo.andlib.service.ExceptionService;
|
||||||
|
import com.todoroo.astrid.api.AstridApiConstants;
|
||||||
|
import com.todoroo.astrid.model.Task;
|
||||||
|
import com.todoroo.astrid.service.TaskService;
|
||||||
|
|
||||||
|
public class RepeatTaskCompleteListener extends BroadcastReceiver {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TaskService taskService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ExceptionService exceptionService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
long taskId = intent.getLongExtra(AstridApiConstants.EXTRAS_TASK_ID, -1);
|
||||||
|
if(taskId == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DependencyInjectionService.getInstance().inject(this);
|
||||||
|
|
||||||
|
Task task = taskService.fetchById(taskId, Task.ID, Task.RECURRENCE,
|
||||||
|
Task.DUE_DATE, Task.FLAGS);
|
||||||
|
if(task == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
String recurrence = task.getValue(Task.RECURRENCE);
|
||||||
|
if(recurrence.length() > 0) {
|
||||||
|
Date date = new Date();
|
||||||
|
DateValue today = new DateValueImpl(date.getYear() + 1900,
|
||||||
|
date.getMonth() + 1, date.getDate());
|
||||||
|
|
||||||
|
DateValue repeatFrom;
|
||||||
|
if(task.hasDueDate() && !task.getFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION)) {
|
||||||
|
date = new Date(task.getValue(Task.DUE_DATE));
|
||||||
|
repeatFrom = new DateTimeValueImpl(date.getYear() + 1900,
|
||||||
|
date.getMonth() + 1, date.getDate(),
|
||||||
|
date.getHours(), date.getMinutes(), date.getSeconds());
|
||||||
|
} else {
|
||||||
|
repeatFrom = today;
|
||||||
|
}
|
||||||
|
|
||||||
|
// invoke the recurrence iterator
|
||||||
|
try {
|
||||||
|
RecurrenceIterator iterator = RecurrenceIteratorFactory.createRecurrenceIterator(recurrence,
|
||||||
|
repeatFrom, TimeZone.getDefault());
|
||||||
|
if(repeatFrom.compareTo(today) < 0)
|
||||||
|
repeatFrom = today;
|
||||||
|
// go to the latest value and advance one more
|
||||||
|
iterator.advanceTo(repeatFrom);
|
||||||
|
if(!iterator.hasNext())
|
||||||
|
return;
|
||||||
|
DateValue nextDate = iterator.next();
|
||||||
|
if(nextDate.equals(repeatFrom)) {
|
||||||
|
if(!iterator.hasNext())
|
||||||
|
return;
|
||||||
|
nextDate = iterator.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
long newDueDate;
|
||||||
|
if(nextDate instanceof DateTimeValueImpl) {
|
||||||
|
DateTimeValueImpl newDateTime = (DateTimeValueImpl)nextDate;
|
||||||
|
newDueDate = task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME,
|
||||||
|
new Date(newDateTime.year() - 1900, newDateTime.month() - 1,
|
||||||
|
newDateTime.day(), newDateTime.hour(),
|
||||||
|
newDateTime.minute(), newDateTime.second()).getTime());
|
||||||
|
} else {
|
||||||
|
newDueDate = task.createDueDate(Task.URGENCY_SPECIFIC_DAY,
|
||||||
|
new Date(nextDate.year() - 1900, nextDate.month() - 1,
|
||||||
|
nextDate.day()).getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
Task newTask = taskService.clone(task);
|
||||||
|
task.setValue(Task.DUE_DATE, newDueDate);
|
||||||
|
taskService.save(newTask, false);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
exceptionService.reportError("recurrence-rule: " + recurrence, e); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
package com.todoroo.astrid.tags;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.AutoCompleteTextView;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.timsu.astrid.R;
|
||||||
|
import com.todoroo.andlib.data.TodorooCursor;
|
||||||
|
import com.todoroo.astrid.activity.TaskEditActivity.TaskEditControlSet;
|
||||||
|
import com.todoroo.astrid.model.Metadata;
|
||||||
|
import com.todoroo.astrid.model.Task;
|
||||||
|
import com.todoroo.astrid.tags.TagService.Tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control set to manage adding and removing tags
|
||||||
|
*
|
||||||
|
* @author Tim Su <tim@todoroo.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final class TagsControlSet implements TaskEditControlSet {
|
||||||
|
|
||||||
|
// --- constants
|
||||||
|
|
||||||
|
/** Number of tags a task can have */
|
||||||
|
static final int MAX_TAGS = 5;
|
||||||
|
|
||||||
|
// --- instance variables
|
||||||
|
|
||||||
|
private final TagService tagService = new TagService();
|
||||||
|
private final Tag[] allTags;
|
||||||
|
private final LinearLayout tagsContainer;
|
||||||
|
private final Activity activity;
|
||||||
|
|
||||||
|
public TagsControlSet(Activity activity, int tagsContainer) {
|
||||||
|
allTags = tagService.getGroupedTags(TagService.GROUPED_TAGS_BY_SIZE);
|
||||||
|
this.activity = activity;
|
||||||
|
this.tagsContainer = (LinearLayout) activity.findViewById(tagsContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
@Override
|
||||||
|
public void readFromTask(Task task) {
|
||||||
|
// tags (only configure if not already set)
|
||||||
|
if(tagsContainer.getChildCount() == 0) {
|
||||||
|
TodorooCursor<Metadata> cursor = tagService.getTags(task.getId());
|
||||||
|
try {
|
||||||
|
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
|
||||||
|
addTag(cursor.get(Metadata.VALUE));
|
||||||
|
} finally {
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
addTag("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToModel(Task task) {
|
||||||
|
ArrayList<String> tags = new ArrayList<String>();
|
||||||
|
|
||||||
|
for(int i = 0; i < tagsContainer.getChildCount(); i++) {
|
||||||
|
TextView tagName = (TextView)tagsContainer.getChildAt(i).findViewById(R.id.text1);
|
||||||
|
if(tagName.getText().length() == 0)
|
||||||
|
continue;
|
||||||
|
tags.add(tagName.getText().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
tagService.synchronizeTags(task.getId(), tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a tag to the tag field */
|
||||||
|
boolean addTag(String tagName) {
|
||||||
|
if (tagsContainer.getChildCount() >= MAX_TAGS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutInflater inflater = activity.getLayoutInflater();
|
||||||
|
final View tagItem = inflater.inflate(R.layout.tag_edit_row, null);
|
||||||
|
tagsContainer.addView(tagItem);
|
||||||
|
|
||||||
|
AutoCompleteTextView textView = (AutoCompleteTextView)tagItem.
|
||||||
|
findViewById(R.id.text1);
|
||||||
|
textView.setText(tagName);
|
||||||
|
ArrayAdapter<Tag> tagsAdapter =
|
||||||
|
new ArrayAdapter<Tag>(activity,
|
||||||
|
android.R.layout.simple_dropdown_item_1line, allTags);
|
||||||
|
textView.setAdapter(tagsAdapter);
|
||||||
|
textView.addTextChangedListener(new TextWatcher() {
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before,
|
||||||
|
int count) {
|
||||||
|
if(start == 0 && tagsContainer.getChildAt(
|
||||||
|
tagsContainer.getChildCount()-1) == tagItem) {
|
||||||
|
addTag("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count,
|
||||||
|
int after) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ImageButton reminderRemoveButton;
|
||||||
|
reminderRemoveButton = (ImageButton)tagItem.findViewById(R.id.button1);
|
||||||
|
reminderRemoveButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
public void onClick(View v) {
|
||||||
|
tagsContainer.removeView(tagItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +1,32 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- See the file "LICENSE" for the full license governing this code. -->
|
<!-- See the file "LICENSE" for the full license governing this code. -->
|
||||||
<resources>
|
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<!-- Resources for built-in tag plug-in -->
|
<!-- Resources for built-in tag plug-in -->
|
||||||
|
|
||||||
<string name="tag_EOE_button">Add Tags</string>
|
<!-- =============================================== Task Edit Controls == -->
|
||||||
<string name="tag_EOE_button_w_tags">Tags: %s</string>
|
|
||||||
|
<!-- Tags label -->
|
||||||
|
<string name="TEA_tags_label">Tags:</string>
|
||||||
|
|
||||||
|
<!-- Tags hint -->
|
||||||
|
<string name="TEA_tag_hint">Tag Name</string>
|
||||||
|
|
||||||
|
<!-- ===================================================== Task Details == -->
|
||||||
|
|
||||||
<string name="tag_TLA_detail">Tags: %s</string>
|
<string name="tag_TLA_detail">Tags: %s</string>
|
||||||
|
|
||||||
|
<!-- ========================================================== Filters == -->
|
||||||
|
|
||||||
<string name="tag_FEx_header">Tags</string>
|
<string name="tag_FEx_header">Tags</string>
|
||||||
<string name="tag_FEx_by_size">By Size</string>
|
<string name="tag_FEx_by_size">By Size</string>
|
||||||
<string name="tag_FEx_alpha">Alphabetical</string>
|
<string name="tag_FEx_alpha">Alphabetical</string>
|
||||||
|
<string name="tag_FEx_untagged">Untagged</string>
|
||||||
|
|
||||||
<!-- $T => tag, $C => count -->
|
<!-- $T => tag, $C => count -->
|
||||||
<string name="tag_FEx_tag_w_size">$T ($C)</string>
|
<string name="tag_FEx_tag_w_size">$T ($C)</string>
|
||||||
|
|
||||||
<!-- %s => tag name -->
|
<!-- %s => tag name -->
|
||||||
<string name="tag_FEx_name">Tagged \'%s\'</string>
|
<string name="tag_FEx_name">Tagged \'%s\'</string>
|
||||||
|
|
||||||
<string name="tag_TEA_hint">Type In a Tag</string>
|
|
||||||
<string name="tag_TEA_title">Edit Tags</string>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue