Merge pull request #2237 from vector-im/feature/ons/expandable_room_topic
Make long topic expandable.
This commit is contained in:
commit
ea5bcc7c77
|
@ -21,6 +21,7 @@ Bugfix 🐛:
|
||||||
- Improve support for image/audio/video/file selection with intent changes (#1376)
|
- Improve support for image/audio/video/file selection with intent changes (#1376)
|
||||||
- Fix Splash layout on small screens
|
- Fix Splash layout on small screens
|
||||||
- Simplifies draft management and should fix bunch of draft issues (#952, #683)
|
- Simplifies draft management and should fix bunch of draft issues (#952, #683)
|
||||||
|
- Very long topic cannot be fully visible (#1957)
|
||||||
|
|
||||||
Translations 🗣:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 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.core.epoxy
|
||||||
|
|
||||||
|
import android.animation.ObjectAnimator
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.view.doOnPreDraw
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.extensions.copyOnLongClick
|
||||||
|
|
||||||
|
@EpoxyModelClass(layout = R.layout.item_expandable_textview)
|
||||||
|
abstract class ExpandableTextItem : VectorEpoxyModel<ExpandableTextItem.Holder>() {
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
lateinit var content: String
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
var maxLines: Int = 3
|
||||||
|
|
||||||
|
private var isExpanded = false
|
||||||
|
private var expandedLines = 0
|
||||||
|
|
||||||
|
override fun bind(holder: Holder) {
|
||||||
|
super.bind(holder)
|
||||||
|
holder.content.text = content
|
||||||
|
holder.content.copyOnLongClick()
|
||||||
|
|
||||||
|
holder.content.doOnPreDraw {
|
||||||
|
if (holder.content.lineCount > maxLines) {
|
||||||
|
expandedLines = holder.content.lineCount
|
||||||
|
holder.content.maxLines = maxLines
|
||||||
|
|
||||||
|
holder.view.setOnClickListener {
|
||||||
|
if (isExpanded) {
|
||||||
|
collapse(holder)
|
||||||
|
} else {
|
||||||
|
expand(holder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
holder.arrow.isVisible = true
|
||||||
|
} else {
|
||||||
|
holder.arrow.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun expand(holder: Holder) {
|
||||||
|
ObjectAnimator
|
||||||
|
.ofInt(holder.content, "maxLines", expandedLines)
|
||||||
|
.setDuration(200)
|
||||||
|
.start()
|
||||||
|
|
||||||
|
holder.content.ellipsize = null
|
||||||
|
holder.arrow.setImageResource(R.drawable.ic_expand_less)
|
||||||
|
holder.arrow.contentDescription = holder.view.context.getString(R.string.merged_events_collapse)
|
||||||
|
isExpanded = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collapse(holder: Holder) {
|
||||||
|
ObjectAnimator
|
||||||
|
.ofInt(holder.content, "maxLines", maxLines)
|
||||||
|
.setDuration(200)
|
||||||
|
.start()
|
||||||
|
|
||||||
|
holder.content.ellipsize = TextUtils.TruncateAt.END
|
||||||
|
holder.arrow.setImageResource(R.drawable.ic_expand_more)
|
||||||
|
holder.arrow.contentDescription = holder.view.context.getString(R.string.merged_events_expand)
|
||||||
|
isExpanded = false
|
||||||
|
}
|
||||||
|
|
||||||
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
val content by bind<TextView>(R.id.expandableContent)
|
||||||
|
val arrow by bind<ImageView>(R.id.expandableArrow)
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ package im.vector.app.features.roomprofile
|
||||||
|
|
||||||
import com.airbnb.epoxy.TypedEpoxyController
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.epoxy.expandableTextItem
|
||||||
import im.vector.app.core.epoxy.profiles.buildProfileAction
|
import im.vector.app.core.epoxy.profiles.buildProfileAction
|
||||||
import im.vector.app.core.epoxy.profiles.buildProfileSection
|
import im.vector.app.core.epoxy.profiles.buildProfileSection
|
||||||
import im.vector.app.core.resources.ColorProvider
|
import im.vector.app.core.resources.ColorProvider
|
||||||
|
@ -57,6 +58,20 @@ class RoomProfileController @Inject constructor(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val roomSummary = data.roomSummary() ?: return
|
val roomSummary = data.roomSummary() ?: return
|
||||||
|
|
||||||
|
// Topic
|
||||||
|
roomSummary
|
||||||
|
.topic
|
||||||
|
.takeIf { it.isNotEmpty() }
|
||||||
|
?.let {
|
||||||
|
buildProfileSection(stringProvider.getString(R.string.room_settings_topic))
|
||||||
|
expandableTextItem {
|
||||||
|
id("topic")
|
||||||
|
content(it)
|
||||||
|
maxLines(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Security
|
// Security
|
||||||
buildProfileSection(stringProvider.getString(R.string.room_profile_section_security))
|
buildProfileSection(stringProvider.getString(R.string.room_profile_section_security))
|
||||||
val learnMoreSubtitle = if (roomSummary.isEncrypted) {
|
val learnMoreSubtitle = if (roomSummary.isEncrypted) {
|
||||||
|
|
|
@ -129,7 +129,6 @@ class RoomProfileFragment @Inject constructor(
|
||||||
private fun setupLongClicks() {
|
private fun setupLongClicks() {
|
||||||
roomProfileNameView.copyOnLongClick()
|
roomProfileNameView.copyOnLongClick()
|
||||||
roomProfileAliasView.copyOnLongClick()
|
roomProfileAliasView.copyOnLongClick()
|
||||||
roomProfileTopicView.copyOnLongClick()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
@ -187,7 +186,6 @@ class RoomProfileFragment @Inject constructor(
|
||||||
roomProfileNameView.text = it.displayName
|
roomProfileNameView.text = it.displayName
|
||||||
matrixProfileToolbarTitleView.text = it.displayName
|
matrixProfileToolbarTitleView.text = it.displayName
|
||||||
roomProfileAliasView.setTextOrHide(it.canonicalAlias)
|
roomProfileAliasView.setTextOrHide(it.canonicalAlias)
|
||||||
roomProfileTopicView.setTextOrHide(it.topic)
|
|
||||||
val matrixItem = it.toMatrixItem()
|
val matrixItem = it.toMatrixItem()
|
||||||
avatarRenderer.render(matrixItem, roomProfileAvatarView)
|
avatarRenderer.render(matrixItem, roomProfileAvatarView)
|
||||||
avatarRenderer.render(matrixItem, matrixProfileToolbarAvatarImageView)
|
avatarRenderer.render(matrixItem, matrixProfileToolbarAvatarImageView)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12,8l-6,6 1.41,1.41L12,10.83l4.59,4.58L18,14z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M16.59,8.59L12,13.17 7.41,8.59 6,10l6,6 6,-6z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/expandableContent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/expandableArrow"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:maxLines="2"
|
||||||
|
tools:text="@sample/matrix.json/data/roomTopic" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/expandableArrow"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:autoLink="web"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@drawable/ic_expand_more"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="normal"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/expandableContent"
|
||||||
|
app:tint="?riotx_text_secondary"
|
||||||
|
tools:ignore="MissingPrefix" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -54,27 +54,9 @@
|
||||||
android:textAppearance="@style/Vector.Toolbar.Title"
|
android:textAppearance="@style/Vector.Toolbar.Title"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/roomProfileTopicView"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/roomProfileNameView"
|
app:layout_constraintTop_toBottomOf="@+id/roomProfileNameView"
|
||||||
tools:text="@sample/matrix.json/data/roomAlias" />
|
tools:text="@sample/matrix.json/data/roomAlias" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/roomProfileTopicView"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="40dp"
|
|
||||||
android:layout_marginEnd="40dp"
|
|
||||||
android:autoLink="web"
|
|
||||||
android:fontFamily="sans-serif"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:textStyle="normal"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/roomProfileAliasView"
|
|
||||||
tools:text="@sample/matrix.json/data/roomTopic" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
Loading…
Reference in New Issue