From 89efd67015149ed047d40b2dab8820afcd55dcdf Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Mon, 20 Apr 2020 23:06:39 +0200 Subject: [PATCH] fix toots showing too much whitespace (#1761) * fix toots showing too much whitespace * use isWhitespace extension function --- .../com/keylesspalace/tusky/db/Converters.kt | 3 +- .../tusky/json/SpannedTypeAdapter.java | 59 ------------------- .../tusky/json/SpannedTypeAdapter.kt | 37 ++++++++++++ .../tusky/repository/TimelineRepository.kt | 6 +- .../keylesspalace/tusky/util/StringUtils.kt | 11 +++- 5 files changed, 53 insertions(+), 63 deletions(-) delete mode 100644 app/src/main/java/com/keylesspalace/tusky/json/SpannedTypeAdapter.java create mode 100644 app/src/main/java/com/keylesspalace/tusky/json/SpannedTypeAdapter.kt diff --git a/app/src/main/java/com/keylesspalace/tusky/db/Converters.kt b/app/src/main/java/com/keylesspalace/tusky/db/Converters.kt index 09f8a5cbd..3492deda8 100644 --- a/app/src/main/java/com/keylesspalace/tusky/db/Converters.kt +++ b/app/src/main/java/com/keylesspalace/tusky/db/Converters.kt @@ -29,6 +29,7 @@ import com.keylesspalace.tusky.entity.Emoji import com.keylesspalace.tusky.entity.Poll import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.json.SpannedTypeAdapter +import com.keylesspalace.tusky.util.trimTrailingWhitespace import java.net.URLDecoder import java.net.URLEncoder import java.util.* @@ -137,7 +138,7 @@ class Converters { if(spannedString == null) { return null } - return spannedString.parseAsHtml() + return spannedString.parseAsHtml().trimTrailingWhitespace() } @TypeConverter diff --git a/app/src/main/java/com/keylesspalace/tusky/json/SpannedTypeAdapter.java b/app/src/main/java/com/keylesspalace/tusky/json/SpannedTypeAdapter.java deleted file mode 100644 index a884695f8..000000000 --- a/app/src/main/java/com/keylesspalace/tusky/json/SpannedTypeAdapter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright 2017 Andrew Dawson - * - * 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 . */ - -package com.keylesspalace.tusky.json; - -import android.text.Spanned; -import android.text.SpannedString; - -import androidx.core.text.HtmlCompat; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -import java.lang.reflect.Type; - -public class SpannedTypeAdapter implements JsonDeserializer, JsonSerializer { - @Override - public Spanned deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - String string = json.getAsString(); - if (string != null) { - /* Html.fromHtml returns trailing whitespace if the html ends in a

tag, which - * all status contents do, so it should be trimmed. */ - return (Spanned)trimTrailingWhitespace(HtmlCompat.fromHtml(string, HtmlCompat.FROM_HTML_MODE_LEGACY)); - } else { - return new SpannedString(""); - } - } - - @Override - public JsonElement serialize(Spanned src, Type typeOfSrc, JsonSerializationContext context) { - return new JsonPrimitive(HtmlCompat.toHtml(src, HtmlCompat.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL)); - } - - private static CharSequence trimTrailingWhitespace(CharSequence s) { - int i = s.length(); - do { - i--; - } while (i >= 0 && Character.isWhitespace(s.charAt(i))); - return s.subSequence(0, i + 1); - } -} diff --git a/app/src/main/java/com/keylesspalace/tusky/json/SpannedTypeAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/json/SpannedTypeAdapter.kt new file mode 100644 index 000000000..6eabea524 --- /dev/null +++ b/app/src/main/java/com/keylesspalace/tusky/json/SpannedTypeAdapter.kt @@ -0,0 +1,37 @@ +/* Copyright 2020 Tusky Contributors + * + * 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 . */ + +package com.keylesspalace.tusky.json + +import android.text.Spanned +import android.text.SpannedString +import androidx.core.text.HtmlCompat +import androidx.core.text.parseAsHtml +import com.google.gson.* +import com.keylesspalace.tusky.util.trimTrailingWhitespace +import java.lang.reflect.Type + +class SpannedTypeAdapter : JsonDeserializer, JsonSerializer { + @Throws(JsonParseException::class) + override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Spanned { + /* Html.fromHtml returns trailing whitespace if the html ends in a

tag, which + * all status contents do, so it should be trimmed. */ + return json.asString?.parseAsHtml()?.trimTrailingWhitespace() ?: SpannedString("") + } + + override fun serialize(src: Spanned?, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { + return JsonPrimitive(HtmlCompat.toHtml(src!!, HtmlCompat.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt b/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt index 0023a9f88..2cb8a2f49 100644 --- a/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt +++ b/app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt @@ -1,5 +1,6 @@ package com.keylesspalace.tusky.repository +import android.text.Spanned import android.text.SpannedString import androidx.core.text.parseAsHtml import androidx.core.text.toHtml @@ -13,6 +14,7 @@ import com.keylesspalace.tusky.repository.TimelineRequestMode.NETWORK import com.keylesspalace.tusky.util.Either import com.keylesspalace.tusky.util.dec import com.keylesspalace.tusky.util.inc +import com.keylesspalace.tusky.util.trimTrailingWhitespace import io.reactivex.Single import io.reactivex.schedulers.Schedulers import java.io.IOException @@ -214,7 +216,7 @@ class TimelineRepositoryImpl( inReplyToId = status.inReplyToId, inReplyToAccountId = status.inReplyToAccountId, reblog = null, - content = status.content?.parseAsHtml() ?: SpannedString(""), + content = status.content?.parseAsHtml()?.trimTrailingWhitespace() ?: SpannedString(""), createdAt = Date(status.createdAt), emojis = emojis, reblogsCount = status.reblogsCount, @@ -269,7 +271,7 @@ class TimelineRepositoryImpl( inReplyToId = status.inReplyToId, inReplyToAccountId = status.inReplyToAccountId, reblog = null, - content = status.content?.parseAsHtml() ?: SpannedString(""), + content = status.content?.parseAsHtml()?.trimTrailingWhitespace() ?: SpannedString(""), createdAt = Date(status.createdAt), emojis = emojis, reblogsCount = status.reblogsCount, diff --git a/app/src/main/java/com/keylesspalace/tusky/util/StringUtils.kt b/app/src/main/java/com/keylesspalace/tusky/util/StringUtils.kt index 32adaf89c..c7af0ca69 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/StringUtils.kt +++ b/app/src/main/java/com/keylesspalace/tusky/util/StringUtils.kt @@ -2,7 +2,8 @@ package com.keylesspalace.tusky.util -import java.util.Random +import android.text.Spanned +import java.util.* private const val POSSIBLE_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -71,3 +72,11 @@ fun String.isLessThan(other: String): Boolean { else -> this < other } } + +fun Spanned.trimTrailingWhitespace(): Spanned { + var i = length + do { + i-- + } while (i >= 0 && get(i).isWhitespace()) + return subSequence(0, i + 1) as Spanned +}