diff options
author | Ricki Hirner <hirner@bitfire.at> | 2022-05-12 11:21:51 +0300 |
---|---|---|
committer | Ricki Hirner <hirner@bitfire.at> | 2022-05-12 11:46:49 +0300 |
commit | 8384730aff4a5e7f45347918d698aa06e9719a99 (patch) | |
tree | ea63d12db59245a62c14b8f2fa3d88f831c7c6ba | |
parent | 8ca3d857d317e609b759ddf75c3161fa7e6def29 (diff) |
Refactor some models to use proper constructors instead of custom initialize() methods
10 files changed, 147 insertions, 189 deletions
diff --git a/app/src/main/java/at/bitfire/davdroid/db/CollectionDao.kt b/app/src/main/java/at/bitfire/davdroid/db/CollectionDao.kt index a6446a35..6e72ede3 100644 --- a/app/src/main/java/at/bitfire/davdroid/db/CollectionDao.kt +++ b/app/src/main/java/at/bitfire/davdroid/db/CollectionDao.kt @@ -15,11 +15,14 @@ import androidx.room.Query interface CollectionDao: SyncableDao<Collection> { @Query("SELECT DISTINCT color FROM collection WHERE serviceId=:id") - fun colorsByService(id: Long): LiveData<List<Int>> + fun colorsByServiceLive(id: Long): LiveData<List<Int>> @Query("SELECT * FROM collection WHERE id=:id") fun get(id: Long): Collection? + @Query("SELECT * FROM collection WHERE id=:id") + fun getLive(id: Long): LiveData<Collection> + @Query("SELECT * FROM collection WHERE serviceId=:serviceId") fun getByService(serviceId: Long): List<Collection> diff --git a/app/src/main/java/at/bitfire/davdroid/db/HomeSetDao.kt b/app/src/main/java/at/bitfire/davdroid/db/HomeSetDao.kt index aebc7146..9d8c2aa2 100644 --- a/app/src/main/java/at/bitfire/davdroid/db/HomeSetDao.kt +++ b/app/src/main/java/at/bitfire/davdroid/db/HomeSetDao.kt @@ -20,7 +20,7 @@ interface HomeSetDao: SyncableDao<HomeSet> { fun getBindableByService(serviceId: Long): List<HomeSet> @Query("SELECT COUNT(*) FROM homeset WHERE serviceId=:serviceId AND privBind") - fun hasBindableByService(serviceId: Long): LiveData<Boolean> + fun hasBindableByServiceLive(serviceId: Long): LiveData<Boolean> @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertOrReplace(homeSet: HomeSet): Long diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionInfoFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionInfoFragment.kt index 96016f2d..4f780a67 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionInfoFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionInfoFragment.kt @@ -4,22 +4,16 @@ package at.bitfire.davdroid.ui.account -import android.app.Application import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.annotation.UiThread import androidx.fragment.app.DialogFragment import androidx.fragment.app.viewModels -import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.viewModelScope +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider import at.bitfire.davdroid.databinding.CollectionPropertiesBinding import at.bitfire.davdroid.db.AppDatabase -import at.bitfire.davdroid.db.Collection -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject @@ -39,13 +33,15 @@ class CollectionInfoFragment: DialogFragment() { } - val model by viewModels<Model>() - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - arguments?.getLong(ARGS_COLLECTION_ID)?.let { id -> - model.initialize(id) + val model by viewModels<Model>() { + object : ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") + override fun <T : ViewModel> create(modelClass: Class<T>) = + Model(requireArguments().getLong(ARGS_COLLECTION_ID)) as T } + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { val view = CollectionPropertiesBinding.inflate(inflater, container, false) view.lifecycleOwner = this view.model = model @@ -55,25 +51,11 @@ class CollectionInfoFragment: DialogFragment() { class Model( - application: Application - ): AndroidViewModel(application), KoinComponent { + collectionId: Long + ): ViewModel(), KoinComponent { val db by inject<AppDatabase>() - var collection = MutableLiveData<Collection>() - - private var initialized = false - - @UiThread - fun initialize(collectionId: Long) { - // TODO use constructor and model factory instead of custom initialize() - if (initialized) - return - initialized = true - - viewModelScope.launch(Dispatchers.IO) { - collection.postValue(db.collectionDao().get(collectionId)) - } - } + var collection = db.collectionDao().getLive(collectionId) } diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionsFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionsFragment.kt index 7c4787d7..29b7dc00 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionsFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/CollectionsFragment.kt @@ -55,7 +55,12 @@ abstract class CollectionsFragment: Fragment(), KoinComponent, SwipeRefreshLayou object: ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T: ViewModel> create(modelClass: Class<T>): T = - Model(requireActivity().application, accountModel) as T + Model( + requireActivity().application, + accountModel, + requireArguments().getLong(EXTRA_SERVICE_ID), + requireArguments().getString(EXTRA_COLLECTION_TYPE) ?: throw IllegalArgumentException("EXTRA_COLLECTION_TYPE required") + ) as T } } @@ -79,12 +84,6 @@ abstract class CollectionsFragment: Fragment(), KoinComponent, SwipeRefreshLayou override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - // don't get the activity ViewModel in onCreate(), it may crash - model.initialize( - arguments?.getLong(EXTRA_SERVICE_ID) ?: throw IllegalArgumentException("EXTRA_SERVICE_ID required"), - arguments?.getString(EXTRA_COLLECTION_TYPE) ?: throw IllegalArgumentException("EXTRA_COLLECTION_TYPE required") - ) - model.isRefreshing.observe(viewLifecycleOwner, Observer { nowRefreshing -> binding.swipeRefresh.isRefreshing = nowRefreshing }) @@ -263,37 +262,28 @@ abstract class CollectionsFragment: Fragment(), KoinComponent, SwipeRefreshLayou class Model( - val context: Application, - val accountModel: AccountActivity.Model + val context: Application, + val accountModel: AccountActivity.Model, + val serviceId: Long, + val collectionType: String ): ViewModel(), DavService.RefreshingStatusListener, KoinComponent, SyncStatusObserver { private val db by inject<AppDatabase>() - val serviceId = MutableLiveData<Long>() - private lateinit var collectionType: String - // cache task provider val taskProvider by lazy { TaskUtils.currentProvider(context) } - val hasWriteableCollections: LiveData<Boolean> = - Transformations.switchMap(serviceId) { service -> - db.homeSetDao().hasBindableByService(service) - } - val collectionsColors: LiveData<List<Int>> = - Transformations.switchMap(serviceId) { service -> - db.collectionDao().colorsByService(service) - } + val hasWriteableCollections = db.homeSetDao().hasBindableByServiceLive(serviceId) + val collectionsColors = db.collectionDao().colorsByServiceLive(serviceId) val collectionsPager: LiveData<Pager<Int, Collection>> = - Transformations.switchMap(accountModel.showOnlyPersonal) { onlyPersonal -> - Transformations.map(serviceId) { service -> - Pager(PagingConfig(pageSize = 25)) { - if (onlyPersonal) - // show only personal collections - db.collectionDao().pagePersonalByServiceAndType(service, collectionType) - else - // show all collections - db.collectionDao().pageByServiceAndType(service, collectionType) - } + Transformations.map(accountModel.showOnlyPersonal) { onlyPersonal -> + Pager(PagingConfig(pageSize = 25)) { + if (onlyPersonal) + // show only personal collections + db.collectionDao().pagePersonalByServiceAndType(serviceId, collectionType) + else + // show all collections + db.collectionDao().pageByServiceAndType(serviceId, collectionType) } } @@ -319,11 +309,7 @@ abstract class CollectionsFragment: Fragment(), KoinComponent, SwipeRefreshLayou val isSyncPending = MutableLiveData<Boolean>() - fun initialize(id: Long, collectionType: String) { - this.collectionType = collectionType - if (serviceId.value == null) - serviceId.value = id - + init { if (context.bindService(Intent(context, DavService::class.java), svcConn, Context.BIND_AUTO_CREATE)) davServiceConn = svcConn @@ -344,14 +330,12 @@ abstract class CollectionsFragment: Fragment(), KoinComponent, SwipeRefreshLayou } fun refresh() { - serviceId.value?.let { svcId -> - DavService.refreshCollections(context, svcId) - } + DavService.refreshCollections(context, serviceId) } @AnyThread override fun onDavRefreshStatusChanged(id: Long, refreshing: Boolean) { - if (id == serviceId.value) + if (id == serviceId) isRefreshing.postValue(refreshing) } diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/CreateAddressBookActivity.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/CreateAddressBookActivity.kt index a3fdb297..2271ec4a 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/CreateAddressBookActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/CreateAddressBookActivity.kt @@ -5,19 +5,18 @@ package at.bitfire.davdroid.ui.account import android.accounts.Account -import android.app.Application import android.content.Intent import android.os.Bundle import android.text.Editable import android.view.Menu import android.view.MenuItem import androidx.activity.viewModels -import androidx.annotation.MainThread import androidx.appcompat.app.AppCompatActivity import androidx.core.app.TaskStackBuilder import androidx.databinding.DataBindingUtil -import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import at.bitfire.davdroid.R import at.bitfire.davdroid.databinding.ActivityCreateAddressBookBinding @@ -39,8 +38,15 @@ class CreateAddressBookActivity: AppCompatActivity() { const val EXTRA_ACCOUNT = "account" } - private val account by lazy { intent.getParcelableExtra<Account>(EXTRA_ACCOUNT) ?: throw IllegalArgumentException("EXTRA_ACCOUNT must be set") } - val model by viewModels<Model>() + val model by viewModels<Model>() { + object: ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") + override fun <T : ViewModel> create(modelClass: Class<T>): T { + val account = intent.getParcelableExtra<Account>(EXTRA_ACCOUNT) ?: throw IllegalArgumentException("EXTRA_ACCOUNT must be set") + return Model(account) as T + } + } + } lateinit var binding: ActivityCreateAddressBookBinding @@ -67,9 +73,6 @@ class CreateAddressBookActivity: AppCompatActivity() { binding.homeset.setOnItemClickListener { parent, view, position, id -> model.homeSet = parent.getItemAtPosition(position) as HomeSet? } - - if (savedInstanceState == null) - model.initialize(account) } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -80,7 +83,7 @@ class CreateAddressBookActivity: AppCompatActivity() { override fun supportShouldUpRecreateTask(targetIntent: Intent) = true override fun onPrepareSupportNavigateUpTaskStack(builder: TaskStackBuilder) { - builder.editIntentAt(builder.intentCount - 1)?.putExtra(AccountActivity.EXTRA_ACCOUNT, account) + builder.editIntentAt(builder.intentCount - 1)?.putExtra(AccountActivity.EXTRA_ACCOUNT, model.account) } @@ -123,10 +126,9 @@ class CreateAddressBookActivity: AppCompatActivity() { class Model( - application: Application - ) : AndroidViewModel(application), KoinComponent { + val account: Account + ) : ViewModel(), KoinComponent { - var account: Account? = null val db by inject<AppDatabase>() val displayName = MutableLiveData<String>() @@ -137,17 +139,7 @@ class CreateAddressBookActivity: AppCompatActivity() { val homeSets = MutableLiveData<List<HomeSet>>() var homeSet: HomeSet? = null - fun clearNameError(s: Editable) { - displayNameError.value = null - } - - @MainThread - fun initialize(account: Account) { - // TODO use constructor and model factory instead of custom initialize() - if (this.account != null) - return - this.account = account - + init { viewModelScope.launch(Dispatchers.IO) { // load account info db.serviceDao().getByAccountAndType(account.name, Service.TYPE_CARDDAV)?.let { service -> @@ -156,6 +148,10 @@ class CreateAddressBookActivity: AppCompatActivity() { } } + fun clearNameError(s: Editable) { + displayNameError.value = null + } + } } diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/CreateCalendarActivity.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/CreateCalendarActivity.kt index a64c2e96..902b6e48 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/CreateCalendarActivity.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/CreateCalendarActivity.kt @@ -5,7 +5,6 @@ package at.bitfire.davdroid.ui.account import android.accounts.Account -import android.app.Application import android.content.Context import android.content.Intent import android.graphics.drawable.ColorDrawable @@ -14,12 +13,12 @@ import android.view.* import android.widget.ArrayAdapter import android.widget.TextView import androidx.activity.viewModels -import androidx.annotation.MainThread import androidx.appcompat.app.AppCompatActivity import androidx.core.app.NavUtils import androidx.databinding.DataBindingUtil -import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import at.bitfire.davdroid.Constants import at.bitfire.davdroid.R @@ -48,8 +47,15 @@ class CreateCalendarActivity: AppCompatActivity(), ColorPickerDialogListener { const val EXTRA_ACCOUNT = "account" } - private val account by lazy { intent.getParcelableExtra<Account>(EXTRA_ACCOUNT) ?: throw IllegalArgumentException("EXTRA_ACCOUNT must be set") } - val model by viewModels<Model>() + val model by viewModels<Model>() { + object: ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") + override fun <T : ViewModel> create(modelClass: Class<T>): T { + val account = intent.getParcelableExtra<Account>(EXTRA_ACCOUNT) ?: throw IllegalArgumentException("EXTRA_ACCOUNT must be set") + return Model(account) as T + } + } + } lateinit var binding: ActivityCreateCalendarBinding @@ -80,15 +86,12 @@ class CreateCalendarActivity: AppCompatActivity(), ColorPickerDialogListener { } } binding.homeset.setAdapter(homeSetAdapter) - binding.homeset.setOnItemClickListener { parent, view, position, id -> + binding.homeset.setOnItemClickListener { parent, _, position, _ -> model.homeSet = parent.getItemAtPosition(position) as HomeSet? } binding.timezone.setAdapter(TimeZoneAdapter(this)) binding.timezone.setText(TimeZone.getDefault().id, false) - - if (savedInstanceState == null) - model.initialize(account) } override fun onColorSelected(dialogId: Int, rgb: Int) { @@ -211,10 +214,9 @@ class CreateCalendarActivity: AppCompatActivity(), ColorPickerDialogListener { class Model( - application: Application - ): AndroidViewModel(application), KoinComponent { + val account: Account + ): ViewModel(), KoinComponent { - var account: Account? = null val db by inject<AppDatabase>() val displayName = MutableLiveData<String>() @@ -233,12 +235,7 @@ class CreateCalendarActivity: AppCompatActivity(), ColorPickerDialogListener { val supportVTODO = MutableLiveData<Boolean>() val supportVJOURNAL = MutableLiveData<Boolean>() - @MainThread - fun initialize(account: Account) { - if (this.account != null) - return - this.account = account - + init { color.value = Constants.DAVDROID_GREEN_RGBA supportVEVENT.value = true diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/CreateCollectionFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/CreateCollectionFragment.kt index cca37bd1..bc47d740 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/CreateCollectionFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/CreateCollectionFragment.kt @@ -53,30 +53,37 @@ class CreateCollectionFragment: DialogFragment() { const val ARG_SUPPORTS_VJOURNAL = "supportsVJOURNAL" } - val model by viewModels<Model>() + val model by viewModels<Model>() { + object : ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") + override fun <T : ViewModel> create(modelClass: Class<T>): T { + val args = requireArguments() + + val account: Account = args.getParcelable(ARG_ACCOUNT) ?: throw IllegalArgumentException("ARG_ACCOUNT required") + val serviceType = args.getString(ARG_SERVICE_TYPE) ?: throw java.lang.IllegalArgumentException("ARG_SERVICE_TYPE required") + val collection = Collection( + type = args.getString(ARG_TYPE) ?: throw IllegalArgumentException("ARG_TYPE required"), + url = (args.getString(ARG_URL) ?: throw IllegalArgumentException("ARG_URL required")).toHttpUrl(), + displayName = args.getString(ARG_DISPLAY_NAME), + description = args.getString(ARG_DESCRIPTION), + + color = args.ifDefined(ARG_COLOR) { it.getInt(ARG_COLOR) }, + timezone = args.getString(ARG_TIMEZONE), + supportsVEVENT = args.ifDefined(ARG_SUPPORTS_VEVENT) { it.getBoolean(ARG_SUPPORTS_VEVENT) }, + supportsVTODO = args.ifDefined(ARG_SUPPORTS_VTODO) { it.getBoolean(ARG_SUPPORTS_VTODO) }, + supportsVJOURNAL = args.ifDefined(ARG_SUPPORTS_VJOURNAL) { it.getBoolean(ARG_SUPPORTS_VJOURNAL) }, + + sync = true /* by default, sync collections which just have been created */ + ) + + return Model(requireActivity().application, account, serviceType, collection) as T + } + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val args = arguments ?: throw IllegalArgumentException() - - model.account = args.getParcelable(ARG_ACCOUNT) ?: throw IllegalArgumentException("ARG_ACCOUNT required") - model.serviceType = args.getString(ARG_SERVICE_TYPE) ?: throw java.lang.IllegalArgumentException("ARG_SERVICE_TYPE required") - - model.collection = Collection( - type = args.getString(ARG_TYPE) ?: throw IllegalArgumentException("ARG_TYPE required"), - url = (args.getString(ARG_URL) ?: throw IllegalArgumentException("ARG_URL required")).toHttpUrl(), - displayName = args.getString(ARG_DISPLAY_NAME), - description = args.getString(ARG_DESCRIPTION), - - color = args.ifDefined(ARG_COLOR) { it.getInt(ARG_COLOR) }, - timezone = args.getString(ARG_TIMEZONE), - supportsVEVENT = args.ifDefined(ARG_SUPPORTS_VEVENT) { it.getBoolean(ARG_SUPPORTS_VEVENT) }, - supportsVTODO = args.ifDefined(ARG_SUPPORTS_VTODO) { it.getBoolean(ARG_SUPPORTS_VTODO) }, - supportsVJOURNAL = args.ifDefined(ARG_SUPPORTS_VJOURNAL) { it.getBoolean(ARG_SUPPORTS_VJOURNAL) }, - - sync = true /* by default, sync collections which just have been created */ - ) model.createCollection().observe(this, Observer { exception -> if (exception == null) @@ -104,13 +111,12 @@ class CreateCollectionFragment: DialogFragment() { class Model( - app: Application + app: Application, + val account: Account, + val serviceType: String, + val collection: Collection ): AndroidViewModel(app), KoinComponent { - lateinit var account: Account - lateinit var serviceType: String - lateinit var collection: Collection - val result = MutableLiveData<Exception>() fun createCollection(): LiveData<Exception> { diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/DeleteCollectionFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/DeleteCollectionFragment.kt index 081d0a8c..9490b1b8 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/DeleteCollectionFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/DeleteCollectionFragment.kt @@ -10,7 +10,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.annotation.MainThread import androidx.fragment.app.DialogFragment import androidx.fragment.app.viewModels import androidx.lifecycle.* @@ -43,17 +42,19 @@ class DeleteCollectionFragment: DialogFragment() { } } - val model by viewModels<Model>() - - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - model.initialize( - requireArguments().getParcelable(ARG_ACCOUNT)!!, - requireArguments().getLong(ARG_COLLECTION_ID) - ) + val model by viewModels<Model>() { + object : ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") + override fun <T : ViewModel> create(modelClass: Class<T>): T = + Model( + requireActivity().application, + requireArguments().getParcelable(ARG_ACCOUNT) ?: throw IllegalArgumentException("ARG_ACCOUNT required"), + requireArguments().getLong(ARG_COLLECTION_ID) + ) as T + } } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { val binding = DeleteCollectionBinding.inflate(layoutInflater, null, false) binding.lifecycleOwner = this @@ -82,31 +83,25 @@ class DeleteCollectionFragment: DialogFragment() { class Model( - application: Application + application: Application, + var account: Account, + val collectionId: Long ): AndroidViewModel(application), KoinComponent { - var account: Account? = null - var collectionInfo: Collection? = null - val db by inject<AppDatabase>() + var collectionInfo: Collection? = null val confirmation = MutableLiveData<Boolean>() val result = MutableLiveData<Exception>() - @MainThread - fun initialize(account: Account, collectionId: Long) { - if (this.account == null) - this.account = account - - if (collectionInfo == null) - viewModelScope.launch(Dispatchers.IO) { - collectionInfo = db.collectionDao().get(collectionId) - } + init { + viewModelScope.launch(Dispatchers.IO) { + collectionInfo = db.collectionDao().get(collectionId) + } } fun deleteCollection(): LiveData<Exception> { viewModelScope.launch(Dispatchers.IO + NonCancellable) { - val account = account ?: return@launch val collectionInfo = collectionInfo ?: return@launch val context = getApplication<Application>() diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt index 4ca95d85..147ac43c 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/RenameAccountFragment.kt @@ -25,6 +25,7 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.viewModels import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.Observer import androidx.lifecycle.viewModelScope import at.bitfire.davdroid.DavUtils import at.bitfire.davdroid.InvalidAccountException @@ -76,7 +77,7 @@ class RenameAccountFragment: DialogFragment() { layout.setPadding(8*density, 8*density, 8*density, 8*density) layout.addView(editText) - model.finished.observe(this, { + model.finished.observe(this, Observer { this@RenameAccountFragment.requireActivity().finish() }) @@ -163,14 +164,15 @@ class RenameAccountFragment: DialogFragment() { if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) try { context.contentResolver.acquireContentProviderClient(ContactsContract.AUTHORITY)?.let { provider -> - for (addrBookAccount in accountManager.getAccountsByType(context.getString(R.string.account_type_address_book))) - try { + try { + for (addrBookAccount in accountManager.getAccountsByType(context.getString(R.string.account_type_address_book))) { val addressBook = LocalAddressBook(context, addrBookAccount, provider) if (oldAccount == addressBook.mainAccount) addressBook.mainAccount = Account(newName, oldAccount.type) - } finally { - provider.closeCompat() } + } finally { + provider.closeCompat() + } } } catch (e: Exception) { Logger.log.log(Level.SEVERE, "Couldn't update address book accounts", e) diff --git a/app/src/main/java/at/bitfire/davdroid/ui/account/WebcalFragment.kt b/app/src/main/java/at/bitfire/davdroid/ui/account/WebcalFragment.kt index 7ba2b223..1b70e3f9 100644 --- a/app/src/main/java/at/bitfire/davdroid/ui/account/WebcalFragment.kt +++ b/app/src/main/java/at/bitfire/davdroid/ui/account/WebcalFragment.kt @@ -19,9 +19,7 @@ import android.view.* import androidx.annotation.WorkerThread import androidx.core.content.ContextCompat import androidx.fragment.app.viewModels -import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.MediatorLiveData -import androidx.lifecycle.viewModelScope +import androidx.lifecycle.* import androidx.room.Transaction import at.bitfire.dav4jvm.UrlUtils import at.bitfire.davdroid.Constants @@ -48,16 +46,23 @@ class WebcalFragment: CollectionsFragment() { override val noCollectionsStringId = R.string.account_no_webcals - val webcalModel by viewModels<WebcalModel>() + val webcalModel by viewModels<WebcalModel>() { + object : ViewModelProvider.Factory { + @Suppress("UNCHECKED_CAST") + override fun <T : ViewModel> create(modelClass: Class<T>) = + WebcalModel( + requireActivity().application, + requireArguments().getLong(EXTRA_SERVICE_ID) + ) as T + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - webcalModel.subscribedUrls.observe(this, { urls -> + webcalModel.subscribedUrls.observe(this, Observer { urls -> Logger.log.log(Level.FINE, "Got Android calendar list", urls.keys) }) - - webcalModel.initialize(arguments?.getLong(EXTRA_SERVICE_ID) ?: throw IllegalArgumentException("EXTRA_SERVICE_ID required")) } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) = @@ -156,10 +161,10 @@ class WebcalFragment: CollectionsFragment() { } - class WebcalModel(application: Application): AndroidViewModel(application), KoinComponent { - - private var initialized = false - private var serviceId: Long = 0 + class WebcalModel( + application: Application, + val serviceId: Long + ): AndroidViewModel(application), KoinComponent { private val db by inject<AppDatabase>() private val resolver = application.contentResolver @@ -167,10 +172,6 @@ class WebcalFragment: CollectionsFragment() { private var calendarPermission = false private val calendarProvider = object: MediatorLiveData<ContentProviderClient>() { init { - init() - } - - fun init() { calendarPermission = ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.READ_CALENDAR) == PackageManager.PERMISSION_GRANTED if (calendarPermission) connect() @@ -273,14 +274,6 @@ class WebcalFragment: CollectionsFragment() { } - fun initialize(dbServiceId: Long) { - if (initialized) - return - initialized = true - - serviceId = dbServiceId - } - fun unsubscribe(webcal: Collection) { viewModelScope.launch(Dispatchers.IO) { // find first matching source (Webcal) URL |