remove flow and use rx

...to stay in line with currently used concepts

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
Andy Scherzinger 2022-06-22 19:53:53 +02:00
parent f7786e1b93
commit 565903b956
No known key found for this signature in database
GPG Key ID: 6CADC7E3523C308B
8 changed files with 458 additions and 279 deletions

View File

@ -245,6 +245,7 @@ dependencies {
kapt 'io.requery:requery-processor:1.6.1' kapt 'io.requery:requery-processor:1.6.1'
implementation "androidx.room:room-runtime:${roomVersion}" implementation "androidx.room:room-runtime:${roomVersion}"
implementation "androidx.room:room-rxjava2:${roomVersion}"
kapt "androidx.room:room-compiler:${roomVersion}" // For Kotlin use kapt instead of annotationProcessor kapt "androidx.room:room-compiler:${roomVersion}" // For Kotlin use kapt instead of annotationProcessor
implementation "androidx.room:room-ktx:${roomVersion}" implementation "androidx.room:room-ktx:${roomVersion}"

View File

@ -46,10 +46,11 @@ import com.nextcloud.talk.controllers.ServerSelectionController
import com.nextcloud.talk.controllers.SettingsController import com.nextcloud.talk.controllers.SettingsController
import com.nextcloud.talk.controllers.WebViewLoginController import com.nextcloud.talk.controllers.WebViewLoginController
import com.nextcloud.talk.controllers.base.providers.ActionBarProvider import com.nextcloud.talk.controllers.base.providers.ActionBarProvider
import com.nextcloud.talk.data.user.UsersRepository import com.nextcloud.talk.data.user.model.UserNgEntity
import com.nextcloud.talk.databinding.ActivityMainBinding import com.nextcloud.talk.databinding.ActivityMainBinding
import com.nextcloud.talk.models.database.UserEntity import com.nextcloud.talk.models.database.UserEntity
import com.nextcloud.talk.models.json.conversations.RoomOverall import com.nextcloud.talk.models.json.conversations.RoomOverall
import com.nextcloud.talk.users.UserManager
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ConductorRemapping.remapChatController import com.nextcloud.talk.utils.ConductorRemapping.remapChatController
import com.nextcloud.talk.utils.SecurityUtils import com.nextcloud.talk.utils.SecurityUtils
@ -65,8 +66,6 @@ import io.reactivex.schedulers.Schedulers
import io.requery.Persistable import io.requery.Persistable
import io.requery.android.sqlcipher.SqlCipherDatabaseSource import io.requery.android.sqlcipher.SqlCipherDatabaseSource
import io.requery.reactivex.ReactiveEntityStore import io.requery.reactivex.ReactiveEntityStore
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.parceler.Parcels import org.parceler.Parcels
import javax.inject.Inject import javax.inject.Inject
@ -84,7 +83,7 @@ class MainActivity : BaseActivity(), ActionBarProvider {
lateinit var ncApi: NcApi lateinit var ncApi: NcApi
@Inject @Inject
lateinit var usersRepository: UsersRepository lateinit var userManager: UserManager
private var router: Router? = null private var router: Router? = null
@ -119,9 +118,14 @@ class MainActivity : BaseActivity(), ActionBarProvider {
if (!appPreferences.isDbRoomMigrated) { if (!appPreferences.isDbRoomMigrated) {
appPreferences.isDbRoomMigrated = true appPreferences.isDbRoomMigrated = true
} }
GlobalScope.launch {
usersRepository.getUsers().collect { userManager.users.subscribe(object : Observer<List<UserNgEntity>> {
if (it.isNotEmpty()) { override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(users: List<UserNgEntity>) {
if (users.isNotEmpty()) {
runOnUiThread { runOnUiThread {
setDefaultRootController() setDefaultRootController()
} }
@ -131,7 +135,15 @@ class MainActivity : BaseActivity(), ActionBarProvider {
} }
} }
} }
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
} else { } else {
launchLoginScreen() launchLoginScreen()
} }
@ -191,15 +203,27 @@ class MainActivity : BaseActivity(), ActionBarProvider {
} }
fun resetConversationsList() { fun resetConversationsList() {
GlobalScope.launch { userManager.users.subscribe(object : Observer<List<UserNgEntity>> {
usersRepository.getUsers().collect { override fun onSubscribe(d: Disposable) {
if (it.isNotEmpty()) { // unused atm
}
override fun onNext(users: List<UserNgEntity>) {
if (users.isNotEmpty()) {
runOnUiThread { runOnUiThread {
setDefaultRootController() setDefaultRootController()
} }
} }
} }
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
} }
fun openSettings() { fun openSettings() {
@ -237,22 +261,15 @@ class MainActivity : BaseActivity(), ActionBarProvider {
"vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat" -> { "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat" -> {
val user = userId.substringBeforeLast("@") val user = userId.substringBeforeLast("@")
val baseUrl = userId.substringAfterLast("@") val baseUrl = userId.substringAfterLast("@")
GlobalScope.launch {
usersRepository.getActiveUser().collect { if (userManager.currentUser?.baseUrl?.endsWith(baseUrl) == true) {
if (it?.baseUrl?.endsWith(baseUrl) == true) { startConversation(user)
runOnUiThread { } else {
startConversation(user) Snackbar.make(
} binding.controllerContainer,
} else { R.string.nc_phone_book_integration_account_not_found,
runOnUiThread { Snackbar.LENGTH_LONG
Snackbar.make( ).show()
binding.controllerContainer,
R.string.nc_phone_book_integration_account_not_found,
Snackbar.LENGTH_LONG
).show()
}
}
}
} }
} }
} }
@ -262,18 +279,40 @@ class MainActivity : BaseActivity(), ActionBarProvider {
private fun startConversation(userId: String) { private fun startConversation(userId: String) {
val roomType = "1" val roomType = "1"
GlobalScope.launch { val currentUser = userManager.currentUser
usersRepository.getActiveUser().collect { currentUser ->
if (currentUser != null) { val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.APIv4, 1))
val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.APIv4, 1)) val credentials = ApiUtils.getCredentials(currentUser?.username, currentUser?.token)
val credentials = ApiUtils.getCredentials(currentUser.username, currentUser.token) val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom( apiVersion, currentUser?.baseUrl, roomType,
apiVersion, currentUser.baseUrl, roomType, null, userId, null
null, userId, null )
)
ncApi.createRoom( ncApi.createRoom(
credentials,
retrofitBucket.url, retrofitBucket.queryMap
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<RoomOverall> {
override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(roomOverall: RoomOverall) {
val bundle = Bundle()
bundle.putParcelable(KEY_USER_ENTITY, currentUser)
bundle.putString(KEY_ROOM_TOKEN, roomOverall.ocs!!.data!!.token)
bundle.putString(KEY_ROOM_ID, roomOverall.ocs!!.data!!.roomId)
// FIXME once APIv2 or later is used only, the createRoom already returns all the data
ncApi.getRoom(
credentials, credentials,
retrofitBucket.url, retrofitBucket.queryMap ApiUtils.getUrlForRoom(
apiVersion,
currentUser?.baseUrl,
roomOverall.ocs!!.data!!.token
)
) )
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -283,46 +322,14 @@ class MainActivity : BaseActivity(), ActionBarProvider {
} }
override fun onNext(roomOverall: RoomOverall) { override fun onNext(roomOverall: RoomOverall) {
val bundle = Bundle() bundle.putParcelable(
bundle.putParcelable(KEY_USER_ENTITY, currentUser) KEY_ACTIVE_CONVERSATION,
bundle.putString(KEY_ROOM_TOKEN, roomOverall.ocs!!.data!!.token) Parcels.wrap(roomOverall.ocs!!.data)
bundle.putString(KEY_ROOM_ID, roomOverall.ocs!!.data!!.roomId) )
remapChatController(
// FIXME once APIv2 or later is used only, the createRoom already returns all the data router!!, currentUser!!.id,
ncApi.getRoom( roomOverall.ocs!!.data!!.token!!, bundle, true
credentials,
ApiUtils.getUrlForRoom(
apiVersion,
currentUser.baseUrl,
roomOverall.ocs!!.data!!.token
)
) )
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<RoomOverall> {
override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(roomOverall: RoomOverall) {
bundle.putParcelable(
KEY_ACTIVE_CONVERSATION,
Parcels.wrap(roomOverall.ocs!!.data)
)
remapChatController(
router!!, currentUser.id,
roomOverall.ocs!!.data!!.token!!, bundle, true
)
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
} }
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
@ -334,8 +341,15 @@ class MainActivity : BaseActivity(), ActionBarProvider {
} }
}) })
} }
}
} override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
} }
@RequiresApi(api = Build.VERSION_CODES.M) @RequiresApi(api = Build.VERSION_CODES.M)

View File

@ -69,7 +69,6 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.setAppT
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.UsersRepository
import com.nextcloud.talk.data.user.model.UserNgEntity import com.nextcloud.talk.data.user.model.UserNgEntity
import com.nextcloud.talk.databinding.ControllerSettingsBinding import com.nextcloud.talk.databinding.ControllerSettingsBinding
import com.nextcloud.talk.jobs.AccountRemovalWorker import com.nextcloud.talk.jobs.AccountRemovalWorker
@ -99,10 +98,6 @@ 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
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
@ -123,9 +118,6 @@ class SettingsController : NewBaseController(R.layout.controller_settings) {
@Inject @Inject
lateinit var userUtils: UserUtils lateinit var userUtils: UserUtils
@Inject
lateinit var userRepository: UsersRepository
@Inject @Inject
lateinit var currentUserProvider: CurrentUserProviderNew lateinit var currentUserProvider: CurrentUserProviderNew
@ -143,18 +135,13 @@ class SettingsController : NewBaseController(R.layout.controller_settings) {
private var profileQueryDisposable: Disposable? = null private var profileQueryDisposable: Disposable? = null
private var dbQueryDisposable: Disposable? = null private var dbQueryDisposable: Disposable? = null
val scope = MainScope()
override val title: String override val title: String
get() = get() =
resources!!.getString(R.string.nc_settings) resources!!.getString(R.string.nc_settings)
private suspend fun getCurrentUser() { private fun getCurrentUser() {
val user = currentUserProvider.currentUser.first() currentUser = currentUserProvider.currentUser
Log.e(TAG, "User: $user") credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token)
currentUser = user
credentials =
ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token)
} }
override fun onViewBound(view: View) { override fun onViewBound(view: View) {
@ -203,20 +190,18 @@ class SettingsController : NewBaseController(R.layout.controller_settings) {
setupClientCertView() setupClientCertView()
} }
Log.i(TAG, "Current user: " + currentUser?.displayName)
} }
private fun setupPhoneBookIntegration() { private fun setupPhoneBookIntegration() {
scope.launch { if (CapabilitiesNgUtil.isPhoneBookIntegrationAvailable(currentUser)) {
userRepository.getActiveUser().collect { activity!!.runOnUiThread {
if (CapabilitiesNgUtil.isPhoneBookIntegrationAvailable(it)) { binding.settingsPhoneBookIntegration.visibility = View.VISIBLE
activity!!.runOnUiThread { }
binding.settingsPhoneBookIntegration.visibility = View.VISIBLE } else {
} activity!!.runOnUiThread {
} else { binding.settingsPhoneBookIntegration.visibility = View.GONE
activity!!.runOnUiThread {
binding.settingsPhoneBookIntegration.visibility = View.GONE
}
}
} }
} }
} }
@ -327,7 +312,7 @@ class SettingsController : NewBaseController(R.layout.controller_settings) {
var port = -1 var port = -1
val uri: URI val uri: URI
try { try {
uri = URI(this@SettingsController.currentUser!!.baseUrl) uri = URI(currentUser!!.baseUrl)
host = uri.host host = uri.host
port = uri.port port = uri.port
} catch (e: URISyntaxException) { } catch (e: URISyntaxException) {
@ -759,8 +744,6 @@ class SettingsController : NewBaseController(R.layout.controller_settings) {
appPreferences?.unregisterReadPrivacyChangeListener(readPrivacyChangeListener) appPreferences?.unregisterReadPrivacyChangeListener(readPrivacyChangeListener)
appPreferences?.unregisterPhoneBookIntegrationChangeListener(phoneBookIntegrationChangeListener) appPreferences?.unregisterPhoneBookIntegrationChangeListener(phoneBookIntegrationChangeListener)
scope.cancel()
super.onDestroy() super.onDestroy()
} }

View File

@ -22,6 +22,7 @@
package com.nextcloud.talk.data.user package com.nextcloud.talk.data.user
import android.util.Log
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.OnConflictStrategy import androidx.room.OnConflictStrategy
@ -29,8 +30,9 @@ import androidx.room.Query
import androidx.room.Transaction import androidx.room.Transaction
import androidx.room.Update import androidx.room.Update
import com.nextcloud.talk.data.user.model.UserNgEntity import com.nextcloud.talk.data.user.model.UserNgEntity
import kotlinx.coroutines.flow.Flow import io.reactivex.Observable
import kotlinx.coroutines.flow.flowOf import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import java.lang.Boolean.FALSE import java.lang.Boolean.FALSE
import java.lang.Boolean.TRUE import java.lang.Boolean.TRUE
@ -39,107 +41,161 @@ import java.lang.Boolean.TRUE
abstract class UsersDao { abstract class UsersDao {
// get active user // get active user
@Query("SELECT * FROM User where current = 1") @Query("SELECT * FROM User where current = 1")
abstract fun getActiveUser(): Flow<UserNgEntity?> abstract fun getActiveUser(): Observable<UserNgEntity?>
@Query("SELECT * FROM User where current = 1")
abstract fun getActiveUserSynchronously(): UserNgEntity?
@Query("SELECT * FROM User WHERE current = 1") @Query("SELECT * FROM User WHERE current = 1")
abstract fun getActiveUserLiveData(): Flow<UserNgEntity?> abstract fun getActiveUserLiveData(): Observable<UserNgEntity?>
@Query("SELECT * FROM User ORDER BY current DESC") @Query("SELECT * FROM User ORDER BY current DESC")
abstract fun getUsersLiveData(): Flow<List<UserNgEntity>> abstract fun getUsersLiveData(): Observable<List<UserNgEntity>>
@Query("SELECT * FROM User WHERE current != 1 ORDER BY current DESC") @Query("SELECT * FROM User WHERE current != 1 ORDER BY current DESC")
abstract fun getUsersLiveDataWithoutActive(): Flow<List<UserNgEntity>> abstract fun getUsersLiveDataWithoutActive(): Observable<List<UserNgEntity>>
@Query("DELETE FROM User WHERE id = :id") @Query("DELETE FROM User WHERE id = :id")
abstract suspend fun deleteUserWithId(id: Long) abstract fun deleteUserWithId(id: Long)
@Update @Update
abstract suspend fun updateUser(user: UserNgEntity): Int abstract fun updateUser(user: UserNgEntity): Int
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
abstract suspend fun saveUser(user: UserNgEntity): Long abstract fun saveUser(user: UserNgEntity): Long
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
abstract suspend fun saveUsers(vararg users: UserNgEntity): List<Long> abstract fun saveUsers(vararg users: UserNgEntity): List<Long>
// get all users not scheduled for deletion // get all users not scheduled for deletion
@Query("SELECT * FROM User where current != 0") @Query("SELECT * FROM User where current != 0")
abstract fun getUsers(): Flow<List<UserNgEntity>> abstract fun getUsers(): Observable<List<UserNgEntity>>
@Query("SELECT * FROM User where id = :id") @Query("SELECT * FROM User where id = :id")
abstract fun getUserWithId(id: Long): Flow<UserNgEntity?> abstract fun getUserWithId(id: Long): Observable<UserNgEntity?>
@Query("SELECT * FROM User where id = :id") @Query("SELECT * FROM User where id = :id")
abstract fun getUserWithIdLiveData(id: Long): Flow<UserNgEntity?> abstract fun getUserWithIdLiveData(id: Long): Observable<UserNgEntity?>
@Query("SELECT * FROM User where id = :id AND scheduledForDeletion != 1") @Query("SELECT * FROM User where id = :id AND scheduledForDeletion != 1")
abstract fun getUserWithIdNotScheduledForDeletion(id: Long): Flow<UserNgEntity?> abstract fun getUserWithIdNotScheduledForDeletion(id: Long): Observable<UserNgEntity?>
@Query("SELECT * FROM User where userId = :userId") @Query("SELECT * FROM User where userId = :userId")
abstract fun getUserWithUserId(userId: String): Flow<UserNgEntity?> abstract fun getUserWithUserId(userId: String): Observable<UserNgEntity?>
@Query("SELECT * FROM User where userId != :userId") @Query("SELECT * FROM User where userId != :userId")
abstract fun getUsersWithoutUserId(userId: Long): Flow<List<UserNgEntity>> abstract fun getUsersWithoutUserId(userId: Long): Observable<List<UserNgEntity>>
@Query("SELECT * FROM User where current = 0") @Query("SELECT * FROM User where current = 0")
abstract fun getUsersScheduledForDeletion(): Flow<List<UserNgEntity>> abstract fun getUsersScheduledForDeletion(): Observable<List<UserNgEntity>>
@Query("SELECT * FROM User where scheduledForDeletion = 0") @Query("SELECT * FROM User where scheduledForDeletion = 0")
abstract fun getUsersNotScheduledForDeletion(): Flow<List<UserNgEntity>> abstract fun getUsersNotScheduledForDeletion(): Observable<List<UserNgEntity>>
@Query("SELECT * FROM User WHERE username = :username AND baseUrl = :server") @Query("SELECT * FROM User WHERE username = :username AND baseUrl = :server")
abstract fun getUserWithUsernameAndServer(username: String, server: String): Flow<UserNgEntity?> abstract fun getUserWithUsernameAndServer(username: String, server: String): Observable<UserNgEntity?>
@Transaction @Transaction
open suspend fun setUserAsActiveWithId(id: Long): Flow<Boolean> { open suspend fun setUserAsActiveWithId(id: Long): Boolean {
val users = getUsers() val users = getUsers()
users.collect { var result = TRUE
for (user in it) {
// removed from clause: && UserStatus.ACTIVE == user.status users.subscribe(object : Observer<List<UserNgEntity>> {
if (user.id != id) { override fun onSubscribe(d: Disposable) {
user.current = TRUE // unused atm
updateUser(user) }
} // removed from clause: && UserStatus.ACTIVE != user.status
else if (user.id == id) { override fun onNext(users: List<UserNgEntity>) {
user.current = TRUE for (user in users) {
updateUser(user) // removed from clause: && UserStatus.ACTIVE == user.status
if (user.id != id) {
user.current = TRUE
updateUser(user)
} // removed from clause: && UserStatus.ACTIVE != user.status
else if (user.id == id) {
user.current = TRUE
updateUser(user)
}
} }
} }
}
return flowOf(TRUE) override fun onError(e: Throwable) {
Log.e(TAG, "Error setting user active", e)
result = FALSE
}
override fun onComplete() {
// unused atm
}
})
return result
} }
@Transaction @Transaction
open suspend fun markUserForDeletion(id: Long): Flow<Boolean> { open suspend fun markUserForDeletion(id: Long): Boolean {
val users = getUsers() val users = getUsers()
users.collect {
for (user in it) { users.subscribe(object : Observer<List<UserNgEntity>> {
if (user.id == id) { override fun onSubscribe(d: Disposable) {
// TODO currently we only have a boolean, no intermediate states // unused atm
user.current = FALSE }
updateUser(user)
break override fun onNext(users: List<UserNgEntity>) {
for (user in users) {
if (user.id == id) {
// TODO currently we only have a boolean, no intermediate states
user.current = FALSE
updateUser(user)
break
}
} }
} }
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
return setAnyUserAsActive() return setAnyUserAsActive()
} }
@Transaction @Transaction
open suspend fun setAnyUserAsActive(): Flow<Boolean> { open suspend fun setAnyUserAsActive(): Boolean {
val users = getUsers() val users = getUsers()
var result = FALSE var result = FALSE
users.collect {
for (user in it) {
user.current = TRUE
updateUser(user)
result = true
break
}
}
return flowOf(result) users.subscribe(object : Observer<List<UserNgEntity>> {
override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(users: List<UserNgEntity>) {
for (user in users) {
user.current = TRUE
updateUser(user)
result = TRUE
break
}
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
return result
}
companion object {
const val TAG = "UsersDao"
} }
} }

View File

@ -23,27 +23,28 @@
package com.nextcloud.talk.data.user package com.nextcloud.talk.data.user
import com.nextcloud.talk.data.user.model.UserNgEntity import com.nextcloud.talk.data.user.model.UserNgEntity
import kotlinx.coroutines.flow.Flow import io.reactivex.Observable
@Suppress("TooManyFunctions") @Suppress("TooManyFunctions")
interface UsersRepository { interface UsersRepository {
fun getActiveUserLiveData(): Flow<UserNgEntity?> fun getActiveUserLiveData(): Observable<UserNgEntity?>
fun getActiveUser(): Flow<UserNgEntity?> fun getActiveUser(): Observable<UserNgEntity?>
fun getUsers(): Flow<List<UserNgEntity>> fun getActiveUserSynchronously(): UserNgEntity?
fun getUserWithId(id: Long): Flow<UserNgEntity?> fun getUsers(): Observable<List<UserNgEntity>>
fun getUserWithIdLiveData(id: Long): Flow<UserNgEntity?> fun getUserWithId(id: Long): Observable<UserNgEntity?>
fun getUserWithIdNotScheduledForDeletion(id: Long): Flow<UserNgEntity?> fun getUserWithIdLiveData(id: Long): Observable<UserNgEntity?>
fun getUserWithUserId(userId: String): Flow<UserNgEntity?> fun getUserWithIdNotScheduledForDeletion(id: Long): Observable<UserNgEntity?>
fun getUsersWithoutUserId(userId: Long): Flow<List<UserNgEntity>> fun getUserWithUserId(userId: String): Observable<UserNgEntity?>
fun getUsersLiveData(): Flow<List<UserNgEntity>> fun getUsersWithoutUserId(userId: Long): Observable<List<UserNgEntity>>
fun getUsersLiveDataWithoutActive(): Flow<List<UserNgEntity>> fun getUsersLiveData(): Observable<List<UserNgEntity>>
fun getUsersScheduledForDeletion(): Flow<List<UserNgEntity>> fun getUsersLiveDataWithoutActive(): Observable<List<UserNgEntity>>
fun getUsersNotScheduledForDeletion(): Flow<List<UserNgEntity>> fun getUsersScheduledForDeletion(): Observable<List<UserNgEntity>>
fun getUserWithUsernameAndServer(username: String, server: String): Flow<UserNgEntity?> fun getUsersNotScheduledForDeletion(): Observable<List<UserNgEntity>>
suspend fun updateUser(user: UserNgEntity): Int fun getUserWithUsernameAndServer(username: String, server: String): Observable<UserNgEntity?>
suspend fun insertUser(user: UserNgEntity): Long fun updateUser(user: UserNgEntity): Int
suspend fun setUserAsActiveWithId(id: Long): Flow<Boolean> fun insertUser(user: UserNgEntity): Long
suspend fun deleteUserWithId(id: Long) suspend fun setUserAsActiveWithId(id: Long): Boolean
suspend fun setAnyUserAsActive(): Flow<Boolean> fun deleteUserWithId(id: Long)
suspend fun markUserForDeletion(id: Long): Flow<Boolean> suspend fun setAnyUserAsActive(): Boolean
suspend fun markUserForDeletion(id: Long): Boolean
} }

View File

@ -23,84 +23,87 @@
package com.nextcloud.talk.data.user package com.nextcloud.talk.data.user
import com.nextcloud.talk.data.user.model.UserNgEntity import com.nextcloud.talk.data.user.model.UserNgEntity
import kotlinx.coroutines.flow.Flow import io.reactivex.Observable
import kotlinx.coroutines.flow.distinctUntilChanged
@Suppress("TooManyFunctions") @Suppress("TooManyFunctions")
class UsersRepositoryImpl(private val usersDao: UsersDao) : UsersRepository { class UsersRepositoryImpl(private val usersDao: UsersDao) : UsersRepository {
override fun getActiveUserLiveData(): Flow<UserNgEntity?> { override fun getActiveUserLiveData(): Observable<UserNgEntity?> {
return usersDao.getActiveUserLiveData().distinctUntilChanged() return usersDao.getActiveUserLiveData()
} }
override fun getActiveUser(): Flow<UserNgEntity?> { override fun getActiveUser(): Observable<UserNgEntity?> {
return usersDao.getActiveUser() return usersDao.getActiveUser()
} }
override fun getUsers(): Flow<List<UserNgEntity>> { override fun getActiveUserSynchronously(): UserNgEntity? {
return usersDao.getActiveUserSynchronously()
}
override fun getUsers(): Observable<List<UserNgEntity>> {
return usersDao.getUsers() return usersDao.getUsers()
} }
override fun getUserWithId(id: Long): Flow<UserNgEntity?> { override fun getUserWithId(id: Long): Observable<UserNgEntity?> {
return usersDao.getUserWithId(id) return usersDao.getUserWithId(id)
} }
override fun getUserWithIdLiveData(id: Long): Flow<UserNgEntity?> { override fun getUserWithIdLiveData(id: Long): Observable<UserNgEntity?> {
return usersDao.getUserWithIdLiveData(id).distinctUntilChanged() return usersDao.getUserWithIdLiveData(id).distinctUntilChanged()
} }
override fun getUserWithIdNotScheduledForDeletion(id: Long): Flow<UserNgEntity?> { override fun getUserWithIdNotScheduledForDeletion(id: Long): Observable<UserNgEntity?> {
return usersDao.getUserWithIdNotScheduledForDeletion(id) return usersDao.getUserWithIdNotScheduledForDeletion(id)
} }
override fun getUserWithUserId(userId: String): Flow<UserNgEntity?> { override fun getUserWithUserId(userId: String): Observable<UserNgEntity?> {
return usersDao.getUserWithUserId(userId) return usersDao.getUserWithUserId(userId)
} }
override fun getUsersWithoutUserId(userId: Long): Flow<List<UserNgEntity>> { override fun getUsersWithoutUserId(userId: Long): Observable<List<UserNgEntity>> {
return usersDao.getUsersWithoutUserId(userId) return usersDao.getUsersWithoutUserId(userId)
} }
override fun getUsersLiveData(): Flow<List<UserNgEntity>> { override fun getUsersLiveData(): Observable<List<UserNgEntity>> {
return usersDao.getUsersLiveData().distinctUntilChanged() return usersDao.getUsersLiveData().distinctUntilChanged()
} }
override fun getUsersLiveDataWithoutActive(): Flow<List<UserNgEntity>> { override fun getUsersLiveDataWithoutActive(): Observable<List<UserNgEntity>> {
return usersDao.getUsersLiveDataWithoutActive().distinctUntilChanged() return usersDao.getUsersLiveDataWithoutActive().distinctUntilChanged()
} }
override fun getUsersScheduledForDeletion(): Flow<List<UserNgEntity>> { override fun getUsersScheduledForDeletion(): Observable<List<UserNgEntity>> {
return usersDao.getUsersScheduledForDeletion() return usersDao.getUsersScheduledForDeletion()
} }
override fun getUsersNotScheduledForDeletion(): Flow<List<UserNgEntity>> { override fun getUsersNotScheduledForDeletion(): Observable<List<UserNgEntity>> {
return usersDao.getUsersNotScheduledForDeletion() return usersDao.getUsersNotScheduledForDeletion()
} }
override fun getUserWithUsernameAndServer(username: String, server: String): Flow<UserNgEntity?> { override fun getUserWithUsernameAndServer(username: String, server: String): Observable<UserNgEntity?> {
return usersDao.getUserWithUsernameAndServer(username, server) return usersDao.getUserWithUsernameAndServer(username, server)
} }
override suspend fun updateUser(user: UserNgEntity): Int { override fun updateUser(user: UserNgEntity): Int {
return usersDao.updateUser(user) return usersDao.updateUser(user)
} }
override suspend fun insertUser(user: UserNgEntity): Long { override fun insertUser(user: UserNgEntity): Long {
return usersDao.saveUser(user) return usersDao.saveUser(user)
} }
override suspend fun setUserAsActiveWithId(id: Long): Flow<Boolean> { override suspend fun setUserAsActiveWithId(id: Long): Boolean {
return usersDao.setUserAsActiveWithId(id) return usersDao.setUserAsActiveWithId(id)
} }
override suspend fun deleteUserWithId(id: Long) { override fun deleteUserWithId(id: Long) {
usersDao.deleteUserWithId(id) usersDao.deleteUserWithId(id)
} }
override suspend fun setAnyUserAsActive(): Flow<Boolean> { override suspend fun setAnyUserAsActive(): Boolean {
return usersDao.setAnyUserAsActive() return usersDao.setAnyUserAsActive()
} }
override suspend fun markUserForDeletion(id: Long): Flow<Boolean> { override suspend fun markUserForDeletion(id: Long): Boolean {
return usersDao.markUserForDeletion(id) return usersDao.markUserForDeletion(id)
} }
} }

View File

@ -29,144 +29,262 @@ import com.nextcloud.talk.models.ExternalSignalingServer
import com.nextcloud.talk.models.json.capabilities.Capabilities import com.nextcloud.talk.models.json.capabilities.Capabilities
import com.nextcloud.talk.models.json.push.PushConfigurationState 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 kotlinx.coroutines.flow.Flow import io.reactivex.Observable
import kotlinx.coroutines.flow.flowOf import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import java.lang.Boolean.FALSE import java.lang.Boolean.FALSE
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 {
suspend fun anyUserExists(): Boolean { val users: Observable<List<UserNgEntity>>
var result = FALSE
userRepository.getUsers().collect {
result = it.isNotEmpty()
}
return result
}
suspend fun hasMultipleUsers(): Flow<Boolean> {
var result = FALSE
userRepository.getUsers().collect {
result = it.size > 1
}
return flowOf(result)
}
val users: Flow<List<UserNgEntity>>
get() = userRepository.getUsers() get() = userRepository.getUsers()
val usersScheduledForDeletion: Flow<List<UserNgEntity>> val usersScheduledForDeletion: Observable<List<UserNgEntity>>
get() = userRepository.getUsersScheduledForDeletion() get() = userRepository.getUsersScheduledForDeletion()
private suspend fun setAnyUserAndSetAsActive(): Flow<UserNgEntity?> { private fun setAnyUserAndSetAsActive(): Observable<UserNgEntity?> {
val results = userRepository.getUsersNotScheduledForDeletion() val results = userRepository.getUsersNotScheduledForDeletion()
var result: UserNgEntity? = null var result: UserNgEntity? = null
results.collect { results.subscribe(object : Observer<List<UserNgEntity>> {
if (it.isNotEmpty()) { override fun onSubscribe(d: Disposable) {
val user = it[0] // unused atm
user.current = true
userRepository.updateUser(user)
result = user
} }
}
return flowOf(result) override fun onNext(users: List<UserNgEntity>) {
if (users.isNotEmpty()) {
val user = users[0]
user.current = true
userRepository.updateUser(user)
result = user
}
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
return Observable.just(result)
} }
override val currentUser: Flow<UserNgEntity?> override val currentUser: UserNgEntity?
get() { get() {
return userRepository.getActiveUser() return userRepository.getActiveUserSynchronously()
} }
suspend fun deleteUser(internalId: Long) { fun deleteUser(internalId: Long) {
userRepository.deleteUserWithId(internalId) userRepository.deleteUserWithId(internalId)
} }
suspend fun deleteUserWithId(internalId: Long) { fun deleteUserWithId(internalId: Long) {
userRepository.deleteUserWithId(internalId) userRepository.deleteUserWithId(internalId)
} }
fun getUserById(userId: String): Flow<UserNgEntity?> { fun getUserById(userId: String): Observable<UserNgEntity?> {
return userRepository.getUserWithUserId(userId) return userRepository.getUserWithUserId(userId)
} }
fun getUserWithId(id: Long): Flow<UserNgEntity?> { fun getUserWithId(id: Long): Observable<UserNgEntity?> {
return userRepository.getUserWithId(id) return userRepository.getUserWithId(id)
} }
suspend fun disableAllUsersWithoutId(userId: Long) { fun disableAllUsersWithoutId(userId: Long) {
val results = userRepository.getUsersWithoutUserId(userId) val results = userRepository.getUsersWithoutUserId(userId)
results.collect { results.subscribe(object : Observer<List<UserNgEntity>> {
if (it.isNotEmpty()) { override fun onSubscribe(d: Disposable) {
for (entity in it) { // unused atm
entity.current = false }
userRepository.updateUser(entity)
override fun onNext(users: List<UserNgEntity>) {
if (users.isNotEmpty()) {
for (entity in users) {
entity.current = false
userRepository.updateUser(entity)
}
} }
} }
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
} }
suspend fun checkIfUserIsScheduledForDeletion(username: String, server: String): Flow<Boolean> { fun checkIfUserIsScheduledForDeletion(username: String, server: String): Observable<Boolean> {
val results = userRepository.getUserWithUsernameAndServer(username, server) val results = userRepository.getUserWithUsernameAndServer(username, server)
var result = FALSE var result = FALSE
results.collect {
result = it?.scheduledForDeletion ?: FALSE
}
return flowOf(result) results.subscribe(object : Observer<UserNgEntity?> {
override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(user: UserNgEntity) {
result = user.scheduledForDeletion
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
return Observable.just(result)
} }
fun getUserWithInternalId(id: Long): Flow<UserNgEntity?> { fun getUserWithInternalId(id: Long): Observable<UserNgEntity?> {
return userRepository.getUserWithIdNotScheduledForDeletion(id) return userRepository.getUserWithIdNotScheduledForDeletion(id)
} }
suspend fun getIfUserWithUsernameAndServer(username: String, server: String): Flow<Boolean> { fun getIfUserWithUsernameAndServer(username: String, server: String): Observable<Boolean> {
val results = userRepository.getUserWithUsernameAndServer(username, server) val results = userRepository.getUserWithUsernameAndServer(username, server)
var result = FALSE var result = FALSE
results.collect {
result = it != null
}
return flowOf(result) results.subscribe(object : Observer<UserNgEntity?> {
override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(users: UserNgEntity) {
result = TRUE
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
return Observable.just(result)
} }
suspend fun scheduleUserForDeletionWithId(id: Long): Flow<Boolean> { suspend fun scheduleUserForDeletionWithId(id: Long): Observable<Boolean> {
val results = userRepository.getUserWithId(id) val results = userRepository.getUserWithId(id)
var result = FALSE var result = FALSE
results.collect { results.subscribe(object : Observer<UserNgEntity?> {
if (it != null) { override fun onSubscribe(d: Disposable) {
it.scheduledForDeletion = true // unused atm
it.current = false
userRepository.updateUser(it)
} }
}
setAnyUserAndSetAsActive().collect { override fun onNext(user: UserNgEntity) {
result = it != null user.scheduledForDeletion = true
} user.current = false
userRepository.updateUser(user)
}
return flowOf(result) override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
results.subscribe(object : Observer<UserNgEntity?> {
override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(user: UserNgEntity) {
user.scheduledForDeletion = true
user.current = false
userRepository.updateUser(user)
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
setAnyUserAndSetAsActive().subscribe(object : Observer<UserNgEntity?> {
override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(user: UserNgEntity) {
result = TRUE
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
return Observable.just(result)
} }
suspend fun createOrUpdateUser( fun createOrUpdateUser(
username: String?, username: String?,
userAttributes: UserAttributes, userAttributes: UserAttributes,
): Flow<UserNgEntity?> { ): Observable<UserNgEntity?> {
var user: UserNgEntity? = null var user: UserNgEntity? = null
if (userAttributes.id == null && username != null && userAttributes.serverUrl != null) { if (userAttributes.id == null && username != null && userAttributes.serverUrl != null) {
userRepository.getUserWithUsernameAndServer(username, userAttributes.serverUrl).collect { userRepository.getUserWithUsernameAndServer(username, userAttributes.serverUrl)
user = it .subscribe(object : Observer<UserNgEntity?> {
} override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(userEntity: UserNgEntity) {
user = userEntity
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
} else if (userAttributes.id != null) { } else if (userAttributes.id != null) {
userRepository.getUserWithId(userAttributes.id).collect { userRepository.getUserWithId(userAttributes.id)
user = it .subscribe(object : Observer<UserNgEntity?> {
} override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(userEntity: UserNgEntity) {
user = userEntity
}
override fun onError(e: Throwable) {
// unused atm
}
override fun onComplete() {
// unused atm
}
})
} }
if (user == null) { if (user == null) {
@ -292,6 +410,10 @@ class UserManager internal constructor(private val userRepository: UsersReposito
} }
} }
companion object {
const val TAG = "UserManager"
}
data class UserAttributes( data class UserAttributes(
val id: Long?, val id: Long?,
val serverUrl: String?, val serverUrl: String?,

View File

@ -21,8 +21,7 @@
package com.nextcloud.talk.utils.database.user package com.nextcloud.talk.utils.database.user
import com.nextcloud.talk.data.user.model.UserNgEntity import com.nextcloud.talk.data.user.model.UserNgEntity
import kotlinx.coroutines.flow.Flow
interface CurrentUserProviderNew { interface CurrentUserProviderNew {
val currentUser: Flow<UserNgEntity?> val currentUser: UserNgEntity?
} }