Display tag blocks for caldav and google tasks

pull/685/merge
Alex Baker 8 years ago
parent fd2437cff3
commit d03698cd2e

@ -79,6 +79,8 @@ public class TaskListFragment extends InjectingFragment
implements SwipeRefreshLayout.OnRefreshListener, Toolbar.OnMenuItemClickListener {
public static final String TAGS_METADATA_JOIN = "for_tags"; // $NON-NLS-1$
public static final String GTASK_METADATA_JOIN = "for_gtask"; // $NON-NLS-1$
public static final String CALDAV_METADATA_JOIN = "for_caldav"; // $NON-NLS-1$
public static final String FILE_METADATA_JOIN = "for_actions"; // $NON-NLS-1$
private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
private static final String EXTRA_FILTER = "extra_filter";

@ -35,6 +35,13 @@ public class TaskAdapter {
+ ".tag_uid, '')"
+ ", ',')")
.as("tags");
private static final StringProperty GTASK =
new StringProperty(null, "nullif(" + TaskListFragment.GTASK_METADATA_JOIN + ".list_id, '')")
.as("googletask");
private static final StringProperty CALDAV =
new StringProperty(null, "nullif(" + TaskListFragment.CALDAV_METADATA_JOIN + ".calendar, '')")
.as("caldav");
private static final LongProperty FILE_ID_PROPERTY =
TaskAttachment.ID.cloneAs(TaskListFragment.FILE_METADATA_JOIN, "fileId");
public static final Property<?>[] PROPERTIES =
@ -42,6 +49,8 @@ public class TaskAdapter {
Task.PROPERTIES,
new Property<?>[] {
TAGS, // Concatenated list of tags
GTASK,
CALDAV,
FILE_ID_PROPERTY // File id
},
Property.class);

@ -55,7 +55,7 @@ public class CaldavFilter extends Filter {
Criterion.and(
TaskDao.TaskCriteria.activeAndVisible(),
Field.field("caldav_tasks.deleted").eq(0),
Field.field("calendar").eq(caldavCalendar.getUuid())));
Field.field("caldav_tasks.calendar").eq(caldavCalendar.getUuid())));
}
private static Map<String, Object> getValuesForNewTask(CaldavCalendar caldavCalendar) {

@ -64,7 +64,7 @@ public class GtasksFilter extends Filter {
Criterion.and(
TaskDao.TaskCriteria.activeAndVisible(),
Field.field("google_tasks.deleted").eq(0),
Field.field("list_id").eq(list.getRemoteId())));
Field.field("google_tasks.list_id").eq(list.getRemoteId())));
}
private static Map<String, Object> getValuesForNewTasks(GoogleTaskList list) {

@ -153,6 +153,7 @@ public class Task implements Parcelable {
/** Name of Task */
@ColumnInfo(name = "title")
public String title = "";
@ColumnInfo(name = "importance")
public Integer priority = Priority.NONE;
/** Unixtime Task is due, 0 if not set */
@ -220,6 +221,8 @@ public class Task implements Parcelable {
@Ignore private transient int indent;
@Ignore private transient String tags;
@Ignore private transient String googleTaskList;
@Ignore private transient String caldav;
@Ignore private transient boolean hasFiles;
@Ignore private transient HashMap<String, Object> transitoryData = null;
@ -250,6 +253,8 @@ public class Task implements Parcelable {
final int _cursorIndexOfRemoteId = _cursor.getColumnIndexOrThrow("remoteId");
final int _cursorIndexOfIndent = _cursor.getColumnIndex("indent");
final int _cursorIndexOfTags = _cursor.getColumnIndex("tags");
final int _cursorIndexOfGoogleTasks = _cursor.getColumnIndex("googletask");
final int _cursorIndexOfCaldav = _cursor.getColumnIndex("caldav");
final int _cursorIndexOfFileId = _cursor.getColumnIndex("fileId");
if (_cursor.isNull(_cursorIndexOfId)) {
id = null;
@ -342,6 +347,12 @@ public class Task implements Parcelable {
if (_cursorIndexOfTags >= 0) {
tags = _cursor.getString(_cursorIndexOfTags);
}
if (_cursorIndexOfGoogleTasks >= 0) {
googleTaskList = _cursor.getString(_cursorIndexOfGoogleTasks);
}
if (_cursorIndexOfCaldav >= 0) {
caldav = _cursor.getString(_cursorIndexOfCaldav);
}
if (_cursorIndexOfFileId >= 0) {
hasFiles = _cursor.getInt(_cursorIndexOfFileId) > 0;
}
@ -1061,10 +1072,6 @@ public class Task implements Parcelable {
return tags;
}
public boolean hasFiles() {
return hasFiles;
}
@Override
public boolean equals(Object o) {
if (this == o) {
@ -1076,6 +1083,9 @@ public class Task implements Parcelable {
Task task = (Task) o;
if (indent != task.indent) {
return false;
}
if (hasFiles != task.hasFiles) {
return false;
}
@ -1152,7 +1162,15 @@ public class Task implements Parcelable {
if (remoteId != null ? !remoteId.equals(task.remoteId) : task.remoteId != null) {
return false;
}
return tags != null ? tags.equals(task.tags) : task.tags == null;
if (tags != null ? !tags.equals(task.tags) : task.tags != null) {
return false;
}
if (googleTaskList != null
? !googleTaskList.equals(task.googleTaskList)
: task.googleTaskList != null) {
return false;
}
return caldav != null ? caldav.equals(task.caldav) : task.caldav == null;
}
@Override
@ -1180,7 +1198,21 @@ public class Task implements Parcelable {
result = 31 * result + (remoteId != null ? remoteId.hashCode() : 0);
result = 31 * result + indent;
result = 31 * result + (tags != null ? tags.hashCode() : 0);
result = 31 * result + (googleTaskList != null ? googleTaskList.hashCode() : 0);
result = 31 * result + (caldav != null ? caldav.hashCode() : 0);
result = 31 * result + (hasFiles ? 1 : 0);
return result;
}
public String getGoogleTaskList() {
return googleTaskList;
}
public String getCaldav() {
return caldav;
}
public boolean hasFiles() {
return hasFiles;
}
}

@ -12,13 +12,20 @@ import android.text.style.ForegroundColorSpan;
import android.util.TypedValue;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.base.Strings;
import com.google.common.collect.Ordering;
import com.todoroo.astrid.tags.TagService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.tasks.R;
import org.tasks.data.CaldavAccount;
import org.tasks.data.CaldavCalendar;
import org.tasks.data.CaldavDao;
import org.tasks.data.GoogleTaskList;
import org.tasks.data.GoogleTaskListDao;
import org.tasks.data.TagData;
import org.tasks.injection.ForApplication;
import org.tasks.themes.ThemeCache;
@ -28,25 +35,30 @@ public class TagFormatter {
private static final char SPACE = '\u0020';
private static final char HAIR_SPACE = '\u200a';
private static final int MAX_TAGS = 4;
private final Map<String, TagData> tagMap = new HashMap<>();
private final Map<String, ColoredString> tagMap = new HashMap<>();
private final Map<String, ColoredString> googleTaskLists = new HashMap<>();
private final Map<String, ColoredString> caldavCalendars = new HashMap<>();
private final TagService tagService;
private final ThemeCache themeCache;
private final GoogleTaskListDao googleTaskListDao;
private final CaldavDao caldavDao;
private final float tagCharacters;
private final Function<String, TagData> uuidToTag = this::getTag;
private final Ordering<TagData> orderByName =
new Ordering<TagData>() {
private final Function<String, ColoredString> uuidToTag = this::getTag;
private final Ordering<ColoredString> orderByName =
new Ordering<ColoredString>() {
@Override
public int compare(TagData left, TagData right) {
return left.getName().compareTo(right.getName());
public int compare(ColoredString left, ColoredString right) {
return left.name.compareTo(right.name);
}
};
private final Ordering<TagData> orderByLength =
new Ordering<TagData>() {
private final Ordering<ColoredString> orderByLength =
new Ordering<ColoredString>() {
@Override
public int compare(TagData left, TagData right) {
int leftLength = left.getName().length();
int rightLength = right.getName().length();
public int compare(ColoredString left, ColoredString right) {
int leftLength = left.name.length();
int rightLength = right.name.length();
if (leftLength < rightLength) {
return -1;
} else if (rightLength < leftLength) {
@ -59,31 +71,71 @@ public class TagFormatter {
@Inject
public TagFormatter(
@ForApplication Context context, TagService tagService, ThemeCache themeCache) {
@ForApplication Context context,
TagService tagService,
ThemeCache themeCache,
GoogleTaskListDao googleTaskListDao,
CaldavDao caldavDao) {
this.tagService = tagService;
this.themeCache = themeCache;
this.googleTaskListDao = googleTaskListDao;
this.caldavDao = caldavDao;
TypedValue typedValue = new TypedValue();
context.getResources().getValue(R.dimen.tag_characters, typedValue, true);
tagCharacters = typedValue.getFloat();
for (TagData tagData : tagService.getTagList()) {
tagMap.put(tagData.getRemoteId(), tagData);
tagMap.put(tagData.getRemoteId(), new ColoredString(tagData));
}
for (CaldavCalendar calendar : caldavDao.getCalendars()) {
caldavCalendars.put(calendar.getUuid(), new ColoredString(calendar));
}
for (GoogleTaskList list : googleTaskListDao.getAllLists()) {
googleTaskLists.put(list.getRemoteId(), new ColoredString(list));
}
}
private class ColoredString {
final String name;
final int color;
ColoredString(TagData tagData) {
name = tagData.getName();
color = tagData.getColor();
}
ColoredString(GoogleTaskList googleTaskList) {
name = googleTaskList.getTitle();
color = googleTaskList.getColor();
}
CharSequence getTagString(List<String> tagUuids) {
Iterable<TagData> t = filter(transform(tagUuids, uuidToTag), Predicates.notNull());
List<TagData> firstFourByName = orderByName.leastOf(t, 4);
int numTags = firstFourByName.size();
ColoredString(CaldavCalendar caldavCalendar) {
name = caldavCalendar.getName();
color = caldavCalendar.getColor();
}
}
CharSequence getTagString(String caldav, String googleTask, List<String> tagUuids) {
List<ColoredString> strings = new ArrayList<>();
if (!Strings.isNullOrEmpty(googleTask)) {
strings.add(getGoogleTaskList(googleTask));
} else if (!Strings.isNullOrEmpty(caldav)) {
strings.add(getCaldavCalendar(caldav));
}
Iterable<ColoredString> tags = filter(transform(tagUuids, uuidToTag), Predicates.notNull());
strings.addAll(0, orderByName.leastOf(tags, MAX_TAGS - strings.size()));
int numTags = strings.size();
if (numTags == 0) {
return null;
}
List<TagData> firstFourByNameLength = orderByLength.sortedCopy(firstFourByName);
List<ColoredString> firstFourByNameLength = orderByLength.sortedCopy(strings);
float maxLength = tagCharacters / numTags;
for (int i = 0; i < numTags - 1; i++) {
TagData tagData = firstFourByNameLength.get(i);
String name = tagData.getName();
ColoredString tagData = firstFourByNameLength.get(i);
String name = tagData.name;
if (name.length() >= maxLength) {
break;
}
@ -92,7 +144,7 @@ public class TagFormatter {
float additional = excess / beneficiaries;
maxLength += additional;
}
List<SpannableString> tagStrings = transform(firstFourByName, tagToString(maxLength));
List<SpannableString> tagStrings = transform(strings, tagToString(maxLength));
SpannableStringBuilder builder = new SpannableStringBuilder();
for (SpannableString tagString : tagStrings) {
if (builder.length() > 0) {
@ -103,12 +155,12 @@ public class TagFormatter {
return builder;
}
private Function<TagData, SpannableString> tagToString(final float maxLength) {
private Function<ColoredString, SpannableString> tagToString(final float maxLength) {
return tagData -> {
String tagName = tagData.getName();
String tagName = tagData.name;
tagName = tagName.substring(0, Math.min(tagName.length(), (int) maxLength));
SpannableString string = new SpannableString(SPACE + tagName + SPACE);
int themeIndex = tagData.getColor();
int themeIndex = tagData.color;
ThemeColor color =
themeIndex >= 0 ? themeCache.getThemeColor(themeIndex) : themeCache.getUntaggedColor();
string.setSpan(
@ -125,10 +177,28 @@ public class TagFormatter {
};
}
private TagData getTag(String uuid) {
TagData tagData = tagMap.get(uuid);
private ColoredString getGoogleTaskList(String remoteId) {
ColoredString googleTaskList = googleTaskLists.get(remoteId);
if (googleTaskList == null) {
googleTaskList = new ColoredString(googleTaskListDao.getByRemoteId(remoteId));
googleTaskLists.put(remoteId, googleTaskList);
}
return googleTaskList;
}
private ColoredString getCaldavCalendar(String uuid) {
ColoredString calendar = caldavCalendars.get(uuid);
if (calendar == null) {
calendar = new ColoredString(caldavDao.getCalendar(uuid));
caldavCalendars.put(uuid, calendar);
}
return calendar;
}
private ColoredString getTag(String uuid) {
ColoredString tagData = tagMap.get(uuid);
if (tagData == null) {
tagData = tagService.getTagByUuid(uuid);
tagData = new ColoredString(tagService.getTagByUuid(uuid));
tagMap.put(uuid, tagData);
}
return tagData;

@ -281,9 +281,8 @@ class ViewHolder extends RecyclerView.ViewHolder {
tagBlock.setVisibility(View.GONE);
} else {
String tags = task.getTagsString();
List<String> tagUuids = tags != null ? newArrayList(tags.split(",")) : Lists.newArrayList();
CharSequence tagString = tagFormatter.getTagString(tagUuids);
CharSequence tagString = tagFormatter.getTagString(task.getCaldav(), task.getGoogleTaskList(), tagUuids);
if (TextUtils.isEmpty(tagString)) {
tagBlock.setVisibility(View.GONE);
} else {

@ -1,6 +1,8 @@
package org.tasks.ui;
import static com.todoroo.astrid.activity.TaskListFragment.CALDAV_METADATA_JOIN;
import static com.todoroo.astrid.activity.TaskListFragment.FILE_METADATA_JOIN;
import static com.todoroo.astrid.activity.TaskListFragment.GTASK_METADATA_JOIN;
import static com.todoroo.astrid.activity.TaskListFragment.TAGS_METADATA_JOIN;
import android.arch.lifecycle.LiveData;
@ -12,12 +14,16 @@ import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Field;
import com.todoroo.andlib.sql.Join;
import com.todoroo.astrid.api.CaldavFilter;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.GtasksFilter;
import com.todoroo.astrid.api.TagFilter;
import com.todoroo.astrid.core.SortHelper;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task;
import javax.inject.Inject;
import org.tasks.data.CaldavTask;
import org.tasks.data.GoogleTask;
import org.tasks.data.LimitOffsetDataSource;
import org.tasks.data.Tag;
import org.tasks.data.TaskAttachment;
@ -62,11 +68,23 @@ public class TaskListViewModel extends ViewModel {
private LimitOffsetDataSource toDataSource(Filter filter, Property<?>[] properties) {
Criterion tagsJoinCriterion =
Criterion.and(Task.ID.eq(Field.field(TAGS_METADATA_JOIN + ".task")));
Criterion gtaskJoinCriterion =
Criterion.and(Task.ID.eq(Field.field(GTASK_METADATA_JOIN + ".task")));
Criterion caldavJoinCriterion =
Criterion.and(Task.ID.eq(Field.field(CALDAV_METADATA_JOIN + ".task")));
if (filter instanceof TagFilter) {
String uuid = ((TagFilter) filter).getUuid();
tagsJoinCriterion =
Criterion.and(tagsJoinCriterion, Field.field(TAGS_METADATA_JOIN + ".tag_uid").neq(uuid));
} else if (filter instanceof GtasksFilter) {
String listId = ((GtasksFilter) filter).getRemoteId();
gtaskJoinCriterion =
Criterion.and(gtaskJoinCriterion, Field.field(GTASK_METADATA_JOIN + ".list_id").neq(listId));
} else if (filter instanceof CaldavFilter) {
String uuid = ((CaldavFilter) filter).getUuid();
caldavJoinCriterion =
Criterion.and(
caldavJoinCriterion, Field.field(CALDAV_METADATA_JOIN + ".calendar").neq(uuid));
}
// TODO: For now, we'll modify the query to join and include the things like tag data here.
@ -77,6 +95,8 @@ public class TaskListViewModel extends ViewModel {
+ Join.left(
TaskAttachment.TABLE.as(FILE_METADATA_JOIN),
Task.UUID.eq(Field.field(FILE_METADATA_JOIN + ".task_id")))
+ Join.left(GoogleTask.TABLE.as(GTASK_METADATA_JOIN), gtaskJoinCriterion).toString()
+ Join.left(CaldavTask.TABLE.as(CALDAV_METADATA_JOIN), caldavJoinCriterion).toString()
+ filter.getSqlQuery();
String query =

Loading…
Cancel
Save