Convert GCalHelper to Kotlin

pull/1055/head
Alex Baker 4 years ago
parent c3c5de1e5c
commit bfe97e77de

@ -1,203 +0,0 @@
/*
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.gcal;
import static org.tasks.Strings.isNullOrEmpty;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.provider.CalendarContract;
import android.text.format.Time;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.dao.TaskDaoBlocking;
import com.todoroo.astrid.data.Task;
import dagger.hilt.android.qualifiers.ApplicationContext;
import java.util.TimeZone;
import javax.inject.Inject;
import org.tasks.R;
import org.tasks.calendars.AndroidCalendarEvent;
import org.tasks.calendars.CalendarEventProvider;
import org.tasks.preferences.PermissionChecker;
import org.tasks.preferences.Preferences;
import timber.log.Timber;
public class GCalHelper {
/** If task has no estimated time, how early to set a task in calendar (seconds) */
private static final long DEFAULT_CAL_TIME = DateUtilities.ONE_HOUR;
private final TaskDaoBlocking taskDao;
private final Preferences preferences;
private final PermissionChecker permissionChecker;
private final CalendarEventProvider calendarEventProvider;
private final ContentResolver cr;
@Inject
public GCalHelper(
@ApplicationContext Context context,
TaskDaoBlocking taskDao,
Preferences preferences,
PermissionChecker permissionChecker,
CalendarEventProvider calendarEventProvider) {
this.taskDao = taskDao;
this.preferences = preferences;
this.permissionChecker = permissionChecker;
this.calendarEventProvider = calendarEventProvider;
cr = context.getContentResolver();
}
private String getTaskEventUri(Task task) {
String uri;
if (!isNullOrEmpty(task.getCalendarURI())) {
uri = task.getCalendarURI();
} else {
task = taskDao.fetchBlocking(task.getId());
if (task == null) {
return null;
}
uri = task.getCalendarURI();
}
return uri;
}
public void createTaskEventIfEnabled(Task t) {
if (!t.hasDueDate()) {
return;
}
createTaskEventIfEnabled(t, true);
}
private void createTaskEventIfEnabled(Task t, boolean deleteEventIfExists) {
if (preferences.isDefaultCalendarSet()) {
Uri calendarUri = createTaskEvent(t, new ContentValues(), deleteEventIfExists);
if (calendarUri != null) {
t.setCalendarURI(calendarUri.toString());
}
}
}
public Uri createTaskEvent(Task task, String calendarId) {
ContentValues values = new ContentValues();
values.put(CalendarContract.Events.CALENDAR_ID, calendarId);
return createTaskEvent(task, values, true);
}
private Uri createTaskEvent(Task task, ContentValues values, boolean deleteEventIfExists) {
if (!permissionChecker.canAccessCalendars()) {
return null;
}
String eventuri = getTaskEventUri(task);
if (!isNullOrEmpty(eventuri) && deleteEventIfExists) {
calendarEventProvider.deleteEvent(task);
}
try {
values.put(CalendarContract.Events.TITLE, task.getTitle());
values.put(CalendarContract.Events.DESCRIPTION, task.getNotes());
values.put(CalendarContract.Events.HAS_ALARM, 0);
boolean valuesContainCalendarId =
(values.containsKey(CalendarContract.Events.CALENDAR_ID)
&& !isNullOrEmpty(values.getAsString(CalendarContract.Events.CALENDAR_ID)));
if (!valuesContainCalendarId) {
String calendarId = preferences.getDefaultCalendar();
if (!isNullOrEmpty(calendarId)) {
values.put(CalendarContract.Events.CALENDAR_ID, calendarId);
}
}
createStartAndEndDate(task, values);
//noinspection MissingPermission
Uri eventUri = cr.insert(CalendarContract.Events.CONTENT_URI, values);
cr.notifyChange(eventUri, null);
return eventUri;
} catch (Exception e) {
// won't work on emulator
Timber.e(e);
}
return null;
}
public void updateEvent(String uri, Task task) {
try {
ContentValues updateValues = new ContentValues();
// check if we need to update the item
updateValues.put(CalendarContract.Events.TITLE, task.getTitle());
updateValues.put(CalendarContract.Events.DESCRIPTION, task.getNotes());
createStartAndEndDate(task, updateValues);
cr.update(Uri.parse(uri), updateValues, null, null);
} catch (Exception e) {
Timber.e(e, "Failed to update calendar: %s [%s]", uri, task);
}
}
public void rescheduleRepeatingTask(Task task) {
String taskUri = getTaskEventUri(task);
if (isNullOrEmpty(taskUri)) {
return;
}
Uri eventUri = Uri.parse(taskUri);
AndroidCalendarEvent event = calendarEventProvider.getEvent(eventUri);
if (event == null) {
task.setCalendarURI("");
return;
}
ContentValues cv = new ContentValues();
cv.put(CalendarContract.Events.CALENDAR_ID, event.getCalendarId());
Uri uri = createTaskEvent(task, cv, false);
task.setCalendarURI(uri.toString());
}
public void createStartAndEndDate(Task task, ContentValues values) {
long dueDate = task.getDueDate();
long tzCorrectedDueDate = dueDate + TimeZone.getDefault().getOffset(dueDate);
long tzCorrectedDueDateNow =
DateUtilities.now() + TimeZone.getDefault().getOffset(DateUtilities.now());
// FIXME: doesnt respect timezones, see story 17443653
if (task.hasDueDate()) {
if (task.hasDueTime()) {
long estimatedTime = task.getEstimatedSeconds() * 1000;
if (estimatedTime <= 0) {
estimatedTime = DEFAULT_CAL_TIME;
}
if (preferences.getBoolean(R.string.p_end_at_deadline, true)) {
values.put(CalendarContract.Events.DTSTART, dueDate);
values.put(CalendarContract.Events.DTEND, dueDate + estimatedTime);
} else {
values.put(CalendarContract.Events.DTSTART, dueDate - estimatedTime);
values.put(CalendarContract.Events.DTEND, dueDate);
}
// setting a duetime to a previously timeless event requires explicitly setting allDay=0
values.put(CalendarContract.Events.ALL_DAY, "0");
values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
} else {
values.put(CalendarContract.Events.DTSTART, tzCorrectedDueDate);
values.put(CalendarContract.Events.DTEND, tzCorrectedDueDate);
values.put(CalendarContract.Events.ALL_DAY, "1");
}
} else {
values.put(CalendarContract.Events.DTSTART, tzCorrectedDueDateNow);
values.put(CalendarContract.Events.DTEND, tzCorrectedDueDateNow);
values.put(CalendarContract.Events.ALL_DAY, "1");
}
if ("1".equals(values.get(CalendarContract.Events.ALL_DAY))) {
values.put(CalendarContract.Events.EVENT_TIMEZONE, Time.TIMEZONE_UTC);
} else {
values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
}
}
}

@ -0,0 +1,169 @@
/*
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.gcal
import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.net.Uri
import android.provider.CalendarContract
import android.text.format.Time
import com.todoroo.andlib.utility.DateUtilities
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.data.Task
import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.calendars.CalendarEventProvider
import org.tasks.preferences.PermissionChecker
import org.tasks.preferences.Preferences
import timber.log.Timber
import java.util.*
import javax.inject.Inject
class GCalHelper @Inject constructor(
@ApplicationContext context: Context,
private val taskDao: TaskDao,
private val preferences: Preferences,
private val permissionChecker: PermissionChecker,
private val calendarEventProvider: CalendarEventProvider) {
private val cr: ContentResolver = context.contentResolver
private suspend fun getTaskEventUri(task: Task) =
if (!task.calendarURI.isNullOrBlank()) {
task.calendarURI
} else {
taskDao.fetch(task.id)
?.calendarURI
}
suspend fun createTaskEventIfEnabled(t: Task) {
if (!t.hasDueDate()) {
return
}
createTaskEventIfEnabled(t, true)
}
private suspend fun createTaskEventIfEnabled(t: Task, deleteEventIfExists: Boolean) {
if (preferences.isDefaultCalendarSet) {
val calendarUri = createTaskEvent(t, ContentValues(), deleteEventIfExists)
if (calendarUri != null) {
t.calendarURI = calendarUri.toString()
}
}
}
suspend fun createTaskEvent(task: Task, calendarId: String?): Uri? {
val values = ContentValues()
values.put(CalendarContract.Events.CALENDAR_ID, calendarId)
return createTaskEvent(task, values, true)
}
private suspend fun createTaskEvent(task: Task, values: ContentValues, deleteEventIfExists: Boolean): Uri? {
if (!permissionChecker.canAccessCalendars()) {
return null
}
val eventuri = getTaskEventUri(task)
if (!isNullOrEmpty(eventuri) && deleteEventIfExists) {
calendarEventProvider.deleteEvent(task)
}
try {
values.put(CalendarContract.Events.TITLE, task.title)
values.put(CalendarContract.Events.DESCRIPTION, task.notes)
values.put(CalendarContract.Events.HAS_ALARM, 0)
val valuesContainCalendarId = (values.containsKey(CalendarContract.Events.CALENDAR_ID)
&& !isNullOrEmpty(values.getAsString(CalendarContract.Events.CALENDAR_ID)))
if (!valuesContainCalendarId) {
val calendarId = preferences.defaultCalendar
if (!isNullOrEmpty(calendarId)) {
values.put(CalendarContract.Events.CALENDAR_ID, calendarId)
}
}
createStartAndEndDate(task, values)
val eventUri = cr.insert(CalendarContract.Events.CONTENT_URI, values)
cr.notifyChange(eventUri!!, null)
return eventUri
} catch (e: Exception) {
// won't work on emulator
Timber.e(e)
}
return null
}
fun updateEvent(uri: String?, task: Task) {
try {
val updateValues = ContentValues()
// check if we need to update the item
updateValues.put(CalendarContract.Events.TITLE, task.title)
updateValues.put(CalendarContract.Events.DESCRIPTION, task.notes)
createStartAndEndDate(task, updateValues)
cr.update(Uri.parse(uri), updateValues, null, null)
} catch (e: Exception) {
Timber.e(e, "Failed to update calendar: %s [%s]", uri, task)
}
}
suspend fun rescheduleRepeatingTask(task: Task) {
val taskUri = getTaskEventUri(task)
if (isNullOrEmpty(taskUri)) {
return
}
val eventUri = Uri.parse(taskUri)
val event = calendarEventProvider.getEvent(eventUri)
if (event == null) {
task.calendarURI = ""
return
}
val cv = ContentValues()
cv.put(CalendarContract.Events.CALENDAR_ID, event.calendarId)
val uri = createTaskEvent(task, cv, false)
task.calendarURI = uri.toString()
}
private fun createStartAndEndDate(task: Task, values: ContentValues) {
val dueDate = task.dueDate
val tzCorrectedDueDate = dueDate + TimeZone.getDefault().getOffset(dueDate)
val tzCorrectedDueDateNow = DateUtilities.now() + TimeZone.getDefault().getOffset(DateUtilities.now())
// FIXME: doesnt respect timezones, see story 17443653
if (task.hasDueDate()) {
if (task.hasDueTime()) {
var estimatedTime = task.estimatedSeconds * 1000.toLong()
if (estimatedTime <= 0) {
estimatedTime = DEFAULT_CAL_TIME
}
if (preferences.getBoolean(R.string.p_end_at_deadline, true)) {
values.put(CalendarContract.Events.DTSTART, dueDate)
values.put(CalendarContract.Events.DTEND, dueDate + estimatedTime)
} else {
values.put(CalendarContract.Events.DTSTART, dueDate - estimatedTime)
values.put(CalendarContract.Events.DTEND, dueDate)
}
// setting a duetime to a previously timeless event requires explicitly setting allDay=0
values.put(CalendarContract.Events.ALL_DAY, "0")
values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().id)
} else {
values.put(CalendarContract.Events.DTSTART, tzCorrectedDueDate)
values.put(CalendarContract.Events.DTEND, tzCorrectedDueDate)
values.put(CalendarContract.Events.ALL_DAY, "1")
}
} else {
values.put(CalendarContract.Events.DTSTART, tzCorrectedDueDateNow)
values.put(CalendarContract.Events.DTEND, tzCorrectedDueDateNow)
values.put(CalendarContract.Events.ALL_DAY, "1")
}
if ("1" == values[CalendarContract.Events.ALL_DAY]) {
values.put(CalendarContract.Events.EVENT_TIMEZONE, Time.TIMEZONE_UTC)
} else {
values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().id)
}
}
companion object {
/** If task has no estimated time, how early to set a task in calendar (seconds) */
private const val DEFAULT_CAL_TIME = DateUtilities.ONE_HOUR
}
}

@ -382,7 +382,7 @@ class TaskEditViewModel @ViewModelInject constructor(
true
} ?: false
private fun applyCalendarChanges() {
private suspend fun applyCalendarChanges() {
if (!permissionChecker.canAccessCalendars()) {
return
}
@ -398,7 +398,7 @@ class TaskEditViewModel @ViewModelInject constructor(
}
selectedCalendar?.let {
try {
task?.calendarURI = gCalHelper.createTaskEvent(task, it)?.toString()
task?.calendarURI = gCalHelper.createTaskEvent(task!!, it)?.toString()
} catch (e: Exception) {
Timber.e(e)
}

Loading…
Cancel
Save