fix shouldTrimStatus and add tests (#1404)
This commit is contained in:
parent
feaea70af4
commit
f975522e63
7 changed files with 96 additions and 41 deletions
|
@ -176,7 +176,7 @@ fun Status.toEntity() =
|
||||||
spoilerText, attachments, mentions,
|
spoilerText, attachments, mentions,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
!shouldTrimStatus(content),
|
shouldTrimStatus(content),
|
||||||
true,
|
true,
|
||||||
poll
|
poll
|
||||||
)
|
)
|
||||||
|
|
|
@ -79,7 +79,7 @@ class StatusViewHolder(itemView: View,
|
||||||
|
|
||||||
private fun updateTextView() {
|
private fun updateTextView() {
|
||||||
status()?.let { status ->
|
status()?.let { status ->
|
||||||
setupCollapsedState(status.isCollapsible(), viewState.isCollapsed(status.id, true),
|
setupCollapsedState(shouldTrimStatus(status.content), viewState.isCollapsed(status.id, true),
|
||||||
viewState.isContentShow(status.id, status.sensitive), status.spoilerText)
|
viewState.isContentShow(status.id, status.sensitive), status.spoilerText)
|
||||||
|
|
||||||
if (status.spoilerText.isBlank()) {
|
if (status.spoilerText.isBlank()) {
|
||||||
|
|
|
@ -48,7 +48,6 @@ import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||||
import com.keylesspalace.tusky.network.MastodonApi;
|
import com.keylesspalace.tusky.network.MastodonApi;
|
||||||
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
|
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
|
||||||
import com.keylesspalace.tusky.util.PairedList;
|
import com.keylesspalace.tusky.util.PairedList;
|
||||||
import com.keylesspalace.tusky.util.SmartLengthInputFilterKt;
|
|
||||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||||
import com.keylesspalace.tusky.util.ViewDataUtils;
|
import com.keylesspalace.tusky.util.ViewDataUtils;
|
||||||
import com.keylesspalace.tusky.view.ConversationLineItemDecoration;
|
import com.keylesspalace.tusky.view.ConversationLineItemDecoration;
|
||||||
|
@ -360,7 +359,6 @@ public final class ViewThreadFragment extends SFragment implements
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusViewData.Concrete updatedStatus = new StatusViewData.Builder(status)
|
StatusViewData.Concrete updatedStatus = new StatusViewData.Builder(status)
|
||||||
.setCollapsible(!SmartLengthInputFilterKt.shouldTrimStatus(status.getContent()))
|
|
||||||
.setCollapsed(isCollapsed)
|
.setCollapsed(isCollapsed)
|
||||||
.createStatusViewData();
|
.createStatusViewData();
|
||||||
statuses.setPairedItem(position, updatedStatus);
|
statuses.setPairedItem(position, updatedStatus);
|
||||||
|
|
|
@ -38,8 +38,7 @@ private const val LENGTH_DEFAULT = 500
|
||||||
* @return Whether the message should be trimmed or not.
|
* @return Whether the message should be trimmed or not.
|
||||||
*/
|
*/
|
||||||
fun shouldTrimStatus(message: Spanned): Boolean {
|
fun shouldTrimStatus(message: Spanned): Boolean {
|
||||||
// Check for emptiness so that we don't divide by zero
|
return message.isNotEmpty() && LENGTH_DEFAULT.toFloat() / message.length < 0.75
|
||||||
return message.isNotEmpty() && LENGTH_DEFAULT.toFloat() / message.length > 0.75
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,7 +59,7 @@ object SmartLengthInputFilter : InputFilter {
|
||||||
// https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/InputFilter.java#175
|
// https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/InputFilter.java#175
|
||||||
|
|
||||||
val sourceLength = source.length
|
val sourceLength = source.length
|
||||||
var keep = LENGTH_DEFAULT - dest.length - dend - dstart
|
var keep = LENGTH_DEFAULT - (dest.length - (dend - dstart))
|
||||||
if (keep <= 0) return ""
|
if (keep <= 0) return ""
|
||||||
if (keep >= end - start) return null // Keep original
|
if (keep >= end - start) return null // Keep original
|
||||||
|
|
||||||
|
@ -78,17 +77,17 @@ object SmartLengthInputFilter : InputFilter {
|
||||||
// those without having to add the ICU4J library at a minimum Api trade-off.
|
// those without having to add the ICU4J library at a minimum Api trade-off.
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||||
val iterator = android.icu.text.BreakIterator.getWordInstance()
|
val iterator = android.icu.text.BreakIterator.getWordInstance()
|
||||||
iterator.setText(source.toString())
|
iterator.setText(source.toString())
|
||||||
boundary = iterator.following(keep)
|
boundary = iterator.following(keep)
|
||||||
if (keep - boundary > RUNWAY) boundary = iterator.preceding(keep)
|
if (keep - boundary > RUNWAY) boundary = iterator.preceding(keep)
|
||||||
} else {
|
} else {
|
||||||
val iterator = java.text.BreakIterator.getWordInstance()
|
val iterator = java.text.BreakIterator.getWordInstance()
|
||||||
iterator.setText(source.toString())
|
iterator.setText(source.toString())
|
||||||
boundary = iterator.following(keep)
|
boundary = iterator.following(keep)
|
||||||
if (keep - boundary > RUNWAY) boundary = iterator.preceding(keep)
|
if (keep - boundary > RUNWAY) boundary = iterator.preceding(keep)
|
||||||
}
|
}
|
||||||
|
|
||||||
keep = boundary
|
keep = boundary
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// If no runway is allowed simply remove whitespaces if present
|
// If no runway is allowed simply remove whitespaces if present
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
/* Copyright 2019 Joel Pyska
|
|
||||||
*
|
|
||||||
* This file is a part of Tusky.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* Tusky 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 Tusky; if not,
|
|
||||||
* see <http://www.gnu.org/licenses>. */
|
|
||||||
|
|
||||||
package com.keylesspalace.tusky.util
|
|
||||||
|
|
||||||
import com.keylesspalace.tusky.entity.Status
|
|
||||||
|
|
||||||
fun Status.isCollapsible(): Boolean {
|
|
||||||
return !shouldTrimStatus(content)
|
|
||||||
}
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ public final class ViewDataUtils {
|
||||||
.setApplication(visibleStatus.getApplication())
|
.setApplication(visibleStatus.getApplication())
|
||||||
.setStatusEmojis(visibleStatus.getEmojis())
|
.setStatusEmojis(visibleStatus.getEmojis())
|
||||||
.setAccountEmojis(visibleStatus.getAccount().getEmojis())
|
.setAccountEmojis(visibleStatus.getAccount().getEmojis())
|
||||||
.setCollapsible(!SmartLengthInputFilterKt.shouldTrimStatus(visibleStatus.getContent()))
|
.setCollapsible(SmartLengthInputFilterKt.shouldTrimStatus(visibleStatus.getContent()))
|
||||||
.setCollapsed(true)
|
.setCollapsed(true)
|
||||||
.setPoll(visibleStatus.getPoll())
|
.setPoll(visibleStatus.getPoll())
|
||||||
.setCard(visibleStatus.getCard())
|
.setCard(visibleStatus.getCard())
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package com.keylesspalace.tusky.util
|
||||||
|
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.keylesspalace.tusky.FakeTuskyApplication
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
|
||||||
|
@Config(application = FakeTuskyApplication::class)
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class SmartLengthInputFilterTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldNotTrimStatusWithLength0() {
|
||||||
|
assertFalse(shouldTrimStatus(SpannableStringBuilder("")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldNotTrimStatusWithLength10() {
|
||||||
|
assertFalse(shouldTrimStatus(SpannableStringBuilder("0123456789")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldNotTrimStatusWithLength500() {
|
||||||
|
assertFalse(shouldTrimStatus(SpannableStringBuilder("u1Pc5TbDVYFnzIdqlQkb3xuZ2S61fFD1K4u" +
|
||||||
|
"cb3q40dnELjAsWxnSH59jqly249Spr0Vod029zfwFHYQ0PkBCNQ7tuk90h6aY661RFC7vhIKJna4yDYOBFj" +
|
||||||
|
"RR9u0CsUa6vlgEE5yUrk5LKn3bmnnzRCXmU6HyT2bFu256qoUWbmMQ6GFXUXjO28tru8Q3UiXKLgrotKdSH" +
|
||||||
|
"mmqPwQgtatbMykTW4RZdKTE46nzlbD3mXHdWQkf4uVPYhVT1CMvVbCPMaimfQ0xuU8CpxyVqA8a6lCL3YX9" +
|
||||||
|
"pNnZjD7DoCg2FCejANnjXsTF6vuqPSHjQZDjy696nSAFy95p9kBeJkc70fHzX5TcfUqSaNtvx3LUtpIkwh4" +
|
||||||
|
"q2EYmKISPsxlANaspEMPuX6r9fSACiEwmHsitZkp4RMKZq5NqRsGPCiAXcNIN3jj9fCYVGxUwVxVeCescDG" +
|
||||||
|
"5naEEszIR3FT1RO4MSn9c2ZZi0UdLizd8ciJAIuwwmcVyYyyM4")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldNotTrimStatusWithLength666() {
|
||||||
|
assertFalse(shouldTrimStatus(SpannableStringBuilder("hIAXqY7DYynQGcr3zxcjCjNZFcdwAzwnWv" +
|
||||||
|
"NHONtT55rO3r2faeMRZLTG3JlOshq8M1mtLRn0Ca8M9w82nIjJDm1jspxhFc4uLFpOjb9Gm2BokgRftA8ih" +
|
||||||
|
"pv6wvMwF5Fg8V4qa8GcXcqt1q7S9g09S3PszCXG4wnrR6dp8GGc9TqVArgmoLSc9EVREIRcLPdzkhV1WWM9" +
|
||||||
|
"ZWw7josT27BfBdMWk0ckQkClHAyqLtlKZ84WamxK2q3NtHR5gr7ohIjU8CZoKDjv1bA8ZI8wBesyOhqbmHf" +
|
||||||
|
"0Ltypq39WKZ63VTGSf5Dd9kuTEjlXJtxZD1DXH4FFplY45DH5WuQ61Ih5dGx0WFEEVb1L3aku3Ht8rKG7YU" +
|
||||||
|
"bOPeanGMBmeI9YRdiD4MmuTUkJfVLkA9rrpRtiEYw8RS3Jf9iqDkTpES9aLQODMip5xTsT4liIcUbLo0Z1d" +
|
||||||
|
"NhHk7YKubigNQIm1mmh2iU3Q0ZEm8TraDpKu2o27gIwSKbAnTllrOokprPxWQWDVrN9bIliwGHzgTKPI5z8" +
|
||||||
|
"gUybaqewxUYe12GvxnzqpfPFvvHricyZAC9i6Fkil5VmFdae75tLFWRBfE8Wfep0dSjL751m2yzvzZTc6uZ" +
|
||||||
|
"RTcUiipvl42DaY8Z5eG2b6xPVhvXshMORvHzwhJhPkHSbnwXX5K")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldTrimStatusWithLength667() {
|
||||||
|
assertTrue(shouldTrimStatus(SpannableStringBuilder("hIAXqY7DYynQGcr3zxcjCjNZFcdwAzwnWv" +
|
||||||
|
"NHONtT55rO3r2faeMRZLTG3JlOshq8M1mtLRn0Ca8M9w82nIjJDm1jspxhFc4uLFpOjb9Gm2BokgRftA8ih" +
|
||||||
|
"pv6wvMwF5Fg8V4qa8GcXcqt1q7S9g09S3PszCXG4wnrR6dp8GGc9TqVArgmoLSc9EVREIRcLPdzkhV1WWM9" +
|
||||||
|
"ZWw7josT27BfBdMWk0ckQkClHAyqLtlKZ84WamxK2q3NtHR5gr7ohIjU8CZoKDjv1bA8ZI8wBesyOhqbmHf" +
|
||||||
|
"0Ltypq39WKZ63VTGSf5Dd9kuTEjlXJtxZD1DXH4FFplY45DH5WuQ61Ih5dGx0WFEEVb1L3aku3Ht8rKG7YU" +
|
||||||
|
"bOPeanGMBmeI9YRdiD4MmuTUkJfVLkA9rrpRtiEYw8RS3Jf9iqDkTpES9aLQODMip5xTsT4liIcUbLo0Z1d" +
|
||||||
|
"NhHk7YKubigNQIm1mmh2iU3Q0ZEm8TraDpKu2o27gIwSKbAnTllrOokprPxWQWDVrN9bIliwGHzgTKPI5z8" +
|
||||||
|
"gUybaqewxUYe12GvxnzqpfPFvvHricyZAC9i6Fkil5VmFdae75tLFWRBfE8Wfep0dSjL751m2yzvzZTc6uZ" +
|
||||||
|
"RTcUiipvl42DaY8Z5eG2b6xPVhvXshMORvHzwhJhPkHSbnwXX5K1")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldTrimStatusWithLength1000() {
|
||||||
|
assertTrue(shouldTrimStatus(SpannableStringBuilder("u1Pc5TbDVYFnzIdqlQkb3xuZ2S61fFD1K4u" +
|
||||||
|
"cb3q40dnELjAsWxnSH59jqly249Spr0Vod029zfwFHYQ0PkBCNQ7tuk90h6aY661RFC7vhIKJna4yDYOBFj" +
|
||||||
|
"RR9u0CsUa6vlgEE5yUrk5LKn3bmnnzRCXmU6HyT2bFu256qoUWbmMQ6GFXUXjO28tru8Q3UiXKLgrotKdSH" +
|
||||||
|
"mmqPwQgtatbMykTW4RZdKTE46nzlbD3mXHdWQkf4uVPYhVT1CMvVbCPMaimfQ0xuU8CpxyVqA8a6lCL3YX9" +
|
||||||
|
"pNnZjD7DoCg2FCejANnjXsTF6vuqPSHjQZDjy696nSAFy95p9kBeJkc70fHzX5TcfUqSaNtvx3LUtpIkwh4" +
|
||||||
|
"q2EYmKISPsxlANaspEMPuX6r9fSACiEwmHsitZkp4RMKZq5NqRsGPCiAXcNIN3jj9fCYVGxUwVxVeCescDG" +
|
||||||
|
"5naEEszIR3FT1RO4MSn9c2ZZi0UdLizd8ciJAIuwwmcVyYyyM4"+
|
||||||
|
"u1Pc5TbDVYFnzIdqlQkb3xuZ2S61fFD1K4u" +
|
||||||
|
"cb3q40dnELjAsWxnSH59jqly249Spr0Vod029zfwFHYQ0PkBCNQ7tuk90h6aY661RFC7vhIKJna4yDYOBFj" +
|
||||||
|
"RR9u0CsUa6vlgEE5yUrk5LKn3bmnnzRCXmU6HyT2bFu256qoUWbmMQ6GFXUXjO28tru8Q3UiXKLgrotKdSH" +
|
||||||
|
"mmqPwQgtatbMykTW4RZdKTE46nzlbD3mXHdWQkf4uVPYhVT1CMvVbCPMaimfQ0xuU8CpxyVqA8a6lCL3YX9" +
|
||||||
|
"pNnZjD7DoCg2FCejANnjXsTF6vuqPSHjQZDjy696nSAFy95p9kBeJkc70fHzX5TcfUqSaNtvx3LUtpIkwh4" +
|
||||||
|
"q2EYmKISPsxlANaspEMPuX6r9fSACiEwmHsitZkp4RMKZq5NqRsGPCiAXcNIN3jj9fCYVGxUwVxVeCescDG" +
|
||||||
|
"5naEEszIR3FT1RO4MSn9c2ZZi0UdLizd8ciJAIuwwmcVyYyyM4")))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue