diff --git a/app/src/main/java/com/todoroo/astrid/dao/Database.java b/app/src/main/java/com/todoroo/astrid/dao/Database.java index afe908a2a..83c1add5b 100644 --- a/app/src/main/java/com/todoroo/astrid/dao/Database.java +++ b/app/src/main/java/com/todoroo/astrid/dao/Database.java @@ -58,7 +58,7 @@ import org.tasks.notifications.NotificationDao; CaldavAccount.class, GoogleTaskAccount.class }, - version = 70) + version = 71) public abstract class Database extends RoomDatabase { public static final String NAME = "database"; diff --git a/app/src/main/java/org/tasks/data/GoogleTask.java b/app/src/main/java/org/tasks/data/GoogleTask.java index e9d9ee8f2..d4b84ea00 100644 --- a/app/src/main/java/org/tasks/data/GoogleTask.java +++ b/app/src/main/java/org/tasks/data/GoogleTask.java @@ -71,6 +71,12 @@ public class GoogleTask { @ColumnInfo(name = "gt_deleted") private long deleted; + @ColumnInfo(name = "gt_email_description") + private String emailDescription; + + @ColumnInfo(name = "gt_email_url") + private String emailUrl; + public GoogleTask() {} @Ignore @@ -171,12 +177,28 @@ public class GoogleTask { this.remoteParent = remoteParent; } + public String getEmailDescription() { + return emailDescription; + } + + public void setEmailDescription(String emailDescription) { + this.emailDescription = emailDescription; + } + + public String getEmailUrl() { + return emailUrl; + } + + public void setEmailUrl(String emailUrl) { + this.emailUrl = emailUrl; + } + @Override public boolean equals(Object o) { if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { + if (!(o instanceof GoogleTask)) { return false; } @@ -212,9 +234,19 @@ public class GoogleTask { if (listId != null ? !listId.equals(that.listId) : that.listId != null) { return false; } - return remoteParent != null - ? remoteParent.equals(that.remoteParent) - : that.remoteParent == null; + if (remoteParent != null + ? !remoteParent.equals(that.remoteParent) + : that.remoteParent != null) { + return false; + } + if (emailDescription != null + ? !emailDescription.equals(that.emailDescription) + : that.emailDescription != null) { + return false; + } + return emailUrl != null + ? emailUrl.equals(that.emailUrl) + : that.emailUrl == null; } @Override @@ -224,12 +256,15 @@ public class GoogleTask { result = 31 * result + (remoteId != null ? remoteId.hashCode() : 0); result = 31 * result + (listId != null ? listId.hashCode() : 0); result = 31 * result + (int) (parent ^ (parent >>> 32)); + result = 31 * result + (remoteParent != null ? remoteParent.hashCode() : 0); result = 31 * result + (moved ? 1 : 0); result = 31 * result + (int) (order ^ (order >>> 32)); - result = 31 * result + (remoteParent != null ? remoteParent.hashCode() : 0); result = 31 * result + (int) (remoteOrder ^ (remoteOrder >>> 32)); result = 31 * result + (int) (lastSync ^ (lastSync >>> 32)); result = 31 * result + (int) (deleted ^ (deleted >>> 32)); + result = + 31 * result + (emailDescription != null ? emailDescription.hashCode() : 0); + result = 31 * result + (emailUrl != null ? emailUrl.hashCode() : 0); return result; } @@ -248,19 +283,25 @@ public class GoogleTask { + '\'' + ", parent=" + parent + + ", remoteParent='" + + remoteParent + + '\'' + ", moved=" + moved + ", order=" + order - + ", remoteParent='" - + remoteParent - + '\'' + ", remoteOrder=" + remoteOrder + ", lastSync=" + lastSync + ", deleted=" + deleted + + ", relatedEmailDescription='" + + emailDescription + + '\'' + + ", relatedEmailUrl='" + + emailUrl + + '\'' + '}'; } } diff --git a/app/src/main/java/org/tasks/data/SubsetGoogleTask.java b/app/src/main/java/org/tasks/data/SubsetGoogleTask.java index de5a1769c..863313892 100644 --- a/app/src/main/java/org/tasks/data/SubsetGoogleTask.java +++ b/app/src/main/java/org/tasks/data/SubsetGoogleTask.java @@ -1,11 +1,15 @@ package org.tasks.data; +import com.google.common.base.Strings; + public class SubsetGoogleTask { public long gt_id; public long gt_parent; public String gt_list_id; public long gt_order; + public String gt_email_description; + public String gt_email_url; public long getId() { return gt_id; @@ -35,6 +39,14 @@ public class SubsetGoogleTask { return gt_parent > 0 ? 1 : 0; } + public String getEmailDescription() { + return gt_email_description; + } + + public String getEmailUrl() { + return gt_email_url; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -55,7 +67,17 @@ public class SubsetGoogleTask { if (gt_order != that.gt_order) { return false; } - return gt_list_id != null ? gt_list_id.equals(that.gt_list_id) : that.gt_list_id == null; + if (gt_list_id != null ? !gt_list_id.equals(that.gt_list_id) : that.gt_list_id != null) { + return false; + } + if (gt_email_description != null + ? !gt_email_description.equals(that.gt_email_description) + : that.gt_email_description != null) { + return false; + } + return gt_email_url != null + ? gt_email_url.equals(that.gt_email_url) + : that.gt_email_url == null; } @Override @@ -64,6 +86,8 @@ public class SubsetGoogleTask { result = 31 * result + (int) (gt_parent ^ (gt_parent >>> 32)); result = 31 * result + (gt_list_id != null ? gt_list_id.hashCode() : 0); result = 31 * result + (int) (gt_order ^ (gt_order >>> 32)); + result = 31 * result + (gt_email_description != null ? gt_email_description.hashCode() : 0); + result = 31 * result + (gt_email_url != null ? gt_email_url.hashCode() : 0); return result; } @@ -79,6 +103,16 @@ public class SubsetGoogleTask { + '\'' + ", gt_order=" + gt_order + + ", gt_email_description='" + + gt_email_description + + '\'' + + ", gt_email_url='" + + gt_email_url + + '\'' + '}'; } + + public boolean hasRelatedEmail() { + return !Strings.isNullOrEmpty(gt_email_url); + } } diff --git a/app/src/main/java/org/tasks/db/Migrations.java b/app/src/main/java/org/tasks/db/Migrations.java index b31916b00..3b6cb06c1 100644 --- a/app/src/main/java/org/tasks/db/Migrations.java +++ b/app/src/main/java/org/tasks/db/Migrations.java @@ -381,6 +381,16 @@ public class Migrations { } }; + private static final Migration MIGRATION_70_71 = + new Migration(70, 71) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + database.execSQL( + "ALTER TABLE `google_tasks` ADD COLUMN `gt_email_description` TEXT"); + database.execSQL("ALTER TABLE `google_tasks` ADD COLUMN `gt_email_url` TEXT"); + } + }; + public static final Migration[] MIGRATIONS = new Migration[] { MIGRATION_35_36, @@ -408,7 +418,8 @@ public class Migrations { MIGRATION_66_67, MIGRATION_67_68, MIGRATION_68_69, - MIGRATION_69_70 + MIGRATION_69_70, + MIGRATION_70_71 }; private static Migration NOOP(int from, int to) { diff --git a/app/src/main/java/org/tasks/gtasks/GoogleTaskSynchronizer.java b/app/src/main/java/org/tasks/gtasks/GoogleTaskSynchronizer.java index c0a0cc352..700caf59d 100644 --- a/app/src/main/java/org/tasks/gtasks/GoogleTaskSynchronizer.java +++ b/app/src/main/java/org/tasks/gtasks/GoogleTaskSynchronizer.java @@ -11,6 +11,7 @@ import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.services.tasks.model.Task.Links; import com.google.api.services.tasks.model.TaskList; import com.google.api.services.tasks.model.TaskLists; import com.google.api.services.tasks.model.Tasks; @@ -475,7 +476,12 @@ public class GoogleTaskSynchronizer { if (task == null) { task = taskCreator.createWithValues(""); } - + List links = gtask.getLinks(); + if (!links.isEmpty()) { + Links link = links.get(0); + googleTask.setEmailDescription(link.getDescription()); + googleTask.setEmailUrl(link.getLink()); + } task.setTitle(getTruncatedValue(task.getTitle(), gtask.getTitle(), MAX_TITLE_LENGTH)); task.setCreationDate(DateUtilities.now()); task.setCompletionDate( diff --git a/app/src/main/java/org/tasks/tasklist/ViewHolder.java b/app/src/main/java/org/tasks/tasklist/ViewHolder.java index 1b6900ccb..dbf3fd8ea 100644 --- a/app/src/main/java/org/tasks/tasklist/ViewHolder.java +++ b/app/src/main/java/org/tasks/tasklist/ViewHolder.java @@ -6,7 +6,11 @@ import static com.todoroo.andlib.utility.DateUtilities.getAbbreviatedRelativeDat import android.annotation.SuppressLint; import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.graphics.Paint; +import android.net.Uri; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; @@ -20,14 +24,13 @@ import butterknife.OnClick; import butterknife.OnLongClick; import com.google.android.material.chip.Chip; import com.google.android.material.chip.ChipGroup; -import com.todoroo.astrid.api.CaldavFilter; import com.todoroo.astrid.api.Filter; -import com.todoroo.astrid.api.GtasksFilter; import com.todoroo.astrid.service.TaskCompleter; import com.todoroo.astrid.ui.CheckableImageView; import java.util.List; import org.tasks.R; import org.tasks.data.Location; +import org.tasks.data.SubsetGoogleTask; import org.tasks.data.TaskContainer; import org.tasks.dialogs.Linkify; import org.tasks.preferences.Preferences; @@ -290,6 +293,20 @@ public class ViewHolder extends RecyclerView.ViewHolder { } else if (tag instanceof TaskContainer) { TaskContainer task = (TaskContainer) tag; callback.toggleSubtasks(task, !task.isCollapsed()); + } else if (tag instanceof SubsetGoogleTask) { + String url = ((SubsetGoogleTask) tag).getEmailUrl(); + Intent intent = new Intent("com.google.android.gm.intent.VIEW_MESSAGE_DEEPLINK"); + intent.putExtra("messageStorageId", url.substring(url.lastIndexOf("/") + 1)); + intent.setPackage("com.google.android.gm"); + List resolveInfos = + context + .getPackageManager() + .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + if (resolveInfos.isEmpty()) { + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + } else { + context.startActivityForResult(intent, 11111); + } } } diff --git a/app/src/main/java/org/tasks/ui/ChipProvider.java b/app/src/main/java/org/tasks/ui/ChipProvider.java index de4b59b88..18de38296 100644 --- a/app/src/main/java/org/tasks/ui/ChipProvider.java +++ b/app/src/main/java/org/tasks/ui/ChipProvider.java @@ -10,6 +10,7 @@ import static com.todoroo.andlib.utility.AndroidUtilities.assertMainThread; import android.app.Activity; import android.content.Context; import android.content.res.ColorStateList; +import android.text.TextUtils.TruncateAt; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -35,6 +36,7 @@ import org.tasks.data.CaldavCalendar; import org.tasks.data.CaldavDao; import org.tasks.data.GoogleTaskList; import org.tasks.data.GoogleTaskListDao; +import org.tasks.data.SubsetGoogleTask; import org.tasks.data.TagData; import org.tasks.data.TagDataDao; import org.tasks.data.TaskContainer; @@ -134,6 +136,16 @@ public class ChipProvider { task.getLocation().getDisplayName(), task.getLocation())); } + SubsetGoogleTask googleTask = task.getGoogleTask(); + if (googleTask != null && googleTask.hasRelatedEmail()) { + Chip chip = newIconChip( + activity, + R.drawable.ic_outline_email_24px, + googleTask.getEmailDescription(), + googleTask); + chip.setEllipsize(TruncateAt.END); + chips.add(chip); + } if (!isSubtask) { if (!Strings.isNullOrEmpty(task.getGoogleTaskList()) && !(filter instanceof GtasksFilter)) { chips.add(newTagChip(activity, googleTaskLists.get(task.getGoogleTaskList())));