mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-15 08:45:04 +01:00
Improvements & new search
Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
93fb37a340
commit
689b8e93af
@ -1,249 +0,0 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017-2018 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.adapters.items
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.text.TextUtils
|
||||
import android.text.format.DateUtils
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import coil.api.load
|
||||
import coil.transform.CircleCropTransformation
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
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.newarch.utils.Images
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.IFilterable
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.davidea.flexibleadapter.utils.FlexibleUtils
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.rv_item_conversation_with_last_message.*
|
||||
import kotlinx.android.synthetic.main.rv_item_conversation_with_last_message.view.*
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class ConversationItem(
|
||||
val model: Conversation,
|
||||
val user: UserNgEntity,
|
||||
private val context: Context
|
||||
) : AbstractFlexibleItem<ConversationItem.ConversationItemViewHolder>(), IFilterable<String> {
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other is ConversationItem) {
|
||||
val inItem = other as ConversationItem?
|
||||
val comparedConversation = inItem!!.model
|
||||
|
||||
return (model.conversationId == comparedConversation.conversationId
|
||||
&& model.token == comparedConversation.token
|
||||
&& model.name == comparedConversation.name
|
||||
&& model.displayName == comparedConversation.displayName
|
||||
&& model.type == comparedConversation.type
|
||||
&& model.lastMessage == comparedConversation.lastMessage
|
||||
&& model.favorite == comparedConversation.favorite
|
||||
&& model.hasPassword == comparedConversation.hasPassword
|
||||
&& model.unreadMessages == comparedConversation.unreadMessages
|
||||
&& model.unreadMention == comparedConversation.unreadMention
|
||||
&& model.objectType == comparedConversation.objectType
|
||||
&& model.changing == comparedConversation.changing
|
||||
&& inItem.user.id == user.id)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return Objects.hash(
|
||||
model.token,
|
||||
user.id
|
||||
)
|
||||
}
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.rv_item_conversation_with_last_message
|
||||
}
|
||||
|
||||
override fun createViewHolder(
|
||||
view: View,
|
||||
adapter: FlexibleAdapter<IFlexible<*>>
|
||||
): ConversationItemViewHolder {
|
||||
return ConversationItemViewHolder(view, adapter)
|
||||
}
|
||||
|
||||
override fun bindViewHolder(
|
||||
adapter: FlexibleAdapter<IFlexible<*>>,
|
||||
holder: ConversationItemViewHolder,
|
||||
position: Int,
|
||||
payloads: List<Any>
|
||||
) {
|
||||
val appContext = NextcloudTalkApplication.sharedApplication!!.applicationContext
|
||||
|
||||
if (model.changing) {
|
||||
holder.actionProgressBar!!.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.actionProgressBar!!.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (adapter.hasFilter()) {
|
||||
FlexibleUtils.highlightText(
|
||||
holder.dialogName!!, model.displayName,
|
||||
adapter.getFilter(String::class.java).toString(),
|
||||
NextcloudTalkApplication.sharedApplication!!
|
||||
.resources.getColor(R.color.colorPrimary)
|
||||
)
|
||||
} else {
|
||||
holder.dialogName!!.text = model.displayName
|
||||
}
|
||||
|
||||
if (model.unreadMessages > 0) {
|
||||
holder.dialogUnreadBubble!!.visibility = View.VISIBLE
|
||||
if (model.unreadMessages < 100) {
|
||||
holder.dialogUnreadBubble!!.text = model.unreadMessages.toLong()
|
||||
.toString()
|
||||
} else {
|
||||
holder.dialogUnreadBubble!!.text = context.getString(R.string.nc_99_plus)
|
||||
}
|
||||
|
||||
if (model.unreadMention) {
|
||||
holder.dialogUnreadBubble!!.background =
|
||||
context.getDrawable(R.drawable.bubble_circle_unread_mention)
|
||||
} else {
|
||||
holder.dialogUnreadBubble!!.background =
|
||||
context.getDrawable(R.drawable.bubble_circle_unread)
|
||||
}
|
||||
} else {
|
||||
holder.dialogUnreadBubble!!.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (model.hasPassword) {
|
||||
holder.passwordProtectedRoomImageView!!.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.passwordProtectedRoomImageView!!.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (model.favorite) {
|
||||
holder.favoriteConversationImageView!!.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.favoriteConversationImageView!!.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (model.lastMessage != null) {
|
||||
holder.dialogDate!!.visibility = View.VISIBLE
|
||||
holder.dialogDate!!.text = DateUtils.getRelativeTimeSpanString(
|
||||
model.lastActivity * 1000L,
|
||||
System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE
|
||||
)
|
||||
|
||||
if (!TextUtils.isEmpty(
|
||||
model.lastMessage!!.systemMessage
|
||||
) || Conversation.ConversationType.SYSTEM_CONVERSATION == model.type
|
||||
) {
|
||||
holder.dialogLastMessage!!.text = model.lastMessage!!.text
|
||||
} else {
|
||||
var authorDisplayName = ""
|
||||
model.lastMessage!!.activeUser = user
|
||||
val text: String
|
||||
if (model.lastMessage!!
|
||||
.messageType == ChatMessage.MessageType.REGULAR_TEXT_MESSAGE && (!(ONE_TO_ONE_CONVERSATION).equals(
|
||||
model.type) || model.lastMessage!!.actorId == user.userId)
|
||||
) {
|
||||
if (model.lastMessage!!.actorId == user.userId) {
|
||||
text = String.format(
|
||||
appContext.getString(R.string.nc_formatted_message_you),
|
||||
model.lastMessage!!.lastMessageDisplayText
|
||||
)
|
||||
} else {
|
||||
authorDisplayName = if (!TextUtils.isEmpty(model.lastMessage!!.actorDisplayName))
|
||||
model.lastMessage!!.actorDisplayName
|
||||
else if ("guests" == model.lastMessage!!.actorType)
|
||||
appContext.getString(R.string.nc_guest)
|
||||
else
|
||||
""
|
||||
text = String.format(
|
||||
appContext.getString(R.string.nc_formatted_message),
|
||||
authorDisplayName,
|
||||
model.lastMessage!!.lastMessageDisplayText
|
||||
)
|
||||
}
|
||||
} else {
|
||||
text = model.lastMessage!!.lastMessageDisplayText
|
||||
}
|
||||
|
||||
holder.dialogLastMessage.text = text
|
||||
}
|
||||
} else {
|
||||
holder.dialogDate.visibility = View.GONE
|
||||
holder.dialogLastMessage.setText(R.string.nc_no_messages_yet)
|
||||
}
|
||||
|
||||
val conversationDrawable: Drawable? = Images().getImageForConversation(context, model)
|
||||
|
||||
conversationDrawable?.let {
|
||||
holder.itemView.dialogAvatar.load(conversationDrawable)
|
||||
}?: run {
|
||||
holder.itemView.dialogAvatar.load(ApiUtils.getUrlForAvatarWithName(
|
||||
user.baseUrl,
|
||||
model.name, R.dimen.avatar_size))
|
||||
{
|
||||
addHeader("Authorization", user.getCredentials())
|
||||
transformations(CircleCropTransformation())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onViewAttached(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>?, holder: ConversationItemViewHolder?, position: Int) {
|
||||
super.onViewAttached(adapter, holder, position)
|
||||
Log.d("MAriO", model.displayName!!)
|
||||
}
|
||||
|
||||
override fun onViewDetached(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>?, holder: ConversationItemViewHolder?, position: Int) {
|
||||
super.onViewDetached(adapter, holder, position)
|
||||
Log.d("MAriO DETACH", model.displayName!!)
|
||||
}
|
||||
|
||||
override fun filter(constraint: String): Boolean {
|
||||
return model.displayName != null && Pattern.compile(
|
||||
constraint, Pattern.CASE_INSENSITIVE or Pattern.LITERAL
|
||||
)
|
||||
.matcher(model.displayName!!.trim { it <= ' ' })
|
||||
.find()
|
||||
}
|
||||
|
||||
class ConversationItemViewHolder(
|
||||
view: View,
|
||||
adapter: FlexibleAdapter<*>
|
||||
) : FlexibleViewHolder(view, adapter), LayoutContainer {
|
||||
|
||||
override val containerView: View?
|
||||
get() = itemView
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -20,11 +20,14 @@
|
||||
|
||||
package com.nextcloud.talk.controllers.base
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ComponentCallbacks
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -33,7 +36,14 @@ import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.ActionBar
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.marginBottom
|
||||
import androidx.core.view.updatePadding
|
||||
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.activities.MainActivity
|
||||
import com.nextcloud.talk.controllers.AccountVerificationController
|
||||
import com.nextcloud.talk.controllers.ServerSelectionController
|
||||
import com.nextcloud.talk.controllers.SwitchAccountController
|
||||
@ -41,6 +51,8 @@ import com.nextcloud.talk.controllers.WebViewLoginController
|
||||
import com.nextcloud.talk.controllers.base.providers.ActionBarProvider
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||
import com.uber.autodispose.lifecycle.LifecycleScopeProvider
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.search_layout.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.util.*
|
||||
@ -68,15 +80,39 @@ abstract class BaseController : ButterKnifeController(), ComponentCallbacks {
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
return when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
router.popCurrentController()
|
||||
return true
|
||||
true
|
||||
}
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSearchOrToolbar() {
|
||||
val value = getIsUsingSearchLayout()
|
||||
activity?.let {
|
||||
if (it is MainActivity) {
|
||||
it.searchCardView.isVisible = value
|
||||
it.inputEditText.hint = getSearchHint()
|
||||
|
||||
val layoutParams = it.toolbar.layoutParams as AppBarLayout.LayoutParams
|
||||
|
||||
if (value) {
|
||||
it.appBar.setBackgroundResource(R.color.transparent)
|
||||
//it.toolbar.setContentInsetsAbsolute(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16f, resources?.displayMetrics).toInt(), 0)
|
||||
//layoutParams.scrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS or AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP
|
||||
it.toolbar.layoutParams = layoutParams
|
||||
} else {
|
||||
it.appBar.setBackgroundResource(R.color.colorPrimary)
|
||||
//it.toolbar.setContentInsetsAbsolute(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24f, resources?.displayMetrics).toInt(), 0)
|
||||
layoutParams.scrollFlags = 0
|
||||
it.toolbar.layoutParams = layoutParams
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private fun cleanTempCertPreference() {
|
||||
val temporaryClassNames = ArrayList<String>()
|
||||
temporaryClassNames.add(ServerSelectionController::class.java.name)
|
||||
@ -95,16 +131,22 @@ abstract class BaseController : ButterKnifeController(), ComponentCallbacks {
|
||||
cleanTempCertPreference()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.isKeyboardIncognito) {
|
||||
disableKeyboardPersonalisedLearning(view as ViewGroup)
|
||||
|
||||
activity?.let {
|
||||
if (it is MainActivity && getIsUsingSearchLayout()) {
|
||||
disableKeyboardPersonalisedLearning(it.appBar)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onAttach(view: View) {
|
||||
super.onAttach(view)
|
||||
|
||||
setTitle()
|
||||
if (actionBar != null) {
|
||||
actionBar!!.setDisplayHomeAsUpEnabled(parentController != null || router.backstackSize > 1)
|
||||
}
|
||||
actionBar?.setDisplayHomeAsUpEnabled(parentController != null || router.backstackSize > 1)
|
||||
showSearchOrToolbar()
|
||||
}
|
||||
|
||||
override fun onDetach(view: View) {
|
||||
@ -159,4 +201,7 @@ abstract class BaseController : ButterKnifeController(), ComponentCallbacks {
|
||||
open fun getTitle(): String? {
|
||||
return null
|
||||
}
|
||||
|
||||
open fun getIsUsingSearchLayout(): Boolean = false
|
||||
open fun getSearchHint(): String? = null
|
||||
}
|
||||
|
@ -100,7 +100,10 @@ class Conversation {
|
||||
@JsonIgnore
|
||||
var changing: Boolean = false
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
val isPublic: Boolean = ConversationType.PUBLIC_CONVERSATION == type
|
||||
@JsonIgnore
|
||||
val isGuest: Boolean =
|
||||
Participant.ParticipantType.GUEST == participantType ||
|
||||
Participant.ParticipantType.USER_FOLLOWING_LINK == participantType
|
||||
@ -155,6 +158,48 @@ class Conversation {
|
||||
) || type != ConversationType.ONE_TO_ONE_CONVERSATION && participants!!.size > 1
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as Conversation
|
||||
|
||||
if (databaseId != other.databaseId) return false
|
||||
if (databaseUserId != other.databaseUserId) 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 (participants != other.participants) return false
|
||||
if (participantType != other.participantType) return false
|
||||
if (hasPassword != other.hasPassword) return false
|
||||
if (password != other.password) 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 != other.lastMessage) 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 (canStartCall != other.canStartCall) return false
|
||||
if (changing != other.changing) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = databaseUserId?.hashCode() ?: 0
|
||||
result = 31 * result + (token?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
|
||||
enum class NotificationLevel {
|
||||
DEFAULT,
|
||||
ALWAYS,
|
||||
|
@ -55,8 +55,12 @@ import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||
import com.otaliastudios.elements.*
|
||||
import com.uber.autodispose.lifecycle.LifecycleScopeProvider
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.activity_main.view.*
|
||||
import kotlinx.android.synthetic.main.controller_conversations_rv.view.*
|
||||
import kotlinx.android.synthetic.main.message_state.view.*
|
||||
import kotlinx.android.synthetic.main.search_layout.*
|
||||
import kotlinx.android.synthetic.main.search_layout.view.*
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.parceler.Parcels
|
||||
import java.util.*
|
||||
@ -68,50 +72,6 @@ class ConversationsListView : BaseView() {
|
||||
private lateinit var viewModel: ConversationsListViewModel
|
||||
val factory: ConversationListViewModelFactory by inject()
|
||||
|
||||
private var searchItem: MenuItem? = null
|
||||
private var settingsItem: MenuItem? = null
|
||||
private var searchView: SearchView? = null
|
||||
|
||||
override fun onCreateOptionsMenu(
|
||||
menu: Menu,
|
||||
inflater: MenuInflater
|
||||
) {
|
||||
super.onCreateOptionsMenu(menu, inflater)
|
||||
inflater.inflate(R.menu.menu_conversation_plus_filter, menu)
|
||||
searchItem = menu.findItem(R.id.action_search)
|
||||
}
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||
super.onPrepareOptionsMenu(menu)
|
||||
settingsItem = menu.findItem(R.id.action_settings)
|
||||
settingsItem?.actionView?.transitionName = "userAvatar.transitionTag"
|
||||
viewModel.loadAvatar()
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_settings -> {
|
||||
val names = ArrayList<String>()
|
||||
names.add("userAvatar.transitionTag")
|
||||
router.pushController(
|
||||
RouterTransaction.with(SettingsController())
|
||||
.pushChangeHandler(
|
||||
TransitionChangeHandlerCompat(
|
||||
SharedElementTransition(names), VerticalChangeHandler()
|
||||
)
|
||||
)
|
||||
.popChangeHandler(
|
||||
TransitionChangeHandlerCompat(
|
||||
SharedElementTransition(names), VerticalChangeHandler()
|
||||
)
|
||||
)
|
||||
)
|
||||
return true
|
||||
}
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
/*private fun initSearchView() {
|
||||
val searchManager = activity!!.getSystemService(Context.SEARCH_SERVICE) as SearchManager
|
||||
searchView = MenuItemCompat.getActionView(searchItem) as SearchView
|
||||
@ -144,7 +104,6 @@ class ConversationsListView : BaseView() {
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup
|
||||
): View {
|
||||
setHasOptionsMenu(true)
|
||||
actionBar?.show()
|
||||
|
||||
viewModel = viewModelProvider(factory).get(ConversationsListViewModel::class.java)
|
||||
@ -172,8 +131,26 @@ class ConversationsListView : BaseView() {
|
||||
swipeRefreshLayoutView.setColorSchemeResources(R.color.colorPrimary)
|
||||
}
|
||||
|
||||
activity?.rightButton?.setOnClickListener {
|
||||
val settingsTransitionName = "userAvatar.transitionTag"
|
||||
router.pushController(
|
||||
RouterTransaction.with(SettingsController())
|
||||
.pushChangeHandler(
|
||||
TransitionChangeHandlerCompat(
|
||||
SharedElementTransition(arrayListOf(settingsTransitionName)), VerticalChangeHandler()
|
||||
)
|
||||
)
|
||||
.popChangeHandler(
|
||||
TransitionChangeHandlerCompat(
|
||||
SharedElementTransition(arrayListOf(settingsTransitionName)), VerticalChangeHandler()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
viewModel.avatar.observe(this@ConversationsListView) { avatar ->
|
||||
settingsItem?.icon = avatar
|
||||
activity?.rightButton?.setImageDrawable(avatar)
|
||||
}
|
||||
|
||||
return view
|
||||
@ -321,6 +298,14 @@ class ConversationsListView : BaseView() {
|
||||
return items
|
||||
}
|
||||
|
||||
override fun getIsUsingSearchLayout(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getSearchHint(): String? {
|
||||
return resources?.getString(R.string.nc_search_conversations)
|
||||
}
|
||||
|
||||
override fun getTitle(): String? {
|
||||
return resources?.getString(R.string.nc_app_name)
|
||||
}
|
||||
|
28
app/src/main/res/drawable/ic_baseline_clear_24.xml
Normal file
28
app/src/main/res/drawable/ic_baseline_clear_24.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<!--
|
||||
~ /*
|
||||
~ * 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/>.
|
||||
~ */
|
||||
-->
|
||||
|
||||
<vector android:autoMirrored="true" android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
|
||||
</vector>
|
@ -33,16 +33,27 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="0dp"
|
||||
android:id="@+id/appBar"
|
||||
app:elevation="0dp"
|
||||
>
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar"
|
||||
app:contentInsetStart="24dp"
|
||||
app:contentInsetStartWithNavigation="0dp"
|
||||
app:popupTheme="@style/appActionBarPopupMenu" />
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
android:background="@color/transparent"
|
||||
app:elevation="0dp"
|
||||
app:contentInsetEnd="12dp"
|
||||
app:contentInsetStart="12dp"
|
||||
app:popupTheme="@style/appActionBarPopupMenu">
|
||||
|
||||
<include layout="@layout/search_layout"/>
|
||||
|
||||
</com.google.android.material.appbar.MaterialToolbar>>
|
||||
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
@ -38,7 +38,8 @@
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="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>
|
||||
|
122
app/src/main/res/layout/search_layout.xml
Normal file
122
app/src/main/res/layout/search_layout.xml
Normal file
@ -0,0 +1,122 @@
|
||||
<?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/>.
|
||||
~ */
|
||||
-->
|
||||
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/searchCardView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:layout_marginVertical="8dp"
|
||||
android:background="@color/transparent"
|
||||
app:cardUseCompatPadding="false"
|
||||
app:cardBackgroundColor="@color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
android:elevation="0dp"
|
||||
app:cardCornerRadius="4dp"
|
||||
tools:cardCornerRadius="4dp"
|
||||
tools:cardElevation="0dp"
|
||||
android:clipToPadding="true"
|
||||
android:clipChildren="true"
|
||||
android:animateLayoutChanges="true"
|
||||
android:layout_centerHorizontal="true">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:clipToPadding="true"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/colorPrimary">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/leftContainer"
|
||||
android:visibility="gone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_centerVertical="true">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/leftButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:scaleType="fitCenter"
|
||||
android:tint="@color/fg_inverse"
|
||||
android:src="@drawable/ic_arrow_back_black_24dp"
|
||||
android:visibility="visible"
|
||||
tools:src="@drawable/ic_arrow_back_black_24dp" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminateTint="@color/colorPrimary"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/inputEditText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="start|center"
|
||||
android:layout_toEndOf="@id/leftContainer"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:layout_marginStart="16dp"
|
||||
android:imeOptions="actionSearch|flagNoExtractUi"
|
||||
android:lines="1"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:maxLines="1"
|
||||
android:background="@null"
|
||||
android:textSize="16sp"
|
||||
tools:hint="Search"
|
||||
android:layout_toStartOf="@id/rightButton"/>
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/rightButton"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:transitionName="userAvatar.transitionTag"
|
||||
android:layout_centerVertical="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_settings_white_24dp"
|
||||
tools:src="@tools:sample/avatars[0]"
|
||||
android:visibility="visible" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
</merge>
|
@ -46,6 +46,7 @@
|
||||
|
||||
<string name="nc_never">Never joined</string>
|
||||
<string name="nc_search">Search</string>
|
||||
<string name="nc_search_conversations">Search conversations</string>
|
||||
|
||||
<string name="nc_certificate_dialog_title">Check out the certificate</string>
|
||||
<string name="nc_certificate_dialog_text">Do you trust the until now unknown SSL certificate, issued by %1$s for %2$s, valid from %3$s to %4$s?</string>
|
||||
|
Loading…
Reference in New Issue
Block a user