mirror of https://github.com/tasks/tasks
Convert GtasksInvoker to Kotlin
parent
90571eca35
commit
b7b8d1667b
@ -1,198 +0,0 @@
|
|||||||
package com.todoroo.astrid.gtasks.api;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import com.google.api.client.http.HttpRequest;
|
|
||||||
import com.google.api.client.http.HttpResponseException;
|
|
||||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
|
||||||
import com.google.api.client.json.GenericJson;
|
|
||||||
import com.google.api.client.json.jackson2.JacksonFactory;
|
|
||||||
import com.google.api.services.tasks.Tasks;
|
|
||||||
import com.google.api.services.tasks.TasksRequest;
|
|
||||||
import com.google.api.services.tasks.TasksScopes;
|
|
||||||
import com.google.api.services.tasks.model.Task;
|
|
||||||
import com.google.api.services.tasks.model.TaskList;
|
|
||||||
import com.google.api.services.tasks.model.TaskLists;
|
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext;
|
|
||||||
import java.io.IOException;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import org.tasks.BuildConfig;
|
|
||||||
import org.tasks.DebugNetworkInterceptor;
|
|
||||||
import org.tasks.gtasks.GoogleAccountManager;
|
|
||||||
import org.tasks.preferences.Preferences;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper around the official Google Tasks API to simplify common operations. In the case of an
|
|
||||||
* exception, each request is tried twice in case of a timeout.
|
|
||||||
*
|
|
||||||
* @author Sam Bosley
|
|
||||||
*/
|
|
||||||
public class GtasksInvoker {
|
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
private final GoogleAccountManager googleAccountManager;
|
|
||||||
private final Preferences preferences;
|
|
||||||
private final DebugNetworkInterceptor interceptor;
|
|
||||||
private final String account;
|
|
||||||
private final Tasks service;
|
|
||||||
private final HttpCredentialsAdapter credentialsAdapter;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public GtasksInvoker(
|
|
||||||
@ApplicationContext Context context,
|
|
||||||
GoogleAccountManager googleAccountManager,
|
|
||||||
Preferences preferences,
|
|
||||||
DebugNetworkInterceptor interceptor) {
|
|
||||||
this.context = context;
|
|
||||||
this.googleAccountManager = googleAccountManager;
|
|
||||||
this.preferences = preferences;
|
|
||||||
this.interceptor = interceptor;
|
|
||||||
account = null;
|
|
||||||
service = null;
|
|
||||||
credentialsAdapter = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GtasksInvoker(
|
|
||||||
Context context,
|
|
||||||
GoogleAccountManager googleAccountManager,
|
|
||||||
Preferences preferences,
|
|
||||||
DebugNetworkInterceptor interceptor,
|
|
||||||
String account) {
|
|
||||||
this.context = context;
|
|
||||||
this.googleAccountManager = googleAccountManager;
|
|
||||||
this.preferences = preferences;
|
|
||||||
this.interceptor = interceptor;
|
|
||||||
this.account = account;
|
|
||||||
|
|
||||||
credentialsAdapter = new HttpCredentialsAdapter(googleAccountManager);
|
|
||||||
service =
|
|
||||||
new Tasks.Builder(new NetHttpTransport(), new JacksonFactory(), credentialsAdapter)
|
|
||||||
.setApplicationName(String.format("Tasks/%s", BuildConfig.VERSION_NAME))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public GtasksInvoker forAccount(String account) {
|
|
||||||
return new GtasksInvoker(context, googleAccountManager, preferences, interceptor, account);
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable TaskLists allGtaskLists(@Nullable String pageToken) throws IOException {
|
|
||||||
return execute(service.tasklists().list().setMaxResults(100L).setPageToken(pageToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable com.google.api.services.tasks.model.Tasks getAllGtasksFromListId(
|
|
||||||
String listId, long lastSyncDate, @Nullable String pageToken) throws IOException {
|
|
||||||
return execute(
|
|
||||||
service
|
|
||||||
.tasks()
|
|
||||||
.list(listId)
|
|
||||||
.setMaxResults(100L)
|
|
||||||
.setShowDeleted(true)
|
|
||||||
.setShowHidden(true)
|
|
||||||
.setPageToken(pageToken)
|
|
||||||
.setUpdatedMin(
|
|
||||||
GtasksApiUtilities.unixTimeToGtasksCompletionTime(lastSyncDate).toStringRfc3339()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public com.google.api.services.tasks.model.Tasks getAllPositions(
|
|
||||||
String listId, @Nullable String pageToken) throws IOException {
|
|
||||||
return execute(
|
|
||||||
service
|
|
||||||
.tasks()
|
|
||||||
.list(listId)
|
|
||||||
.setMaxResults(100L)
|
|
||||||
.setShowDeleted(false)
|
|
||||||
.setShowHidden(false)
|
|
||||||
.setPageToken(pageToken)
|
|
||||||
.setFields("items(id,parent,position),nextPageToken"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable Task createGtask(
|
|
||||||
String listId, Task task, @Nullable String parent, @Nullable String previous)
|
|
||||||
throws IOException {
|
|
||||||
return execute(service.tasks().insert(listId, task).setParent(parent).setPrevious(previous));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateGtask(String listId, Task task) throws IOException {
|
|
||||||
execute(service.tasks().update(listId, task.getId(), task));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Task moveGtask(String listId, String taskId, String parentId, String previousId)
|
|
||||||
throws IOException {
|
|
||||||
return execute(
|
|
||||||
service.tasks().move(listId, taskId).setParent(parentId).setPrevious(previousId));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteGtaskList(String listId) throws IOException {
|
|
||||||
try {
|
|
||||||
execute(service.tasklists().delete(listId));
|
|
||||||
} catch (HttpNotFoundException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable TaskList renameGtaskList(String listId, String title) throws IOException {
|
|
||||||
return execute(service.tasklists().patch(listId, new TaskList().setTitle(title)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable TaskList createGtaskList(String title) throws IOException {
|
|
||||||
return execute(service.tasklists().insert(new TaskList().setTitle(title)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteGtask(String listId, String taskId) throws IOException {
|
|
||||||
try {
|
|
||||||
execute(service.tasks().delete(listId, taskId));
|
|
||||||
} catch (HttpNotFoundException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized @Nullable <T> T execute(TasksRequest<T> request) throws IOException {
|
|
||||||
return execute(request, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized @Nullable <T> T execute(TasksRequest<T> request, boolean retry)
|
|
||||||
throws IOException {
|
|
||||||
credentialsAdapter.checkToken(account, TasksScopes.TASKS);
|
|
||||||
T response;
|
|
||||||
try {
|
|
||||||
HttpRequest httpRequest = request.buildHttpRequest();
|
|
||||||
Timber.d("%s", httpRequest.getUrl());
|
|
||||||
if (preferences.isFlipperEnabled()) {
|
|
||||||
response = interceptor.execute(httpRequest, request.getResponseClass());
|
|
||||||
} else {
|
|
||||||
response = httpRequest.execute().parseAs(request.getResponseClass());
|
|
||||||
}
|
|
||||||
} catch (HttpResponseException e) {
|
|
||||||
if (e.getStatusCode() == 401 && !retry) {
|
|
||||||
credentialsAdapter.invalidateToken();
|
|
||||||
return execute(request, true);
|
|
||||||
} else if (e.getStatusCode() == 404) {
|
|
||||||
throw new HttpNotFoundException(e);
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Timber.d("%s response: %s", getCaller(retry), prettyPrint(response));
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> Object prettyPrint(T object) throws IOException {
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
if (object instanceof GenericJson) {
|
|
||||||
return ((GenericJson) object).toPrettyString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCaller(boolean retry) {
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
try {
|
|
||||||
return Thread.currentThread().getStackTrace()[retry ? 6 : 5].getMethodName();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Timber.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,204 @@
|
|||||||
|
package com.todoroo.astrid.gtasks.api
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.google.api.client.http.HttpResponseException
|
||||||
|
import com.google.api.client.http.javanet.NetHttpTransport
|
||||||
|
import com.google.api.client.json.GenericJson
|
||||||
|
import com.google.api.client.json.jackson2.JacksonFactory
|
||||||
|
import com.google.api.services.tasks.Tasks
|
||||||
|
import com.google.api.services.tasks.TasksRequest
|
||||||
|
import com.google.api.services.tasks.TasksScopes
|
||||||
|
import com.google.api.services.tasks.model.Task
|
||||||
|
import com.google.api.services.tasks.model.TaskList
|
||||||
|
import com.google.api.services.tasks.model.TaskLists
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import org.tasks.BuildConfig
|
||||||
|
import org.tasks.DebugNetworkInterceptor
|
||||||
|
import org.tasks.gtasks.GoogleAccountManager
|
||||||
|
import org.tasks.preferences.Preferences
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.io.IOException
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around the official Google Tasks API to simplify common operations. In the case of an
|
||||||
|
* exception, each request is tried twice in case of a timeout.
|
||||||
|
*
|
||||||
|
* @author Sam Bosley
|
||||||
|
*/
|
||||||
|
class GtasksInvoker {
|
||||||
|
private val context: Context
|
||||||
|
private val googleAccountManager: GoogleAccountManager
|
||||||
|
private val preferences: Preferences
|
||||||
|
private val interceptor: DebugNetworkInterceptor
|
||||||
|
private val account: String?
|
||||||
|
private val service: Tasks?
|
||||||
|
private val credentialsAdapter: HttpCredentialsAdapter?
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
@ApplicationContext context: Context,
|
||||||
|
googleAccountManager: GoogleAccountManager,
|
||||||
|
preferences: Preferences,
|
||||||
|
interceptor: DebugNetworkInterceptor) {
|
||||||
|
this.context = context
|
||||||
|
this.googleAccountManager = googleAccountManager
|
||||||
|
this.preferences = preferences
|
||||||
|
this.interceptor = interceptor
|
||||||
|
account = null
|
||||||
|
service = null
|
||||||
|
credentialsAdapter = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructor(
|
||||||
|
context: Context,
|
||||||
|
googleAccountManager: GoogleAccountManager,
|
||||||
|
preferences: Preferences,
|
||||||
|
interceptor: DebugNetworkInterceptor,
|
||||||
|
account: String) {
|
||||||
|
this.context = context
|
||||||
|
this.googleAccountManager = googleAccountManager
|
||||||
|
this.preferences = preferences
|
||||||
|
this.interceptor = interceptor
|
||||||
|
this.account = account
|
||||||
|
credentialsAdapter = HttpCredentialsAdapter(googleAccountManager)
|
||||||
|
service = Tasks.Builder(NetHttpTransport(), JacksonFactory(), credentialsAdapter)
|
||||||
|
.setApplicationName(String.format("Tasks/%s", BuildConfig.VERSION_NAME))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forAccount(account: String): GtasksInvoker {
|
||||||
|
return GtasksInvoker(context, googleAccountManager, preferences, interceptor, account)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun allGtaskLists(pageToken: String?): TaskLists? {
|
||||||
|
return execute(service!!.tasklists().list().setMaxResults(100L).setPageToken(pageToken))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun getAllGtasksFromListId(
|
||||||
|
listId: String?, lastSyncDate: Long, pageToken: String?): com.google.api.services.tasks.model.Tasks? {
|
||||||
|
return execute(
|
||||||
|
service!!
|
||||||
|
.tasks()
|
||||||
|
.list(listId)
|
||||||
|
.setMaxResults(100L)
|
||||||
|
.setShowDeleted(true)
|
||||||
|
.setShowHidden(true)
|
||||||
|
.setPageToken(pageToken)
|
||||||
|
.setUpdatedMin(
|
||||||
|
GtasksApiUtilities.unixTimeToGtasksCompletionTime(lastSyncDate).toStringRfc3339()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun getAllPositions(
|
||||||
|
listId: String?, pageToken: String?): com.google.api.services.tasks.model.Tasks {
|
||||||
|
return execute(
|
||||||
|
service!!
|
||||||
|
.tasks()
|
||||||
|
.list(listId)
|
||||||
|
.setMaxResults(100L)
|
||||||
|
.setShowDeleted(false)
|
||||||
|
.setShowHidden(false)
|
||||||
|
.setPageToken(pageToken)
|
||||||
|
.setFields("items(id,parent,position),nextPageToken"))!!
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun createGtask(
|
||||||
|
listId: String?, task: Task?, parent: String?, previous: String?): Task? {
|
||||||
|
return execute(service!!.tasks().insert(listId, task).setParent(parent).setPrevious(previous))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun updateGtask(listId: String?, task: Task) {
|
||||||
|
execute(service!!.tasks().update(listId, task.id, task))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun moveGtask(listId: String?, taskId: String?, parentId: String?, previousId: String?): Task? {
|
||||||
|
return execute(
|
||||||
|
service!!.tasks().move(listId, taskId).setParent(parentId).setPrevious(previousId))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun deleteGtaskList(listId: String?) {
|
||||||
|
try {
|
||||||
|
execute(service!!.tasklists().delete(listId))
|
||||||
|
} catch (ignored: HttpNotFoundException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun renameGtaskList(listId: String?, title: String?): TaskList? {
|
||||||
|
return execute(service!!.tasklists().patch(listId, TaskList().setTitle(title)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun createGtaskList(title: String?): TaskList? {
|
||||||
|
return execute(service!!.tasklists().insert(TaskList().setTitle(title)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun deleteGtask(listId: String?, taskId: String?) {
|
||||||
|
try {
|
||||||
|
execute(service!!.tasks().delete(listId, taskId))
|
||||||
|
} catch (ignored: HttpNotFoundException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun <T> execute(request: TasksRequest<T>): T? {
|
||||||
|
return execute(request, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun <T> execute(request: TasksRequest<T>, retry: Boolean): T? {
|
||||||
|
credentialsAdapter!!.checkToken(account, TasksScopes.TASKS)
|
||||||
|
val response: T?
|
||||||
|
response = try {
|
||||||
|
val httpRequest = request.buildHttpRequest()
|
||||||
|
Timber.d("%s", httpRequest.url)
|
||||||
|
if (preferences.isFlipperEnabled) {
|
||||||
|
interceptor.execute(httpRequest, request.responseClass)
|
||||||
|
} else {
|
||||||
|
httpRequest.execute().parseAs(request.responseClass)
|
||||||
|
}
|
||||||
|
} catch (e: HttpResponseException) {
|
||||||
|
return if (e.statusCode == 401 && !retry) {
|
||||||
|
credentialsAdapter.invalidateToken()
|
||||||
|
execute(request, true)
|
||||||
|
} else if (e.statusCode == 404) {
|
||||||
|
throw HttpNotFoundException(e)
|
||||||
|
} else {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Timber.d("%s response: %s", getCaller(retry), prettyPrint(response))
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun <T> prettyPrint(`object`: T?): Any? {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
if (`object` is GenericJson) {
|
||||||
|
return (`object` as GenericJson).toPrettyString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `object`
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCaller(retry: Boolean): String {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
try {
|
||||||
|
return Thread.currentThread().stackTrace[if (retry) 6 else 5].methodName
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue