Various improvements

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2020-01-13 09:39:31 +01:00
parent b2fe5c6004
commit 1fe2bbdeed
No known key found for this signature in database
GPG Key ID: CDE0BBD2738C4CC0
19 changed files with 321 additions and 98 deletions

View File

@ -2,11 +2,11 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 1, "version": 1,
"identityHash": "24ed06b3e6bdb36d2657cc9735999e89", "identityHash": "2c4f372b48cd11e679b04c6d577f1cd8",
"entities": [ "entities": [
{ {
"tableName": "conversations", "tableName": "conversations",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `user_id` INTEGER, `conversation_id` TEXT, `token` TEXT, `name` TEXT, `display_name` TEXT, `type` INTEGER, `count` INTEGER NOT NULL, `number_of_guests` INTEGER NOT NULL, `participants` TEXT, `participant_type` INTEGER, `has_password` INTEGER NOT NULL, `session_id` TEXT, `favorite` INTEGER NOT NULL, `last_activity` INTEGER NOT NULL, `unread_messages` INTEGER NOT NULL, `unread_mention` INTEGER NOT NULL, `last_message` TEXT, `object_type` TEXT, `notification_level` INTEGER, `read_only_state` INTEGER, `lobby_state` INTEGER, `lobby_timer` INTEGER, `last_read_message` INTEGER NOT NULL, `can_start_call` INTEGER, `modified_at` INTEGER, `changing` INTEGER NOT NULL, `local_configuration` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`user_id`) REFERENCES `users`(`id`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `user_id` INTEGER, `conversation_id` TEXT, `token` TEXT, `name` TEXT, `display_name` TEXT, `type` INTEGER, `count` INTEGER NOT NULL, `number_of_guests` INTEGER NOT NULL, `participants` TEXT, `participant_type` INTEGER, `has_password` INTEGER NOT NULL, `session_id` TEXT, `favorite` INTEGER NOT NULL, `last_activity` INTEGER NOT NULL, `unread_messages` INTEGER NOT NULL, `unread_mention` INTEGER NOT NULL, `last_message` TEXT, `object_type` TEXT, `notification_level` INTEGER, `read_only_state` INTEGER, `lobby_state` INTEGER, `lobby_timer` INTEGER, `last_read_message` INTEGER NOT NULL, `can_start_call` INTEGER, `modified_at` INTEGER, `changing` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`user_id`) REFERENCES `users`(`id`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
@ -169,12 +169,6 @@
"columnName": "changing", "columnName": "changing",
"affinity": "INTEGER", "affinity": "INTEGER",
"notNull": true "notNull": true
},
{
"fieldPath": "localConfiguration",
"columnName": "local_configuration",
"affinity": "TEXT",
"notNull": false
} }
], ],
"primaryKey": { "primaryKey": {
@ -395,7 +389,7 @@
"views": [], "views": [],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "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, '24ed06b3e6bdb36d2657cc9735999e89')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2c4f372b48cd11e679b04c6d577f1cd8')"
] ]
} }
} }

View File

@ -29,7 +29,6 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.models.json.converters.* import com.nextcloud.talk.models.json.converters.*
import com.nextcloud.talk.models.json.participants.Participant import com.nextcloud.talk.models.json.participants.Participant
import com.nextcloud.talk.newarch.data.model.LocalConversationConfiguration
import com.nextcloud.talk.newarch.local.models.UserNgEntity import com.nextcloud.talk.newarch.local.models.UserNgEntity
import lombok.Data import lombok.Data
import org.parceler.Parcel import org.parceler.Parcel
@ -40,8 +39,6 @@ import java.util.*
@Data @Data
@JsonObject(serializeNullCollectionElements = true, serializeNullObjects = true) @JsonObject(serializeNullCollectionElements = true, serializeNullObjects = true)
class Conversation { class Conversation {
@JsonIgnore
var localConfiguration: LocalConversationConfiguration? = null
@JsonIgnore @JsonIgnore
var databaseId: String? = null var databaseId: String? = null
@JsonIgnore @JsonIgnore
@ -193,7 +190,6 @@ class Conversation {
if (lastReadMessageId != other.lastReadMessageId) return false if (lastReadMessageId != other.lastReadMessageId) return false
if (canStartCall != other.canStartCall) return false if (canStartCall != other.canStartCall) return false
if (changing != other.changing) return false if (changing != other.changing) return false
if (localConfiguration != other.localConfiguration) return false
return true return true
} }

View File

@ -20,6 +20,7 @@
package com.nextcloud.talk.newarch.data.repository.online package com.nextcloud.talk.newarch.data.repository.online
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
import com.nextcloud.talk.models.json.conversations.Conversation import com.nextcloud.talk.models.json.conversations.Conversation
import com.nextcloud.talk.models.json.conversations.RoomOverall import com.nextcloud.talk.models.json.conversations.RoomOverall
import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.generic.GenericOverall
@ -63,6 +64,10 @@ class NextcloudTalkRepositoryImpl(private val apiService: ApiService) : Nextclou
return apiService.exitConversation(userNgEntity.getCredentials(), ApiUtils.getUrlForSettingMyselfAsActiveParticipant(userNgEntity.baseUrl, conversationToken)) return apiService.exitConversation(userNgEntity.getCredentials(), ApiUtils.getUrlForSettingMyselfAsActiveParticipant(userNgEntity.baseUrl, conversationToken))
} }
override suspend fun getCapabilitiesForServer(server: String): CapabilitiesOverall {
return apiService.getCapabilities(ApiUtils.getUrlForCapabilities(server))
}
override suspend fun setFavoriteValueForConversation( override suspend fun setFavoriteValueForConversation(
user: UserNgEntity, user: UserNgEntity,
conversation: Conversation, conversation: Conversation,

View File

@ -20,6 +20,7 @@
package com.nextcloud.talk.newarch.data.source.remote package com.nextcloud.talk.newarch.data.source.remote
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
import com.nextcloud.talk.models.json.conversations.RoomOverall import com.nextcloud.talk.models.json.conversations.RoomOverall
import com.nextcloud.talk.models.json.conversations.RoomsOverall import com.nextcloud.talk.models.json.conversations.RoomsOverall
import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.generic.GenericOverall
@ -30,6 +31,9 @@ interface ApiService {
/* /*
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room
*/ */
@GET
suspend fun getCapabilities(@Url url: String): CapabilitiesOverall
@GET @GET
suspend fun getConversations( suspend fun getConversations(
@Header( @Header(

View File

@ -20,6 +20,7 @@
package com.nextcloud.talk.newarch.domain.repository.online package com.nextcloud.talk.newarch.domain.repository.online
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
import com.nextcloud.talk.models.json.conversations.Conversation import com.nextcloud.talk.models.json.conversations.Conversation
import com.nextcloud.talk.models.json.conversations.RoomOverall import com.nextcloud.talk.models.json.conversations.RoomOverall
import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.generic.GenericOverall
@ -58,4 +59,8 @@ interface NextcloudTalkRepository {
userNgEntity: UserNgEntity, userNgEntity: UserNgEntity,
conversationToken: String conversationToken: String
): GenericOverall ): GenericOverall
suspend fun getCapabilitiesForServer(
server: String
): CapabilitiesOverall
} }

View File

@ -0,0 +1,39 @@
/*
*
* * Nextcloud Talk application
* *
* * @author Mario Danic
* * Copyright (C) 2017-2020 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.capabilities.CapabilitiesOverall
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 GetCapabilitiesUseCase constructor(
private val nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler?
) : UseCase<CapabilitiesOverall, Any?>(apiErrorHandler) {
override suspend fun run(params: Any?): CapabilitiesOverall {
val definitionParameters = params as DefinitionParameters
return nextcloudTalkRepository.getCapabilitiesForServer(definitionParameters[0])
}
}

View File

@ -20,18 +20,11 @@
* *
*/ */
package com.nextcloud.talk.newarch.data.model package com.nextcloud.talk.newarch.features.account
import android.os.Parcelable enum class ServerEntryCapabilitiesCheckState {
import kotlinx.android.parcel.Parcelize WAITING_FOR_INPUT,
import kotlinx.serialization.SerialName CHECKING,
import kotlinx.serialization.Serializable SERVER_UNSUPPORTED,
SERVER_SUPPORTED
@Parcelize }
@Serializable
data class LocalConversationConfiguration(
@SerialName("important_conversation")
var importantConversation: Boolean = false,
@SerialName("ignore_calls")
var ignoreCalls: Boolean = false
) : Parcelable

View File

@ -0,0 +1,34 @@
/*
*
* * Nextcloud Talk application
* *
* * @author Mario Danic
* * Copyright (C) 2017-2020 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.features.account
import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.nextcloud.talk.newarch.domain.usecases.GetCapabilitiesUseCase
class ServerEntryVideModelFactory constructor(private val application: Application, private val getCapabilitiesUseCase: GetCapabilitiesUseCase): ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return ServerEntryViewModel(application, getCapabilitiesUseCase) as T
}
}

View File

@ -0,0 +1,77 @@
/*
*
* * Nextcloud Talk application
* *
* * @author Mario Danic
* * Copyright (C) 2017-2020 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.features.account
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.lifecycle.Observer
import com.nextcloud.talk.R
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseView
import kotlinx.android.synthetic.main.server_entry_view.view.*
import org.koin.android.ext.android.inject
class ServerEntryView : BaseView() {
private lateinit var viewModel: ServerEntryViewModel
val factory: ServerEntryVideModelFactory by inject()
override fun getLayoutId(): Int {
return R.layout.server_entry_view
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
actionBar?.hide()
viewModel = viewModelProvider(factory).get(ServerEntryViewModel::class.java)
val view = super.onCreateView(inflater, container)
viewModel.apply {
checkState.observe(this@ServerEntryView, Observer {
when(it) {
ServerEntryCapabilitiesCheckState.WAITING_FOR_INPUT -> {
view.serverEntryTextInputLayout.isEnabled = true
view.serverEntryProgressBar.isVisible = false
view.serverEntryTextInputEditText.setCompoundDrawablesRelative(null, null, resources?.getDrawable(R.drawable.ic_arrow_forward_white_24px), null)
}
ServerEntryCapabilitiesCheckState.CHECKING -> {
view.serverEntryTextInputLayout.isEnabled = false
view.serverEntryTextInputEditText.setCompoundDrawablesRelative(null, null, null, null)
view.serverEntryProgressBar.isVisible = true
}
ServerEntryCapabilitiesCheckState.SERVER_SUPPORTED -> {
}
// Unsupported
else -> {
view.serverEntryTextInputLayout.isEnabled = true
view.serverEntryProgressBar.isVisible = false
view.serverEntryTextInputEditText.setCompoundDrawablesRelative(null, null, resources?.getDrawable(R.drawable.ic_arrow_forward_white_24px), null)
}
}
})
}
return view
}
}

View File

@ -0,0 +1,59 @@
/*
*
* * Nextcloud Talk application
* *
* * @author Mario Danic
* * Copyright (C) 2017-2020 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.features.account
import android.app.Application
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseViewModel
import com.nextcloud.talk.newarch.data.model.ErrorModel
import com.nextcloud.talk.newarch.domain.usecases.*
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
import org.koin.core.parameter.parametersOf
class ServerEntryViewModel constructor(
application: Application,
private val getCapabilitiesUseCase: GetCapabilitiesUseCase
) : BaseViewModel<ServerEntryView>(application) {
val checkState: MutableLiveData<ServerEntryCapabilitiesCheckState> = MutableLiveData(ServerEntryCapabilitiesCheckState.WAITING_FOR_INPUT)
fun fetchCapabilities(url: String) {
checkState.postValue(ServerEntryCapabilitiesCheckState.CHECKING)
getCapabilitiesUseCase.invoke(viewModelScope, parametersOf(url), object : UseCaseResponse<CapabilitiesOverall> {
override suspend fun onSuccess(result: CapabilitiesOverall) {
val hasSupportedTalkVersion = result.ocs?.data?.capabilities?.spreedCapability?.features?.contains("no-ping") == true
if (hasSupportedTalkVersion) {
checkState.postValue(ServerEntryCapabilitiesCheckState.SERVER_SUPPORTED)
} else {
checkState.postValue(ServerEntryCapabilitiesCheckState.SERVER_UNSUPPORTED)
}
}
override suspend fun onError(errorModel: ErrorModel?) {
checkState.postValue(ServerEntryCapabilitiesCheckState.SERVER_UNSUPPORTED)
}
})
}
}

View File

@ -43,7 +43,7 @@ import com.stfalcon.chatkit.messages.MessageHolders
import com.stfalcon.chatkit.messages.MessagesListAdapter import com.stfalcon.chatkit.messages.MessagesListAdapter
import com.stfalcon.chatkit.utils.DateFormatter import com.stfalcon.chatkit.utils.DateFormatter
import kotlinx.android.synthetic.main.controller_chat.view.* import kotlinx.android.synthetic.main.controller_chat.view.*
import kotlinx.android.synthetic.main.controller_conversations_rv.view.* import kotlinx.android.synthetic.main.conversations_list_view.view.*
import kotlinx.android.synthetic.main.lobby_view.view.* import kotlinx.android.synthetic.main.lobby_view.view.*
import kotlinx.android.synthetic.main.view_message_input.view.* import kotlinx.android.synthetic.main.view_message_input.view.*
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject

View File

@ -22,7 +22,6 @@ package com.nextcloud.talk.newarch.features.conversationsList
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -59,7 +58,7 @@ import com.otaliastudios.elements.Page
import com.otaliastudios.elements.Presenter import com.otaliastudios.elements.Presenter
import com.uber.autodispose.lifecycle.LifecycleScopeProvider import com.uber.autodispose.lifecycle.LifecycleScopeProvider
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import kotlinx.android.synthetic.main.controller_conversations_rv.view.* import kotlinx.android.synthetic.main.conversations_list_view.view.*
import kotlinx.android.synthetic.main.message_state.view.* import kotlinx.android.synthetic.main.message_state.view.*
import kotlinx.android.synthetic.main.search_layout.* import kotlinx.android.synthetic.main.search_layout.*
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
@ -222,7 +221,7 @@ class ConversationsListView : BaseView() {
} }
override fun getLayoutId(): Int { override fun getLayoutId(): Int {
return R.layout.controller_conversations_rv return R.layout.conversations_list_view
} }
private fun openNewConversationScreen() { private fun openNewConversationScreen() {

View File

@ -1,47 +0,0 @@
/*
*
* * Nextcloud Talk application
* *
* * @author Mario Danic
* * Copyright (C) 2017-2020 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.local.converters
import androidx.room.TypeConverter
import com.nextcloud.talk.newarch.data.model.LocalConversationConfiguration
import kotlinx.serialization.json.Json
class LocalConversationConfigurationConverter {
@TypeConverter
fun fromLocalConversationConfigurationToString(localConversationConfiguration: LocalConversationConfiguration?): String {
return if (localConversationConfiguration != null) {
Json.stringify(LocalConversationConfiguration.serializer(), localConversationConfiguration)
} else {
Json.stringify(LocalConversationConfiguration.serializer(), LocalConversationConfiguration())
}
}
@TypeConverter
fun fromStringToLocalConversationConfiguration(value: String?): LocalConversationConfiguration? {
return if (value.isNullOrEmpty()) {
LocalConversationConfiguration()
} else {
Json.parse(LocalConversationConfiguration.serializer(), value)
}
}
}

View File

@ -44,8 +44,7 @@ import com.nextcloud.talk.newarch.local.models.UserNgEntity
ConversationTypeConverter::class, ParticipantTypeConverter::class, ConversationTypeConverter::class, ParticipantTypeConverter::class,
PushConfigurationConverter::class, CapabilitiesConverter::class, PushConfigurationConverter::class, CapabilitiesConverter::class,
ExternalSignalingConverter::class, ExternalSignalingConverter::class,
UserStatusConverter::class, SystemMessageTypeConverter::class, ParticipantMapConverter::class, UserStatusConverter::class, SystemMessageTypeConverter::class, ParticipantMapConverter::class
LocalConversationConfigurationConverter::class
) )
abstract class TalkDatabase : RoomDatabase() { abstract class TalkDatabase : RoomDatabase() {

View File

@ -27,7 +27,6 @@ import com.nextcloud.talk.models.json.conversations.Conversation
import com.nextcloud.talk.models.json.conversations.Conversation.* import com.nextcloud.talk.models.json.conversations.Conversation.*
import com.nextcloud.talk.models.json.participants.Participant import com.nextcloud.talk.models.json.participants.Participant
import com.nextcloud.talk.models.json.participants.Participant.ParticipantType import com.nextcloud.talk.models.json.participants.Participant.ParticipantType
import com.nextcloud.talk.newarch.data.model.LocalConversationConfiguration
import java.util.* import java.util.*
@Entity( @Entity(
@ -72,8 +71,7 @@ data class ConversationEntity(
@ColumnInfo(name = "can_start_call") var canStartCall: Boolean? = true, @ColumnInfo(name = "can_start_call") var canStartCall: Boolean? = true,
@ColumnInfo(name = "modified_at") var modifiedAt: Long? = null, @ColumnInfo(name = "modified_at") var modifiedAt: Long? = null,
@ColumnInfo(name = "changing") var changing: Boolean = false, @ColumnInfo(name = "changing") var changing: Boolean = false
@ColumnInfo(name = "local_configuration") var localConfiguration: LocalConversationConfiguration? = null
) { ) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
@ -107,7 +105,6 @@ data class ConversationEntity(
if (canStartCall != other.canStartCall) return false if (canStartCall != other.canStartCall) return false
if (lastReadMessageId != other.lastReadMessageId) return false if (lastReadMessageId != other.lastReadMessageId) return false
if (changing != other.changing) return false if (changing != other.changing) return false
if (localConfiguration != other.localConfiguration) return false
return true return true
} }
@ -147,7 +144,6 @@ fun ConversationEntity.toConversation(): Conversation {
conversation.canStartCall = this.canStartCall conversation.canStartCall = this.canStartCall
conversation.lastReadMessageId = this.lastReadMessageId conversation.lastReadMessageId = this.lastReadMessageId
conversation.changing = this.changing conversation.changing = this.changing
conversation.localConfiguration = this.localConfiguration
return conversation return conversation
} }
@ -179,7 +175,6 @@ fun Conversation.toConversationEntity(): ConversationEntity {
conversationEntity.canStartCall = this.canStartCall conversationEntity.canStartCall = this.canStartCall
conversationEntity.type = this.type conversationEntity.type = this.type
conversationEntity.changing = this.changing conversationEntity.changing = this.changing
conversationEntity.localConfiguration = this.localConfiguration
return conversationEntity return conversationEntity
} }

View File

@ -85,16 +85,9 @@ data class UserNgEntity(
fun UserNgEntity.getCredentials() = ApiUtils.getCredentials(username, token) fun UserNgEntity.getCredentials() = ApiUtils.getCredentials(username, token)
fun UserNgEntity.hasSpreedFeatureCapability(capabilityName: String): Boolean { fun UserNgEntity.hasSpreedFeatureCapability(capabilityName: String): Boolean {
val capabilityExists = capabilities?.spreedCapability?.features?.contains(capabilityName) return capabilities?.spreedCapability?.features?.contains(capabilityName) ?: false
if (capabilityExists != null) {
return capabilityExists
} else {
return false
}
} }
fun UserNgEntity.getMaxMessageLength(): Int { fun UserNgEntity.getMaxMessageLength(): Int {
val maxLength = capabilities?.spreedCapability?.config?.get("chat") return capabilities?.spreedCapability?.config?.get("chat")?.get("max-length")?.toInt() ?: 1000
?.get("max-length")
return maxLength?.toInt() ?: 1000
} }

View File

@ -30,15 +30,15 @@
android:id="@+id/swipeRefreshLayoutView" android:id="@+id/swipeRefreshLayoutView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:visibility="visible"> android:visibility="visible"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView" android:id="@+id/recyclerView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:listitem="@layout/rv_item_conversation_with_last_message" tools:listitem="@layout/rv_item_conversation_with_last_message" />
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ /*
~ * Nextcloud Talk application
~ *
~ * @author Mario Danic
~ * Copyright (C) 2017-2020 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/>.
~ */
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary">
<ImageView
android:id="@+id/image_logo"
android:layout_width="96dp"
android:layout_height="96dp"
android:layout_above="@+id/serverEntryTextInputLayout"
android:layout_centerHorizontal="true"
android:layout_marginBottom="8dp"
android:scaleType="fitXY"
app:srcCompat="@drawable/ic_logo" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/serverEntryTextInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="16dp"
app:errorTextColor="@color/white">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:id="@+id/serverEntryTextInputEditText"
android:hint="@string/nc_server_url"
android:imeOptions="actionDone"
android:inputType="textUri"
android:drawableEnd="@drawable/ic_arrow_forward_white_24px"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:singleLine="true"
android:textColor="@color/fg_inverse"
android:textCursorDrawable="@null" />
<ProgressBar
android:layout_width="24dp"
android:layout_height="wrap_content"
android:id="@+id/serverEntryProgressBar"
android:visibility="gone"
android:indeterminateTint="@color/white"
android:layout_gravity="end|center_vertical"
android:layout_marginHorizontal="8dp"
/>
</FrameLayout>
</com.google.android.material.textfield.TextInputLayout>
</RelativeLayout>