diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteHeaderItem.kt b/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteHeaderItem.kt new file mode 100644 index 0000000000..f287104415 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteHeaderItem.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.autocomplete + +import android.widget.TextView +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.app.R +import im.vector.app.core.epoxy.VectorEpoxyHolder +import im.vector.app.core.epoxy.VectorEpoxyModel + +@EpoxyModelClass(layout = R.layout.item_autocomplete_header_item) +abstract class AutocompleteHeaderItem : VectorEpoxyModel() { + + @EpoxyAttribute var title: String? = null + + override fun bind(holder: Holder) { + super.bind(holder) + holder.titleView.text = title + } + + class Holder : VectorEpoxyHolder() { + val titleView by bind(R.id.headerItemAutocompleteTitle) + } +} diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteMatrixItem.kt b/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteMatrixItem.kt index d0e2c81b56..dba2661927 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteMatrixItem.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/AutocompleteMatrixItem.kt @@ -30,7 +30,6 @@ import im.vector.app.features.displayname.getBestName import im.vector.app.features.home.AvatarRenderer import org.matrix.android.sdk.api.util.MatrixItem -// TODO create a new item for sections: AutocompleteSection @EpoxyModelClass(layout = R.layout.item_autocomplete_matrix_item) abstract class AutocompleteMatrixItem : VectorEpoxyModel() { diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt index 2132cc2f1d..ce515ad6ad 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberController.kt @@ -20,6 +20,7 @@ import android.content.Context import com.airbnb.epoxy.TypedEpoxyController import im.vector.app.R import im.vector.app.features.autocomplete.AutocompleteClickListener +import im.vector.app.features.autocomplete.autocompleteHeaderItem import im.vector.app.features.autocomplete.autocompleteMatrixItem import im.vector.app.features.home.AvatarRenderer import org.matrix.android.sdk.api.util.toEveryoneInRoomMatrixItem @@ -51,6 +52,7 @@ class AutocompleteMemberController @Inject constructor(private val context: Cont } data.forEach { item -> when (item) { + is AutocompleteMemberItem.Header -> buildHeaderItem(item) is AutocompleteMemberItem.RoomMember -> buildRoomMemberItem(item) is AutocompleteMemberItem.Everyone -> buildEveryoneItem(item) } @@ -61,6 +63,13 @@ class AutocompleteMemberController @Inject constructor(private val context: Cont // HELPER METHODS /////////////////////////////////////////////////////////////////////////// + private fun buildHeaderItem(header: AutocompleteMemberItem.Header) { + autocompleteHeaderItem { + id(header.id) + title(header.title) + } + } + private fun buildRoomMemberItem(roomMember: AutocompleteMemberItem.RoomMember) { val host = this autocompleteMatrixItem { diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberItem.kt b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberItem.kt index fa9693895f..77c5069938 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberItem.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberItem.kt @@ -20,7 +20,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary sealed class AutocompleteMemberItem { - // TODO add section class + data class Header(val id: String, val title: String) : AutocompleteMemberItem() data class RoomMember(val roomMemberSummary: RoomMemberSummary) : AutocompleteMemberItem() data class Everyone(val roomSummary: RoomSummary) : AutocompleteMemberItem() } diff --git a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt index 5640632ec2..3830742adc 100644 --- a/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt +++ b/vector/src/main/java/im/vector/app/features/autocomplete/member/AutocompleteMemberPresenter.kt @@ -21,6 +21,7 @@ import androidx.recyclerview.widget.RecyclerView import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import im.vector.app.R import im.vector.app.features.autocomplete.AutocompleteClickListener import im.vector.app.features.autocomplete.RecyclerViewPresenter import org.matrix.android.sdk.api.query.QueryStringValue @@ -36,12 +37,24 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context, private val controller: AutocompleteMemberController ) : RecyclerViewPresenter(context), AutocompleteClickListener { + /////////////////////////////////////////////////////////////////////////// + // FIELDS + /////////////////////////////////////////////////////////////////////////// + private val room by lazy { session.getRoom(roomId)!! } + /////////////////////////////////////////////////////////////////////////// + // INIT + /////////////////////////////////////////////////////////////////////////// + init { controller.listener = this } + /////////////////////////////////////////////////////////////////////////// + // PUBLIC API + /////////////////////////////////////////////////////////////////////////// + fun clear() { controller.listener = null } @@ -51,6 +64,10 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context, fun create(roomId: String): AutocompleteMemberPresenter } + /////////////////////////////////////////////////////////////////////////// + // SPECIALIZATION + /////////////////////////////////////////////////////////////////////////// + override fun instantiateAdapter(): RecyclerView.Adapter<*> { return controller.adapter } @@ -70,6 +87,10 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context, excludeSelf = true } + val membersHeader = AutocompleteMemberItem.Header( + ID_HEADER_MEMBERS, + context.getString(R.string.room_message_autocomplete_users) + ) val members = room.getRoomMembers(queryParams) .asSequence() .sortedBy { it.displayName } @@ -81,17 +102,35 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context, val everyone = room.roomSummary() ?.takeIf { query.isNullOrBlank() || MatrixItem.NOTIFY_EVERYONE.startsWith("@$query") } ?.let { - AutocompleteMemberItem.Everyone(it) - } + AutocompleteMemberItem.Everyone(it) + } val items = mutableListOf().apply { - // TODO add header sections - addAll(members) - everyone?.let { add(it) } + if(members.isNotEmpty()) { + add(membersHeader) + addAll(members) + } + everyone?.let { + val everyoneHeader = AutocompleteMemberItem.Header( + ID_HEADER_EVERYONE, + context.getString(R.string.room_message_autocomplete_notification) + ) + add(everyoneHeader) + add(it) + } } controller.setData(items) } + + /////////////////////////////////////////////////////////////////////////// + // CONST + /////////////////////////////////////////////////////////////////////////// + + companion object { + private const val ID_HEADER_MEMBERS = "ID_HEADER_MEMBERS" + private const val ID_HEADER_EVERYONE = "ID_HEADER_EVERYONE" + } } private fun Sequence.disambiguate(): Sequence { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt index 550f89dd70..38548377aa 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/AutoCompleter.kt @@ -133,13 +133,17 @@ class AutoCompleter @AssistedInject constructor( .with(backgroundDrawable) .with(object : AutocompleteCallback { override fun onPopupItemClicked(editable: Editable, item: AutocompleteMemberItem): Boolean { - when (item) { - is AutocompleteMemberItem.RoomMember -> + return when (item) { + is AutocompleteMemberItem.Header -> false // do nothing header is not clickable + is AutocompleteMemberItem.RoomMember -> { insertMatrixItem(editText, editable, TRIGGER_AUTO_COMPLETE_MEMBERS, item.roomMemberSummary.toMatrixItem()) - is AutocompleteMemberItem.Everyone -> + true + } + is AutocompleteMemberItem.Everyone -> { insertMatrixItem(editText, editable, TRIGGER_AUTO_COMPLETE_MEMBERS, item.roomSummary.toEveryoneInRoomMatrixItem()) + true + } } - return true } override fun onPopupVisibilityChanged(shown: Boolean) { diff --git a/vector/src/main/res/layout/item_autocomplete_header_item.xml b/vector/src/main/res/layout/item_autocomplete_header_item.xml new file mode 100644 index 0000000000..f842129e0c --- /dev/null +++ b/vector/src/main/res/layout/item_autocomplete_header_item.xml @@ -0,0 +1,21 @@ + + + + + +