mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-22 04:59:34 +01:00
Fix some of the issues
This commit is contained in:
parent
a9933b484c
commit
4cd1b9fb18
@ -2,7 +2,7 @@
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 1,
|
||||
"identityHash": "26585a95894baebb7d811a80f3811b85",
|
||||
"identityHash": "0bb77d35d80f74e97eea4a5415d9a102",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "conversations",
|
||||
@ -15,7 +15,7 @@
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "user",
|
||||
"fieldPath": "userId",
|
||||
"columnName": "user_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
@ -198,7 +198,7 @@
|
||||
},
|
||||
{
|
||||
"tableName": "messages",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `conversation_id` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `actor_id` TEXT, `actor_type` TEXT, `actor_display_name` TEXT, `timestamp` INTEGER NOT NULL, `message` TEXT, `system_message_type` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`conversation_id`) REFERENCES `conversations`(`id`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `conversation_id` TEXT NOT NULL, `message_id` INTEGER NOT NULL, `actor_id` TEXT, `actor_type` TEXT, `actor_display_name` TEXT, `timestamp` INTEGER NOT NULL, `message` TEXT, `replyable` INTEGER NOT NULL, `system_message_type` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`conversation_id`) REFERENCES `conversations`(`id`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
@ -207,7 +207,7 @@
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "conversation",
|
||||
"fieldPath": "conversationId",
|
||||
"columnName": "conversation_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
@ -248,6 +248,12 @@
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "replyable",
|
||||
"columnName": "replyable",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "systemMessageType",
|
||||
"columnName": "system_message_type",
|
||||
@ -369,7 +375,7 @@
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '26585a95894baebb7d811a80f3811b85')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '0bb77d35d80f74e97eea4a5415d9a102')"
|
||||
]
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.ONE_TO_ONE_CONVERSATION
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||
import com.nextcloud.talk.newarch.local.models.getCredentials
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
@ -67,14 +68,14 @@ class ConversationItem(
|
||||
&& model.unreadMention == comparedConversation.unreadMention
|
||||
&& model.objectType == comparedConversation.objectType
|
||||
&& model.changing == comparedConversation.changing
|
||||
&& user.id == inItem.user.id)
|
||||
&& inItem.user.id == other.user.id)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return Objects.hash(
|
||||
model.conversationId, model.token,
|
||||
model.token,
|
||||
user.id
|
||||
)
|
||||
}
|
||||
@ -245,6 +246,7 @@ class ConversationItem(
|
||||
model.name, R.dimen.avatar_size
|
||||
)
|
||||
) {
|
||||
addHeader("Authorization", user.getCredentials())
|
||||
transformations(CircleCropTransformation())
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ import coil.transform.CircleCropTransformation
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||
import com.nextcloud.talk.newarch.local.models.getCredentials
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
@ -112,6 +113,7 @@ class MentionAutocompleteItem(
|
||||
}
|
||||
|
||||
holder.avatarImageView!!.load(avatarUrl) {
|
||||
addHeader("Authorization", currentUser.getCredentials())
|
||||
transformations(CircleCropTransformation())
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.models.json.conversations.RoomsOverall
|
||||
import com.nextcloud.talk.models.json.participants.Participant
|
||||
import com.nextcloud.talk.models.json.participants.ParticipantsOverall
|
||||
import com.nextcloud.talk.newarch.utils.getCredentials
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.DoNotDisturbUtils
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||
@ -393,6 +394,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
||||
currentConversation!!.name, R.dimen.avatar_size_very_big
|
||||
)
|
||||
) {
|
||||
addHeader("Authorization", userBeingCalled.getCredentials())
|
||||
transformations(CircleCropTransformation())
|
||||
listener(onSuccess = { data, dataSource ->
|
||||
GlobalScope.launch {
|
||||
|
@ -105,7 +105,6 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
.OnMessageLongClickListener<IMessage>, MessageHolders.ContentChecker<IMessage> {
|
||||
|
||||
val ncApi: NcApi by inject()
|
||||
val userUtils: UserUtils by inject()
|
||||
|
||||
@BindView(R.id.messagesListView)
|
||||
@JvmField
|
||||
@ -306,7 +305,7 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
imageLoader, context, ApiUtils.getUrlForAvatarWithNameAndPixels(
|
||||
conversationUser?.baseUrl,
|
||||
currentConversation?.name, avatarSize / 2
|
||||
), null, target, null,
|
||||
), conversationUser, target, null,
|
||||
CircleCropTransformation()
|
||||
)
|
||||
|
||||
|
@ -256,10 +256,10 @@ class SettingsController : BaseController() {
|
||||
}
|
||||
|
||||
private fun removeCurrentAccount() {
|
||||
val user = usersRepository.getActiveUser()
|
||||
user!!.status = UserStatus.PENDING_DELETE
|
||||
GlobalScope.launch {
|
||||
val job = async {
|
||||
val user = usersRepository.getActiveUser()
|
||||
user!!.status = UserStatus.PENDING_DELETE
|
||||
usersRepository.updateUser(user)
|
||||
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java)
|
||||
.build()
|
||||
@ -274,13 +274,14 @@ class SettingsController : BaseController() {
|
||||
onAttach(view!!)
|
||||
}
|
||||
} else {
|
||||
router.setRoot(RouterTransaction.with(
|
||||
ServerSelectionController()
|
||||
)
|
||||
.pushChangeHandler(VerticalChangeHandler())
|
||||
.popChangeHandler(VerticalChangeHandler())
|
||||
)
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
router.setRoot(RouterTransaction.with(
|
||||
ServerSelectionController()
|
||||
)
|
||||
.pushChangeHandler(VerticalChangeHandler())
|
||||
.popChangeHandler(VerticalChangeHandler())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -293,7 +294,7 @@ class SettingsController : BaseController() {
|
||||
}
|
||||
|
||||
GlobalScope.launch {
|
||||
var hasMultipleUsers: Boolean = false
|
||||
var hasMultipleUsers = false
|
||||
val job = async {
|
||||
currentUser = usersRepository.getActiveUser()
|
||||
hasMultipleUsers = usersRepository.getUsers().size > 0
|
||||
|
@ -37,12 +37,21 @@ import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.adapters.items.AdvancedUserItem
|
||||
import com.nextcloud.talk.controllers.base.BaseController
|
||||
import com.nextcloud.talk.models.ImportAccount
|
||||
import com.nextcloud.talk.models.json.participants.Participant
|
||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||
import com.nextcloud.talk.newarch.local.models.other.UserStatus
|
||||
import com.nextcloud.talk.utils.AccountUtils
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.net.CookieManager
|
||||
import java.util.*
|
||||
@ -53,7 +62,7 @@ class SwitchAccountController : BaseController {
|
||||
internal var recyclerView: RecyclerView? = null
|
||||
|
||||
val cookieManager: CookieManager by inject()
|
||||
val userUtils: UserUtils by inject()
|
||||
val usersRepository: UsersRepository by inject()
|
||||
|
||||
@JvmField
|
||||
@BindView(R.id.swipe_refresh_layout)
|
||||
@ -75,30 +84,13 @@ class SwitchAccountController : BaseController {
|
||||
private val onSwitchItemClickListener = FlexibleAdapter.OnItemClickListener { view, position ->
|
||||
if (userItems.size > position) {
|
||||
val userEntity = (userItems[position] as AdvancedUserItem).entity
|
||||
/*userUtils!!.createOrUpdateUser(null, null, null, null, null, true, null, userEntity!!.getId(), null, null, null)
|
||||
.`as`(AutoDispose.autoDisposable<Any>(scopeProvider))
|
||||
.subscribe(object : Observer<UserEntity> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
|
||||
}
|
||||
|
||||
override fun onNext(userEntity: UserEntity) {
|
||||
cookieManager!!.cookieStore.removeAll()
|
||||
|
||||
userUtils!!.disableAllUsersWithoutId(userEntity.getId())
|
||||
if (activity != null) {
|
||||
activity!!.runOnUiThread { router.popCurrentController() }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
|
||||
}
|
||||
})*/
|
||||
GlobalScope.launch {
|
||||
usersRepository.setUserAsActiveWithId(userEntity!!.id!!)
|
||||
cookieManager.cookieStore.removeAll()
|
||||
withContext(Dispatchers.Main) {
|
||||
router.popCurrentController()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
@ -130,7 +122,69 @@ class SwitchAccountController : BaseController {
|
||||
return inflater.inflate(R.layout.controller_generic_rv, container, false)
|
||||
}
|
||||
|
||||
override fun onViewBound(view: View) {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup
|
||||
): View {
|
||||
swipeRefreshLayout?.isEnabled = false
|
||||
actionBar?.show()
|
||||
|
||||
adapter = FlexibleAdapter(userItems, activity, false)
|
||||
GlobalScope.launch {
|
||||
val users = usersRepository.getUsers()
|
||||
var userEntity: UserNgEntity
|
||||
var participant: Participant
|
||||
|
||||
if (isAccountImport) {
|
||||
var account: Account
|
||||
var importAccount: ImportAccount
|
||||
for (accountObject in AccountUtils.findAccounts(users)) {
|
||||
account = accountObject
|
||||
importAccount = AccountUtils.getInformationFromAccount(account)
|
||||
|
||||
participant = Participant()
|
||||
participant.name = importAccount.username
|
||||
participant.userId = importAccount.username
|
||||
userEntity = UserNgEntity(-1, "!", "!", importAccount.baseUrl)
|
||||
userItems.add(AdvancedUserItem(participant, userEntity, account))
|
||||
}
|
||||
|
||||
adapter!!.addListener(onImportItemClickListener)
|
||||
withContext(Dispatchers.Main) {
|
||||
adapter!!.updateDataSet(userItems, false)
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
for (userEntityObject in users) {
|
||||
userEntity = userEntityObject
|
||||
if (userEntity.status != UserStatus.ACTIVE) {
|
||||
participant = Participant()
|
||||
participant.name = userEntity.displayName
|
||||
|
||||
val userId: String
|
||||
|
||||
if (userEntity.userId != null) {
|
||||
userId = userEntity.userId
|
||||
} else {
|
||||
userId = userEntity.username
|
||||
}
|
||||
participant.userId = userId
|
||||
userItems.add(AdvancedUserItem(participant, userEntity, null))
|
||||
}
|
||||
}
|
||||
|
||||
adapter!!.addListener(onSwitchItemClickListener)
|
||||
withContext(Dispatchers.Main) {
|
||||
adapter!!.updateDataSet(userItems, false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return super.onCreateView(inflater, container)
|
||||
}
|
||||
override fun onViewBound(view: View) {
|
||||
super.onViewBound(view)
|
||||
swipeRefreshLayout!!.isEnabled = false
|
||||
|
||||
|
@ -486,7 +486,7 @@ class NotificationWorker(
|
||||
}
|
||||
|
||||
val request = Images().getRequestForUrl(
|
||||
Coil.loader(), context!!, avatarUrl!!, null,
|
||||
Coil.loader(), context!!, avatarUrl!!, signatureVerification!!.userEntity,
|
||||
target, null, CircleCropTransformation()
|
||||
)
|
||||
|
||||
|
@ -44,6 +44,7 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
|
@ -29,6 +29,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.models.json.converters.*
|
||||
import com.nextcloud.talk.models.json.participants.Participant
|
||||
import com.nextcloud.talk.newarch.local.models.ConversationEntity
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||
import lombok.Data
|
||||
import org.parceler.Parcel
|
||||
@ -42,8 +43,6 @@ class Conversation {
|
||||
@JsonIgnore
|
||||
@NonNull
|
||||
var internalUserId: Long? = null
|
||||
@JsonIgnore
|
||||
var internalId: Long? = null
|
||||
@JsonField(name = ["id"])
|
||||
var conversationId: String? = null
|
||||
@JsonField(name = ["token"])
|
||||
|
@ -20,9 +20,7 @@
|
||||
|
||||
package com.nextcloud.talk.newarch.data.repository.offline
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import androidx.lifecycle.map
|
||||
import androidx.lifecycle.*
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
||||
import com.nextcloud.talk.newarch.local.dao.ConversationsDao
|
||||
@ -58,14 +56,11 @@ class ConversationsRepositoryImpl(val conversationsDao: ConversationsDao) :
|
||||
}
|
||||
|
||||
override fun getConversationsForUser(userId: Long): LiveData<List<Conversation>> {
|
||||
return Transformations.distinctUntilChanged(conversationsDao
|
||||
.getConversationsForUser(userId)
|
||||
.map { data ->
|
||||
data.map {
|
||||
it.toConversation()
|
||||
}
|
||||
}
|
||||
)
|
||||
return conversationsDao.getConversationsForUser(userId).distinctUntilChanged().map { data ->
|
||||
data.map {
|
||||
it.toConversation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation? {
|
||||
|
@ -21,13 +21,15 @@
|
||||
package com.nextcloud.talk.newarch.data.repository.offline
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import androidx.lifecycle.distinctUntilChanged
|
||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
||||
import com.nextcloud.talk.newarch.local.dao.UsersDao
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||
|
||||
class UsersRepositoryImpl(val usersDao: UsersDao) : UsersRepository {
|
||||
class UsersRepositoryImpl(private val usersDao: UsersDao) : UsersRepository {
|
||||
override fun getActiveUserLiveData(): LiveData<UserNgEntity> {
|
||||
return usersDao.getActiveUserLiveData()
|
||||
return usersDao.getActiveUserLiveData().distinctUntilChanged()
|
||||
}
|
||||
|
||||
override fun getActiveUser(): UserNgEntity {
|
||||
|
@ -55,18 +55,26 @@ class NextcloudTalkRepositoryImpl(private val apiService: ApiService) : Nextclou
|
||||
return apiService.getConversation(userEntity.getCredentials(), conversationToken)
|
||||
}
|
||||
|
||||
override suspend fun joinConversationForUser(userNgEntity: UserNgEntity, conversationToken: String, conversationPassword: String?): RoomOverall {
|
||||
return apiService.joinConversation(userNgEntity.getCredentials(), ApiUtils.getUrlForSettingMyselfAsActiveParticipant(userNgEntity.baseUrl, conversationToken), conversationPassword)
|
||||
}
|
||||
|
||||
override suspend fun exitConversationForUser(userNgEntity: UserNgEntity, conversationToken: String): GenericOverall {
|
||||
return apiService.exitConversation(userNgEntity.getCredentials(), ApiUtils.getUrlForSettingMyselfAsActiveParticipant(userNgEntity.baseUrl, conversationToken))
|
||||
}
|
||||
|
||||
override suspend fun setFavoriteValueForConversation(
|
||||
user: UserNgEntity,
|
||||
conversation: Conversation,
|
||||
favorite: Boolean
|
||||
): GenericOverall {
|
||||
if (favorite) {
|
||||
return apiService.addConversationToFavorites(
|
||||
return if (favorite) {
|
||||
apiService.addConversationToFavorites(
|
||||
user.getCredentials(),
|
||||
ApiUtils.getUrlForConversationFavorites(user.baseUrl, conversation.token)
|
||||
)
|
||||
} else {
|
||||
return apiService.removeConversationFromFavorites(
|
||||
apiService.removeConversationFromFavorites(
|
||||
user.getCredentials(),
|
||||
ApiUtils.getUrlForConversationFavorites(user.baseUrl, conversation.token)
|
||||
)
|
||||
|
@ -23,6 +23,7 @@ package com.nextcloud.talk.newarch.data.source.remote
|
||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||
import com.nextcloud.talk.models.json.conversations.RoomsOverall
|
||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||
import io.reactivex.Observable
|
||||
import retrofit2.http.*
|
||||
|
||||
interface ApiService {
|
||||
@ -63,4 +64,14 @@ interface ApiService {
|
||||
|
||||
@GET
|
||||
suspend fun getConversation(@Header("Authorization") authorization: String, @Url url: String): RoomOverall
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST
|
||||
suspend fun joinConversation(@Header("Authorization") authorization: String,
|
||||
@Url url: String, @Field("password") password: String?): RoomOverall
|
||||
|
||||
@DELETE
|
||||
suspend fun exitConversation(@Header("Authorization") authorization: String,
|
||||
@Url url: String): GenericOverall
|
||||
|
||||
}
|
||||
|
@ -47,4 +47,15 @@ interface NextcloudTalkRepository {
|
||||
userEntity: UserNgEntity,
|
||||
conversationToken: String
|
||||
): RoomOverall
|
||||
|
||||
suspend fun joinConversationForUser(
|
||||
userNgEntity: UserNgEntity,
|
||||
conversationToken: String,
|
||||
conversationPassword: String?
|
||||
): RoomOverall
|
||||
|
||||
suspend fun exitConversationForUser(
|
||||
userNgEntity: UserNgEntity,
|
||||
conversationToken: String
|
||||
): GenericOverall
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.newarch.domain.usecases
|
||||
|
||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||
import com.nextcloud.talk.newarch.data.source.remote.ApiErrorHandler
|
||||
import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository
|
||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCase
|
||||
import org.koin.core.parameter.DefinitionParameters
|
||||
|
||||
class ExitConversationUseCase constructor(
|
||||
private val nextcloudTalkRepository: NextcloudTalkRepository,
|
||||
apiErrorHandler: ApiErrorHandler?
|
||||
) : UseCase<GenericOverall, Any?>(apiErrorHandler) {
|
||||
|
||||
override suspend fun run(params: Any?): GenericOverall {
|
||||
val definitionParameters = params as DefinitionParameters
|
||||
return nextcloudTalkRepository.exitConversationForUser(
|
||||
definitionParameters[0],
|
||||
definitionParameters[1])
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.newarch.domain.usecases
|
||||
|
||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||
import com.nextcloud.talk.newarch.data.source.remote.ApiErrorHandler
|
||||
import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository
|
||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCase
|
||||
import org.koin.core.parameter.DefinitionParameters
|
||||
|
||||
class JoinConversationUseCase constructor(
|
||||
private val nextcloudTalkRepository: NextcloudTalkRepository,
|
||||
apiErrorHandler: ApiErrorHandler?
|
||||
) : UseCase<RoomOverall, Any?>(apiErrorHandler) {
|
||||
|
||||
override suspend fun run(params: Any?): RoomOverall {
|
||||
val definitionParameters = params as DefinitionParameters
|
||||
return nextcloudTalkRepository.joinConversationForUser(
|
||||
definitionParameters[0],
|
||||
definitionParameters[1],
|
||||
definitionParameters[2]
|
||||
)
|
||||
}
|
||||
}
|
@ -355,7 +355,8 @@ class ChatView : BaseView(), MessageHolders.ContentChecker<IMessage>, MessagesLi
|
||||
}
|
||||
}
|
||||
|
||||
if (url.startsWith(viewModel.user.baseUrl) && url.contains("index.php/core/preview?fileId=")) {
|
||||
val needsAuthBasedOnUrl = url.contains("index.php/core/preview?fileId=") || url.contains("index.php/avatar/")
|
||||
if (url.startsWith(viewModel.user.baseUrl) && needsAuthBasedOnUrl) {
|
||||
addHeader("Authorization", viewModel.user.getCredentials())
|
||||
|
||||
}
|
||||
@ -384,7 +385,7 @@ class ChatView : BaseView(), MessageHolders.ContentChecker<IMessage>, MessagesLi
|
||||
imageLoader, context, ApiUtils.getUrlForAvatarWithNameAndPixels(
|
||||
viewModel.user.baseUrl,
|
||||
it.name, avatarSize / 2
|
||||
), null, target, this,
|
||||
), viewModel.user, target, this,
|
||||
CircleCropTransformation()
|
||||
)
|
||||
|
||||
|
@ -2,16 +2,37 @@ package com.nextcloud.talk.newarch.features.chat
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseViewModel
|
||||
import com.nextcloud.talk.newarch.data.model.ErrorModel
|
||||
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
||||
import com.nextcloud.talk.newarch.domain.repository.offline.MessagesRepository
|
||||
import com.nextcloud.talk.newarch.domain.usecases.ExitConversationUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
||||
import com.nextcloud.talk.newarch.features.conversationsList.ConversationsListViewState
|
||||
import com.nextcloud.talk.newarch.local.models.MessageEntity
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.parameter.parametersOf
|
||||
|
||||
class ChatViewModel constructor(application: Application, private val conversationsRepository: ConversationsRepository) : BaseViewModel<ChatView>(application) {
|
||||
class ChatViewModel constructor(application: Application,
|
||||
private val joinConversationUseCase: JoinConversationUseCase,
|
||||
private val exitConversationUseCase: ExitConversationUseCase,
|
||||
private val conversationsRepository: ConversationsRepository,
|
||||
private val messagesRepository: MessagesRepository) : BaseViewModel<ChatView>(application) {
|
||||
lateinit var user: UserNgEntity
|
||||
val conversation: MutableLiveData<Conversation?> = MutableLiveData()
|
||||
val messagesLiveData = Transformations.switchMap(conversation) {
|
||||
it?.let {
|
||||
messagesRepository.getMessagesWithUserForConversation(it.conversationId!!)
|
||||
}
|
||||
}
|
||||
var conversationPassword: String? = null
|
||||
|
||||
|
||||
@ -23,6 +44,38 @@ class ChatViewModel constructor(application: Application, private val conversati
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun joinConversation() {
|
||||
joinConversationUseCase.invoke(viewModelScope, parametersOf(
|
||||
user,
|
||||
conversation.value!!.token,
|
||||
conversationPassword
|
||||
),
|
||||
object : UseCaseResponse<RoomOverall> {
|
||||
override suspend fun onSuccess(result: RoomOverall) {
|
||||
conversationsRepository.saveConversationsForUser(user.id!!, listOf(result.ocs.data))
|
||||
}
|
||||
|
||||
override fun onError(errorModel: ErrorModel?) {
|
||||
// what do we do on error
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun exitConversation() {
|
||||
exitConversationUseCase.invoke(backgroundScope, parametersOf(
|
||||
user,
|
||||
conversation.value!!.token
|
||||
),
|
||||
object : UseCaseResponse<GenericOverall> {
|
||||
override suspend fun onSuccess(result: GenericOverall) {
|
||||
}
|
||||
|
||||
override fun onError(errorModel: ErrorModel?) {
|
||||
// what do we do on error
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun sendMessage(message: CharSequence) {
|
||||
|
||||
}
|
||||
|
@ -4,15 +4,21 @@ import android.app.Application
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
||||
import com.nextcloud.talk.newarch.domain.repository.offline.MessagesRepository
|
||||
import com.nextcloud.talk.newarch.domain.usecases.ExitConversationUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
||||
|
||||
class ChatViewModelFactory constructor(
|
||||
private val application: Application,
|
||||
private val conversationsRepository: ConversationsRepository
|
||||
private val joinConversationUseCase: JoinConversationUseCase,
|
||||
private val exitConversationUseCase: ExitConversationUseCase,
|
||||
private val conversationsRepository: ConversationsRepository,
|
||||
private val messagesRepository: MessagesRepository
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||
return ChatViewModel(
|
||||
application, conversationsRepository
|
||||
application, joinConversationUseCase, exitConversationUseCase, conversationsRepository, messagesRepository
|
||||
) as T
|
||||
}
|
||||
}
|
||||
|
@ -26,12 +26,15 @@ import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.InputType
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.appcompat.widget.SearchView.OnQueryTextListener
|
||||
import androidx.core.view.MenuItemCompat
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.distinctUntilChanged
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import butterknife.OnClick
|
||||
import coil.ImageLoader
|
||||
@ -74,11 +77,12 @@ import java.util.*
|
||||
class ConversationsListView : BaseView(), OnQueryTextListener,
|
||||
OnItemClickListener, OnItemLongClickListener {
|
||||
|
||||
lateinit var viewModel: ConversationsListViewModel
|
||||
private lateinit var viewModel: ConversationsListViewModel
|
||||
val factory: ConversationListViewModelFactory by inject()
|
||||
val imageLoader: ImageLoader by inject()
|
||||
private val imageLoader: ImageLoader by inject()
|
||||
private val viewState: MutableLiveData<ConversationsListViewState> = MutableLiveData(LOADING)
|
||||
|
||||
private val recyclerViewAdapter = FlexibleAdapter(mutableListOf(), null, true)
|
||||
private val recyclerViewAdapter = FlexibleAdapter(mutableListOf(), null, false)
|
||||
|
||||
private var searchItem: MenuItem? = null
|
||||
private var settingsItem: MenuItem? = null
|
||||
@ -178,9 +182,12 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
||||
searchView!!.imeOptions = imeOptions
|
||||
searchView!!.queryHint = resources?.getString(R.string.nc_search)
|
||||
searchView!!.setSearchableInfo(searchManager.getSearchableInfo(activity!!.componentName))
|
||||
|
||||
searchView!!.setOnQueryTextListener(this)
|
||||
}
|
||||
|
||||
override fun onRestoreViewState(view: View, savedViewState: Bundle) {
|
||||
super.onRestoreViewState(view, savedViewState)
|
||||
viewModel.loadConversations()
|
||||
}
|
||||
|
||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||
@ -208,71 +215,15 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
||||
loadAvatar()
|
||||
})
|
||||
|
||||
viewState.observe(this@ConversationsListView, Observer { value ->
|
||||
when (value) {
|
||||
LOADING -> {
|
||||
view?.swipeRefreshLayoutView?.isEnabled = false
|
||||
view?.loadingStateView?.visibility = View.VISIBLE
|
||||
view?.stateWithMessageView?.visibility = View.GONE
|
||||
view?.dataStateView?.visibility = View.GONE
|
||||
view?.floatingActionButton?.visibility = View.GONE
|
||||
searchItem?.isVisible = false
|
||||
}
|
||||
LOADED -> {
|
||||
view?.swipeRefreshLayoutView?.isEnabled = true
|
||||
view?.swipeRefreshLayoutView?.post {
|
||||
view?.swipeRefreshLayoutView?.isRefreshing = false
|
||||
}
|
||||
view?.loadingStateView?.visibility = View.GONE
|
||||
view?.stateWithMessageView?.visibility = View.GONE
|
||||
view?.dataStateView?.visibility = View.VISIBLE
|
||||
view?.floatingActionButton?.visibility = View.VISIBLE
|
||||
searchItem?.isVisible = true
|
||||
}
|
||||
LOADED_EMPTY, FAILED -> {
|
||||
view?.swipeRefreshLayoutView?.post {
|
||||
view?.swipeRefreshLayoutView?.isRefreshing = false
|
||||
}
|
||||
view?.swipeRefreshLayoutView?.isEnabled = true
|
||||
view?.loadingStateView?.visibility = View.GONE
|
||||
view?.dataStateView?.visibility = View.GONE
|
||||
searchItem?.isVisible = false
|
||||
|
||||
if (value.equals(FAILED)) {
|
||||
view?.stateWithMessageView?.errorStateTextView?.text = messageData
|
||||
if (messageData.equals(
|
||||
context.resources.getString(R.string.nc_no_connection_error)
|
||||
)
|
||||
) {
|
||||
view?.stateWithMessageView?.errorStateImageView?.setImageResource(
|
||||
drawable.ic_signal_wifi_off_white_24dp
|
||||
)
|
||||
} else {
|
||||
view?.stateWithMessageView?.errorStateImageView?.setImageResource(
|
||||
drawable.ic_announcement_white_24dp
|
||||
)
|
||||
}
|
||||
view?.floatingActionButton?.visibility = View.GONE
|
||||
} else {
|
||||
view?.floatingActionButton?.visibility = View.VISIBLE
|
||||
view?.stateWithMessageView?.errorStateTextView?.text =
|
||||
resources?.getText(R.string.nc_conversations_empty)
|
||||
view?.stateWithMessageView?.errorStateImageView?.setImageResource(drawable.ic_logo)
|
||||
}
|
||||
|
||||
view?.stateWithMessageView?.visibility = View.VISIBLE
|
||||
}
|
||||
else -> {
|
||||
// We should not be here
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
conversationsLiveData.observe(this@ConversationsListView, Observer {
|
||||
if (it.isEmpty()) {
|
||||
viewState.value = LOADED_EMPTY
|
||||
if (viewState.value != LOADED_EMPTY) {
|
||||
viewState.value = LOADED_EMPTY
|
||||
}
|
||||
} else {
|
||||
viewState.value = LOADED
|
||||
if (viewState.value != LOADED) {
|
||||
viewState.value = LOADED
|
||||
}
|
||||
}
|
||||
|
||||
val newConversations = mutableListOf<ConversationItem>()
|
||||
@ -297,6 +248,67 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
||||
})
|
||||
}
|
||||
|
||||
viewState.observe(this@ConversationsListView, Observer { value ->
|
||||
when (value) {
|
||||
LOADING -> {
|
||||
view?.swipeRefreshLayoutView?.isEnabled = false
|
||||
view?.loadingStateView?.visibility = View.VISIBLE
|
||||
view?.stateWithMessageView?.visibility = View.GONE
|
||||
view?.dataStateView?.visibility = View.GONE
|
||||
view?.floatingActionButton?.visibility = View.GONE
|
||||
searchItem?.isVisible = false
|
||||
}
|
||||
LOADED -> {
|
||||
view?.swipeRefreshLayoutView?.isEnabled = true
|
||||
view?.swipeRefreshLayoutView?.post {
|
||||
view?.swipeRefreshLayoutView?.isRefreshing = false
|
||||
}
|
||||
view?.loadingStateView?.visibility = View.GONE
|
||||
view?.stateWithMessageView?.visibility = View.GONE
|
||||
view?.dataStateView?.visibility = View.VISIBLE
|
||||
view?.floatingActionButton?.visibility = View.VISIBLE
|
||||
searchItem?.isVisible = true
|
||||
}
|
||||
LOADED_EMPTY, FAILED -> {
|
||||
view?.swipeRefreshLayoutView?.post {
|
||||
view?.swipeRefreshLayoutView?.isRefreshing = false
|
||||
}
|
||||
view?.swipeRefreshLayoutView?.isEnabled = true
|
||||
view?.loadingStateView?.visibility = View.GONE
|
||||
view?.dataStateView?.visibility = View.GONE
|
||||
searchItem?.isVisible = false
|
||||
|
||||
if (value.equals(FAILED)) {
|
||||
view?.stateWithMessageView?.errorStateTextView?.text = viewModel.messageData
|
||||
if (viewModel.messageData.equals(
|
||||
context.resources.getString(R.string.nc_no_connection_error)
|
||||
)
|
||||
) {
|
||||
view?.stateWithMessageView?.errorStateImageView?.setImageResource(
|
||||
drawable.ic_signal_wifi_off_white_24dp
|
||||
)
|
||||
} else {
|
||||
view?.stateWithMessageView?.errorStateImageView?.setImageResource(
|
||||
drawable.ic_announcement_white_24dp
|
||||
)
|
||||
}
|
||||
view?.floatingActionButton?.visibility = View.GONE
|
||||
} else {
|
||||
view?.floatingActionButton?.visibility = View.VISIBLE
|
||||
view?.stateWithMessageView?.errorStateTextView?.text =
|
||||
resources?.getText(R.string.nc_conversations_empty)
|
||||
view?.stateWithMessageView?.errorStateImageView?.setImageResource(drawable.ic_logo)
|
||||
}
|
||||
|
||||
view?.stateWithMessageView?.visibility = View.VISIBLE
|
||||
}
|
||||
else -> {
|
||||
// We should not be here
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
return super.onCreateView(inflater, container)
|
||||
}
|
||||
|
||||
@ -311,7 +323,7 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
||||
|
||||
@OnClick(R.id.stateWithMessageView)
|
||||
fun onStateWithMessageViewClick() {
|
||||
if (viewModel.viewState.equals(LOADED_EMPTY)) {
|
||||
if (viewState.value!! == LOADED_EMPTY) {
|
||||
openNewConversationScreen()
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.LeaveConversationUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.SetConversationFavoriteValueUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
||||
import com.nextcloud.talk.newarch.features.conversationsList.ConversationsListViewState.LOADING
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||
import com.nextcloud.talk.utils.ShareUtils
|
||||
import kotlinx.coroutines.launch
|
||||
@ -57,14 +56,11 @@ class ConversationsListViewModel constructor(
|
||||
usersRepository: UsersRepository
|
||||
) : BaseViewModel<ConversationsListView>(application) {
|
||||
|
||||
val viewState = MutableLiveData(LOADING)
|
||||
var messageData: String? = null
|
||||
val searchQuery = MutableLiveData<String>()
|
||||
val currentUserLiveData: LiveData<UserNgEntity> = usersRepository.getActiveUserLiveData()
|
||||
val conversationsLiveData = Transformations.switchMap(currentUserLiveData) {
|
||||
if (viewState.value != LOADING) {
|
||||
viewState.value = LOADING
|
||||
}
|
||||
loadConversations()
|
||||
conversationsRepository.getConversationsForUser(it.id!!)
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
package com.nextcloud.talk.newarch.features.conversationsList
|
||||
|
||||
enum class ConversationsListViewState {
|
||||
INITIAL_LOAD,
|
||||
LOADING,
|
||||
LOADED_EMPTY,
|
||||
LOADED,
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
package com.nextcloud.talk.newarch.local.models
|
||||
|
||||
import android.util.Log
|
||||
import androidx.room.*
|
||||
import androidx.room.ForeignKey.CASCADE
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
@ -42,7 +43,7 @@ import java.util.*
|
||||
)
|
||||
data class ConversationEntity(
|
||||
@PrimaryKey @ColumnInfo(name = "id") var id: String,
|
||||
@ColumnInfo(name = "user_id") var user: Long? = null,
|
||||
@ColumnInfo(name = "user_id") var userId: Long? = null,
|
||||
@ColumnInfo(name = "conversation_id") var conversationId: String? = null,
|
||||
@ColumnInfo(name = "token") var token: String? = null,
|
||||
@ColumnInfo(name = "name") var name: String? = null,
|
||||
@ -74,11 +75,52 @@ data class ConversationEntity(
|
||||
@ColumnInfo(name = "last_read_message") var lastReadMessageId: Long = 0,
|
||||
@ColumnInfo(name = "modified_at") var modifiedAt: Long? = null,
|
||||
@ColumnInfo(name = "changing") var changing: Boolean = false
|
||||
)
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ConversationEntity
|
||||
|
||||
if (id != other.id) return false
|
||||
if (userId != other.userId) return false
|
||||
if (conversationId != other.conversationId) return false
|
||||
if (token != other.token) return false
|
||||
if (name != other.name) return false
|
||||
if (displayName != other.displayName) return false
|
||||
if (type != other.type) return false
|
||||
if (count != other.count) return false
|
||||
if (numberOfGuests != other.numberOfGuests) return false
|
||||
if (participantsCount != other.participantsCount) return false
|
||||
if (participantType != other.participantType) return false
|
||||
if (hasPassword != other.hasPassword) return false
|
||||
if (sessionId != other.sessionId) return false
|
||||
if (favorite != other.favorite) return false
|
||||
if (lastActivity != other.lastActivity) return false
|
||||
if (unreadMessages != other.unreadMessages) return false
|
||||
if (unreadMention != other.unreadMention) return false
|
||||
if (lastMessage?.internalMessageId != other.lastMessage?.internalMessageId) return false
|
||||
if (objectType != other.objectType) return false
|
||||
if (notificationLevel != other.notificationLevel) return false
|
||||
if (conversationReadOnlyState != other.conversationReadOnlyState) return false
|
||||
if (lobbyState != other.lobbyState) return false
|
||||
if (lobbyTimer != other.lobbyTimer) return false
|
||||
if (lastReadMessageId != other.lastReadMessageId) return false
|
||||
if (changing != other.changing) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = userId?.hashCode() ?: 0
|
||||
result = 31 * result + (token?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
fun ConversationEntity.toConversation(): Conversation {
|
||||
val conversation = Conversation()
|
||||
conversation.internalUserId = this.user
|
||||
conversation.internalUserId = this.userId
|
||||
conversation.conversationId = this.conversationId
|
||||
conversation.type = this.type
|
||||
conversation.token = this.token
|
||||
@ -111,7 +153,7 @@ fun ConversationEntity.toConversation(): Conversation {
|
||||
|
||||
fun Conversation.toConversationEntity(): ConversationEntity {
|
||||
val conversationEntity = ConversationEntity(this.internalUserId.toString() + "@" + this.token)
|
||||
conversationEntity.user = this.internalUserId
|
||||
conversationEntity.userId = this.internalUserId
|
||||
conversationEntity.conversationId = this.conversationId
|
||||
conversationEntity.token = this.token
|
||||
conversationEntity.name = this.name
|
||||
|
@ -39,7 +39,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType
|
||||
)
|
||||
data class MessageEntity(
|
||||
@PrimaryKey @ColumnInfo(name = "id") var id: String,
|
||||
@ColumnInfo(name = "conversation_id") var conversation: String,
|
||||
@ColumnInfo(name = "conversation_id") var conversationId: String,
|
||||
@ColumnInfo(name = "message_id") var messageId: Long = 0,
|
||||
@ColumnInfo(name = "actor_id") var actorId: String? = null,
|
||||
@ColumnInfo(name = "actor_type") var actorType: String? = null,
|
||||
@ -56,7 +56,7 @@ data class MessageEntity(
|
||||
fun MessageEntity.toChatMessage(): ChatMessage {
|
||||
val chatMessage = ChatMessage()
|
||||
chatMessage.internalMessageId = this.id
|
||||
chatMessage.internalConversationId = this.conversation
|
||||
chatMessage.internalConversationId = this.conversationId
|
||||
chatMessage.jsonMessageId = this.messageId
|
||||
chatMessage.actorType = this.actorType
|
||||
chatMessage.actorId = this.actorId
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.newarch.utils
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||
import com.nextcloud.talk.newarch.data.model.ErrorModel
|
||||
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
||||
import com.nextcloud.talk.newarch.domain.usecases.GetConversationUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koin.core.KoinComponent
|
||||
import org.koin.core.parameter.parametersOf
|
||||
import java.net.CookieManager
|
||||
|
||||
class ConversationsManager constructor(usersRepository: UsersRepository,
|
||||
cookieManager: CookieManager,
|
||||
okHttpClient: OkHttpClient,
|
||||
private val conversationsRepository: ConversationsRepository,
|
||||
private val joinConversationUseCase: JoinConversationUseCase,
|
||||
private val getConversationUseCase: GetConversationUseCase): KoinComponent {
|
||||
private val applicationScope = CoroutineScope(Dispatchers.Default)
|
||||
private val previousUser: UserNgEntity? = null
|
||||
private val currentUserLiveData: LiveData<UserNgEntity> = usersRepository.getActiveUserLiveData()
|
||||
private var currentConversation: Conversation? = null
|
||||
|
||||
init {
|
||||
currentUserLiveData.observeForever { user ->
|
||||
cookieManager.cookieStore.removeAll()
|
||||
okHttpClient.dispatcher().cancelAll()
|
||||
currentConversation = null
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getConversation(conversationToken: String) {
|
||||
val currentUser = currentUserLiveData.value
|
||||
getConversationUseCase.invoke(applicationScope, parametersOf(
|
||||
currentUser,
|
||||
conversationToken
|
||||
),
|
||||
object : UseCaseResponse<RoomOverall> {
|
||||
override suspend fun onSuccess(result: RoomOverall) {
|
||||
currentUser?.let {
|
||||
conversationsRepository.saveConversationsForUser(it.id!!, listOf(result.ocs.data))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(errorModel: ErrorModel?) {
|
||||
// what do we do on error
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun joinConversation(conversationToken: String, conversationPassword: String?, conversationsManagerInterface: ConversationsManagerInterface) {
|
||||
val currentUser = currentUserLiveData.value
|
||||
joinConversationUseCase.invoke(applicationScope, parametersOf(
|
||||
currentUser,
|
||||
conversationToken,
|
||||
conversationPassword
|
||||
),
|
||||
object : UseCaseResponse<RoomOverall> {
|
||||
override suspend fun onSuccess(result: RoomOverall) {
|
||||
currentUser?.let {
|
||||
conversationsRepository.saveConversationsForUser(it.id!!, listOf(result.ocs.data))
|
||||
currentConversation = conversationsRepository.getConversationForUserWithToken(it.id!!, result.ocs!!.data!!.token!!)
|
||||
conversationsManagerInterface.joinedConversationForUser(it, currentConversation)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(errorModel: ErrorModel?) {
|
||||
// what do we do on error
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.newarch.utils
|
||||
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||
|
||||
interface ConversationsManagerInterface {
|
||||
fun joinedConversationForUser(userNgEntity: UserNgEntity, conversation: Conversation?)
|
||||
}
|
@ -51,9 +51,8 @@ class Images {
|
||||
target(target)
|
||||
}
|
||||
|
||||
if (userEntity != null && url.startsWith(userEntity.baseUrl) && url.contains(
|
||||
"index.php/core/preview?fileId="
|
||||
)
|
||||
if (userEntity != null && url.startsWith(userEntity.baseUrl) && (url.contains(
|
||||
"index.php/core/preview?fileId=") || url.contains("index.php/avatar/"))
|
||||
) {
|
||||
addHeader("Authorization", userEntity.getCredentials())
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
package com.nextcloud.talk.newarch.utils
|
||||
|
||||
import android.util.Log
|
||||
import androidx.annotation.MainThread
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class LiveDataTransformations {
|
||||
|
||||
/**
|
||||
* Creates a new [LiveData] object that does not emit a value until the source LiveData
|
||||
* value has been changed. The value is considered changed if `equals()` yields
|
||||
* `false`.
|
||||
*
|
||||
* @param source the input [LiveData]
|
||||
* @param <X> the generic type parameter of `source`
|
||||
* @return a new [LiveData] of type `X`
|
||||
</X> */
|
||||
@MainThread
|
||||
fun <X> distinctUntilChangedForArray(source: LiveData<X>): LiveData<X> {
|
||||
val outputLiveData = MediatorLiveData<X>()
|
||||
outputLiveData.addSource(source, object : Observer<X> {
|
||||
|
||||
var mFirstTime = true
|
||||
|
||||
override fun onChanged(currentValue: X?) {
|
||||
val previousValue = outputLiveData.value
|
||||
if (mFirstTime && currentValue != null
|
||||
|| (previousValue == null && currentValue != null)) {
|
||||
mFirstTime = false
|
||||
outputLiveData.value = currentValue
|
||||
} else if (previousValue != null) {
|
||||
if (currentValue == null) {
|
||||
outputLiveData.value = currentValue
|
||||
} else {
|
||||
val previousArray: Array<X> = (previousValue as ArrayList<X>).toArray() as Array<X>
|
||||
val currentArray: Array<X> = (currentValue as ArrayList<X>).toArray() as Array<X>
|
||||
|
||||
if (previousArray.size != currentArray.size) {
|
||||
outputLiveData.value = currentValue
|
||||
} else {
|
||||
var counter = 0
|
||||
for(element in previousArray) {
|
||||
if (!element!!.equals(currentArray[counter])) {
|
||||
outputLiveData.value = currentValue
|
||||
return
|
||||
}
|
||||
|
||||
counter++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return outputLiveData
|
||||
}
|
||||
}
|
@ -262,7 +262,7 @@ object DisplayUtils {
|
||||
)
|
||||
}
|
||||
|
||||
val request = Images().getRequestForUrl(Coil.loader(), context, url, null, target, null, CircleCropTransformation())
|
||||
val request = Images().getRequestForUrl(Coil.loader(), context, url, conversationUser, target, null, CircleCropTransformation())
|
||||
Coil.loader().load(request)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user