From 9ba34ab14fb44365aed09e5605603a45c51bcce2 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Tue, 2 Jun 2020 11:37:43 -0500 Subject: [PATCH] Convert Upgrader to Kotlin --- .../com/todoroo/astrid/service/Upgrader.java | 411 ------------------ .../com/todoroo/astrid/service/Upgrader.kt | 339 +++++++++++++++ 2 files changed, 339 insertions(+), 411 deletions(-) delete mode 100644 app/src/main/java/com/todoroo/astrid/service/Upgrader.java create mode 100644 app/src/main/java/com/todoroo/astrid/service/Upgrader.kt diff --git a/app/src/main/java/com/todoroo/astrid/service/Upgrader.java b/app/src/main/java/com/todoroo/astrid/service/Upgrader.java deleted file mode 100644 index 0adc5cb27..000000000 --- a/app/src/main/java/com/todoroo/astrid/service/Upgrader.java +++ /dev/null @@ -1,411 +0,0 @@ -package com.todoroo.astrid.service; - -import static com.google.common.collect.Iterables.transform; -import static org.tasks.Strings.isNullOrEmpty; -import static org.tasks.db.DbUtils.batch; - -import android.content.Context; -import androidx.annotation.ColorRes; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableListMultimap; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Multimaps; -import com.todoroo.astrid.api.GtasksFilter; -import com.todoroo.astrid.dao.TaskDao; -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import javax.inject.Inject; -import net.fortuna.ical4j.model.property.Geo; -import org.tasks.R; -import org.tasks.caldav.iCalendar; -import org.tasks.data.CaldavCalendar; -import org.tasks.data.CaldavDao; -import org.tasks.data.CaldavTask; -import org.tasks.data.CaldavTaskContainer; -import org.tasks.data.Filter; -import org.tasks.data.FilterDao; -import org.tasks.data.GoogleTaskAccount; -import org.tasks.data.GoogleTaskList; -import org.tasks.data.GoogleTaskListDao; -import org.tasks.data.Location; -import org.tasks.data.LocationDao; -import org.tasks.data.Tag; -import org.tasks.data.TagDao; -import org.tasks.data.TagData; -import org.tasks.data.TagDataDao; -import org.tasks.data.TaskAttachment; -import org.tasks.data.TaskAttachmentDao; -import org.tasks.data.UserActivity; -import org.tasks.data.UserActivityDao; -import org.tasks.injection.ForApplication; -import org.tasks.preferences.DefaultFilterProvider; -import org.tasks.preferences.Preferences; -import org.tasks.widget.AppWidgetManager; -import org.tasks.widget.WidgetPreferences; - -public class Upgrader { - - private static final int V4_9_5 = 434; - private static final int V5_3_0 = 491; - private static final int V6_0_beta_1 = 522; - private static final int V6_0_beta_2 = 523; - private static final int V6_4 = 546; - private static final int V6_7 = 585; - private static final int V6_8_1 = 607; - private static final int V6_9 = 608; - private static final int V7_0 = 617; - public static final int V8_2 = 675; - private static final int V8_5 = 700; - private static final int V8_8 = 717; - private static final int V8_10 = 735; - private static final int V9_3 = 90300; - private final Context context; - private final Preferences preferences; - private final TagDataDao tagDataDao; - private final TagDao tagDao; - private final FilterDao filterDao; - private final DefaultFilterProvider defaultFilterProvider; - private final GoogleTaskListDao googleTaskListDao; - private final UserActivityDao userActivityDao; - private final TaskAttachmentDao taskAttachmentDao; - private final CaldavDao caldavDao; - private final TaskDao taskDao; - private final LocationDao locationDao; - private final iCalendar iCal; - private final AppWidgetManager widgetManager; - - @Inject - public Upgrader( - @ForApplication Context context, - Preferences preferences, - TagDataDao tagDataDao, - TagDao tagDao, - FilterDao filterDao, - DefaultFilterProvider defaultFilterProvider, - GoogleTaskListDao googleTaskListDao, - UserActivityDao userActivityDao, - TaskAttachmentDao taskAttachmentDao, - CaldavDao caldavDao, - TaskDao taskDao, - LocationDao locationDao, - iCalendar iCal, - AppWidgetManager widgetManager) { - this.context = context; - this.preferences = preferences; - this.tagDataDao = tagDataDao; - this.tagDao = tagDao; - this.filterDao = filterDao; - this.defaultFilterProvider = defaultFilterProvider; - this.googleTaskListDao = googleTaskListDao; - this.userActivityDao = userActivityDao; - this.taskAttachmentDao = taskAttachmentDao; - this.caldavDao = caldavDao; - this.taskDao = taskDao; - this.locationDao = locationDao; - this.iCal = iCal; - this.widgetManager = widgetManager; - } - - public void upgrade(int from, int to) { - if (from > 0) { - run(from, V4_9_5, this::removeDuplicateTags); - run(from, V5_3_0, this::migrateFilters); - run(from, V6_0_beta_1, this::migrateDefaultSyncList); - run(from, V6_0_beta_2, this::migrateGoogleTaskAccount); - run(from, V6_4, this::migrateUris); - run(from, V6_7, this::migrateGoogleTaskFilters); - run(from, V6_8_1, this::migrateCaldavFilters); - run(from, V6_9, this::applyCaldavCategories); - run(from, V7_0, this::applyCaldavSubtasks); - run(from, V8_2, this::migrateColors); - run(from, V8_5, this::applyCaldavGeo); - run(from, V8_8, () -> { - preferences.setBoolean(R.string.p_linkify_task_edit, true); - preferences.setBoolean(R.string.p_auto_dismiss_datetime_edit_screen, true); - }); - run(from, V8_10, this::migrateWidgets); - run(from, V9_3, this::applyCaldavOrder); - preferences.setBoolean(R.string.p_just_updated, true); - } - preferences.setCurrentVersion(to); - } - - private void run(int from, int version, Runnable runnable) { - if (from < version) { - runnable.run(); - preferences.setCurrentVersion(version); - } - } - - private void migrateWidgets() { - for (int widgetId : widgetManager.getWidgetIds()) { - WidgetPreferences widgetPreferences = new WidgetPreferences(context, preferences, widgetId); - widgetPreferences.maintainExistingConfiguration(); - } - } - - private void migrateColors() { - preferences.setInt( - R.string.p_theme_color, getAndroidColor(preferences.getInt(R.string.p_theme_color, 7))); - for (CaldavCalendar calendar : caldavDao.getCalendars()) { - calendar.setColor(getAndroidColor(calendar.getColor())); - caldavDao.update(calendar); - } - for (GoogleTaskList list : googleTaskListDao.getAllLists()) { - list.setColor(getAndroidColor(list.getColor())); - googleTaskListDao.update(list); - } - for (TagData tagData : tagDataDao.getAll()) { - tagData.setColor(getAndroidColor(tagData.getColor())); - tagDataDao.update(tagData); - } - for (Filter filter : filterDao.getFilters()) { - filter.setColor(getAndroidColor(filter.getColor())); - filterDao.update(filter); - } - } - - private int getAndroidColor(int index) { - return getAndroidColor(context, index); - } - - public static int getAndroidColor(Context context, int index) { - int legacyColor = getLegacyColor(index, 0); - return legacyColor == 0 ? 0 : context.getColor(legacyColor); - } - - public static @ColorRes int getLegacyColor(int index, int def) { - switch (index) { - case 0: return R.color.blue_grey_500; - case 1: return R.color.grey_900; - case 2: return R.color.red_500; - case 3: return R.color.pink_500; - case 4: return R.color.purple_500; - case 5: return R.color.deep_purple_500; - case 6: return R.color.indigo_500; - case 7: return R.color.blue_500; - case 8: return R.color.light_blue_500; - case 9: return R.color.cyan_500; - case 10: return R.color.teal_500; - case 11: return R.color.green_500; - case 12: return R.color.light_green_500; - case 13: return R.color.lime_500; - case 14: return R.color.yellow_500; - case 15: return R.color.amber_500; - case 16: return R.color.orange_500; - case 17: return R.color.deep_orange_500; - case 18: return R.color.brown_500; - case 19: return R.color.grey_500; - case 20: return R.color.white_100; - default: return def; - } - } - - private void applyCaldavOrder() { - for (CaldavTask task : transform(caldavDao.getTasks(), CaldavTaskContainer::getCaldavTask)) { - at.bitfire.ical4android.Task remoteTask = iCalendar.Companion.fromVtodo(task.getVtodo()); - if (remoteTask == null) { - continue; - } - - Long order = iCalendar.Companion.getOrder(remoteTask); - if (order != null) { - task.setOrder(order); - caldavDao.update(task); - } - } - } - - private void applyCaldavGeo() { - List tasksWithLocations = - Lists.transform(locationDao.getActiveGeofences(), Location::getTask); - - for (CaldavTask task : transform(caldavDao.getTasks(), CaldavTaskContainer::getCaldavTask)) { - long taskId = task.getTask(); - if (tasksWithLocations.contains(taskId)) { - continue; - } - - at.bitfire.ical4android.Task remoteTask = iCalendar.Companion.fromVtodo(task.getVtodo()); - if (remoteTask == null) { - continue; - } - - Geo geo = remoteTask.getGeoPosition(); - if (geo == null) { - continue; - } - - iCal.setPlace(taskId, geo); - } - - batch(tasksWithLocations, taskDao::touch); - } - - private void applyCaldavSubtasks() { - List updated = new ArrayList<>(); - - for (CaldavTask task : transform(caldavDao.getTasks(), CaldavTaskContainer::getCaldavTask)) { - at.bitfire.ical4android.Task remoteTask = iCalendar.Companion.fromVtodo(task.getVtodo()); - if (remoteTask == null) { - continue; - } - task.setRemoteParent(iCalendar.Companion.getParent(remoteTask)); - if (!isNullOrEmpty(task.getRemoteParent())) { - updated.add(task); - } - } - - caldavDao.update(updated); - caldavDao.updateParents(); - } - - private void applyCaldavCategories() { - List tasksWithTags = caldavDao.getTasksWithTags(); - for (CaldavTaskContainer container : caldavDao.getTasks()) { - at.bitfire.ical4android.Task remoteTask = - iCalendar.Companion.fromVtodo(container.getVtodo()); - if (remoteTask != null) { - tagDao.insert(container.getTask(), iCal.getTags(remoteTask.getCategories())); - } - } - batch(tasksWithTags, taskDao::touch); - } - - private void removeDuplicateTags() { - ListMultimap tagsByUuid = - Multimaps.index(tagDataDao.tagDataOrderedByName(), TagData::getRemoteId); - for (String uuid : tagsByUuid.keySet()) { - removeDuplicateTagData(tagsByUuid.get(uuid)); - removeDuplicateTagMetadata(uuid); - } - } - - private void migrateGoogleTaskFilters() { - for (Filter filter : filterDao.getAll()) { - filter.setSql(migrateGoogleTaskFilters(filter.getSql())); - filter.setCriterion(migrateGoogleTaskFilters(filter.getCriterion())); - filterDao.update(filter); - } - } - - private void migrateCaldavFilters() { - for (Filter filter : filterDao.getAll()) { - filter.setSql(migrateCaldavFilters(filter.getSql())); - filter.setCriterion(migrateCaldavFilters(filter.getCriterion())); - filterDao.update(filter); - } - } - - private void migrateFilters() { - for (Filter filter : filterDao.getFilters()) { - filter.setSql(migrateMetadata(filter.getSql())); - filter.setCriterion(migrateMetadata(filter.getCriterion())); - filterDao.update(filter); - } - } - - private void migrateDefaultSyncList() { - String account = preferences.getStringValue("gtasks_user"); - if (isNullOrEmpty(account)) { - return; - } - - String defaultGoogleTaskList = preferences.getStringValue("gtasks_defaultlist"); - if (isNullOrEmpty(defaultGoogleTaskList)) { - // TODO: look up default list - } else { - GoogleTaskList googleTaskList = googleTaskListDao.getByRemoteId(defaultGoogleTaskList); - if (googleTaskList != null) { - defaultFilterProvider.setDefaultRemoteList(new GtasksFilter(googleTaskList)); - } - } - } - - private void migrateGoogleTaskAccount() { - String account = preferences.getStringValue("gtasks_user"); - if (!isNullOrEmpty(account)) { - GoogleTaskAccount googleTaskAccount = new GoogleTaskAccount(); - googleTaskAccount.setAccount(account); - googleTaskListDao.insert(googleTaskAccount); - for (GoogleTaskList list : googleTaskListDao.getAllLists()) { - list.setAccount(account); - googleTaskListDao.insertOrReplace(list); - } - } - } - - private void migrateUris() { - migrateUriPreference(R.string.p_backup_dir); - migrateUriPreference(R.string.p_attachment_dir); - for (UserActivity userActivity : userActivityDao.getComments()) { - userActivity.convertPictureUri(); - userActivityDao.update(userActivity); - } - for (TaskAttachment attachment : taskAttachmentDao.getAttachments()) { - attachment.convertPathUri(); - taskAttachmentDao.update(attachment); - } - } - - private void migrateUriPreference(int pref) { - String path = preferences.getStringValue(pref); - if (isNullOrEmpty(path)) { - return; - } - File file = new File(path); - try { - if (file.canWrite()) { - preferences.setUri(pref, file.toURI()); - } else { - preferences.remove(pref); - } - } catch (SecurityException ignored) { - preferences.remove(pref); - } - } - - private String migrateGoogleTaskFilters(String input) { - return input - .replace("SELECT task FROM google_tasks", "SELECT gt_task as task FROM google_tasks") - .replace("(list_id", "(gt_list_id") - .replace("google_tasks.list_id", "google_tasks.gt_list_id") - .replace("google_tasks.task", "google_tasks.gt_task"); - } - - private String migrateCaldavFilters(String input) { - return input - .replace("SELECT task FROM caldav_tasks", "SELECT cd_task as task FROM caldav_tasks") - .replace("(calendar", "(cd_calendar"); - } - - private String migrateMetadata(String input) { - return input - .replaceAll( - "SELECT metadata\\.task AS task FROM metadata INNER JOIN tasks ON \\(\\(metadata\\.task=tasks\\._id\\)\\) WHERE \\(\\(\\(tasks\\.completed=0\\) AND \\(tasks\\.deleted=0\\) AND \\(tasks\\.hideUntil<\\(strftime\\(\\'%s\\',\\'now\\'\\)\\*1000\\)\\)\\) AND \\(metadata\\.key=\\'tags-tag\\'\\) AND \\(metadata\\.value", - "SELECT tags.task AS task FROM tags INNER JOIN tasks ON ((tags.task=tasks._id)) WHERE (((tasks.completed=0) AND (tasks.deleted=0) AND (tasks.hideUntil<(strftime('%s','now')*1000))) AND (tags.name") - .replaceAll( - "SELECT metadata\\.task AS task FROM metadata INNER JOIN tasks ON \\(\\(metadata\\.task=tasks\\._id\\)\\) WHERE \\(\\(\\(tasks\\.completed=0\\) AND \\(tasks\\.deleted=0\\) AND \\(tasks\\.hideUntil<\\(strftime\\(\\'%s\\',\\'now\\'\\)\\*1000\\)\\)\\) AND \\(metadata\\.key=\\'gtasks\\'\\) AND \\(metadata\\.value2", - "SELECT google_tasks.task AS task FROM google_tasks INNER JOIN tasks ON ((google_tasks.task=tasks._id)) WHERE (((tasks.completed=0) AND (tasks.deleted=0) AND (tasks.hideUntil<(strftime('%s','now')*1000))) AND (google_tasks.list_id") - .replaceAll("AND \\(metadata\\.deleted=0\\)", ""); - } - - private void removeDuplicateTagData(List tagData) { - if (tagData.size() > 1) { - tagDataDao.delete(tagData.subList(1, tagData.size())); - } - } - - private void removeDuplicateTagMetadata(String uuid) { - List metadatas = tagDao.getByTagUid(uuid); - ImmutableListMultimap metadataByTask = Multimaps.index(metadatas, Tag::getTask); - for (Long key : metadataByTask.keySet()) { - ImmutableList tags = metadataByTask.get(key); - if (tags.size() > 1) { - tagDao.delete(tags.subList(1, tags.size())); - } - } - } -} diff --git a/app/src/main/java/com/todoroo/astrid/service/Upgrader.kt b/app/src/main/java/com/todoroo/astrid/service/Upgrader.kt new file mode 100644 index 000000000..b1e19e8ba --- /dev/null +++ b/app/src/main/java/com/todoroo/astrid/service/Upgrader.kt @@ -0,0 +1,339 @@ +package com.todoroo.astrid.service + +import android.content.Context +import androidx.annotation.ColorRes +import com.google.common.collect.ImmutableListMultimap +import com.google.common.collect.ListMultimap +import com.google.common.collect.Multimaps +import com.todoroo.astrid.api.GtasksFilter +import com.todoroo.astrid.dao.TaskDao +import org.tasks.R +import org.tasks.Strings.isNullOrEmpty +import org.tasks.caldav.iCalendar +import org.tasks.caldav.iCalendar.Companion.fromVtodo +import org.tasks.caldav.iCalendar.Companion.getParent +import org.tasks.caldav.iCalendar.Companion.order +import org.tasks.data.* +import org.tasks.db.DbUtils +import org.tasks.injection.ForApplication +import org.tasks.preferences.DefaultFilterProvider +import org.tasks.preferences.Preferences +import org.tasks.widget.AppWidgetManager +import org.tasks.widget.WidgetPreferences +import java.io.File +import java.util.* +import javax.inject.Inject + +class Upgrader @Inject constructor( + @param:ForApplication private val context: Context, + private val preferences: Preferences, + private val tagDataDao: TagDataDao, + private val tagDao: TagDao, + private val filterDao: FilterDao, + private val defaultFilterProvider: DefaultFilterProvider, + private val googleTaskListDao: GoogleTaskListDao, + private val userActivityDao: UserActivityDao, + private val taskAttachmentDao: TaskAttachmentDao, + private val caldavDao: CaldavDao, + private val taskDao: TaskDao, + private val locationDao: LocationDao, + private val iCal: iCalendar, + private val widgetManager: AppWidgetManager) { + + fun upgrade(from: Int, to: Int) { + if (from > 0) { + run(from, V4_9_5) { removeDuplicateTags() } + run(from, V5_3_0) { migrateFilters() } + run(from, V6_0_beta_1) { migrateDefaultSyncList() } + run(from, V6_0_beta_2) { migrateGoogleTaskAccount() } + run(from, V6_4) { migrateUris() } + run(from, V6_7) { this.migrateGoogleTaskFilters() } + run(from, V6_8_1) { this.migrateCaldavFilters() } + run(from, V6_9) { applyCaldavCategories() } + run(from, V7_0) { applyCaldavSubtasks() } + run(from, V8_2) { migrateColors() } + run(from, V8_5) { applyCaldavGeo() } + run(from, V8_8) { + preferences.setBoolean(R.string.p_linkify_task_edit, true) + preferences.setBoolean(R.string.p_auto_dismiss_datetime_edit_screen, true) + } + run(from, V8_10) { migrateWidgets() } + run(from, V9_3) { applyCaldavOrder() } + preferences.setBoolean(R.string.p_just_updated, true) + } + preferences.setCurrentVersion(to) + } + + private fun run(from: Int, version: Int, runnable: () -> Unit) { + if (from < version) { + runnable.invoke() + preferences.setCurrentVersion(version) + } + } + + private fun migrateWidgets() { + for (widgetId in widgetManager.widgetIds) { + val widgetPreferences = WidgetPreferences(context, preferences, widgetId) + widgetPreferences.maintainExistingConfiguration() + } + } + + private fun migrateColors() { + preferences.setInt( + R.string.p_theme_color, getAndroidColor(preferences.getInt(R.string.p_theme_color, 7))) + for (calendar in caldavDao.getCalendars()) { + calendar.color = getAndroidColor(calendar.color) + caldavDao.update(calendar) + } + for (list in googleTaskListDao.getAllLists()) { + list.setColor(getAndroidColor(list.getColor()!!)) + googleTaskListDao.update(list) + } + for (tagData in tagDataDao.getAll()) { + tagData.setColor(getAndroidColor(tagData.getColor()!!)) + tagDataDao.update(tagData) + } + for (filter in filterDao.getFilters()) { + filter.setColor(getAndroidColor(filter.getColor()!!)) + filterDao.update(filter) + } + } + + private fun getAndroidColor(index: Int): Int { + return getAndroidColor(context, index) + } + + private fun applyCaldavOrder() { + for (task in caldavDao.getTasks().map(CaldavTaskContainer::caldavTask)) { + val remoteTask = fromVtodo(task.vtodo!!) ?: continue + val order: Long? = remoteTask.order + if (order != null) { + task.order = order + caldavDao.update(task) + } + } + } + + private fun applyCaldavGeo() { + val tasksWithLocations = locationDao.getActiveGeofences().map(Location::task) + for (task in caldavDao.getTasks().map(CaldavTaskContainer::caldavTask)) { + val taskId = task.task + if (tasksWithLocations.contains(taskId)) { + continue + } + val remoteTask = fromVtodo(task.vtodo!!) ?: continue + val geo = remoteTask.geoPosition ?: continue + iCal.setPlace(taskId, geo) + } + DbUtils.batch(tasksWithLocations) { ids: List? -> taskDao.touch(ids!!) } + } + + private fun applyCaldavSubtasks() { + val updated: MutableList = ArrayList() + for (task in caldavDao.getTasks().map(CaldavTaskContainer::caldavTask)) { + val remoteTask = fromVtodo(task.vtodo!!) ?: continue + task.remoteParent = getParent(remoteTask) + if (!isNullOrEmpty(task.remoteParent)) { + updated.add(task) + } + } + caldavDao.update(updated) + caldavDao.updateParents() + } + + private fun applyCaldavCategories() { + val tasksWithTags: List = caldavDao.getTasksWithTags() + for (container in caldavDao.getTasks()) { + val remoteTask = fromVtodo(container.vtodo!!) + if (remoteTask != null) { + tagDao.insert(container.task, iCal.getTags(remoteTask.categories)) + } + } + DbUtils.batch(tasksWithTags) { ids: List -> taskDao.touch(ids) } + } + + private fun removeDuplicateTags() { + val tagsByUuid: ListMultimap = Multimaps.index(tagDataDao.tagDataOrderedByName()) { it!!.remoteId } + for (uuid in tagsByUuid.keySet()) { + removeDuplicateTagData(tagsByUuid[uuid]) + removeDuplicateTagMetadata(uuid) + } + } + + private fun migrateGoogleTaskFilters() { + for (filter in filterDao.getAll()) { + filter.setSql(migrateGoogleTaskFilters(filter.getSql())) + filter.criterion = migrateGoogleTaskFilters(filter.criterion) + filterDao.update(filter) + } + } + + private fun migrateCaldavFilters() { + for (filter in filterDao.getAll()) { + filter.setSql(migrateCaldavFilters(filter.getSql())) + filter.criterion = migrateCaldavFilters(filter.criterion) + filterDao.update(filter) + } + } + + private fun migrateFilters() { + for (filter in filterDao.getFilters()) { + filter.setSql(migrateMetadata(filter.getSql())) + filter.criterion = migrateMetadata(filter.criterion) + filterDao.update(filter) + } + } + + private fun migrateDefaultSyncList() { + val account = preferences.getStringValue("gtasks_user") + if (isNullOrEmpty(account)) { + return + } + val defaultGoogleTaskList = preferences.getStringValue("gtasks_defaultlist") + if (isNullOrEmpty(defaultGoogleTaskList)) { + // TODO: look up default list + } else { + val googleTaskList = googleTaskListDao.getByRemoteId(defaultGoogleTaskList) + if (googleTaskList != null) { + defaultFilterProvider.defaultRemoteList = GtasksFilter(googleTaskList) + } + } + } + + private fun migrateGoogleTaskAccount() { + val account = preferences.getStringValue("gtasks_user") + if (!isNullOrEmpty(account)) { + val googleTaskAccount = GoogleTaskAccount() + googleTaskAccount.account = account + googleTaskListDao.insert(googleTaskAccount) + for (list in googleTaskListDao.getAllLists()) { + list.account = account + googleTaskListDao.insertOrReplace(list) + } + } + } + + private fun migrateUris() { + migrateUriPreference(R.string.p_backup_dir) + migrateUriPreference(R.string.p_attachment_dir) + for (userActivity in userActivityDao.getComments()) { + userActivity.convertPictureUri() + userActivityDao.update(userActivity) + } + for (attachment in taskAttachmentDao.getAttachments()) { + attachment.convertPathUri() + taskAttachmentDao.update(attachment) + } + } + + private fun migrateUriPreference(pref: Int) { + val path = preferences.getStringValue(pref) + if (isNullOrEmpty(path)) { + return + } + val file = File(path) + try { + if (file.canWrite()) { + preferences.setUri(pref, file.toURI()) + } else { + preferences.remove(pref) + } + } catch (ignored: SecurityException) { + preferences.remove(pref) + } + } + + private fun migrateGoogleTaskFilters(input: String?): String { + return input.orEmpty() + .replace("SELECT task FROM google_tasks", "SELECT gt_task as task FROM google_tasks") + .replace("(list_id", "(gt_list_id") + .replace("google_tasks.list_id", "google_tasks.gt_list_id") + .replace("google_tasks.task", "google_tasks.gt_task") + } + + private fun migrateCaldavFilters(input: String?): String { + return input.orEmpty() + .replace("SELECT task FROM caldav_tasks", "SELECT cd_task as task FROM caldav_tasks") + .replace("(calendar", "(cd_calendar") + } + + private fun migrateMetadata(input: String?): String { + return input.orEmpty() + .replace( + "SELECT metadata\\.task AS task FROM metadata INNER JOIN tasks ON \\(\\(metadata\\.task=tasks\\._id\\)\\) WHERE \\(\\(\\(tasks\\.completed=0\\) AND \\(tasks\\.deleted=0\\) AND \\(tasks\\.hideUntil<\\(strftime\\(\\'%s\\',\\'now\\'\\)\\*1000\\)\\)\\) AND \\(metadata\\.key=\\'tags-tag\\'\\) AND \\(metadata\\.value".toRegex(), + "SELECT tags.task AS task FROM tags INNER JOIN tasks ON ((tags.task=tasks._id)) WHERE (((tasks.completed=0) AND (tasks.deleted=0) AND (tasks.hideUntil<(strftime('%s','now')*1000))) AND (tags.name") + .replace( + "SELECT metadata\\.task AS task FROM metadata INNER JOIN tasks ON \\(\\(metadata\\.task=tasks\\._id\\)\\) WHERE \\(\\(\\(tasks\\.completed=0\\) AND \\(tasks\\.deleted=0\\) AND \\(tasks\\.hideUntil<\\(strftime\\(\\'%s\\',\\'now\\'\\)\\*1000\\)\\)\\) AND \\(metadata\\.key=\\'gtasks\\'\\) AND \\(metadata\\.value2".toRegex(), + "SELECT google_tasks.task AS task FROM google_tasks INNER JOIN tasks ON ((google_tasks.task=tasks._id)) WHERE (((tasks.completed=0) AND (tasks.deleted=0) AND (tasks.hideUntil<(strftime('%s','now')*1000))) AND (google_tasks.list_id") + .replace("AND \\(metadata\\.deleted=0\\)".toRegex(), "") + } + + private fun removeDuplicateTagData(tagData: List) { + if (tagData.size > 1) { + tagDataDao.delete(tagData.subList(1, tagData.size)) + } + } + + private fun removeDuplicateTagMetadata(uuid: String) { + val metadatas = tagDao.getByTagUid(uuid) + val metadataByTask: ImmutableListMultimap = Multimaps.index(metadatas) { it!!.task } + for (key in metadataByTask.keySet()) { + val tags = metadataByTask[key] + if (tags.size > 1) { + tagDao.delete(tags.subList(1, tags.size)) + } + } + } + + companion object { + private const val V4_9_5 = 434 + private const val V5_3_0 = 491 + private const val V6_0_beta_1 = 522 + private const val V6_0_beta_2 = 523 + private const val V6_4 = 546 + private const val V6_7 = 585 + private const val V6_8_1 = 607 + private const val V6_9 = 608 + private const val V7_0 = 617 + const val V8_2 = 675 + private const val V8_5 = 700 + private const val V8_8 = 717 + private const val V8_10 = 735 + private const val V9_3 = 90300 + + @JvmStatic + fun getAndroidColor(context: Context, index: Int): Int { + val legacyColor = getLegacyColor(index, 0) + return if (legacyColor == 0) 0 else context.getColor(legacyColor) + } + + @JvmStatic + @ColorRes + fun getLegacyColor(index: Int, def: Int): Int { + return when (index) { + 0 -> R.color.blue_grey_500 + 1 -> R.color.grey_900 + 2 -> R.color.red_500 + 3 -> R.color.pink_500 + 4 -> R.color.purple_500 + 5 -> R.color.deep_purple_500 + 6 -> R.color.indigo_500 + 7 -> R.color.blue_500 + 8 -> R.color.light_blue_500 + 9 -> R.color.cyan_500 + 10 -> R.color.teal_500 + 11 -> R.color.green_500 + 12 -> R.color.light_green_500 + 13 -> R.color.lime_500 + 14 -> R.color.yellow_500 + 15 -> R.color.amber_500 + 16 -> R.color.orange_500 + 17 -> R.color.deep_orange_500 + 18 -> R.color.brown_500 + 19 -> R.color.grey_500 + 20 -> R.color.white_100 + else -> def + } + } + } +} \ No newline at end of file