Skip to content
Snippets Groups Projects
Verified Commit b2f22f0f authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Implemented more tests, added "view spoilers" feature

parent 2081636c
No related branches found
No related tags found
No related merge requests found
Showing
with 359 additions and 46 deletions
...@@ -98,6 +98,10 @@ android { ...@@ -98,6 +98,10 @@ android {
setTargetCompatibility(JavaVersion.VERSION_1_8) setTargetCompatibility(JavaVersion.VERSION_1_8)
} }
testOptions {
unitTests.isIncludeAndroidResources = true
}
lintOptions { lintOptions {
isWarningsAsErrors = true isWarningsAsErrors = true
setLintConfig(file("../lint.xml")) setLintConfig(file("../lint.xml"))
...@@ -182,4 +186,7 @@ dependencies { ...@@ -182,4 +186,7 @@ dependencies {
} }
testImplementation("junit", "junit", "4.12") testImplementation("junit", "junit", "4.12")
testImplementation("org.robolectric", "robolectric", "4.1") {
exclude(group = "org.threeten", module = "threetenbp")
}
} }
...@@ -38,12 +38,11 @@ import de.kuschku.quasseldroid.util.compatibility.AndroidLoggingHandler ...@@ -38,12 +38,11 @@ import de.kuschku.quasseldroid.util.compatibility.AndroidLoggingHandler
import de.kuschku.quasseldroid.util.compatibility.AndroidStreamChannelFactory import de.kuschku.quasseldroid.util.compatibility.AndroidStreamChannelFactory
import de.kuschku.quasseldroid.util.ui.LocaleHelper import de.kuschku.quasseldroid.util.ui.LocaleHelper
class Quasseldroid : DaggerApplication() { open class Quasseldroid : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<Quasseldroid> = override fun applicationInjector(): AndroidInjector<Quasseldroid> =
DaggerAppComponent.builder().create(this) DaggerAppComponent.builder().create(this)
override fun onCreate() { protected open fun init() {
super.onCreate()
if (LeakCanary.isInAnalyzerProcess(this)) { if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis. // This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process. // You should not init your app in this process.
...@@ -232,6 +231,11 @@ class Quasseldroid : DaggerApplication() { ...@@ -232,6 +231,11 @@ class Quasseldroid : DaggerApplication() {
} }
} }
override fun onCreate() {
super.onCreate()
init()
}
override fun attachBaseContext(base: Context) { override fun attachBaseContext(base: Context) {
super.attachBaseContext(LocaleHelper.setLocale(base)) super.attachBaseContext(LocaleHelper.setLocale(base))
} }
......
...@@ -351,7 +351,7 @@ class QuasselNotificationBackend @Inject constructor( ...@@ -351,7 +351,7 @@ class QuasselNotificationBackend @Inject constructor(
selfColor = selfColor selfColor = selfColor
)) ))
} }
val content = contentFormatter.formatContent(it.content, false, it.networkId) val content = contentFormatter.formatContent(it.content, false, false, it.networkId)
NotificationMessage( NotificationMessage(
messageId = it.messageId, messageId = it.messageId,
......
...@@ -250,6 +250,12 @@ class MessageListFragment : ServiceBoundFragment() { ...@@ -250,6 +250,12 @@ class MessageListFragment : ServiceBoundFragment() {
1 -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = true 1 -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = true
else -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = false else -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = false
} }
} else {
val value = viewModel.expandedMessages.value
viewModel.expandedMessages.onNext(
if (value.contains(msg.original.messageId)) value - msg.original.messageId
else value + msg.original.messageId
)
} }
} }
adapter.setOnLongClickListener { msg -> adapter.setOnLongClickListener { msg ->
...@@ -289,14 +295,6 @@ class MessageListFragment : ServiceBoundFragment() { ...@@ -289,14 +295,6 @@ class MessageListFragment : ServiceBoundFragment() {
} }
adapter.setOnUrlLongClickListener(LinkLongClickMenuHelper()) adapter.setOnUrlLongClickListener(LinkLongClickMenuHelper())
adapter.setOnExpansionListener {
val value = viewModel.expandedMessages.value
viewModel.expandedMessages.onNext(
if (value.contains(it.messageId)) value - it.messageId
else value + it.messageId
)
}
messageList.adapter = adapter messageList.adapter = adapter
messageList.layoutManager = linearLayoutManager messageList.layoutManager = linearLayoutManager
messageList.itemAnimator = null messageList.itemAnimator = null
......
...@@ -259,6 +259,7 @@ class QuasselMessageRenderer @Inject constructor( ...@@ -259,6 +259,7 @@ class QuasselMessageRenderer @Inject constructor(
} }
val content = contentFormatter.formatContent(message.content.content, val content = contentFormatter.formatContent(message.content.content,
monochromeForeground, monochromeForeground,
message.isExpanded,
message.content.networkId) message.content.networkId)
val nickName = HostmaskHelper.nick(message.content.sender) val nickName = HostmaskHelper.nick(message.content.sender)
val senderColorIndex = SenderColorUtil.senderColor(nickName) val senderColorIndex = SenderColorUtil.senderColor(nickName)
...@@ -317,6 +318,7 @@ class QuasselMessageRenderer @Inject constructor( ...@@ -317,6 +318,7 @@ class QuasselMessageRenderer @Inject constructor(
contentFormatter.formatNick(message.content.sender, self, monochromeForeground, false), contentFormatter.formatNick(message.content.sender, self, monochromeForeground, false),
contentFormatter.formatContent(message.content.content, contentFormatter.formatContent(message.content.content,
monochromeForeground, monochromeForeground,
message.isExpanded,
message.content.networkId) message.content.networkId)
), ),
avatarUrls = AvatarHelper.avatar(messageSettings, message.content, avatarSize), avatarUrls = AvatarHelper.avatar(messageSettings, message.content, avatarSize),
...@@ -337,6 +339,7 @@ class QuasselMessageRenderer @Inject constructor( ...@@ -337,6 +339,7 @@ class QuasselMessageRenderer @Inject constructor(
contentFormatter.formatNick(message.content.sender, self, monochromeForeground, false), contentFormatter.formatNick(message.content.sender, self, monochromeForeground, false),
contentFormatter.formatContent(message.content.content, contentFormatter.formatContent(message.content.content,
monochromeForeground, monochromeForeground,
message.isExpanded,
message.content.networkId) message.content.networkId)
), ),
hasDayChange = message.hasDayChange, hasDayChange = message.hasDayChange,
...@@ -448,6 +451,7 @@ class QuasselMessageRenderer @Inject constructor( ...@@ -448,6 +451,7 @@ class QuasselMessageRenderer @Inject constructor(
), ),
contentFormatter.formatContent(message.content.content, contentFormatter.formatContent(message.content.content,
monochromeForeground, monochromeForeground,
message.isExpanded,
message.content.networkId) message.content.networkId)
) )
}, },
...@@ -483,6 +487,7 @@ class QuasselMessageRenderer @Inject constructor( ...@@ -483,6 +487,7 @@ class QuasselMessageRenderer @Inject constructor(
), ),
contentFormatter.formatContent(message.content.content, contentFormatter.formatContent(message.content.content,
monochromeForeground, monochromeForeground,
message.isExpanded,
message.content.networkId) message.content.networkId)
) )
}, },
...@@ -518,6 +523,7 @@ class QuasselMessageRenderer @Inject constructor( ...@@ -518,6 +523,7 @@ class QuasselMessageRenderer @Inject constructor(
false), false),
contentFormatter.formatContent(reason, contentFormatter.formatContent(reason,
monochromeForeground, monochromeForeground,
message.isExpanded,
message.content.networkId) message.content.networkId)
) )
}, },
...@@ -554,6 +560,7 @@ class QuasselMessageRenderer @Inject constructor( ...@@ -554,6 +560,7 @@ class QuasselMessageRenderer @Inject constructor(
false), false),
contentFormatter.formatContent(reason, contentFormatter.formatContent(reason,
monochromeForeground, monochromeForeground,
message.isExpanded,
message.content.networkId) message.content.networkId)
) )
}, },
...@@ -623,6 +630,7 @@ class QuasselMessageRenderer @Inject constructor( ...@@ -623,6 +630,7 @@ class QuasselMessageRenderer @Inject constructor(
dayChange = formatDayChange(message), dayChange = formatDayChange(message),
combined = contentFormatter.formatContent(message.content.content, combined = contentFormatter.formatContent(message.content.content,
monochromeForeground, monochromeForeground,
message.isExpanded,
message.content.networkId), message.content.networkId),
hasDayChange = message.hasDayChange, hasDayChange = message.hasDayChange,
isMarkerLine = message.isMarkerLine, isMarkerLine = message.isMarkerLine,
...@@ -635,6 +643,7 @@ class QuasselMessageRenderer @Inject constructor( ...@@ -635,6 +643,7 @@ class QuasselMessageRenderer @Inject constructor(
dayChange = formatDayChange(message), dayChange = formatDayChange(message),
combined = contentFormatter.formatContent(message.content.content, combined = contentFormatter.formatContent(message.content.content,
monochromeForeground, monochromeForeground,
message.isExpanded,
message.content.networkId), message.content.networkId),
hasDayChange = message.hasDayChange, hasDayChange = message.hasDayChange,
isMarkerLine = message.isMarkerLine, isMarkerLine = message.isMarkerLine,
...@@ -657,6 +666,7 @@ class QuasselMessageRenderer @Inject constructor( ...@@ -657,6 +666,7 @@ class QuasselMessageRenderer @Inject constructor(
dayChange = formatDayChange(message), dayChange = formatDayChange(message),
combined = contentFormatter.formatContent(message.content.content, combined = contentFormatter.formatContent(message.content.content,
monochromeForeground, monochromeForeground,
message.isExpanded,
message.content.networkId), message.content.networkId),
hasDayChange = message.hasDayChange, hasDayChange = message.hasDayChange,
isMarkerLine = message.isMarkerLine, isMarkerLine = message.isMarkerLine,
......
...@@ -24,10 +24,7 @@ import android.graphics.Typeface ...@@ -24,10 +24,7 @@ import android.graphics.Typeface
import android.text.SpannableString import android.text.SpannableString
import android.text.Spanned import android.text.Spanned
import android.text.TextPaint import android.text.TextPaint
import android.text.style.ClickableSpan import android.text.style.*
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.text.style.URLSpan
import android.view.View import android.view.View
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import de.kuschku.libquassel.protocol.NetworkId import de.kuschku.libquassel.protocol.NetworkId
...@@ -37,6 +34,8 @@ import de.kuschku.quasseldroid.R ...@@ -37,6 +34,8 @@ import de.kuschku.quasseldroid.R
import de.kuschku.quasseldroid.settings.MessageSettings import de.kuschku.quasseldroid.settings.MessageSettings
import de.kuschku.quasseldroid.ui.chat.ChatActivity import de.kuschku.quasseldroid.ui.chat.ChatActivity
import de.kuschku.quasseldroid.util.helper.styledAttributes import de.kuschku.quasseldroid.util.helper.styledAttributes
import de.kuschku.quasseldroid.util.irc.format.spans.IrcBackgroundColorSpan
import de.kuschku.quasseldroid.util.irc.format.spans.IrcForegroundColorSpan
import de.kuschku.quasseldroid.util.ui.SpanFormatter import de.kuschku.quasseldroid.util.ui.SpanFormatter
import org.intellij.lang.annotations.Language import org.intellij.lang.annotations.Language
import javax.inject.Inject import javax.inject.Inject
...@@ -110,10 +109,34 @@ class ContentFormatter @Inject constructor( ...@@ -110,10 +109,34 @@ class ContentFormatter @Inject constructor(
fun formatContent(content: String, fun formatContent(content: String,
highlight: Boolean = false, highlight: Boolean = false,
showSpoilers: Boolean = false,
networkId: NetworkId?): CharSequence { networkId: NetworkId?): CharSequence {
val formattedText = ircFormatDeserializer.formatString(content, messageSettings.colorizeMirc) val formattedText = ircFormatDeserializer.formatString(content, messageSettings.colorizeMirc)
val text = SpannableString(formattedText) val text = SpannableString(formattedText)
if (showSpoilers) {
val spans = mutableMapOf<Triple<Int, Int, Int>, MutableList<Any>>()
for (span in text.getSpans(0, text.length, IrcForegroundColorSpan::class.java)) {
val from = text.getSpanStart(span)
val to = text.getSpanEnd(span)
spans.getOrPut(Triple(from, to, span.getForegroundColor()), ::mutableListOf).add(span)
}
for (span in text.getSpans(0, text.length, IrcBackgroundColorSpan::class.java)) {
val from = text.getSpanStart(span)
val to = text.getSpanEnd(span)
spans.getOrPut(Triple(from, to, span.getBackgroundColor()), ::mutableListOf).add(span)
}
for (group in spans.values) {
if (group.size > 1 &&
group.any { it is ForegroundColorSpan } &&
group.any { it is BackgroundColorSpan }) {
for (span in group) {
text.removeSpan(span)
}
}
}
}
for (result in urlPattern.findAll(formattedText)) { for (result in urlPattern.findAll(formattedText)) {
val group = result.groups[1] val group = result.groups[1]
if (group != null) { if (group != null) {
......
...@@ -32,8 +32,10 @@ import javax.inject.Inject ...@@ -32,8 +32,10 @@ import javax.inject.Inject
* A helper class to turn mIRC formatted Strings into Android’s SpannableStrings with the same * A helper class to turn mIRC formatted Strings into Android’s SpannableStrings with the same
* color and format codes * color and format codes
*/ */
class IrcFormatDeserializer @Inject constructor(context: Context) { class IrcFormatDeserializer(private val mircColors: IntArray) {
private val mircColors = listOf( @Inject
constructor(context: Context) : this(
mircColors = listOf(
R.color.mircColor00, R.color.mircColor01, R.color.mircColor02, R.color.mircColor03, R.color.mircColor00, R.color.mircColor01, R.color.mircColor02, R.color.mircColor03,
R.color.mircColor04, R.color.mircColor05, R.color.mircColor06, R.color.mircColor07, R.color.mircColor04, R.color.mircColor05, R.color.mircColor06, R.color.mircColor07,
R.color.mircColor08, R.color.mircColor09, R.color.mircColor10, R.color.mircColor11, R.color.mircColor08, R.color.mircColor09, R.color.mircColor10, R.color.mircColor11,
...@@ -60,6 +62,7 @@ class IrcFormatDeserializer @Inject constructor(context: Context) { ...@@ -60,6 +62,7 @@ class IrcFormatDeserializer @Inject constructor(context: Context) {
R.color.mircColor92, R.color.mircColor93, R.color.mircColor94, R.color.mircColor95, R.color.mircColor92, R.color.mircColor93, R.color.mircColor94, R.color.mircColor95,
R.color.mircColor96, R.color.mircColor97, R.color.mircColor98 R.color.mircColor96, R.color.mircColor97, R.color.mircColor98
).map(context::getColorCompat).toIntArray() ).map(context::getColorCompat).toIntArray()
)
/** /**
* Function to handle mIRC formatted strings * Function to handle mIRC formatted strings
...@@ -274,6 +277,8 @@ class IrcFormatDeserializer @Inject constructor(context: Context) { ...@@ -274,6 +277,8 @@ class IrcFormatDeserializer @Inject constructor(context: Context) {
i++ i++
} }
plainText.append(str.substring(str.length - normalCount, str.length))
// End all formatting tags // End all formatting tags
if (bold != null) { if (bold != null) {
if (colorize) bold.apply(plainText, plainText.length) if (colorize) bold.apply(plainText, plainText.length)
...@@ -296,7 +301,6 @@ class IrcFormatDeserializer @Inject constructor(context: Context) { ...@@ -296,7 +301,6 @@ class IrcFormatDeserializer @Inject constructor(context: Context) {
if (hexColor != null) { if (hexColor != null) {
if (colorize) hexColor.apply(plainText, plainText.length) if (colorize) hexColor.apply(plainText, plainText.length)
} }
plainText.append(str.substring(str.length - normalCount, str.length))
return plainText return plainText
} }
......
...@@ -27,10 +27,26 @@ sealed class IrcBackgroundColorSpan<T : IrcBackgroundColorSpan<T>>(@ColorInt col ...@@ -27,10 +27,26 @@ sealed class IrcBackgroundColorSpan<T : IrcBackgroundColorSpan<T>>(@ColorInt col
class MIRC(private val mircColor: Int, @ColorInt color: Int) : class MIRC(private val mircColor: Int, @ColorInt color: Int) :
IrcBackgroundColorSpan<MIRC>(color), Copyable<MIRC> { IrcBackgroundColorSpan<MIRC>(color), Copyable<MIRC> {
override fun copy() = MIRC(mircColor, backgroundColor) override fun copy() = MIRC(mircColor, backgroundColor)
override fun toString(): String {
return "IrcBackgroundColorSpan.MIRC(mircColor=$mircColor, color=${backgroundColor.toString(16)})"
}
override fun equals(other: Any?) = when (other) {
is IrcBackgroundColorSpan.MIRC -> other.mircColor == mircColor
else -> false
}
} }
class HEX(@ColorInt color: Int) : class HEX(@ColorInt color: Int) :
IrcBackgroundColorSpan<HEX>(color), Copyable<HEX> { IrcBackgroundColorSpan<HEX>(color), Copyable<HEX> {
override fun copy() = HEX(backgroundColor) override fun copy() = HEX(backgroundColor)
override fun toString(): String {
return "IrcBackgroundColorSpan.HEX(color=${backgroundColor.toString(16)})"
}
override fun equals(other: Any?) = when (other) {
is IrcBackgroundColorSpan.HEX -> other.backgroundColor == backgroundColor
else -> false
}
} }
} }
...@@ -24,4 +24,5 @@ import android.text.style.StyleSpan ...@@ -24,4 +24,5 @@ import android.text.style.StyleSpan
class IrcBoldSpan : StyleSpan(Typeface.BOLD), Copyable<IrcBoldSpan> { class IrcBoldSpan : StyleSpan(Typeface.BOLD), Copyable<IrcBoldSpan> {
override fun copy() = IrcBoldSpan() override fun copy() = IrcBoldSpan()
override fun equals(other: Any?) = other is IrcBoldSpan
} }
...@@ -24,13 +24,31 @@ import androidx.annotation.ColorInt ...@@ -24,13 +24,31 @@ import androidx.annotation.ColorInt
sealed class IrcForegroundColorSpan<T : IrcForegroundColorSpan<T>>(@ColorInt color: Int) : sealed class IrcForegroundColorSpan<T : IrcForegroundColorSpan<T>>(@ColorInt color: Int) :
ForegroundColorSpan(color), Copyable<T> { ForegroundColorSpan(color), Copyable<T> {
class MIRC(private val mircColor: Int, @ColorInt color: Int) : class MIRC(private val mircColor: Int, @ColorInt color: Int) :
IrcForegroundColorSpan<MIRC>(color), Copyable<MIRC> { IrcForegroundColorSpan<MIRC>(color), Copyable<MIRC> {
override fun copy() = MIRC(mircColor, foregroundColor) override fun copy() = MIRC(mircColor, foregroundColor)
override fun toString(): String {
return "IrcForegroundColorSpan.MIRC(mircColor=$mircColor, color=${foregroundColor.toString(16)})"
}
override fun equals(other: Any?) = when (other) {
is MIRC -> other.mircColor == mircColor
else -> false
}
} }
class HEX(@ColorInt color: Int) : class HEX(@ColorInt color: Int) :
IrcForegroundColorSpan<HEX>(color), Copyable<HEX> { IrcForegroundColorSpan<HEX>(color), Copyable<HEX> {
override fun copy() = HEX(foregroundColor) override fun copy() = HEX(foregroundColor)
override fun toString(): String {
return "IrcBackgroundColorSpan.HEX(color=${foregroundColor.toString(16)})"
}
override fun equals(other: Any?) = when (other) {
is HEX -> other.foregroundColor == foregroundColor
else -> false
}
} }
} }
...@@ -24,4 +24,5 @@ import android.text.style.StyleSpan ...@@ -24,4 +24,5 @@ import android.text.style.StyleSpan
class IrcItalicSpan : StyleSpan(Typeface.ITALIC), Copyable<IrcItalicSpan> { class IrcItalicSpan : StyleSpan(Typeface.ITALIC), Copyable<IrcItalicSpan> {
override fun copy() = IrcItalicSpan() override fun copy() = IrcItalicSpan()
override fun equals(other: Any?) = other is IrcBoldSpan
} }
...@@ -23,4 +23,5 @@ import android.text.style.TypefaceSpan ...@@ -23,4 +23,5 @@ import android.text.style.TypefaceSpan
class IrcMonospaceSpan : TypefaceSpan("monospace"), Copyable<IrcMonospaceSpan> { class IrcMonospaceSpan : TypefaceSpan("monospace"), Copyable<IrcMonospaceSpan> {
override fun copy() = IrcMonospaceSpan() override fun copy() = IrcMonospaceSpan()
override fun equals(other: Any?) = other is IrcBoldSpan
} }
...@@ -23,4 +23,5 @@ import android.text.style.StrikethroughSpan ...@@ -23,4 +23,5 @@ import android.text.style.StrikethroughSpan
class IrcStrikethroughSpan : StrikethroughSpan(), Copyable<IrcStrikethroughSpan> { class IrcStrikethroughSpan : StrikethroughSpan(), Copyable<IrcStrikethroughSpan> {
override fun copy() = IrcStrikethroughSpan() override fun copy() = IrcStrikethroughSpan()
override fun equals(other: Any?) = other is IrcBoldSpan
} }
...@@ -23,4 +23,5 @@ import android.text.style.UnderlineSpan ...@@ -23,4 +23,5 @@ import android.text.style.UnderlineSpan
class IrcUnderlineSpan : UnderlineSpan(), Copyable<IrcUnderlineSpan> { class IrcUnderlineSpan : UnderlineSpan(), Copyable<IrcUnderlineSpan> {
override fun copy() = IrcUnderlineSpan() override fun copy() = IrcUnderlineSpan()
override fun equals(other: Any?) = other is IrcBoldSpan
} }
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2019 Janne Koschinski
* Copyright (c) 2019 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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 de.kuschku.quasseldroid
class QuasseldroidTest : Quasseldroid() {
override fun init() {
applicationInjector().inject(this)
}
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2019 Janne Koschinski
* Copyright (c) 2019 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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 de.kuschku.quasseldroid.util.irc.format
import android.text.Spanned
import android.text.SpannedString
import de.kuschku.quasseldroid.QuasseldroidTest
import de.kuschku.quasseldroid.util.irc.format.spans.IrcBackgroundColorSpan
import de.kuschku.quasseldroid.util.irc.format.spans.IrcForegroundColorSpan
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@Config(application = QuasseldroidTest::class)
@RunWith(RobolectricTestRunner::class)
class IrcFormatDeserializerTest {
lateinit var deserializer: IrcFormatDeserializer
@Before
fun setUp() {
deserializer = IrcFormatDeserializer(mircColors = colors)
}
@Test
fun testMissingEndTag() {
val text = SpannedString.valueOf(deserializer.formatString(
"\u000301,01weeeeeeeeee",
colorize = true
))
assertEquals(
listOf(
SpanInfo(
from = 0,
to = 11,
flags = Spanned.SPAN_INCLUSIVE_EXCLUSIVE,
span = IrcForegroundColorSpan.MIRC(mircColor = 1, color = colors[1])
),
SpanInfo(
from = 0,
to = 11,
flags = Spanned.SPAN_INCLUSIVE_EXCLUSIVE,
span = IrcBackgroundColorSpan.MIRC(mircColor = 1, color = colors[1])
)
),
text.allSpans<Any>()
)
}
inline fun <reified T> Spanned.allSpans(): List<SpanInfo> =
getSpans(0, length, T::class.java).map {
SpanInfo(
from = getSpanStart(it),
to = getSpanEnd(it),
flags = getSpanFlags(it),
span = it
)
}
data class SpanInfo(
val from: Int,
val to: Int,
val flags: Int,
val span: Any?
)
companion object {
val colors = intArrayOf(
0x00ffffff,
0x00000000,
0x00000080,
0x00008000,
0x00ff0000,
0x00800000,
0x00800080,
0x00ffa500,
0x00ffff00,
0x0000ff00,
0x00008080,
0x0000ffff,
0x004169e1,
0x00ff00ff,
0x00808080,
0x00c0c0c0,
0x00470000,
0x00740000,
0x00b50000,
0x00ff0000,
0x00ff5959,
0x00ff9c9c,
0x00472100,
0x00743a00,
0x00b56300,
0x00ff8c00,
0x00ffb459,
0x00ffd39c,
0x00474700,
0x00747400,
0x00b5b500,
0x00ffff00,
0x00ffff71,
0x00ffff9c,
0x00324700,
0x00517400,
0x007db500,
0x00b2ff00,
0x00cfff60,
0x00e2ff9c,
0x00004700,
0x00007400,
0x0000b500,
0x0000ff00,
0x006fff6f,
0x009cff9c,
0x0000472c,
0x00007449,
0x0000b571,
0x0000ffa0,
0x0065ffc9,
0x009cffdb,
0x00004747,
0x00007474,
0x0000b5b5,
0x0000ffff,
0x006dffff,
0x009cffff,
0x00002747,
0x00004074,
0x000063b5,
0x00008cff,
0x0059b4ff,
0x009cd3ff,
0x00000047,
0x00000074,
0x000000b5,
0x000000ff,
0x005959ff,
0x009c9cff,
0x002e0047,
0x004b0074,
0x007500b5,
0x00a500ff,
0x00c459ff,
0x00dc9cff,
0x00470047,
0x00740074,
0x00b500b5,
0x00ff00ff,
0x00ff66ff,
0x00ff9cff,
0x0047002a,
0x00740045,
0x00b5006b,
0x00ff0098,
0x00ff59bc,
0x00ff94d3,
0x00000000,
0x00131313,
0x00282828,
0x00363636,
0x004d4d4d,
0x00656565,
0x00818181,
0x009f9f9f,
0x00bcbcbc,
0x00e2e2e2,
0x00ffffff
)
}
}
...@@ -33,7 +33,7 @@ android.enableD8=true ...@@ -33,7 +33,7 @@ android.enableD8=true
# Enable new Android R8 Optimizer # Enable new Android R8 Optimizer
android.enableR8=true android.enableR8=true
# Enable gradle build cache # Enable gradle build cache
org.gradle.caching=false org.gradle.caching=true
# Enable android build cache # Enable android build cache
android.enableBuildCache=true android.enableBuildCache=true
# Enable AndroidX # Enable AndroidX
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment