mirror of https://github.com/tasks/tasks
Convert GCalHelper to Kotlin
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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue