mirror of
https://github.com/etesync/android
synced 2025-07-09 16:18:26 +00:00
NewAccountWizard: add a new account setup wizard.
This commit is contained in:
parent
82ce1783bc
commit
db843d8798
@ -237,6 +237,10 @@
|
|||||||
android:name=".ui.etebase.CollectionActivity"
|
android:name=".ui.etebase.CollectionActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
/>
|
/>
|
||||||
|
<activity
|
||||||
|
android:name=".ui.etebase.NewAccountWizardActivity"
|
||||||
|
android:exported="false"
|
||||||
|
/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.etebase.InvitationsActivity"
|
android:name=".ui.etebase.InvitationsActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
@ -0,0 +1,212 @@
|
|||||||
|
package com.etesync.syncadapter.ui.etebase
|
||||||
|
|
||||||
|
import android.accounts.Account
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.ProgressBar
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
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.exceptions.EtebaseException
|
||||||
|
import com.etesync.syncadapter.R
|
||||||
|
import com.etesync.syncadapter.syncadapter.requestSync
|
||||||
|
import com.etesync.syncadapter.ui.BaseActivity
|
||||||
|
import org.jetbrains.anko.doAsync
|
||||||
|
import org.jetbrains.anko.uiThread
|
||||||
|
|
||||||
|
class NewAccountWizardActivity : BaseActivity() {
|
||||||
|
private lateinit var account: Account
|
||||||
|
private val model: AccountViewModel by viewModels()
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
account = intent.extras!!.getParcelable(EXTRA_ACCOUNT)!!
|
||||||
|
|
||||||
|
setContentView(R.layout.etebase_collection_activity)
|
||||||
|
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
setTitle(R.string.account_wizard_collections_title)
|
||||||
|
model.loadAccount(this, account)
|
||||||
|
supportFragmentManager.commit {
|
||||||
|
replace(R.id.fragment_container, WizardCheckFragment())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val EXTRA_ACCOUNT = "account"
|
||||||
|
|
||||||
|
fun newIntent(context: Context, account: Account): Intent {
|
||||||
|
val intent = Intent(context, NewAccountWizardActivity::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 WizardCheckFragment : Fragment() {
|
||||||
|
private val model: AccountViewModel by activityViewModels()
|
||||||
|
private val loadingModel: LoadingViewModel by viewModels()
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
val ret = inflater.inflate(R.layout.account_wizard_check, container, false)
|
||||||
|
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
if (container != null) {
|
||||||
|
initUi(inflater, ret)
|
||||||
|
model.observe(this, {
|
||||||
|
checkAccountInit()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initUi(inflater: LayoutInflater, v: View) {
|
||||||
|
val button = v.findViewById<Button>(R.id.button_retry)
|
||||||
|
val progress = v.findViewById<ProgressBar>(R.id.loading)
|
||||||
|
button.setOnClickListener {
|
||||||
|
checkAccountInit()
|
||||||
|
}
|
||||||
|
loadingModel.observe(this, {
|
||||||
|
if (it) {
|
||||||
|
progress.visibility = View.VISIBLE
|
||||||
|
button.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
progress.visibility = View.GONE
|
||||||
|
button.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkAccountInit() {
|
||||||
|
val colMgr = model.value?.colMgr ?: return
|
||||||
|
loadingModel.setLoading(true)
|
||||||
|
doAsync {
|
||||||
|
try {
|
||||||
|
val collections = colMgr.list(FetchOptions().limit(1))
|
||||||
|
uiThread {
|
||||||
|
if (collections.data.size > 0) {
|
||||||
|
activity?.finish()
|
||||||
|
} else {
|
||||||
|
parentFragmentManager.commit {
|
||||||
|
replace(R.id.fragment_container, WizardFragment())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
uiThread {
|
||||||
|
reportErrorHelper(requireContext(), e)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
uiThread {
|
||||||
|
loadingModel.setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WizardFragment : Fragment() {
|
||||||
|
private val model: AccountViewModel by activityViewModels()
|
||||||
|
private val loadingModel: LoadingViewModel by viewModels()
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
val ret = inflater.inflate(R.layout.account_wizard_collections, container, false)
|
||||||
|
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
if (container != null) {
|
||||||
|
initUi(inflater, ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initUi(inflater: LayoutInflater, v: View) {
|
||||||
|
v.findViewById<Button>(R.id.button_create).setOnClickListener {
|
||||||
|
createCollections()
|
||||||
|
}
|
||||||
|
|
||||||
|
v.findViewById<Button>(R.id.button_skip).setOnClickListener {
|
||||||
|
activity?.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
val buttons = v.findViewById<View>(R.id.buttons_holder)
|
||||||
|
val progress = v.findViewById<ProgressBar>(R.id.loading)
|
||||||
|
loadingModel.observe(this, {
|
||||||
|
if (it) {
|
||||||
|
progress.visibility = View.VISIBLE
|
||||||
|
buttons.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
progress.visibility = View.GONE
|
||||||
|
buttons.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCollections() {
|
||||||
|
val accountHolder = model.value ?: return
|
||||||
|
val colMgr = accountHolder.colMgr
|
||||||
|
loadingModel.setLoading(true)
|
||||||
|
|
||||||
|
doAsync {
|
||||||
|
try {
|
||||||
|
val baseMeta = listOf(
|
||||||
|
Pair("etebase.vcard", "My Contacts"),
|
||||||
|
Pair("etebase.vevent", "My Calendar"),
|
||||||
|
Pair("etebase.vtodo", "My Tasks"),
|
||||||
|
)
|
||||||
|
|
||||||
|
baseMeta.forEach {
|
||||||
|
val meta = CollectionMetadata(it.first, it.second)
|
||||||
|
meta.mtime = System.currentTimeMillis()
|
||||||
|
|
||||||
|
val col = colMgr.create(meta, "")
|
||||||
|
uploadCollection(accountHolder, col)
|
||||||
|
}
|
||||||
|
requestSync(requireContext(), accountHolder.account)
|
||||||
|
activity?.finish()
|
||||||
|
} catch (e: EtebaseException) {
|
||||||
|
uiThread {
|
||||||
|
reportErrorHelper(requireContext(), e)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
uiThread {
|
||||||
|
loadingModel.setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun uploadCollection(accountHolder: AccountHolder, col: Collection) {
|
||||||
|
val etebaseLocalCache = accountHolder.etebaseLocalCache
|
||||||
|
val colMgr = accountHolder.colMgr
|
||||||
|
colMgr.upload(col)
|
||||||
|
synchronized(etebaseLocalCache) {
|
||||||
|
etebaseLocalCache.collectionSet(colMgr, col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@ import androidx.fragment.app.DialogFragment
|
|||||||
import at.bitfire.ical4android.TaskProvider.Companion.TASK_PROVIDERS
|
import at.bitfire.ical4android.TaskProvider.Companion.TASK_PROVIDERS
|
||||||
import com.etesync.syncadapter.*
|
import com.etesync.syncadapter.*
|
||||||
import com.etesync.syncadapter.log.Logger
|
import com.etesync.syncadapter.log.Logger
|
||||||
|
import com.etesync.syncadapter.ui.etebase.NewAccountWizardActivity
|
||||||
import com.etesync.syncadapter.ui.setup.BaseConfigurationFinder.Configuration
|
import com.etesync.syncadapter.ui.setup.BaseConfigurationFinder.Configuration
|
||||||
import com.etesync.syncadapter.utils.AndroidCompat
|
import com.etesync.syncadapter.utils.AndroidCompat
|
||||||
import com.etesync.syncadapter.utils.TaskProviderHandling
|
import com.etesync.syncadapter.utils.TaskProviderHandling
|
||||||
@ -42,14 +43,16 @@ class CreateAccountFragment : DialogFragment() {
|
|||||||
val config = requireArguments().getSerializable(KEY_CONFIG) as Configuration
|
val config = requireArguments().getSerializable(KEY_CONFIG) as Configuration
|
||||||
|
|
||||||
val activity = requireActivity()
|
val activity = requireActivity()
|
||||||
if (createAccount(config.userName, config)) {
|
val account = createAccount(config.userName, config)
|
||||||
|
if (account != null) {
|
||||||
activity.setResult(Activity.RESULT_OK)
|
activity.setResult(Activity.RESULT_OK)
|
||||||
|
startActivity(NewAccountWizardActivity.newIntent(requireContext(), account))
|
||||||
activity.finish()
|
activity.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(InvalidAccountException::class)
|
@Throws(InvalidAccountException::class)
|
||||||
protected fun createAccount(accountName: String, config: Configuration): Boolean {
|
protected fun createAccount(accountName: String, config: Configuration): Account? {
|
||||||
val account = Account(accountName, App.accountType)
|
val account = Account(accountName, App.accountType)
|
||||||
|
|
||||||
// create Android account
|
// create Android account
|
||||||
@ -57,7 +60,7 @@ class CreateAccountFragment : DialogFragment() {
|
|||||||
|
|
||||||
val accountManager = AccountManager.get(context)
|
val accountManager = AccountManager.get(context)
|
||||||
if (!accountManager.addAccountExplicitly(account, config.password, null))
|
if (!accountManager.addAccountExplicitly(account, config.password, null))
|
||||||
return false
|
return null
|
||||||
|
|
||||||
AccountSettings.setUserData(accountManager, account, config.url, config.userName)
|
AccountSettings.setUserData(accountManager, account, config.url, config.userName)
|
||||||
|
|
||||||
@ -86,7 +89,7 @@ class CreateAccountFragment : DialogFragment() {
|
|||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return account
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
47
app/src/main/res/layout/account_wizard_check.xml
Normal file
47
app/src/main/res/layout/account_wizard_check.xml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright © 2013 – 2016 Ricki Hirner (bitfire web engineering).
|
||||||
|
~ All rights reserved. This program and the accompanying materials
|
||||||
|
~ are made available under the terms of the GNU Public License v3.0
|
||||||
|
~ which accompanies this distribution, and is available at
|
||||||
|
~ http://www.gnu.org/licenses/gpl.html
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/account_wizard_collections_title"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/loading"
|
||||||
|
style="@android:style/Widget.Material.ProgressBar.Large"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:indeterminateOnly="true"
|
||||||
|
android:keepScreenOn="true" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_retry"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/retry"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
</LinearLayout>
|
72
app/src/main/res/layout/account_wizard_collections.xml
Normal file
72
app/src/main/res/layout/account_wizard_collections.xml
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright © 2013 – 2016 Ricki Hirner (bitfire web engineering).
|
||||||
|
~ All rights reserved. This program and the accompanying materials
|
||||||
|
~ are made available under the terms of the GNU Public License v3.0
|
||||||
|
~ which accompanies this distribution, and is available at
|
||||||
|
~ http://www.gnu.org/licenses/gpl.html
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/account_wizard_collections_title"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/account_wizard_collections_body" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/loading"
|
||||||
|
style="@android:style/Widget.Material.ProgressBar.Large"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:indeterminateOnly="true"
|
||||||
|
android:keepScreenOn="true"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/buttons_holder"
|
||||||
|
style="@style/stepper_nav_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_skip"
|
||||||
|
style="@style/stepper_nav_button"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/skip" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
style="@style/stepper_nav_button"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_create"
|
||||||
|
style="@style/stepper_nav_button"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/create" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
@ -18,8 +18,11 @@
|
|||||||
<string name="address_books_authority_title">Address books</string>
|
<string name="address_books_authority_title">Address books</string>
|
||||||
<string name="help">Help</string>
|
<string name="help">Help</string>
|
||||||
<string name="manage_accounts">Manage accounts</string>
|
<string name="manage_accounts">Manage accounts</string>
|
||||||
<string name="please_wait">Please wait …</string>
|
<string name="please_wait">Please wait…</string>
|
||||||
<string name="send">Send</string>
|
<string name="send">Send</string>
|
||||||
|
<string name="create">Create</string>
|
||||||
|
<string name="skip">Skip</string>
|
||||||
|
<string name="retry">Retry</string>
|
||||||
|
|
||||||
<string name="notification_channel_crash_reports">Crash Reports</string>
|
<string name="notification_channel_crash_reports">Crash Reports</string>
|
||||||
<string name="notification_channel_debugging">Debugging</string>
|
<string name="notification_channel_debugging">Debugging</string>
|
||||||
@ -83,6 +86,10 @@
|
|||||||
<string name="accounts_showcase_add">You need to add an account in order to use EteSync. Click here to add one...</string>
|
<string name="accounts_showcase_add">You need to add an account in order to use EteSync. Click here to add one...</string>
|
||||||
<string name="accounts_missing_permissions">Missing permissions: %s</string>
|
<string name="accounts_missing_permissions">Missing permissions: %s</string>
|
||||||
|
|
||||||
|
<!-- Account Wizard -->
|
||||||
|
<string name="account_wizard_collections_title">Welcome to EteSync!</string>
|
||||||
|
<string name="account_wizard_collections_body">In order to start using EteSync you need to create collections to store your data. Click "Create" to create a default calendar, address book and a task list for you.</string>
|
||||||
|
|
||||||
<!-- AccountUpdateService -->
|
<!-- AccountUpdateService -->
|
||||||
|
|
||||||
<!-- AppSettingsActivity -->
|
<!-- AppSettingsActivity -->
|
||||||
|
Loading…
Reference in New Issue
Block a user