Browse Source

Merge pull request #2223 from nextcloud/chore/1549/roomMigration5

Migrate remaining controllers from requery to room
Andy Scherzinger 2 years ago
parent
commit
12efda5064

+ 34 - 34
app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt

@@ -26,6 +26,7 @@ import android.content.pm.ActivityInfo
 import android.os.Bundle
 import android.os.Bundle
 import android.os.Handler
 import android.os.Handler
 import android.text.TextUtils
 import android.text.TextUtils
+import android.util.Log
 import android.view.View
 import android.view.View
 import androidx.work.Data
 import androidx.work.Data
 import androidx.work.OneTimeWorkRequest
 import androidx.work.OneTimeWorkRequest
@@ -39,15 +40,16 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
 import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
 import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
 import com.nextcloud.talk.controllers.base.NewBaseController
 import com.nextcloud.talk.controllers.base.NewBaseController
 import com.nextcloud.talk.controllers.util.viewBinding
 import com.nextcloud.talk.controllers.util.viewBinding
+import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.databinding.ControllerAccountVerificationBinding
 import com.nextcloud.talk.databinding.ControllerAccountVerificationBinding
 import com.nextcloud.talk.events.EventStatus
 import com.nextcloud.talk.events.EventStatus
 import com.nextcloud.talk.jobs.CapabilitiesWorker
 import com.nextcloud.talk.jobs.CapabilitiesWorker
 import com.nextcloud.talk.jobs.PushRegistrationWorker
 import com.nextcloud.talk.jobs.PushRegistrationWorker
 import com.nextcloud.talk.jobs.SignalingSettingsWorker
 import com.nextcloud.talk.jobs.SignalingSettingsWorker
-import com.nextcloud.talk.models.database.UserEntity
 import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
 import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
 import com.nextcloud.talk.models.json.generic.Status
 import com.nextcloud.talk.models.json.generic.Status
 import com.nextcloud.talk.models.json.userprofile.UserProfileOverall
 import com.nextcloud.talk.models.json.userprofile.UserProfileOverall
+import com.nextcloud.talk.users.UserManager
 import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.ClosedInterfaceImpl
 import com.nextcloud.talk.utils.ClosedInterfaceImpl
 import com.nextcloud.talk.utils.UriUtils
 import com.nextcloud.talk.utils.UriUtils
@@ -57,9 +59,8 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_ACCOUNT_IMPORT
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ORIGINAL_PROTOCOL
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ORIGINAL_PROTOCOL
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_TOKEN
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_TOKEN
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USERNAME
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USERNAME
-import com.nextcloud.talk.utils.database.user.UserUtils
 import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
 import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
-import io.reactivex.CompletableObserver
+import io.reactivex.MaybeObserver
 import io.reactivex.Observer
 import io.reactivex.Observer
 import io.reactivex.android.schedulers.AndroidSchedulers
 import io.reactivex.android.schedulers.AndroidSchedulers
 import io.reactivex.disposables.Disposable
 import io.reactivex.disposables.Disposable
@@ -68,7 +69,6 @@ import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 import org.greenrobot.eventbus.ThreadMode
 import java.net.CookieManager
 import java.net.CookieManager
-import java.util.ArrayList
 import javax.inject.Inject
 import javax.inject.Inject
 
 
 @AutoInjector(NextcloudTalkApplication::class)
 @AutoInjector(NextcloudTalkApplication::class)
@@ -83,7 +83,7 @@ class AccountVerificationController(args: Bundle? = null) :
     lateinit var ncApi: NcApi
     lateinit var ncApi: NcApi
 
 
     @Inject
     @Inject
-    lateinit var userUtils: UserUtils
+    lateinit var userManager: UserManager
 
 
     @Inject
     @Inject
     lateinit var cookieManager: CookieManager
     lateinit var cookieManager: CookieManager
@@ -248,28 +248,36 @@ class AccountVerificationController(args: Bundle? = null) :
     }
     }
 
 
     private fun storeProfile(displayName: String?, userId: String) {
     private fun storeProfile(displayName: String?, userId: String) {
-        userUtils.createOrUpdateUser(
-            username, token,
-            baseUrl, displayName, null, java.lang.Boolean.TRUE,
-            userId, null, null,
-            appPreferences!!.temporaryClientCertAlias, null
+        userManager.storeProfile(
+            username,
+            UserManager.UserAttributes(
+                id = null,
+                serverUrl = baseUrl,
+                currentUser = true,
+                userId = userId,
+                token = token,
+                displayName = displayName,
+                pushConfigurationState = null,
+                capabilities = null,
+                certificateAlias = appPreferences!!.temporaryClientCertAlias,
+                externalSignalingServer = null
+            )
         )
         )
             .subscribeOn(Schedulers.io())
             .subscribeOn(Schedulers.io())
-            .subscribe(object : Observer<UserEntity> {
+            .subscribe(object : MaybeObserver<User> {
                 override fun onSubscribe(d: Disposable) {
                 override fun onSubscribe(d: Disposable) {
                     disposables.add(d)
                     disposables.add(d)
                 }
                 }
 
 
                 @SuppressLint("SetTextI18n")
                 @SuppressLint("SetTextI18n")
-                override fun onNext(userEntity: UserEntity) {
-                    internalAccountId = userEntity.id
+                override fun onSuccess(user: User) {
+                    internalAccountId = user.id!!
                     if (ClosedInterfaceImpl().isGooglePlayServicesAvailable) {
                     if (ClosedInterfaceImpl().isGooglePlayServicesAvailable) {
                         registerForPush()
                         registerForPush()
                     } else {
                     } else {
                         activity!!.runOnUiThread {
                         activity!!.runOnUiThread {
                             binding.progressText.text =
                             binding.progressText.text =
-                                """
-                                    ${binding.progressText.text}
+                                """ ${binding.progressText.text}
                                     ${resources!!.getString(R.string.nc_push_disabled)}
                                     ${resources!!.getString(R.string.nc_push_disabled)}
                                 """.trimIndent()
                                 """.trimIndent()
                         }
                         }
@@ -280,10 +288,9 @@ class AccountVerificationController(args: Bundle? = null) :
                 @SuppressLint("SetTextI18n")
                 @SuppressLint("SetTextI18n")
                 override fun onError(e: Throwable) {
                 override fun onError(e: Throwable) {
                     binding.progressText.text =
                     binding.progressText.text =
+                        """ ${binding.progressText.text}
                         """
                         """
-                            ${binding.progressText.text}
-                    """.trimIndent() +
-                        resources!!.getString(R.string.nc_display_name_not_stored)
+                        .trimIndent() + resources!!.getString(R.string.nc_display_name_not_stored)
                     abortVerification()
                     abortVerification()
                 }
                 }
 
 
@@ -431,10 +438,11 @@ class AccountVerificationController(args: Bundle? = null) :
 
 
     private fun proceedWithLogin() {
     private fun proceedWithLogin() {
         cookieManager.cookieStore.removeAll()
         cookieManager.cookieStore.removeAll()
-        userUtils.disableAllUsersWithoutId(internalAccountId)
+        val userDisabledCount = userManager.disableAllUsersWithoutId(internalAccountId).blockingGet()
+        Log.d(TAG, "Disabled $userDisabledCount users that had no id")
         if (activity != null) {
         if (activity != null) {
             activity!!.runOnUiThread {
             activity!!.runOnUiThread {
-                if (userUtils.users.size == 1) {
+                if (userManager.users.blockingGet().size == 1) {
                     router.setRoot(
                     router.setRoot(
                         RouterTransaction.with(ConversationsListController(Bundle()))
                         RouterTransaction.with(ConversationsListController(Bundle()))
                             .pushChangeHandler(HorizontalChangeHandler())
                             .pushChangeHandler(HorizontalChangeHandler())
@@ -472,18 +480,10 @@ class AccountVerificationController(args: Bundle? = null) :
     private fun abortVerification() {
     private fun abortVerification() {
         if (!isAccountImport) {
         if (!isAccountImport) {
             if (internalAccountId != -1L) {
             if (internalAccountId != -1L) {
-                userUtils.deleteUserWithId(internalAccountId).subscribe(object : CompletableObserver {
-                    override fun onSubscribe(d: Disposable) {
-                        // unused atm
-                    }
-                    override fun onComplete() {
-                        activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
-                    }
-
-                    override fun onError(e: Throwable) {
-                        // unused atm
-                    }
-                })
+                val count = userManager.deleteUser(internalAccountId)
+                if (count > 0) {
+                    activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
+                }
             } else {
             } else {
                 activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
                 activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
             }
             }
@@ -498,7 +498,7 @@ class AccountVerificationController(args: Bundle? = null) :
                             router.popToRoot()
                             router.popToRoot()
                         }
                         }
                     } else {
                     } else {
-                        if (userUtils.anyUserExists()) {
+                        if (userManager.users.blockingGet().isNotEmpty()) {
                             router.setRoot(
                             router.setRoot(
                                 RouterTransaction.with(ConversationsListController(Bundle()))
                                 RouterTransaction.with(ConversationsListController(Bundle()))
                                     .pushChangeHandler(HorizontalChangeHandler())
                                     .pushChangeHandler(HorizontalChangeHandler())
@@ -518,7 +518,7 @@ class AccountVerificationController(args: Bundle? = null) :
     }
     }
 
 
     companion object {
     companion object {
-        const val TAG = "AccountVerificationController"
+        const val TAG = "AccountVerification"
         const val DELAY_IN_MILLIS: Long = 7500
         const val DELAY_IN_MILLIS: Long = 7500
     }
     }
 
 

+ 12 - 19
app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt

@@ -168,7 +168,6 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_ID
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USER_ENTITY
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USER_ENTITY
 import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
 import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
-import com.nextcloud.talk.utils.database.user.UserUtils
 import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil
 import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil
 import com.nextcloud.talk.utils.rx.DisposableSet
 import com.nextcloud.talk.utils.rx.DisposableSet
 import com.nextcloud.talk.utils.singletons.ApplicationWideCurrentRoomHolder
 import com.nextcloud.talk.utils.singletons.ApplicationWideCurrentRoomHolder
@@ -222,16 +221,10 @@ class ChatController(args: Bundle) :
     private val binding: ControllerChatBinding by viewBinding(ControllerChatBinding::bind)
     private val binding: ControllerChatBinding by viewBinding(ControllerChatBinding::bind)
 
 
     @Inject
     @Inject
-    @JvmField
-    var ncApi: NcApi? = null
+    lateinit var ncApi: NcApi
 
 
     @Inject
     @Inject
-    @JvmField
-    var userUtils: UserUtils? = null
-
-    @Inject
-    @JvmField
-    var eventBus: EventBus? = null
+    lateinit var eventBus: EventBus
 
 
     @Inject
     @Inject
     lateinit var permissionUtil: PlatformPermissionUtil
     lateinit var permissionUtil: PlatformPermissionUtil
@@ -332,7 +325,7 @@ class ChatController(args: Bundle) :
 
 
             val startNanoTime = System.nanoTime()
             val startNanoTime = System.nanoTime()
             Log.d(TAG, "getRoomInfo - getRoom - calling: " + startNanoTime)
             Log.d(TAG, "getRoomInfo - getRoom - calling: " + startNanoTime)
-            ncApi?.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, conversationUser.baseUrl, roomToken))
+            ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, conversationUser.baseUrl, roomToken))
                 ?.subscribeOn(Schedulers.io())
                 ?.subscribeOn(Schedulers.io())
                 ?.observeOn(AndroidSchedulers.mainThread())
                 ?.observeOn(AndroidSchedulers.mainThread())
                 ?.subscribe(object : Observer<RoomOverall> {
                 ?.subscribe(object : Observer<RoomOverall> {
@@ -399,7 +392,7 @@ class ChatController(args: Bundle) :
         }
         }
 
 
         Log.d(TAG, "handleFromNotification - getRooms - calling")
         Log.d(TAG, "handleFromNotification - getRooms - calling")
-        ncApi?.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, conversationUser?.baseUrl))
+        ncApi.getRooms(credentials, ApiUtils.getUrlForRooms(apiVersion, conversationUser?.baseUrl))
             ?.subscribeOn(Schedulers.io())?.observeOn(AndroidSchedulers.mainThread())
             ?.subscribeOn(Schedulers.io())?.observeOn(AndroidSchedulers.mainThread())
             ?.subscribe(object : Observer<RoomsOverall> {
             ?.subscribe(object : Observer<RoomsOverall> {
                 override fun onSubscribe(d: Disposable) {
                 override fun onSubscribe(d: Disposable) {
@@ -1687,7 +1680,7 @@ class ChatController(args: Bundle) :
             "onAttach: Controller: " + System.identityHashCode(this).toString() +
             "onAttach: Controller: " + System.identityHashCode(this).toString() +
                 " Activity: " + System.identityHashCode(activity).toString()
                 " Activity: " + System.identityHashCode(activity).toString()
         )
         )
-        eventBus?.register(this)
+        eventBus.register(this)
 
 
         if (conversationUser?.userId != "?" &&
         if (conversationUser?.userId != "?" &&
             CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "mention-flag") ?: false &&
             CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "mention-flag") ?: false &&
@@ -1777,7 +1770,7 @@ class ChatController(args: Bundle) :
                 " Activity: " + System.identityHashCode(activity).toString()
                 " Activity: " + System.identityHashCode(activity).toString()
         )
         )
 
 
-        eventBus?.unregister(this)
+        eventBus.unregister(this)
 
 
         if (activity != null) {
         if (activity != null) {
             activity?.findViewById<View>(R.id.toolbar)?.setOnClickListener(null)
             activity?.findViewById<View>(R.id.toolbar)?.setOnClickListener(null)
@@ -1849,7 +1842,7 @@ class ChatController(args: Bundle) :
 
 
             val startNanoTime = System.nanoTime()
             val startNanoTime = System.nanoTime()
             Log.d(TAG, "joinRoomWithPassword - joinRoom - calling: " + startNanoTime)
             Log.d(TAG, "joinRoomWithPassword - joinRoom - calling: " + startNanoTime)
-            ncApi?.joinRoom(
+            ncApi.joinRoom(
                 credentials,
                 credentials,
                 ApiUtils.getUrlForParticipantsActive(apiVersion, conversationUser?.baseUrl, roomToken),
                 ApiUtils.getUrlForParticipantsActive(apiVersion, conversationUser?.baseUrl, roomToken),
                 roomPassword
                 roomPassword
@@ -1935,7 +1928,7 @@ class ChatController(args: Bundle) :
 
 
         val startNanoTime = System.nanoTime()
         val startNanoTime = System.nanoTime()
         Log.d(TAG, "leaveRoom - leaveRoom - calling: " + startNanoTime)
         Log.d(TAG, "leaveRoom - leaveRoom - calling: " + startNanoTime)
-        ncApi?.leaveRoom(
+        ncApi.leaveRoom(
             credentials,
             credentials,
             ApiUtils.getUrlForParticipantsActive(
             ApiUtils.getUrlForParticipantsActive(
                 apiVersion,
                 apiVersion,
@@ -2150,7 +2143,7 @@ class ChatController(args: Bundle) :
         if (lookIntoFuture > 0) {
         if (lookIntoFuture > 0) {
             val finalTimeout = timeout
             val finalTimeout = timeout
             Log.d(TAG, "pullChatMessages - pullChatMessages[lookIntoFuture > 0] - calling")
             Log.d(TAG, "pullChatMessages - pullChatMessages[lookIntoFuture > 0] - calling")
-            ncApi?.pullChatMessages(
+            ncApi.pullChatMessages(
                 credentials,
                 credentials,
                 ApiUtils.getUrlForChat(apiVersion, conversationUser?.baseUrl, roomToken), fieldMap
                 ApiUtils.getUrlForChat(apiVersion, conversationUser?.baseUrl, roomToken), fieldMap
             )
             )
@@ -2192,7 +2185,7 @@ class ChatController(args: Bundle) :
                 })
                 })
         } else {
         } else {
             Log.d(TAG, "pullChatMessages - pullChatMessages[lookIntoFuture <= 0] - calling")
             Log.d(TAG, "pullChatMessages - pullChatMessages[lookIntoFuture <= 0] - calling")
-            ncApi?.pullChatMessages(
+            ncApi.pullChatMessages(
                 credentials,
                 credentials,
                 ApiUtils.getUrlForChat(apiVersion, conversationUser?.baseUrl, roomToken), fieldMap
                 ApiUtils.getUrlForChat(apiVersion, conversationUser?.baseUrl, roomToken), fieldMap
             )
             )
@@ -2700,7 +2693,7 @@ class ChatController(args: Bundle) :
                 apiVersion = ApiUtils.getChatApiVersion(conversationUser, intArrayOf(1))
                 apiVersion = ApiUtils.getChatApiVersion(conversationUser, intArrayOf(1))
             }
             }
 
 
-            ncApi?.deleteChatMessage(
+            ncApi.deleteChatMessage(
                 credentials,
                 credentials,
                 ApiUtils.getUrlForChatMessage(
                 ApiUtils.getUrlForChatMessage(
                     apiVersion,
                     apiVersion,
@@ -3066,7 +3059,7 @@ class ChatController(args: Bundle) :
                 null
                 null
             )
             )
 
 
-            ncApi?.createRoom(
+            ncApi.createRoom(
                 credentials,
                 credentials,
                 retrofitBucket.url, retrofitBucket.queryMap
                 retrofitBucket.url, retrofitBucket.queryMap
             )
             )

+ 0 - 4
app/src/main/java/com/nextcloud/talk/controllers/GeocodingController.kt

@@ -45,7 +45,6 @@ import com.nextcloud.talk.controllers.base.NewBaseController
 import com.nextcloud.talk.controllers.util.viewBinding
 import com.nextcloud.talk.controllers.util.viewBinding
 import com.nextcloud.talk.databinding.ControllerGeocodingBinding
 import com.nextcloud.talk.databinding.ControllerGeocodingBinding
 import com.nextcloud.talk.utils.bundle.BundleKeys
 import com.nextcloud.talk.utils.bundle.BundleKeys
-import com.nextcloud.talk.utils.database.user.UserUtils
 import fr.dudie.nominatim.client.TalkJsonNominatimClient
 import fr.dudie.nominatim.client.TalkJsonNominatimClient
 import fr.dudie.nominatim.model.Address
 import fr.dudie.nominatim.model.Address
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.CoroutineScope
@@ -69,9 +68,6 @@ class GeocodingController(args: Bundle) :
     @Inject
     @Inject
     lateinit var ncApi: NcApi
     lateinit var ncApi: NcApi
 
 
-    @Inject
-    lateinit var userUtils: UserUtils
-
     @Inject
     @Inject
     lateinit var okHttpClient: OkHttpClient
     lateinit var okHttpClient: OkHttpClient
 
 

+ 8 - 5
app/src/main/java/com/nextcloud/talk/controllers/LocationPickerController.kt

@@ -53,11 +53,11 @@ import com.nextcloud.talk.controllers.base.NewBaseController
 import com.nextcloud.talk.controllers.util.viewBinding
 import com.nextcloud.talk.controllers.util.viewBinding
 import com.nextcloud.talk.databinding.ControllerLocationBinding
 import com.nextcloud.talk.databinding.ControllerLocationBinding
 import com.nextcloud.talk.models.json.generic.GenericOverall
 import com.nextcloud.talk.models.json.generic.GenericOverall
+import com.nextcloud.talk.users.UserManager
 import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.bundle.BundleKeys
 import com.nextcloud.talk.utils.bundle.BundleKeys
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
-import com.nextcloud.talk.utils.database.user.UserUtils
 import fr.dudie.nominatim.client.TalkJsonNominatimClient
 import fr.dudie.nominatim.client.TalkJsonNominatimClient
 import fr.dudie.nominatim.model.Address
 import fr.dudie.nominatim.model.Address
 import io.reactivex.Observer
 import io.reactivex.Observer
@@ -96,7 +96,7 @@ class LocationPickerController(args: Bundle) :
     lateinit var ncApi: NcApi
     lateinit var ncApi: NcApi
 
 
     @Inject
     @Inject
-    lateinit var userUtils: UserUtils
+    lateinit var userManager: UserManager
 
 
     @Inject
     @Inject
     lateinit var okHttpClient: OkHttpClient
     lateinit var okHttpClient: OkHttpClient
@@ -135,11 +135,13 @@ class LocationPickerController(args: Bundle) :
     @Suppress("Detekt.TooGenericExceptionCaught")
     @Suppress("Detekt.TooGenericExceptionCaught")
     override fun onDetach(view: View) {
     override fun onDetach(view: View) {
         super.onDetach(view)
         super.onDetach(view)
+
         try {
         try {
             locationManager!!.removeUpdates(this)
             locationManager!!.removeUpdates(this)
         } catch (e: Exception) {
         } catch (e: Exception) {
             Log.e(TAG, "error when trying to remove updates for location Manager", e)
             Log.e(TAG, "error when trying to remove updates for location Manager", e)
         }
         }
+
         locationOverlay.disableMyLocation()
         locationOverlay.disableMyLocation()
     }
     }
 
 
@@ -404,11 +406,12 @@ class LocationPickerController(args: Bundle) :
             "{\"type\":\"geo-location\",\"id\":\"geo:$selectedLat,$selectedLon\",\"latitude\":\"$selectedLat\"," +
             "{\"type\":\"geo-location\",\"id\":\"geo:$selectedLat,$selectedLon\",\"latitude\":\"$selectedLat\"," +
                 "\"longitude\":\"$selectedLon\",\"name\":\"$locationNameToShare\"}"
                 "\"longitude\":\"$selectedLon\",\"name\":\"$locationNameToShare\"}"
 
 
-        val apiVersion = ApiUtils.getChatApiVersion(userUtils.currentUser, intArrayOf(1))
+        val currentUser = userManager.currentUser.blockingGet()
+        val apiVersion = ApiUtils.getChatApiVersion(currentUser, intArrayOf(1))
 
 
         ncApi.sendLocation(
         ncApi.sendLocation(
-            ApiUtils.getCredentials(userUtils.currentUser?.username, userUtils.currentUser?.token),
-            ApiUtils.getUrlToSendLocation(apiVersion, userUtils.currentUser?.baseUrl, roomToken),
+            ApiUtils.getCredentials(currentUser?.username, currentUser?.token),
+            ApiUtils.getUrlToSendLocation(apiVersion, currentUser?.baseUrl, roomToken),
             "geo-location",
             "geo-location",
             objectId,
             objectId,
             metaData
             metaData

+ 10 - 11
app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt

@@ -3,8 +3,8 @@
  *
  *
  * @author Andy Scherzinger
  * @author Andy Scherzinger
  * @author Mario Danic
  * @author Mario Danic
- * Copyright (C) 2021 Andy Scherzinger (info@andy-scherzinger.de)
- * Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
+ * Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
+ * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
  *
  *
  * This program is free software: you can redistribute it and/or modify
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
@@ -44,15 +44,14 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedA
 import com.nextcloud.talk.controllers.base.NewBaseController
 import com.nextcloud.talk.controllers.base.NewBaseController
 import com.nextcloud.talk.controllers.util.viewBinding
 import com.nextcloud.talk.controllers.util.viewBinding
 import com.nextcloud.talk.databinding.ControllerServerSelectionBinding
 import com.nextcloud.talk.databinding.ControllerServerSelectionBinding
-import com.nextcloud.talk.models.database.UserEntity
 import com.nextcloud.talk.models.json.generic.Status
 import com.nextcloud.talk.models.json.generic.Status
-import com.nextcloud.talk.utils.AccountUtils.findAccounts
+import com.nextcloud.talk.users.UserManager
+import com.nextcloud.talk.utils.AccountUtils.findAccountsForUsers
 import com.nextcloud.talk.utils.AccountUtils.getAppNameBasedOnPackage
 import com.nextcloud.talk.utils.AccountUtils.getAppNameBasedOnPackage
 import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.UriUtils
 import com.nextcloud.talk.utils.UriUtils
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_ACCOUNT_IMPORT
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_IS_ACCOUNT_IMPORT
-import com.nextcloud.talk.utils.database.user.UserUtils
 import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
 import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
 import io.reactivex.android.schedulers.AndroidSchedulers
 import io.reactivex.android.schedulers.AndroidSchedulers
 import io.reactivex.disposables.Disposable
 import io.reactivex.disposables.Disposable
@@ -70,7 +69,7 @@ class ServerSelectionController :
     lateinit var ncApi: NcApi
     lateinit var ncApi: NcApi
 
 
     @Inject
     @Inject
-    lateinit var userUtils: UserUtils
+    lateinit var userManager: UserManager
 
 
     private var statusQueryDisposable: Disposable? = null
     private var statusQueryDisposable: Disposable? = null
 
 
@@ -119,9 +118,9 @@ class ServerSelectionController :
             if (
             if (
                 (
                 (
                     TextUtils.isEmpty(resources!!.getString(R.string.nc_import_account_type)) ||
                     TextUtils.isEmpty(resources!!.getString(R.string.nc_import_account_type)) ||
-                        findAccounts(userUtils.users as List<UserEntity>).isEmpty()
+                        findAccountsForUsers(userManager.users.blockingGet()).isEmpty()
                     ) &&
                     ) &&
-                userUtils.users.size == 0
+                userManager.users.blockingGet().isEmpty()
             ) {
             ) {
                 binding.helperTextView.setText(R.string.nc_get_from_provider)
                 binding.helperTextView.setText(R.string.nc_get_from_provider)
                 binding.helperTextView.setOnClickListener {
                 binding.helperTextView.setOnClickListener {
@@ -134,12 +133,12 @@ class ServerSelectionController :
                     )
                     )
                     startActivity(browserIntent)
                     startActivity(browserIntent)
                 }
                 }
-            } else if (findAccounts(userUtils.users as List<UserEntity>).size > 0) {
+            } else if (findAccountsForUsers(userManager.users.blockingGet()).isNotEmpty()) {
                 if (!TextUtils.isEmpty(
                 if (!TextUtils.isEmpty(
                         getAppNameBasedOnPackage(resources!!.getString(R.string.nc_import_accounts_from))
                         getAppNameBasedOnPackage(resources!!.getString(R.string.nc_import_accounts_from))
                     )
                     )
                 ) {
                 ) {
-                    if (findAccounts(userUtils.users as List<UserEntity>).size > 1) {
+                    if (findAccountsForUsers(userManager.users.blockingGet()).size > 1) {
                         binding.helperTextView.setText(
                         binding.helperTextView.setText(
                             String.format(
                             String.format(
                                 resources!!.getString(R.string.nc_server_import_accounts),
                                 resources!!.getString(R.string.nc_server_import_accounts),
@@ -155,7 +154,7 @@ class ServerSelectionController :
                         )
                         )
                     }
                     }
                 } else {
                 } else {
-                    if (findAccounts(userUtils.users as List<UserEntity>).size > 1) {
+                    if (findAccountsForUsers(userManager.users.blockingGet()).size > 1) {
                         binding.helperTextView.text = resources!!.getString(R.string.nc_server_import_accounts_plain)
                         binding.helperTextView.text = resources!!.getString(R.string.nc_server_import_accounts_plain)
                     } else {
                     } else {
                         binding.helperTextView.text = resources!!.getString(R.string.nc_server_import_account_plain)
                         binding.helperTextView.text = resources!!.getString(R.string.nc_server_import_account_plain)

+ 34 - 47
app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt

@@ -57,18 +57,16 @@ import com.nextcloud.talk.databinding.ControllerWebViewLoginBinding
 import com.nextcloud.talk.events.CertificateEvent
 import com.nextcloud.talk.events.CertificateEvent
 import com.nextcloud.talk.jobs.PushRegistrationWorker
 import com.nextcloud.talk.jobs.PushRegistrationWorker
 import com.nextcloud.talk.models.LoginData
 import com.nextcloud.talk.models.LoginData
+import com.nextcloud.talk.users.UserManager
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_BASE_URL
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_BASE_URL
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ORIGINAL_PROTOCOL
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ORIGINAL_PROTOCOL
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_TOKEN
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_TOKEN
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USERNAME
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USERNAME
-import com.nextcloud.talk.utils.database.user.UserUtils
 import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
 import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
 import com.nextcloud.talk.utils.ssl.MagicTrustManager
 import com.nextcloud.talk.utils.ssl.MagicTrustManager
 import de.cotech.hw.fido.WebViewFidoBridge
 import de.cotech.hw.fido.WebViewFidoBridge
-import io.reactivex.android.schedulers.AndroidSchedulers
 import io.reactivex.disposables.Disposable
 import io.reactivex.disposables.Disposable
-import io.reactivex.schedulers.Schedulers
 import io.requery.Persistable
 import io.requery.Persistable
 import io.requery.reactivex.ReactiveEntityStore
 import io.requery.reactivex.ReactiveEntityStore
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.EventBus
@@ -89,7 +87,7 @@ class WebViewLoginController(args: Bundle? = null) : NewBaseController(
     private val binding: ControllerWebViewLoginBinding by viewBinding(ControllerWebViewLoginBinding::bind)
     private val binding: ControllerWebViewLoginBinding by viewBinding(ControllerWebViewLoginBinding::bind)
 
 
     @Inject
     @Inject
-    lateinit var userUtils: UserUtils
+    lateinit var userManager: UserManager
 
 
     @Inject
     @Inject
     lateinit var dataStore: ReactiveEntityStore<Persistable>
     lateinit var dataStore: ReactiveEntityStore<Persistable>
@@ -223,13 +221,13 @@ class WebViewLoginController(args: Bundle? = null) : NewBaseController(
             }
             }
 
 
             override fun onReceivedClientCertRequest(view: WebView, request: ClientCertRequest) {
             override fun onReceivedClientCertRequest(view: WebView, request: ClientCertRequest) {
-                val userEntity = userUtils.currentUser
+                val user = userManager.currentUser.blockingGet()
                 var alias: String? = null
                 var alias: String? = null
                 if (!isPasswordUpdate) {
                 if (!isPasswordUpdate) {
                     alias = appPreferences!!.temporaryClientCertAlias
                     alias = appPreferences!!.temporaryClientCertAlias
                 }
                 }
-                if (TextUtils.isEmpty(alias) && userEntity != null) {
-                    alias = userEntity.clientCertificate
+                if (TextUtils.isEmpty(alias) && user != null) {
+                    alias = user.clientCertificate
                 }
                 }
                 if (!TextUtils.isEmpty(alias)) {
                 if (!TextUtils.isEmpty(alias)) {
                     val finalAlias = alias
                     val finalAlias = alias
@@ -327,15 +325,16 @@ class WebViewLoginController(args: Bundle? = null) : NewBaseController(
         val loginData = parseLoginData(assembledPrefix, dataString)
         val loginData = parseLoginData(assembledPrefix, dataString)
         if (loginData != null) {
         if (loginData != null) {
             dispose()
             dispose()
-            val currentUser = userUtils.currentUser
+            val currentUser = userManager.currentUser.blockingGet()
             var messageType: ApplicationWideMessageHolder.MessageType? = null
             var messageType: ApplicationWideMessageHolder.MessageType? = null
-            if (!isPasswordUpdate && userUtils.getIfUserWithUsernameAndServer(loginData.username, baseUrl)) {
+            if (!isPasswordUpdate &&
+                userManager.checkIfUserExists(loginData.username!!, baseUrl!!).blockingGet()
+            ) {
                 messageType = ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED
                 messageType = ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED
             }
             }
-            if (userUtils.checkIfUserIsScheduledForDeletion(loginData.username, baseUrl)) {
-                ApplicationWideMessageHolder.getInstance().setMessageType(
+            if (userManager.checkIfUserIsScheduledForDeletion(loginData.username!!, baseUrl!!).blockingGet()) {
+                ApplicationWideMessageHolder.getInstance().messageType =
                     ApplicationWideMessageHolder.MessageType.ACCOUNT_SCHEDULED_FOR_DELETION
                     ApplicationWideMessageHolder.MessageType.ACCOUNT_SCHEDULED_FOR_DELETION
-                )
                 if (!isPasswordUpdate) {
                 if (!isPasswordUpdate) {
                     router.popToRoot()
                     router.popToRoot()
                 } else {
                 } else {
@@ -366,47 +365,35 @@ class WebViewLoginController(args: Bundle? = null) : NewBaseController(
             } else {
             } else {
                 if (isPasswordUpdate) {
                 if (isPasswordUpdate) {
                     if (currentUser != null) {
                     if (currentUser != null) {
-                        userQueryDisposable = userUtils.createOrUpdateUser(
-                            null,
-                            loginData.token,
-                            null,
-                            null,
-                            "",
-                            java.lang.Boolean.TRUE,
-                            null,
-                            currentUser.id,
-                            null,
-                            appPreferences!!.temporaryClientCertAlias,
-                            null
+                        currentUser.clientCertificate = appPreferences!!.temporaryClientCertAlias
+                        currentUser.token = loginData.token
+                        val rowsUpdated = userManager.updateOrCreateUser(currentUser).blockingGet()
+                        Log.d(TAG, "User rows updated: $rowsUpdated")
+
+                        if (finalMessageType != null) {
+                            ApplicationWideMessageHolder.getInstance().messageType = finalMessageType
+                        }
+
+                        val data = Data.Builder().putString(
+                            PushRegistrationWorker.ORIGIN,
+                            "WebViewLoginController#parseAndLoginFromWebView"
+                        ).build()
+
+                        val pushRegistrationWork = OneTimeWorkRequest.Builder(
+                            PushRegistrationWorker::class.java
                         )
                         )
-                            .subscribeOn(Schedulers.io())
-                            .observeOn(AndroidSchedulers.mainThread())
-                            .subscribe(
-                                {
-                                    if (finalMessageType != null) {
-                                        ApplicationWideMessageHolder.getInstance().setMessageType(finalMessageType)
-                                    }
-                                    val data = Data.Builder().putString(
-                                        PushRegistrationWorker.ORIGIN,
-                                        "WebViewLoginController#parseAndLoginFromWebView"
-                                    ).build()
-                                    val pushRegistrationWork = OneTimeWorkRequest.Builder(
-                                        PushRegistrationWorker::class.java
-                                    )
-                                        .setInputData(data)
-                                        .build()
-                                    WorkManager.getInstance().enqueue(pushRegistrationWork)
-                                    router.popCurrentController()
-                                },
-                                { dispose() }
-                            ) { dispose() }
+                            .setInputData(data)
+                            .build()
+
+                        WorkManager.getInstance().enqueue(pushRegistrationWork)
+                        router.popCurrentController()
                     }
                     }
                 } else {
                 } else {
                     if (finalMessageType != null) {
                     if (finalMessageType != null) {
                         // FIXME when the user registers a new account that was setup before (aka
                         // FIXME when the user registers a new account that was setup before (aka
                         //  ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED)
                         //  ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED)
-                        //  The token is not updated in the database and therefor the account not visible/usable
-                        ApplicationWideMessageHolder.getInstance().setMessageType(finalMessageType)
+                        //  The token is not updated in the database and therefore the account not visible/usable
+                        ApplicationWideMessageHolder.getInstance().messageType = finalMessageType
                     }
                     }
                     router.popToRoot()
                     router.popToRoot()
                 }
                 }

+ 5 - 4
app/src/main/java/com/nextcloud/talk/data/user/UsersDao.kt

@@ -24,6 +24,7 @@ package com.nextcloud.talk.data.user
 
 
 import android.util.Log
 import android.util.Log
 import androidx.room.Dao
 import androidx.room.Dao
+import androidx.room.Delete
 import androidx.room.Insert
 import androidx.room.Insert
 import androidx.room.OnConflictStrategy
 import androidx.room.OnConflictStrategy
 import androidx.room.Query
 import androidx.room.Query
@@ -45,8 +46,8 @@ abstract class UsersDao {
     @Query("SELECT * FROM User where current = 1")
     @Query("SELECT * FROM User where current = 1")
     abstract fun getActiveUserSynchronously(): UserEntity?
     abstract fun getActiveUserSynchronously(): UserEntity?
 
 
-    @Query("DELETE FROM User WHERE id = :id")
-    abstract fun deleteUserWithId(id: Long)
+    @Delete
+    abstract fun deleteUser(user: UserEntity): Int
 
 
     @Update
     @Update
     abstract fun updateUser(user: UserEntity): Int
     abstract fun updateUser(user: UserEntity): Int
@@ -70,8 +71,8 @@ abstract class UsersDao {
     @Query("SELECT * FROM User where userId = :userId")
     @Query("SELECT * FROM User where userId = :userId")
     abstract fun getUserWithUserId(userId: String): Maybe<UserEntity>
     abstract fun getUserWithUserId(userId: String): Maybe<UserEntity>
 
 
-    @Query("SELECT * FROM User where userId != :userId")
-    abstract fun getUsersWithoutUserId(userId: Long): Single<List<UserEntity>>
+    @Query("SELECT * FROM User where id != :id")
+    abstract fun getUsersWithoutId(id: Long): Single<List<UserEntity>>
 
 
     @Query("SELECT * FROM User where scheduledForDeletion = 1")
     @Query("SELECT * FROM User where scheduledForDeletion = 1")
     abstract fun getUsersScheduledForDeletion(): Single<List<UserEntity>>
     abstract fun getUsersScheduledForDeletion(): Single<List<UserEntity>>

+ 2 - 2
app/src/main/java/com/nextcloud/talk/data/user/UsersRepository.kt

@@ -33,14 +33,14 @@ interface UsersRepository {
     fun getUserWithId(id: Long): Maybe<User>
     fun getUserWithId(id: Long): Maybe<User>
     fun getUserWithIdNotScheduledForDeletion(id: Long): Maybe<User>
     fun getUserWithIdNotScheduledForDeletion(id: Long): Maybe<User>
     fun getUserWithUserId(userId: String): Maybe<User>
     fun getUserWithUserId(userId: String): Maybe<User>
-    fun getUsersWithoutUserId(userId: Long): Single<List<User>>
+    fun getUsersWithoutUserId(id: Long): Single<List<User>>
     fun getUsersScheduledForDeletion(): Single<List<User>>
     fun getUsersScheduledForDeletion(): Single<List<User>>
     fun getUsersNotScheduledForDeletion(): Single<List<User>>
     fun getUsersNotScheduledForDeletion(): Single<List<User>>
     fun getUserWithUsernameAndServer(username: String, server: String): Maybe<User>
     fun getUserWithUsernameAndServer(username: String, server: String): Maybe<User>
     fun updateUser(user: User): Int
     fun updateUser(user: User): Int
     fun insertUser(user: User): Long
     fun insertUser(user: User): Long
     fun setUserAsActiveWithId(id: Long): Single<Boolean>
     fun setUserAsActiveWithId(id: Long): Single<Boolean>
-    fun deleteUserWithId(id: Long)
+    fun deleteUser(user: User): Int
     fun setAnyUserAsActive(): Boolean
     fun setAnyUserAsActive(): Boolean
     fun markUserForDeletion(id: Long): Boolean
     fun markUserForDeletion(id: Long): Boolean
 }
 }

+ 4 - 4
app/src/main/java/com/nextcloud/talk/data/user/UsersRepositoryImpl.kt

@@ -49,8 +49,8 @@ class UsersRepositoryImpl(private val usersDao: UsersDao) : UsersRepository {
         return usersDao.getUserWithUserId(userId).map { UserMapper.toModel(it) }
         return usersDao.getUserWithUserId(userId).map { UserMapper.toModel(it) }
     }
     }
 
 
-    override fun getUsersWithoutUserId(userId: Long): Single<List<User>> {
-        return usersDao.getUsersWithoutUserId(userId).map { UserMapper.toModel(it) }
+    override fun getUsersWithoutUserId(id: Long): Single<List<User>> {
+        return usersDao.getUsersWithoutId(id).map { UserMapper.toModel(it) }
     }
     }
 
 
     override fun getUsersScheduledForDeletion(): Single<List<User>> {
     override fun getUsersScheduledForDeletion(): Single<List<User>> {
@@ -77,8 +77,8 @@ class UsersRepositoryImpl(private val usersDao: UsersDao) : UsersRepository {
         return Single.just(usersDao.setUserAsActiveWithId(id))
         return Single.just(usersDao.setUserAsActiveWithId(id))
     }
     }
 
 
-    override fun deleteUserWithId(id: Long) {
-        usersDao.deleteUserWithId(id)
+    override fun deleteUser(user: User): Int {
+        return usersDao.deleteUser(UserMapper.toEntity(user))
     }
     }
 
 
     override fun setAnyUserAsActive(): Boolean {
     override fun setAnyUserAsActive(): Boolean {

+ 97 - 46
app/src/main/java/com/nextcloud/talk/users/UserManager.kt

@@ -31,7 +31,6 @@ import com.nextcloud.talk.models.json.push.PushConfigurationState
 import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
 import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
 import io.reactivex.Maybe
 import io.reactivex.Maybe
 import io.reactivex.Single
 import io.reactivex.Single
-import java.lang.Boolean.TRUE
 
 
 @Suppress("TooManyFunctions")
 @Suppress("TooManyFunctions")
 class UserManager internal constructor(private val userRepository: UsersRepository) : CurrentUserProviderNew {
 class UserManager internal constructor(private val userRepository: UsersRepository) : CurrentUserProviderNew {
@@ -41,31 +40,13 @@ class UserManager internal constructor(private val userRepository: UsersReposito
     val usersScheduledForDeletion: Single<List<User>>
     val usersScheduledForDeletion: Single<List<User>>
         get() = userRepository.getUsersScheduledForDeletion()
         get() = userRepository.getUsersScheduledForDeletion()
 
 
-    private fun setAnyUserAndSetAsActive(): Single<User> {
-        val results = userRepository.getUsersNotScheduledForDeletion()
-
-        return results.map { users ->
-            users
-                .firstOrNull()
-                ?.apply {
-                    current = true
-                }.also { user ->
-                    userRepository.updateUser(user!!)
-                }
-        }
-    }
-
     override val currentUser: Maybe<User>
     override val currentUser: Maybe<User>
         get() {
         get() {
             return userRepository.getActiveUser()
             return userRepository.getActiveUser()
         }
         }
 
 
-    fun deleteUser(internalId: Long) {
-        userRepository.deleteUserWithId(internalId)
-    }
-
-    fun deleteUserWithId(internalId: Long) {
-        userRepository.deleteUserWithId(internalId)
+    fun deleteUser(internalId: Long): Int {
+        return userRepository.deleteUser(userRepository.getUserWithId(internalId).blockingGet())
     }
     }
 
 
     fun getUserById(userId: String): Maybe<User> {
     fun getUserById(userId: String): Maybe<User> {
@@ -76,8 +57,8 @@ class UserManager internal constructor(private val userRepository: UsersReposito
         return userRepository.getUserWithId(id)
         return userRepository.getUserWithId(id)
     }
     }
 
 
-    fun disableAllUsersWithoutId(userId: Long): Single<Int> {
-        val results = userRepository.getUsersWithoutUserId(userId)
+    fun disableAllUsersWithoutId(id: Long): Single<Int> {
+        val results = userRepository.getUsersWithoutUserId(id)
 
 
         return results.map { users ->
         return results.map { users ->
             var count = 0
             var count = 0
@@ -92,28 +73,58 @@ class UserManager internal constructor(private val userRepository: UsersReposito
         }
         }
     }
     }
 
 
-    fun checkIfUserIsScheduledForDeletion(username: String, server: String): Maybe<Boolean> {
-        return userRepository.getUserWithUsernameAndServer(username, server).map { it.scheduledForDeletion }
+    fun checkIfUserIsScheduledForDeletion(username: String, server: String): Single<Boolean> {
+        return userRepository
+            .getUserWithUsernameAndServer(username, server)
+            .map { it.scheduledForDeletion }
+            .switchIfEmpty(Single.just(false))
     }
     }
 
 
     fun getUserWithInternalId(id: Long): Maybe<User> {
     fun getUserWithInternalId(id: Long): Maybe<User> {
         return userRepository.getUserWithIdNotScheduledForDeletion(id)
         return userRepository.getUserWithIdNotScheduledForDeletion(id)
     }
     }
 
 
-    fun getIfUserWithUsernameAndServer(username: String, server: String): Maybe<Boolean> {
-        return userRepository.getUserWithUsernameAndServer(username, server).map { TRUE }
+    fun checkIfUserExists(username: String, server: String): Single<Boolean> {
+        return userRepository
+            .getUserWithUsernameAndServer(username, server)
+            .map { true }
+            .switchIfEmpty(Single.just(false))
     }
     }
 
 
+    /**
+     * Don't ask
+     *
+     * @return `true` if the user was updated **AND** there is another user to set as active, `false` otherwise
+     */
     fun scheduleUserForDeletionWithId(id: Long): Single<Boolean> {
     fun scheduleUserForDeletionWithId(id: Long): Single<Boolean> {
-        return userRepository.getUserWithId(id).map { user ->
-            user.scheduledForDeletion = true
-            user.current = false
-            userRepository.updateUser(user)
-        }
-            .toSingle()
-            .flatMap {
-                setAnyUserAndSetAsActive()
-            }.map { TRUE }
+        return userRepository.getUserWithId(id)
+            .map { user ->
+                user.scheduledForDeletion = true
+                user.current = false
+                userRepository.updateUser(user)
+            }
+            .flatMap { getAnyUserAndSetAsActive() }
+            .map { true }
+            .switchIfEmpty(Single.just(false))
+    }
+
+    private fun getAnyUserAndSetAsActive(): Maybe<User> {
+        val results = userRepository.getUsersNotScheduledForDeletion()
+
+        return results
+            .flatMapMaybe {
+                if (it.isNotEmpty()) {
+                    val user = it.first()
+                    user.apply {
+                        current = true
+                    }.also { currentUser ->
+                        userRepository.updateUser(currentUser)
+                    }
+                    Maybe.just(user)
+                } else {
+                    Maybe.empty()
+                }
+            }
     }
     }
 
 
     fun updateExternalSignalingServer(id: Long, externalSignalingServer: ExternalSignalingServer): Single<Int> {
     fun updateExternalSignalingServer(id: Long, externalSignalingServer: ExternalSignalingServer): Single<Int> {
@@ -136,19 +147,49 @@ class UserManager internal constructor(private val userRepository: UsersReposito
         return userRepository.setUserAsActiveWithId(user.id!!)
         return userRepository.setUserAsActiveWithId(user.id!!)
     }
     }
 
 
+    fun storeProfile(username: String?, userAttributes: UserAttributes): Maybe<User> {
+        val userMaybe: Maybe<User> = findUser(null, userAttributes)
+
+        return userMaybe
+            .map { user: User? ->
+                when (user) {
+                    null -> createUser(
+                        username,
+                        userAttributes
+                    )
+                    else -> {
+                        user.token = userAttributes.token
+                        user.baseUrl = userAttributes.serverUrl
+                        user.current = true
+                        user.userId = userAttributes.userId
+                        user.token = userAttributes.token
+                        user.displayName = userAttributes.displayName
+                        user.clientCertificate = userAttributes.certificateAlias
+
+                        updateUserData(
+                            user,
+                            userAttributes
+                        )
+
+                        user
+                    }
+                }
+            }
+            .switchIfEmpty(Maybe.just(createUser(username, userAttributes)))
+            .map { user ->
+                userRepository.insertUser(user)
+            }
+            .flatMap { id ->
+                userRepository.getUserWithId(id)
+            }
+    }
+
     @Deprecated("Only available for migration, use updateExternalSignalingServer or create new methods")
     @Deprecated("Only available for migration, use updateExternalSignalingServer or create new methods")
     fun createOrUpdateUser(
     fun createOrUpdateUser(
         username: String?,
         username: String?,
-        userAttributes: UserAttributes,
+        userAttributes: UserAttributes
     ): Maybe<User> {
     ): Maybe<User> {
-
-        val userMaybe: Maybe<User> = if (userAttributes.id != null) {
-            userRepository.getUserWithId(userAttributes.id)
-        } else if (username != null && userAttributes.serverUrl != null) {
-            userRepository.getUserWithUsernameAndServer(username, userAttributes.serverUrl)
-        } else {
-            Maybe.empty()
-        }
+        val userMaybe: Maybe<User> = findUser(username, userAttributes)
 
 
         return userMaybe
         return userMaybe
             .map { user: User? ->
             .map { user: User? ->
@@ -175,6 +216,16 @@ class UserManager internal constructor(private val userRepository: UsersReposito
             }
             }
     }
     }
 
 
+    private fun findUser(username: String?, userAttributes: UserAttributes): Maybe<User> {
+        return if (userAttributes.id != null) {
+            userRepository.getUserWithId(userAttributes.id)
+        } else if (username != null && userAttributes.serverUrl != null) {
+            userRepository.getUserWithUsernameAndServer(username, userAttributes.serverUrl)
+        } else {
+            Maybe.empty()
+        }
+    }
+
     fun getUserWithUsernameAndServer(username: String, server: String): Maybe<User> {
     fun getUserWithUsernameAndServer(username: String, server: String): Maybe<User> {
         return userRepository.getUserWithUsernameAndServer(username, server)
         return userRepository.getUserWithUsernameAndServer(username, server)
     }
     }
@@ -224,7 +275,7 @@ class UserManager internal constructor(private val userRepository: UsersReposito
             user.externalSignalingServer = LoganSquare
             user.externalSignalingServer = LoganSquare
                 .parse(userAttributes.externalSignalingServer, ExternalSignalingServer::class.java)
                 .parse(userAttributes.externalSignalingServer, ExternalSignalingServer::class.java)
         }
         }
-        user.current = true
+        user.current = userAttributes.currentUser == true
         return user
         return user
     }
     }
 
 

+ 2 - 6
app/src/main/java/com/nextcloud/talk/utils/AccountUtils.kt

@@ -1,7 +1,9 @@
 /*
 /*
  * Nextcloud Talk application
  * Nextcloud Talk application
  *
  *
+ * @author Andy Scherzinger
  * @author Mario Danic
  * @author Mario Danic
+ * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
  * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
  * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
  *
  *
  * This program is free software: you can redistribute it and/or modify
  * This program is free software: you can redistribute it and/or modify
@@ -32,7 +34,6 @@ import com.nextcloud.talk.R
 import com.nextcloud.talk.application.NextcloudTalkApplication
 import com.nextcloud.talk.application.NextcloudTalkApplication
 import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.models.ImportAccount
 import com.nextcloud.talk.models.ImportAccount
-import com.nextcloud.talk.models.database.UserEntity
 import java.util.Arrays
 import java.util.Arrays
 
 
 object AccountUtils {
 object AccountUtils {
@@ -40,11 +41,6 @@ object AccountUtils {
     private const val TAG = "AccountUtils"
     private const val TAG = "AccountUtils"
     private const val MIN_SUPPORTED_FILES_APP_VERSION = 30060151
     private const val MIN_SUPPORTED_FILES_APP_VERSION = 30060151
 
 
-    @Deprecated("Migrate to findAccountsForUsers")
-    fun findAccounts(userEntitiesList: List<UserEntity>): List<Account> {
-        return findAccountsForUsers(LegacyUserEntityMapper.toModel(userEntitiesList))
-    }
-
     fun findAccountsForUsers(users: List<User>): List<Account> {
     fun findAccountsForUsers(users: List<User>): List<Account> {
         val context = NextcloudTalkApplication.sharedApplication!!.applicationContext
         val context = NextcloudTalkApplication.sharedApplication!!.applicationContext
         val accMgr = AccountManager.get(context)
         val accMgr = AccountManager.get(context)