From b524ae21f4c1c9dfca1c7c853932e8fdc22bb87e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Sun, 11 Oct 2020 05:24:19 +0000 Subject: [PATCH 01/89] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegian?= =?UTF-8?q?=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 95.5% (321 of 336 strings) Translation: EteSync/Android Translate-URL: https://hosted.weblate.org/projects/etesync/android/nb_NO/ --- app/src/main/res/values-nb-rNO/strings.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index c6d4c434..0b334a87 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -378,4 +378,11 @@ Kun administratorer kan håndtere samlingsmedlemskap. Ønsker du å forlate denne samlingen\? Fjerning av tilganger for administratorer støttes ikke. Kun eiere av denne samlingen kan redigere den. - + Invitasjon sendt. Brukeren vil bli lagt til når invitasjonen har blitt godkjent. + Skrivebeskyttet + For å kunne bruke EteSync må du opprette samlinger å lagre dataen din i. Klikk «Opprett» for å opprette en forvalgt kalender, adressebok og gjøremålsliste. + Velkommen til EteSync. + Prøv igjen + Hopp over + Opprett + \ No newline at end of file From 008f91d7153d7a18219fed3f452dbed3e3aae246 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Fri, 9 Oct 2020 09:41:05 +0300 Subject: [PATCH 02/89] Settings: Implement the dashboard link. --- app/build.gradle | 2 +- .../syncadapter/ui/AccountSettingsActivity.kt | 27 +++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d45cb316..6f781ffc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -138,7 +138,7 @@ dependencies { implementation "org.jetbrains.anko:anko-commons:0.10.4" implementation "com.etesync:journalmanager:1.1.1" - def etebaseVersion = '0.2.2' + def etebaseVersion = '2.0.1-SNAPSHOT' implementation "com.etebase:client:$etebaseVersion" def acraVersion = '5.3.0' diff --git a/app/src/main/java/com/etesync/syncadapter/ui/AccountSettingsActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/AccountSettingsActivity.kt index 893a946b..97590224 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/AccountSettingsActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/AccountSettingsActivity.kt @@ -17,20 +17,24 @@ import android.os.Bundle import android.provider.CalendarContract import android.text.TextUtils import android.view.MenuItem -import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.core.app.NavUtils +import androidx.core.net.toUri import androidx.fragment.app.Fragment import androidx.loader.app.LoaderManager import androidx.loader.content.AsyncTaskLoader import androidx.loader.content.Loader import androidx.preference.* import at.bitfire.ical4android.TaskProvider.Companion.TASK_PROVIDERS +import com.etebase.client.exceptions.EtebaseException import com.etesync.syncadapter.* import com.etesync.syncadapter.Constants.KEY_ACCOUNT import com.etesync.syncadapter.R import com.etesync.syncadapter.log.Logger import com.etesync.syncadapter.ui.setup.LoginCredentials import com.etesync.syncadapter.ui.setup.LoginCredentialsChangeFragment +import org.jetbrains.anko.doAsync +import org.jetbrains.anko.uiThread class AccountSettingsActivity : BaseActivity() { private lateinit var account: Account @@ -92,7 +96,26 @@ class AccountSettingsFragment() : PreferenceFragmentCompat(), LoaderManager.Load // Category: dashboard val prefManageAccount = findPreference("manage_account") prefManageAccount.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ -> - Toast.makeText(requireContext(), "Not yet supported", Toast.LENGTH_LONG).show() + doAsync { + try { + + val httpClient = HttpClient.Builder(requireContext()).build() + val etebase = EtebaseLocalCache.getEtebase(requireContext(), httpClient.okHttpClient, settings) + val url = etebase.fetchDashboardUrl() + uiThread { + WebViewActivity.openUrl(requireActivity(), url.toUri()) + } + } catch (e: EtebaseException) { + uiThread { + AlertDialog.Builder(requireContext()) + .setIcon(R.drawable.ic_error_dark) + .setTitle(R.string.exception) + .setMessage(e.localizedMessage) + .setPositiveButton(android.R.string.yes) { _, _ -> } + .show() + } + } + } true } From 624372f527fb4f08e4f00e93e171c38894ae1ae1 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Wed, 14 Oct 2020 20:29:57 +0300 Subject: [PATCH 03/89] NewAccountWizard: use the etebase types constants. --- .../syncadapter/ui/etebase/NewAccountWizardActivity.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt index a3804832..2252cacf 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt @@ -19,6 +19,7 @@ import com.etebase.client.Collection import com.etebase.client.CollectionMetadata import com.etebase.client.FetchOptions import com.etebase.client.exceptions.EtebaseException +import com.etesync.syncadapter.Constants.* import com.etesync.syncadapter.R import com.etesync.syncadapter.syncadapter.requestSync import com.etesync.syncadapter.ui.BaseActivity @@ -175,9 +176,9 @@ class WizardFragment : Fragment() { doAsync { try { val baseMeta = listOf( - Pair("etebase.vcard", "My Contacts"), - Pair("etebase.vevent", "My Calendar"), - Pair("etebase.vtodo", "My Tasks"), + Pair(ETEBASE_TYPE_ADDRESS_BOOK, "My Contacts"), + Pair(ETEBASE_TYPE_CALENDAR, "My Calendar"), + Pair(ETEBASE_TYPE_TASKS, "My Tasks"), ) baseMeta.forEach { From edb1579fe0f3a4373a7da59629722a86b7f47573 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Wed, 14 Oct 2020 20:54:00 +0300 Subject: [PATCH 04/89] LocalCache: allow trying to unset non-existent collection. --- .../main/java/com/etesync/syncadapter/EtebaseLocalCache.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt b/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt index 9f51ccf9..bfcacfa7 100644 --- a/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt +++ b/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt @@ -4,6 +4,7 @@ import android.content.Context import com.etebase.client.* import com.etebase.client.Collection import com.etebase.client.exceptions.EtebaseException +import com.etebase.client.exceptions.UrlParseException import okhttp3.OkHttpClient import java.io.File import java.util.* @@ -58,7 +59,11 @@ class EtebaseLocalCache private constructor(context: Context, username: String) } fun collectionUnset(colMgr: CollectionManager, colUid: String) { - fsCache.collectionUnset(colMgr, colUid) + try { + fsCache.collectionUnset(colMgr, colUid) + } catch (e: UrlParseException) { + // Ignore, as it just means the file doesn't exist + } } fun itemList(itemMgr: ItemManager, colUid: String, withDeleted: Boolean = false): List { From 73c1d1ee0b51c173be5394cfe7063a8eed78cd16 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Thu, 15 Oct 2020 09:45:45 +0300 Subject: [PATCH 05/89] Update etebase dep and adjust code accordingly. --- app/build.gradle | 2 +- app/src/main/java/com/etesync/syncadapter/Constants.java | 5 +++++ .../java/com/etesync/syncadapter/EtebaseLocalCache.kt | 6 +++--- .../syncadapter/AddressBooksSyncAdapterService.kt | 2 +- .../syncadapter/CalendarsSyncAdapterService.kt | 2 +- .../syncadapter/syncadapter/SyncAdapterService.kt | 6 +++--- .../syncadapter/syncadapter/TasksSyncAdapterService.kt | 2 +- .../java/com/etesync/syncadapter/ui/AccountActivity.kt | 5 +++-- .../etesync/syncadapter/ui/etebase/CollectionActivity.kt | 7 ++++--- .../syncadapter/ui/etebase/CollectionItemFragment.kt | 4 ++-- .../syncadapter/ui/etebase/CollectionMembersFragment.kt | 3 ++- .../syncadapter/ui/etebase/EditCollectionFragment.kt | 6 +++--- .../syncadapter/ui/etebase/ImportCollectionFragment.kt | 6 +++--- .../syncadapter/ui/etebase/ItemRevisionsListFragment.kt | 2 +- .../syncadapter/ui/etebase/ListEntriesFragment.kt | 2 +- .../syncadapter/ui/etebase/NewAccountWizardActivity.kt | 9 +++++---- .../syncadapter/ui/etebase/ViewCollectionFragment.kt | 2 +- .../etesync/syncadapter/ui/importlocal/ImportFragment.kt | 2 +- 18 files changed, 41 insertions(+), 32 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 6f781ffc..cbfa2897 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -138,7 +138,7 @@ dependencies { implementation "org.jetbrains.anko:anko-commons:0.10.4" implementation "com.etesync:journalmanager:1.1.1" - def etebaseVersion = '2.0.1-SNAPSHOT' + def etebaseVersion = '2.2.0' implementation "com.etebase:client:$etebaseVersion" def acraVersion = '5.3.0' diff --git a/app/src/main/java/com/etesync/syncadapter/Constants.java b/app/src/main/java/com/etesync/syncadapter/Constants.java index 9c008ab0..102aa95f 100644 --- a/app/src/main/java/com/etesync/syncadapter/Constants.java +++ b/app/src/main/java/com/etesync/syncadapter/Constants.java @@ -48,4 +48,9 @@ public class Constants { public final static String ETEBASE_TYPE_ADDRESS_BOOK = "etebase.vcard"; public final static String ETEBASE_TYPE_CALENDAR = "etebase.vevent"; public final static String ETEBASE_TYPE_TASKS = "etebase.vtodo"; + public final static String[] COLLECTION_TYPES = new String[] { + ETEBASE_TYPE_ADDRESS_BOOK, + ETEBASE_TYPE_CALENDAR, + ETEBASE_TYPE_TASKS + }; } diff --git a/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt b/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt index bfcacfa7..75bf54ec 100644 --- a/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt +++ b/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt @@ -44,13 +44,13 @@ class EtebaseLocalCache private constructor(context: Context, username: String) return fsCache._unstable_collectionList(colMgr).filter { withDeleted || !it.isDeleted }.map{ - CachedCollection(it, it.meta) + CachedCollection(it, it.meta, it.collectionType) } } fun collectionGet(colMgr: CollectionManager, colUid: String): CachedCollection { return fsCache.collectionGet(colMgr, colUid).let { - CachedCollection(it, it.meta) + CachedCollection(it, it.meta, it.collectionType) } } @@ -124,6 +124,6 @@ class EtebaseLocalCache private constructor(context: Context, username: String) } } -data class CachedCollection(val col: Collection, val meta: CollectionMetadata) +data class CachedCollection(val col: Collection, val meta: ItemMetadata, val collectionType: String) data class CachedItem(val item: Item, val meta: ItemMetadata, val content: String) \ No newline at end of file diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/AddressBooksSyncAdapterService.kt b/app/src/main/java/com/etesync/syncadapter/syncadapter/AddressBooksSyncAdapterService.kt index 67e7a300..b13c085f 100644 --- a/app/src/main/java/com/etesync/syncadapter/syncadapter/AddressBooksSyncAdapterService.kt +++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/AddressBooksSyncAdapterService.kt @@ -77,7 +77,7 @@ class AddressBooksSyncAdapterService : SyncAdapterService() { val etebase = EtebaseLocalCache.getEtebase(context, httpClient.okHttpClient, settings) val colMgr = etebase.collectionManager - collections = etebaseLocalCache.collectionList(colMgr).filter { it.meta.collectionType == Constants.ETEBASE_TYPE_ADDRESS_BOOK } + collections = etebaseLocalCache.collectionList(colMgr).filter { it.collectionType == Constants.ETEBASE_TYPE_ADDRESS_BOOK } } for (collection in collections) { diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/CalendarsSyncAdapterService.kt b/app/src/main/java/com/etesync/syncadapter/syncadapter/CalendarsSyncAdapterService.kt index 8dc159e9..29d8b4e7 100644 --- a/app/src/main/java/com/etesync/syncadapter/syncadapter/CalendarsSyncAdapterService.kt +++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/CalendarsSyncAdapterService.kt @@ -63,7 +63,7 @@ class CalendarsSyncAdapterService : SyncAdapterService() { val etebase = EtebaseLocalCache.getEtebase(context, httpClient.okHttpClient, settings) val colMgr = etebase.collectionManager - collections = etebaseLocalCache.collectionList(colMgr).filter { it.meta.collectionType == Constants.ETEBASE_TYPE_CALENDAR } + collections = etebaseLocalCache.collectionList(colMgr).filter { it.collectionType == Constants.ETEBASE_TYPE_CALENDAR } } for (collection in collections) { diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.kt b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.kt index 63b2273b..62488fc5 100644 --- a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.kt +++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncAdapterService.kt @@ -26,10 +26,11 @@ import com.etebase.client.FetchOptions import com.etebase.client.exceptions.ConnectionException import com.etebase.client.exceptions.TemporaryServerErrorException import com.etebase.client.exceptions.UnauthorizedException -import com.etesync.syncadapter.* import com.etesync.journalmanager.Crypto import com.etesync.journalmanager.Exceptions import com.etesync.journalmanager.JournalManager +import com.etesync.syncadapter.* +import com.etesync.syncadapter.Constants.COLLECTION_TYPES import com.etesync.syncadapter.log.Logger import com.etesync.syncadapter.model.CollectionInfo import com.etesync.syncadapter.model.JournalEntity @@ -243,7 +244,6 @@ abstract class SyncAdapterService : Service() { return } - val etebaseLocalCache = EtebaseLocalCache.getInstance(context, account.name) synchronized(etebaseLocalCache) { val cacheAge = 5 * 1000 // 5 seconds - it's just a hack for burst fetching @@ -259,7 +259,7 @@ abstract class SyncAdapterService : Service() { var stoken = etebaseLocalCache.loadStoken() var done = false while (!done) { - val colList = colMgr.list(FetchOptions().stoken(stoken)) + val colList = colMgr.list(COLLECTION_TYPES, FetchOptions().stoken(stoken)) for (col in colList.data) { etebaseLocalCache.collectionSet(colMgr, col) } diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/TasksSyncAdapterService.kt b/app/src/main/java/com/etesync/syncadapter/syncadapter/TasksSyncAdapterService.kt index 22d18caf..b2c4224b 100644 --- a/app/src/main/java/com/etesync/syncadapter/syncadapter/TasksSyncAdapterService.kt +++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/TasksSyncAdapterService.kt @@ -83,7 +83,7 @@ class TasksSyncAdapterService: SyncAdapterService() { val etebase = EtebaseLocalCache.getEtebase(context, httpClient.okHttpClient, settings) val colMgr = etebase.collectionManager - collections = etebaseLocalCache.collectionList(colMgr).filter { it.meta.collectionType == Constants.ETEBASE_TYPE_TASKS } + collections = etebaseLocalCache.collectionList(colMgr).filter { it.collectionType == Constants.ETEBASE_TYPE_TASKS } } for (collection in collections) { diff --git a/app/src/main/java/com/etesync/syncadapter/ui/AccountActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/AccountActivity.kt index dbea30be..98df3c02 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/AccountActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/AccountActivity.kt @@ -398,8 +398,9 @@ class AccountActivity : BaseActivity(), Toolbar.OnMenuItemClickListener, PopupMe synchronized(etebaseLocalCache) { return etebaseLocalCache.collectionList(colMgr).map { val meta = it.meta + val collectionType = it.collectionType - if (strType != meta.collectionType) { + if (strType != collectionType) { return@map null } @@ -409,7 +410,7 @@ class AccountActivity : BaseActivity(), Toolbar.OnMenuItemClickListener, PopupMe val metaColor = meta.color val color = if (!metaColor.isNullOrBlank()) LocalCalendar.parseColor(metaColor) else null - CollectionListItemInfo(it.col.uid, type, meta.name, meta.description + CollectionListItemInfo(it.col.uid, type, meta.name!!, meta.description ?: "", color, isReadOnly, isAdmin, null) }.filterNotNull() } diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionActivity.kt index f3dbf5f7..add5d988 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionActivity.kt @@ -11,7 +11,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.observe import com.etebase.client.CollectionManager -import com.etebase.client.CollectionMetadata +import com.etebase.client.ItemMetadata import com.etesync.syncadapter.* import com.etesync.syncadapter.ui.BaseActivity import org.jetbrains.anko.doAsync @@ -47,8 +47,9 @@ class CollectionActivity() : BaseActivity() { } else if (colType != null) { model.observe(this) { doAsync { - val meta = CollectionMetadata(colType, "") - val cachedCollection = CachedCollection(it.colMgr.create(meta, ""), meta) + val meta = ItemMetadata() + meta.name = "" + val cachedCollection = CachedCollection(it.colMgr.create(colType, meta, ""), meta, colType) uiThread { supportFragmentManager.commit { replace(R.id.fragment_container, EditCollectionFragment(cachedCollection, true)) diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionItemFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionItemFragment.kt index 3e59b6ba..a2e2a0f7 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionItemFragment.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionItemFragment.kt @@ -101,7 +101,7 @@ class CollectionItemFragment(private val cachedItem: CachedItem) : Fragment() { val context = requireContext() val account = accountHolder.account val cachedCol = collectionModel.value!! - when (cachedCol.meta.collectionType) { + when (cachedCol.collectionType) { Constants.ETEBASE_TYPE_CALENDAR -> { val provider = context.contentResolver.acquireContentProviderClient(CalendarContract.CONTENT_URI)!! val localCalendar = LocalCalendar.findByName(account, provider, LocalCalendar.Factory, cachedCol.col.uid)!! @@ -205,7 +205,7 @@ class PrettyFragment(private val mainFragment: CollectionItemFragment, private v override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { var v: View? = null - when (cachedCollection.meta.collectionType) { + when (cachedCollection.collectionType) { Constants.ETEBASE_TYPE_ADDRESS_BOOK -> { v = inflater.inflate(R.layout.contact_info, container, false) asyncTask = loadContactTask(v) diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersFragment.kt index a5e92ac4..6861080f 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersFragment.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionMembersFragment.kt @@ -54,9 +54,10 @@ class CollectionMembersFragment : Fragment() { private fun initUi(inflater: LayoutInflater, v: View, cachedCollection: CachedCollection) { val meta = cachedCollection.meta + val collectionType = cachedCollection.collectionType val colorSquare = v.findViewById(R.id.color) val color = LocalCalendar.parseColor(meta.color) - when (meta.collectionType) { + when (collectionType) { Constants.ETEBASE_TYPE_CALENDAR -> { colorSquare.setBackgroundColor(color) } diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/EditCollectionFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/EditCollectionFragment.kt index 245822ab..d95a6b36 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/EditCollectionFragment.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/EditCollectionFragment.kt @@ -47,7 +47,7 @@ class EditCollectionFragment(private val cachedCollection: CachedCollection, pri cachedCollection.let { var titleId: Int = R.string.create_calendar if (isCreating) { - when (cachedCollection.meta.collectionType) { + when (cachedCollection.collectionType) { Constants.ETEBASE_TYPE_CALENDAR -> { titleId = R.string.create_calendar } @@ -75,7 +75,7 @@ class EditCollectionFragment(private val cachedCollection: CachedCollection, pri desc.setText(meta.description) val colorSquare = v.findViewById(R.id.color) - when (cachedCollection.meta.collectionType) { + when (cachedCollection.collectionType) { Constants.ETEBASE_TYPE_CALENDAR -> { title.setHint(R.string.create_calendar_display_name_hint) @@ -200,7 +200,7 @@ class EditCollectionFragment(private val cachedCollection: CachedCollection, pri meta.mtime = System.currentTimeMillis() if (ok) { - when (meta.collectionType) { + when (cachedCollection.collectionType) { Constants.ETEBASE_TYPE_CALENDAR, Constants.ETEBASE_TYPE_TASKS -> { val view = v.findViewById(R.id.color) val color = (view.background as ColorDrawable).color diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/ImportCollectionFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/ImportCollectionFragment.kt index 14017fe9..93e032fb 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/ImportCollectionFragment.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/ImportCollectionFragment.kt @@ -57,12 +57,12 @@ class ImportCollectionFragment : Fragment() { img.setImageResource(R.drawable.ic_account_circle_white) text.setText(R.string.import_button_local) card.setOnClickListener { - if (cachedCollection.meta.collectionType == Constants.ETEBASE_TYPE_CALENDAR) { + if (cachedCollection.collectionType == Constants.ETEBASE_TYPE_CALENDAR) { parentFragmentManager.commit { replace(R.id.fragment_container, LocalCalendarImportFragment(accountHolder.account, cachedCollection.col.uid)) addToBackStack(null) } - } else if (cachedCollection.meta.collectionType == Constants.ETEBASE_TYPE_ADDRESS_BOOK) { + } else if (cachedCollection.collectionType == Constants.ETEBASE_TYPE_ADDRESS_BOOK) { parentFragmentManager.commit { replace(R.id.fragment_container, LocalContactImportFragment(accountHolder.account, cachedCollection.col.uid)) addToBackStack(null) @@ -72,7 +72,7 @@ class ImportCollectionFragment : Fragment() { (activity as? BaseActivity?)?.supportActionBar?.setTitle(R.string.import_select_account) } - if (collectionModel.value!!.meta.collectionType == Constants.ETEBASE_TYPE_TASKS) { + if (collectionModel.value!!.collectionType == Constants.ETEBASE_TYPE_TASKS) { card.visibility = View.GONE } } diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/ItemRevisionsListFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/ItemRevisionsListFragment.kt index 4f4ee7a9..cdf425c9 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/ItemRevisionsListFragment.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/ItemRevisionsListFragment.kt @@ -97,7 +97,7 @@ class ItemRevisionsListFragment(private val cachedCollection: CachedCollection, val item = getItem(position) - setItemView(v, cachedCollection.meta.collectionType, item) + setItemView(v, cachedCollection.collectionType, item) /* FIXME: handle entry error: val entryError = data.select(EntryErrorEntity::class.java).where(EntryErrorEntity.ENTRY.eq(entryEntity)).limit(1).get().firstOrNull() diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/ListEntriesFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/ListEntriesFragment.kt index 62bc36b0..b4a0629e 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/ListEntriesFragment.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/ListEntriesFragment.kt @@ -85,7 +85,7 @@ class ListEntriesFragment : ListFragment(), AdapterView.OnItemClickListener { val item = getItem(position) - setItemView(v, cachedCollection.meta.collectionType, item) + setItemView(v, cachedCollection.collectionType, item) /* FIXME: handle entry error: val entryError = data.select(EntryErrorEntity::class.java).where(EntryErrorEntity.ENTRY.eq(entryEntity)).limit(1).get().firstOrNull() diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt index 2252cacf..fab6823d 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt @@ -16,8 +16,8 @@ import androidx.fragment.app.activityViewModels import androidx.fragment.app.commit import androidx.fragment.app.viewModels import com.etebase.client.Collection -import com.etebase.client.CollectionMetadata import com.etebase.client.FetchOptions +import com.etebase.client.ItemMetadata import com.etebase.client.exceptions.EtebaseException import com.etesync.syncadapter.Constants.* import com.etesync.syncadapter.R @@ -107,7 +107,7 @@ class WizardCheckFragment : Fragment() { loadingModel.setLoading(true) doAsync { try { - val collections = colMgr.list(FetchOptions().limit(1)) + val collections = colMgr.list(COLLECTION_TYPES, FetchOptions().limit(1)) uiThread { if (collections.data.size > 0) { activity?.finish() @@ -182,10 +182,11 @@ class WizardFragment : Fragment() { ) baseMeta.forEach { - val meta = CollectionMetadata(it.first, it.second) + val meta = ItemMetadata() + meta.name = it.second meta.mtime = System.currentTimeMillis() - val col = colMgr.create(meta, "") + val col = colMgr.create(it.first, meta, "") uploadCollection(accountHolder, col) } requestSync(requireContext(), accountHolder.account) diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/ViewCollectionFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/ViewCollectionFragment.kt index 9f3cbf24..c12feebc 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/ViewCollectionFragment.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/ViewCollectionFragment.kt @@ -68,7 +68,7 @@ class ViewCollectionFragment : Fragment() { val colorSquare = container.findViewById(R.id.color) val color = LocalCalendar.parseColor(meta.color) - when (meta.collectionType) { + when (cachedCollection.collectionType) { Constants.ETEBASE_TYPE_CALENDAR -> { colorSquare.setBackgroundColor(color) } diff --git a/app/src/main/java/com/etesync/syncadapter/ui/importlocal/ImportFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/importlocal/ImportFragment.kt index c2bef3c9..ee694c27 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/importlocal/ImportFragment.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/importlocal/ImportFragment.kt @@ -436,7 +436,7 @@ class ImportFragment(private val account: Account, private val uid: String, priv } fun newInstance(account: Account, cachedCollection: CachedCollection): ImportFragment { - val enumType = when (cachedCollection.meta.collectionType) { + val enumType = when (cachedCollection.collectionType) { ETEBASE_TYPE_CALENDAR -> CollectionInfo.Type.CALENDAR ETEBASE_TYPE_TASKS -> CollectionInfo.Type.TASKS ETEBASE_TYPE_ADDRESS_BOOK -> CollectionInfo.Type.ADDRESS_BOOK From 6a8ea1633d9fe5a2bfeaa12352edae734bd4e705 Mon Sep 17 00:00:00 2001 From: koffevar Date: Tue, 13 Oct 2020 13:07:13 +0000 Subject: [PATCH 06/89] Translated using Weblate (Russian) Currently translated at 21.1% (71 of 336 strings) Translation: EteSync/Android Translate-URL: https://hosted.weblate.org/projects/etesync/android/ru/ --- app/src/main/res/values-ru/strings.xml | 40 +++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 0a242e10..f2842fb7 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -52,8 +52,46 @@ Синхронизация Другие важные сообщения Отладка - Пожалуйста, подождите … + Пожалуйста, подождите… Управление аккаунтами Адресные книги EteSync + Включить + Общесистемная автоматическая синхронизация отключена + Добро пожаловать в EteSync! + Связаться с нами + Сообщить о проблеме + Инструкция пользователя + FAQ + Веб-сайт + Полезные ссылки + Настройки + О / Лицензия + Адаптер безопасной синхронизации + Закрыть панель навигации + Невозможно создать внешний файл лога: %s + Выключение удалит логи + Логирование на внешнее хранилище: %s + Логирование файлов EteSync включено + Эта программа поставляется СОВЕРШЕННО БЕЗ ГАРАНТИЙ. Это бесплатное программное обеспечение, и вы можете распространять его при определенных условиях. + EteSync обнаружил, что вы используете версию Android, которая может содержать ошибки производителя. +\nПожалуйста, посмотрите FAQ для получения дополнительной информации. + Возможные ошибки поставщика + Это разрабатываемая версия EteSync. Имейте в виду, что все может работать не так, как ожидалось. Пожалуйста, дайте нам конструктивный отзыв для улучшения EteSync. + Выключить для EteSync + Android может отключить / уменьшить синхронизацию EteSync через несколько дней. Чтобы этого не произошло, отключите оптимизацию батареи. + Если возможно, укажите любую другую соответствующую информацию, например, что вы сделали, чтобы вызвать эту ошибку. + Отладочная информация EteSync + Пожалуйста, отправьте трассировку стека разработчикам. + EteSync сломался! + Информационные сообщения о состоянии, такие как сводка изменений синхронизации + Статус сообщений + Не критические проблемы синхронизации, такие как отклоненные изменения коллекций, доступных только для чтения + Предупреждения синхронизации + Важные ошибки, которые останавливают синхронизацию, например, неожиданные ответы сервера + Отчеты о падениях + Повторить + Пропустить + Создать + Адресная книга EteSync \ No newline at end of file From 181dd45e2c63017d82ea3472997d796972044882 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Fri, 16 Oct 2020 16:25:00 +0300 Subject: [PATCH 07/89] NewAccountWizard: don't show retry button when loading is successful. --- .../etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt index fab6823d..a8aa5b38 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt @@ -120,9 +120,6 @@ class WizardCheckFragment : Fragment() { } catch (e: Exception) { uiThread { reportErrorHelper(requireContext(), e) - } - } finally { - uiThread { loadingModel.setLoading(false) } } From b5355b47e3de91e29b4c493cabfcfd615fdc5811 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Fri, 16 Oct 2020 18:54:28 +0300 Subject: [PATCH 08/89] Webview: cleanup the code a bit. --- .../com/etesync/syncadapter/ui/WebViewActivity.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/etesync/syncadapter/ui/WebViewActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/WebViewActivity.kt index 67ef44e5..f56ca8af 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/WebViewActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/WebViewActivity.kt @@ -166,7 +166,7 @@ class WebViewActivity : BaseActivity() { fun openUrl(context: Context, uri: Uri) { if (isAllowedUrl(uri)) { val intent = Intent(context, WebViewActivity::class.java) - intent.putExtra(WebViewActivity.KEY_URL, uri) + intent.putExtra(KEY_URL, uri) context.startActivity(intent) } else { try { @@ -191,7 +191,14 @@ class WebViewActivity : BaseActivity() { } private fun isAllowedUrl(uri: Uri): Boolean { - val allowedUris = arrayOf(Constants.faqUri, Constants.helpUri, Constants.registrationUrl, Constants.dashboard, Constants.webUri.buildUpon().appendEncodedPath("tos/").build(), Constants.webUri.buildUpon().appendEncodedPath("about/").build()) + val allowedUris = arrayOf( + Constants.faqUri, + Constants.helpUri, + Constants.registrationUrl, + Constants.dashboard, + Constants.webUri.buildUpon().appendEncodedPath("tos/").build(), + Constants.webUri.buildUpon().appendEncodedPath("about/").build(), + ) val accountsUri = Constants.webUri.buildUpon().appendEncodedPath("accounts/").build() return allowedUris(allowedUris, uri) || uri.host == accountsUri.host && uri.path!!.startsWith(accountsUri.path!!) From fd94ea51f52944e48029b3d2b3bca9459b27ef73 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Fri, 16 Oct 2020 18:58:20 +0300 Subject: [PATCH 09/89] Signup page: add a notice about the pricing. --- app/src/main/java/com/etesync/syncadapter/Constants.java | 2 ++ .../java/com/etesync/syncadapter/ui/WebViewActivity.kt | 7 ++++++- .../com/etesync/syncadapter/ui/etebase/SignupFragment.kt | 5 +++++ app/src/main/res/layout/signup_fragment.xml | 9 +++++++++ app/src/main/res/values/styles.xml | 1 + 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/etesync/syncadapter/Constants.java b/app/src/main/java/com/etesync/syncadapter/Constants.java index 102aa95f..d83541a0 100644 --- a/app/src/main/java/com/etesync/syncadapter/Constants.java +++ b/app/src/main/java/com/etesync/syncadapter/Constants.java @@ -25,10 +25,12 @@ public class Constants { NOTIFICATION_PERMISSIONS = 20; public static final Uri webUri = Uri.parse((DEBUG_REMOTE_URL == null) ? "https://www.etesync.com/" : DEBUG_REMOTE_URL); + public static final Uri etebaseDashboardPrefix = Uri.parse("https://dashboard.etebase.com/user/partner/"); public static final Uri contactUri = webUri.buildUpon().appendEncodedPath("about/#contact").build(); public static final Uri registrationUrl = webUri.buildUpon().appendEncodedPath("accounts/signup/").build(); public static final Uri reportIssueUri = Uri.parse("https://github.com/etesync/android/issues"); public static final Uri feedbackUri = reportIssueUri; + public static final Uri pricing = webUri.buildUpon().appendEncodedPath("pricing/").build(); public static final Uri dashboard = webUri.buildUpon().appendEncodedPath("dashboard/").build(); public static final Uri faqUri = webUri.buildUpon().appendEncodedPath("faq/").build(); public static final Uri helpUri = webUri.buildUpon().appendEncodedPath("user-guide/android/").build(); diff --git a/app/src/main/java/com/etesync/syncadapter/ui/WebViewActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/WebViewActivity.kt index f56ca8af..7d8b46f2 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/WebViewActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/WebViewActivity.kt @@ -198,10 +198,15 @@ class WebViewActivity : BaseActivity() { Constants.dashboard, Constants.webUri.buildUpon().appendEncodedPath("tos/").build(), Constants.webUri.buildUpon().appendEncodedPath("about/").build(), + Constants.pricing, ) val accountsUri = Constants.webUri.buildUpon().appendEncodedPath("accounts/").build() - return allowedUris(allowedUris, uri) || uri.host == accountsUri.host && uri.path!!.startsWith(accountsUri.path!!) + return allowedUris(allowedUris, uri) || ( + uri.host == accountsUri.host && uri.path!!.startsWith(accountsUri.path!!) + ) || ( + uri.host == Constants.etebaseDashboardPrefix.host && uri.path!!.startsWith(Constants.etebaseDashboardPrefix.path!!) + ) } } } diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/SignupFragment.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/SignupFragment.kt index a7b571c0..5804731c 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/SignupFragment.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/SignupFragment.kt @@ -17,6 +17,7 @@ import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.CheckedTextView +import android.widget.TextView import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment import androidx.fragment.app.commit @@ -32,6 +33,7 @@ import com.etebase.client.exceptions.EtebaseException import com.etesync.syncadapter.Constants import com.etesync.syncadapter.HttpClient import com.etesync.syncadapter.R +import com.etesync.syncadapter.ui.WebViewActivity import com.etesync.syncadapter.ui.setup.BaseConfigurationFinder import com.etesync.syncadapter.ui.setup.CreateAccountFragment import com.etesync.syncadapter.ui.setup.DetectConfigurationFragment @@ -62,6 +64,9 @@ class SignupFragment(private val initialUsername: String?, private val initialPa editPassword = v.findViewById(R.id.url_password) showAdvanced = v.findViewById(R.id.show_advanced) customServer = v.findViewById(R.id.custom_server) + v.findViewById(R.id.trial_notice).setOnClickListener { + WebViewActivity.openUrl(requireContext(), Constants.pricing) + } if (savedInstanceState == null) { editUserName.editText?.setText(initialUsername ?: "") diff --git a/app/src/main/res/layout/signup_fragment.xml b/app/src/main/res/layout/signup_fragment.xml index bf4e2da2..ea620aee 100644 --- a/app/src/main/res/layout/signup_fragment.xml +++ b/app/src/main/res/layout/signup_fragment.xml @@ -29,6 +29,15 @@ android:text="@string/signup_title" android:layout_marginBottom="14dp"/> + + #000000 #d32f2f + #E8F4FD From 18c784692f596419105b8de7dc34ef663f57c7a1 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Sun, 18 Oct 2020 10:31:34 +0300 Subject: [PATCH 10/89] Enable desugaring (needed by ical4android). ical4j and thus ical4android now rely on java.time.ZoneOffset which is only available in Android starting from Android 8. This will make it work on older Android versions too. --- app/build.gradle | 5 +++++ app/proguard-rules.txt | 8 -------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index cbfa2897..de50a1cb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -122,6 +122,9 @@ android { buildTypes.release.signingConfig = null } compileOptions { + // enable because ical4android requires desugaring + coreLibraryDesugaringEnabled true + sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } @@ -135,6 +138,8 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.5' + implementation "org.jetbrains.anko:anko-commons:0.10.4" implementation "com.etesync:journalmanager:1.1.1" diff --git a/app/proguard-rules.txt b/app/proguard-rules.txt index b981122e..345ebb71 100644 --- a/app/proguard-rules.txt +++ b/app/proguard-rules.txt @@ -10,7 +10,6 @@ -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/* -optimizationpasses 5 -allowaccessmodification --dontpreverify # Kotlin -dontwarn kotlin.** @@ -25,14 +24,7 @@ -keep class ezvcard.property.** { *; } # keep all vCard properties (created at runtime) # ical4j: ignore unused dynamic libraries --dontwarn aQute.** --dontwarn groovy.** # Groovy-based ContentBuilder not used --dontwarn javax.cache.** # no JCache support in Android --dontwarn net.fortuna.ical4j.model.** --dontwarn org.codehaus.groovy.** --dontwarn org.apache.log4j.** # ignore warnings from log4j dependency -keep class net.fortuna.ical4j.** { *; } # keep all model classes (properties/factories, created at runtime) --keep class org.threeten.bp.** { *; } # keep ThreeTen (for time zone processing) # okhttp # JSR 305 annotations are for embedding nullability information. From 17e7085aa4bbebf68c428f69c00e370958b79fa6 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Sun, 18 Oct 2020 10:51:47 +0300 Subject: [PATCH 11/89] Fix crash when deleting an item before it was ever uploaded. --- .../syncadapter/syncadapter/SyncManager.kt | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.kt b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.kt index 0722be42..ab91120e 100644 --- a/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.kt +++ b/app/src/main/java/com/etesync/syncadapter/syncadapter/SyncManager.kt @@ -644,15 +644,48 @@ constructor(protected val context: Context, protected val account: Account, prot item.meta = meta } + private fun prepareLocalItemForUpload(colUid: String, local: T): Item { + val cacheItem = if (local.fileName != null) etebaseLocalCache.itemGet(itemMgr, colUid, local.fileName!!) else null + val item: Item + if (cacheItem != null) { + item = cacheItem.item + itemUpdateMtime(item) + } else { + val uid = UUID.randomUUID().toString() + val meta = ItemMetadata() + meta.name = uid + meta.mtime = System.currentTimeMillis() + item = itemMgr.create(meta, "") + + local.prepareForUpload(item.uid, uid) + } + + try { + item.setContent(local.content) + } catch (e: Exception) { + Logger.log.warning("Failed creating local entry ${local.uuid}") + if (local is LocalContact) { + Logger.log.warning("Contact with title ${local.contact?.displayName}") + } else if (local is LocalEvent) { + Logger.log.warning("Event with title ${local.event?.summary}") + } else if (local is LocalTask) { + Logger.log.warning("Task with title ${local.task?.summary}") + } + throw e + } + + return item + } + private fun createPushItems(): List { val ret = LinkedList() val colUid = cachedCollection.col.uid synchronized(etebaseLocalCache) { for (local in localDeleted!!) { - val item = etebaseLocalCache.itemGet(itemMgr, colUid, local.fileName!!)!!.item - itemUpdateMtime(item) + val item = prepareLocalItemForUpload(colUid, local) item.delete() + ret.add(item) if (ret.size == MAX_PUSH) { @@ -663,34 +696,7 @@ constructor(protected val context: Context, protected val account: Account, prot synchronized(etebaseLocalCache) { for (local in localDirty) { - val cacheItem = if (local.fileName != null) etebaseLocalCache.itemGet(itemMgr, colUid, local.fileName!!) else null - val item: Item - if (cacheItem != null) { - item = cacheItem.item - itemUpdateMtime(item) - } else { - val uid = UUID.randomUUID().toString() - val meta = ItemMetadata() - meta.name = uid - meta.mtime = System.currentTimeMillis() - item = itemMgr.create(meta, "") - - local.prepareForUpload(item.uid, uid) - } - - try { - item.setContent(local.content) - } catch (e: Exception) { - Logger.log.warning("Failed creating local entry ${local.uuid}") - if (local is LocalContact) { - Logger.log.warning("Contact with title ${local.contact?.displayName}") - } else if (local is LocalEvent) { - Logger.log.warning("Event with title ${local.event?.summary}") - } else if (local is LocalTask) { - Logger.log.warning("Task with title ${local.task?.summary}") - } - throw e - } + val item = prepareLocalItemForUpload(colUid, local) ret.add(item) From fac8ff65a8626f644665835ab6342a04958505d1 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Sun, 18 Oct 2020 11:42:18 +0300 Subject: [PATCH 12/89] Upgrade desugaring lib. --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index de50a1cb..378d5106 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -138,7 +138,7 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.5' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.9' implementation "org.jetbrains.anko:anko-commons:0.10.4" From 2277888aee6794458e736192097e6429aa0df02b Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Mon, 19 Oct 2020 10:53:01 +0300 Subject: [PATCH 13/89] Rename the etebase_fragment_activity layout. --- .../com/etesync/syncadapter/ui/etebase/CollectionActivity.kt | 2 +- .../com/etesync/syncadapter/ui/etebase/InvitationsActivity.kt | 2 +- .../etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt | 2 +- ...se_collection_activity.xml => etebase_fragment_activity.xml} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename app/src/main/res/layout/{etebase_collection_activity.xml => etebase_fragment_activity.xml} (100%) diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionActivity.kt index add5d988..9b790138 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/CollectionActivity.kt @@ -30,7 +30,7 @@ class CollectionActivity() : BaseActivity() { val colUid = intent.extras!!.getString(EXTRA_COLLECTION_UID) val colType = intent.extras!!.getString(EXTRA_COLLECTION_TYPE) - setContentView(R.layout.etebase_collection_activity) + setContentView(R.layout.etebase_fragment_activity) if (savedInstanceState == null) { model.loadAccount(this, account) diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/InvitationsActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/InvitationsActivity.kt index 124a810b..8da0756d 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/InvitationsActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/InvitationsActivity.kt @@ -18,7 +18,7 @@ class InvitationsActivity : BaseActivity() { account = intent.extras!!.getParcelable(EXTRA_ACCOUNT)!! - setContentView(R.layout.etebase_collection_activity) + setContentView(R.layout.etebase_fragment_activity) if (savedInstanceState == null) { model.loadAccount(this, account) diff --git a/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt b/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt index a8aa5b38..65c9f3b7 100644 --- a/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt +++ b/app/src/main/java/com/etesync/syncadapter/ui/etebase/NewAccountWizardActivity.kt @@ -35,7 +35,7 @@ class NewAccountWizardActivity : BaseActivity() { account = intent.extras!!.getParcelable(EXTRA_ACCOUNT)!! - setContentView(R.layout.etebase_collection_activity) + setContentView(R.layout.etebase_fragment_activity) if (savedInstanceState == null) { setTitle(R.string.account_wizard_collections_title) diff --git a/app/src/main/res/layout/etebase_collection_activity.xml b/app/src/main/res/layout/etebase_fragment_activity.xml similarity index 100% rename from app/src/main/res/layout/etebase_collection_activity.xml rename to app/src/main/res/layout/etebase_fragment_activity.xml From 05b41c7f7d5f62ce5f347fb145e06de6ccb40027 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Mon, 19 Oct 2020 16:09:06 +0300 Subject: [PATCH 14/89] Migration: add a tool for migrating to EteSync v2. --- app/src/main/AndroidManifest.xml | 4 + .../etesync/syncadapter/ui/AccountActivity.kt | 5 + .../syncadapter/ui/MigrateV2Activity.kt | 739 ++++++++++++++++++ .../syncadapter/ui/etebase/SignupFragment.kt | 35 +- .../res/layout/account_collection_item.xml | 10 + .../res/layout/migrate_v2_collections.xml | 194 +++++ .../res/layout/migrate_v2_wizard_welcome.xml | 73 ++ app/src/main/res/menu/activity_account.xml | 5 + app/src/main/res/values/strings.xml | 9 + 9 files changed, 1069 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/com/etesync/syncadapter/ui/MigrateV2Activity.kt create mode 100644 app/src/main/res/layout/migrate_v2_collections.xml create mode 100644 app/src/main/res/layout/migrate_v2_wizard_welcome.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0c4fe99b..58976e3e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -245,6 +245,10 @@ android:name=".ui.etebase.InvitationsActivity" android:exported="false" /> + { + val intent = MigrateV2Activity.newIntent(this, account) + startActivity(intent) + } else -> return super.onOptionsItemSelected(item) } return true diff --git a/app/src/main/java/com/etesync/syncadapter/ui/MigrateV2Activity.kt b/app/src/main/java/com/etesync/syncadapter/ui/MigrateV2Activity.kt new file mode 100644 index 00000000..e15ff488 --- /dev/null +++ b/app/src/main/java/com/etesync/syncadapter/ui/MigrateV2Activity.kt @@ -0,0 +1,739 @@ +package com.etesync.syncadapter.ui + +import android.accounts.Account +import android.accounts.AccountManager +import android.app.Dialog +import android.app.ProgressDialog +import android.content.ContentResolver +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.provider.ContactsContract +import android.text.TextUtils +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.* +import androidx.activity.viewModels +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.* +import at.bitfire.ical4android.Event +import at.bitfire.ical4android.Task +import at.bitfire.vcard4android.Contact +import at.bitfire.vcard4android.ContactsStorageException +import com.etebase.client.Account as EtebaseAccount +import com.etebase.client.Client +import com.etebase.client.Item +import com.etebase.client.ItemMetadata +import com.etesync.journalmanager.model.SyncEntry +import com.etesync.syncadapter.* +import com.etesync.syncadapter.model.* +import com.etesync.syncadapter.resource.LocalAddressBook +import com.etesync.syncadapter.resource.LocalCalendar +import com.etesync.syncadapter.ui.etebase.* +import com.etesync.syncadapter.ui.setup.CreateAccountFragment +import com.etesync.syncadapter.ui.setup.LoginCredentials +import com.google.android.material.textfield.TextInputEditText +import com.google.android.material.textfield.TextInputLayout +import net.cachapa.expandablelayout.ExpandableLayout +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +import okhttp3.Request +import okhttp3.RequestBody +import org.jetbrains.anko.doAsync +import org.jetbrains.anko.uiThread +import java.io.StringReader +import java.net.URI +import java.util.* +import kotlin.collections.HashMap + +class MigrateV2Activity : BaseActivity() { + private lateinit var accountV1: Account + private val model: AccountViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + accountV1 = intent.extras!!.getParcelable(EXTRA_ACCOUNT)!! + + setContentView(R.layout.etebase_fragment_activity) + + if (savedInstanceState == null) { + setTitle(R.string.migrate_v2_wizard_welcome_title) + supportFragmentManager.commit { + replace(R.id.fragment_container, WizardWelcomeFragment(accountV1)) + } + } + } + + companion object { + private val EXTRA_ACCOUNT = "account" + + fun newIntent(context: Context, account: Account): Intent { + val intent = Intent(context, MigrateV2Activity::class.java) + intent.putExtra(EXTRA_ACCOUNT, account) + return intent + } + } +} + + +fun reportErrorHelper(context: Context, e: Throwable) { + AlertDialog.Builder(context) + .setIcon(R.drawable.ic_info_dark) + .setTitle(R.string.exception) + .setMessage(e.localizedMessage) + .setPositiveButton(android.R.string.yes) { _, _ -> }.show() +} + +class WizardWelcomeFragment(private val accountV1: Account) : Fragment() { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val ret = inflater.inflate(R.layout.migrate_v2_wizard_welcome, container, false) + + if (savedInstanceState == null) { + if (container != null) { + initUi(inflater, ret) + } + } + + return ret + } + + private fun initUi(inflater: LayoutInflater, v: View) { + v.findViewById