From 077d57be77e70e37ff11493ac3385ea1b8d26140 Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Sun, 25 Feb 2018 03:28:57 +0100 Subject: [PATCH] Properly read and write new format options - Strikethrough - Monospace - Hex colors (only read) --- .../quasseldroid_ng/ui/chat/ChatActivity.kt | 10 +- .../util/irc/format/IrcFormatDeserializer.kt | 209 +++++++++++++--- .../util/irc/format/IrcFormatSerializer.kt | 65 ++++- .../util/irc/format/spans/IrcHexColorSpan.kt | 9 + .../util/irc/format/spans/IrcMonospaceSpan.kt | 7 + .../irc/format/spans/IrcStrikethroughSpan.kt | 7 + app/src/main/res/values/attrs.xml | 115 +++++++-- app/src/main/res/values/themes_base.xml | 230 +++++++++++++++--- 8 files changed, 560 insertions(+), 92 deletions(-) create mode 100644 app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcHexColorSpan.kt create mode 100644 app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcMonospaceSpan.kt create mode 100644 app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcStrikethroughSpan.kt diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt index 3b1f64e2e..dfa0c43ea 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt @@ -1,5 +1,6 @@ package de.kuschku.quasseldroid_ng.ui.chat +import android.annotation.TargetApi import android.app.Activity import android.arch.lifecycle.Observer import android.arch.lifecycle.ViewModelProviders @@ -38,6 +39,7 @@ import de.kuschku.quasseldroid_ng.util.helper.editApply import de.kuschku.quasseldroid_ng.util.helper.invoke import de.kuschku.quasseldroid_ng.util.helper.let import de.kuschku.quasseldroid_ng.util.helper.sharedPreferences +import de.kuschku.quasseldroid_ng.util.irc.format.IrcFormatSerializer import de.kuschku.quasseldroid_ng.util.service.ServiceBoundActivity import de.kuschku.quasseldroid_ng.util.ui.MaterialContentLoadingProgressBar @@ -72,6 +74,8 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc private lateinit var backlogSettings: BacklogSettings + private lateinit var ircFormatSerializer: IrcFormatSerializer + private val panelSlideListener: SlidingUpPanelLayout.PanelSlideListener = object : SlidingUpPanelLayout.PanelSlideListener { override fun onPanelSlide(panel: View?, slideOffset: Float) = Unit @@ -102,6 +106,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc viewModel = ViewModelProviders.of(this)[QuasselViewModel::class.java] viewModel.setBackend(this.backend) backlogSettings = Settings.backlog(this) + ircFormatSerializer = IrcFormatSerializer(this) database = QuasselDatabase.Creator.init(application) @@ -162,7 +167,9 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc viewModel.session { session -> viewModel.getBuffer().let { bufferId -> session.bufferSyncer?.bufferInfo(bufferId)?.also { bufferInfo -> - session.rpcHandler?.sendInput(bufferInfo, chatline.text.toString()) + session.rpcHandler?.sendInput( + bufferInfo, ircFormatSerializer.toEscapeCodes(chatline.text) + ) } } } @@ -186,6 +193,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc viewModel.setBuffer(savedInstanceState?.getInt("OPEN_BUFFER", -1) ?: -1) } + @TargetApi(Build.VERSION_CODES.LOLLIPOP) override fun onRestoreInstanceState(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { super.onRestoreInstanceState(savedInstanceState, persistentState) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/IrcFormatDeserializer.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/IrcFormatDeserializer.kt index 4a7f9048b..c8e8c56c9 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/IrcFormatDeserializer.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/IrcFormatDeserializer.kt @@ -25,20 +25,46 @@ package de.kuschku.quasseldroid_ng.util.irc.format import android.content.Context import android.text.SpannableStringBuilder import android.text.Spanned -import android.text.style.UnderlineSpan import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.util.helper.styledAttributes -import de.kuschku.quasseldroid_ng.util.irc.format.spans.IrcBackgroundColorSpan -import de.kuschku.quasseldroid_ng.util.irc.format.spans.IrcBoldSpan -import de.kuschku.quasseldroid_ng.util.irc.format.spans.IrcForegroundColorSpan -import de.kuschku.quasseldroid_ng.util.irc.format.spans.IrcItalicSpan -import java.util.* +import de.kuschku.quasseldroid_ng.util.irc.format.spans.* /** * A helper class to turn mIRC formatted Strings into Android’s SpannableStrings with the same * color and format codes */ class IrcFormatDeserializer(private val context: Context) { + val mircColors = context.theme.styledAttributes( + R.attr.mircColor00, R.attr.mircColor01, R.attr.mircColor02, R.attr.mircColor03, + R.attr.mircColor04, R.attr.mircColor05, R.attr.mircColor06, R.attr.mircColor07, + R.attr.mircColor08, R.attr.mircColor09, R.attr.mircColor10, R.attr.mircColor11, + R.attr.mircColor12, R.attr.mircColor13, R.attr.mircColor14, R.attr.mircColor15, + R.attr.mircColor16, R.attr.mircColor17, R.attr.mircColor18, R.attr.mircColor19, + R.attr.mircColor20, R.attr.mircColor21, R.attr.mircColor22, R.attr.mircColor23, + R.attr.mircColor24, R.attr.mircColor25, R.attr.mircColor26, R.attr.mircColor27, + R.attr.mircColor28, R.attr.mircColor29, R.attr.mircColor30, R.attr.mircColor31, + R.attr.mircColor32, R.attr.mircColor33, R.attr.mircColor34, R.attr.mircColor35, + R.attr.mircColor36, R.attr.mircColor37, R.attr.mircColor38, R.attr.mircColor39, + R.attr.mircColor40, R.attr.mircColor41, R.attr.mircColor42, R.attr.mircColor43, + R.attr.mircColor44, R.attr.mircColor45, R.attr.mircColor46, R.attr.mircColor47, + R.attr.mircColor48, R.attr.mircColor49, R.attr.mircColor50, R.attr.mircColor51, + R.attr.mircColor52, R.attr.mircColor53, R.attr.mircColor54, R.attr.mircColor55, + R.attr.mircColor56, R.attr.mircColor57, R.attr.mircColor58, R.attr.mircColor59, + R.attr.mircColor60, R.attr.mircColor61, R.attr.mircColor62, R.attr.mircColor63, + R.attr.mircColor64, R.attr.mircColor65, R.attr.mircColor66, R.attr.mircColor67, + R.attr.mircColor68, R.attr.mircColor69, R.attr.mircColor70, R.attr.mircColor71, + R.attr.mircColor72, R.attr.mircColor73, R.attr.mircColor74, R.attr.mircColor75, + R.attr.mircColor76, R.attr.mircColor77, R.attr.mircColor78, R.attr.mircColor79, + R.attr.mircColor80, R.attr.mircColor81, R.attr.mircColor82, R.attr.mircColor83, + R.attr.mircColor84, R.attr.mircColor85, R.attr.mircColor86, R.attr.mircColor87, + R.attr.mircColor88, R.attr.mircColor89, R.attr.mircColor90, R.attr.mircColor91, + R.attr.mircColor92, R.attr.mircColor93, R.attr.mircColor94, R.attr.mircColor95, + R.attr.mircColor96, R.attr.mircColor97, R.attr.mircColor98 + ) { + IntArray(99) { + getColor(it, 0) + } + } /** * Function to handle mIRC formatted strings @@ -53,7 +79,10 @@ class IrcFormatDeserializer(private val context: Context) { var bold: FormatDescription? = null var italic: FormatDescription? = null var underline: FormatDescription? = null + var strikethrough: FormatDescription? = null + var monospace: FormatDescription? = null var color: FormatDescription? = null + var hexColor: FormatDescription? = null // Iterating over every character var normalCount = 0 @@ -61,7 +90,7 @@ class IrcFormatDeserializer(private val context: Context) { while (i < str.length) { val character = str[i] when (character) { - CODE_BOLD -> { + CODE_BOLD -> { plainText.append(str.substring(i - normalCount, i)) normalCount = 0 @@ -89,7 +118,7 @@ class IrcFormatDeserializer(private val context: Context) { italic = FormatDescription(plainText.length, format!!) } } - CODE_UNDERLINE -> { + CODE_UNDERLINE -> { plainText.append(str.substring(i - normalCount, i)) normalCount = 0 @@ -103,7 +132,35 @@ class IrcFormatDeserializer(private val context: Context) { underline = FormatDescription(plainText.length, format!!) } } - CODE_COLOR -> { + CODE_STRIKETHROUGH -> { + plainText.append(str.substring(i - normalCount, i)) + normalCount = 0 + + // If there is an element on stack with the same code, close it + if (strikethrough != null) { + if (colorize) strikethrough.apply(plainText, plainText.length) + strikethrough = null + // Otherwise create a new one + } else { + val format = fromId(character) + strikethrough = FormatDescription(plainText.length, format!!) + } + } + CODE_MONOSPACE -> { + plainText.append(str.substring(i - normalCount, i)) + normalCount = 0 + + // If there is an element on stack with the same code, close it + if (monospace != null) { + if (colorize) monospace.apply(plainText, plainText.length) + monospace = null + // Otherwise create a new one + } else { + val format = fromId(character) + monospace = FormatDescription(plainText.length, format!!) + } + } + CODE_COLOR -> { plainText.append(str.substring(i - normalCount, i)) normalCount = 0 @@ -140,7 +197,28 @@ class IrcFormatDeserializer(private val context: Context) { color = null } } - CODE_SWAP -> { + CODE_HEXCOLOR -> { + plainText.append(str.substring(i - normalCount, i)) + normalCount = 0 + + val colorStart = i + 1 + val colorEnd = findEndOfHexNumber(str, colorStart) + // If we have a foreground element + if (colorEnd > colorStart) { + val foreground = readHexNumber(str, colorStart, colorEnd) + // Add new format + hexColor = FormatDescription(plainText.length, ColorHexFormat(foreground)) + + // i points in front of the next character + i = colorEnd - 1 + + // Otherwise assume this is a closing tag + } else if (hexColor != null) { + if (colorize) hexColor.apply(plainText, plainText.length) + hexColor = null + } + } + CODE_SWAP -> { plainText.append(str.substring(i - normalCount, i)) normalCount = 0 @@ -152,7 +230,7 @@ class IrcFormatDeserializer(private val context: Context) { ) } } - CODE_RESET -> { + CODE_RESET -> { plainText.append(str.substring(i - normalCount, i)) normalCount = 0 @@ -224,7 +302,7 @@ class IrcFormatDeserializer(private val context: Context) { private class UnderlineIrcFormat : IrcFormat { override fun applyTo(editable: SpannableStringBuilder, from: Int, to: Int) { - editable.setSpan(UnderlineSpan(), from, to, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) + editable.setSpan(IrcUnderlineSpan(), from, to, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) } override fun id(): Byte { @@ -232,6 +310,26 @@ class IrcFormatDeserializer(private val context: Context) { } } + private class StrikethroughIrcFormat : IrcFormat { + override fun applyTo(editable: SpannableStringBuilder, from: Int, to: Int) { + editable.setSpan(IrcStrikethroughSpan(), from, to, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) + } + + override fun id(): Byte { + return CODE_STRIKETHROUGH.toByte() + } + } + + private class MonospaceIrcFormat : IrcFormat { + override fun applyTo(editable: SpannableStringBuilder, from: Int, to: Int) { + editable.setSpan(IrcMonospaceSpan(), from, to, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) + } + + override fun id(): Byte { + return CODE_MONOSPACE.toByte() + } + } + private class BoldIrcFormat : IrcFormat { override fun applyTo(editable: SpannableStringBuilder, from: Int, to: Int) { editable.setSpan(IrcBoldSpan(), from, to, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) @@ -242,29 +340,32 @@ class IrcFormatDeserializer(private val context: Context) { } } - private inner class ColorIrcFormat(val foreground: Byte, val background: Byte) : IrcFormat { + private inner class ColorHexFormat(val color: Int) : IrcFormat { override fun applyTo(editable: SpannableStringBuilder, from: Int, to: Int) { - val mircColors = context.theme.styledAttributes( - R.attr.mircColor0, R.attr.mircColor1, R.attr.mircColor2, R.attr.mircColor3, - R.attr.mircColor4, R.attr.mircColor5, R.attr.mircColor6, R.attr.mircColor7, - R.attr.mircColor8, R.attr.mircColor9, R.attr.mircColorA, R.attr.mircColorB, - R.attr.mircColorC, R.attr.mircColorD, R.attr.mircColorE, R.attr.mircColorF - ) { - IntArray(16) { - getColor(it, 0) - } - } + editable.setSpan( + IrcHexColorSpan(color), from, to, + Spanned.SPAN_INCLUSIVE_EXCLUSIVE + ) + } - if (foreground.toInt() != -1 && foreground.toInt() != 99) { + override fun id(): Byte { + return CODE_HEXCOLOR.toByte() + } + } + + private inner class ColorIrcFormat(val foreground: Byte, val background: Byte) : IrcFormat { + + override fun applyTo(editable: SpannableStringBuilder, from: Int, to: Int) { + if (foreground.toInt() > 0 && foreground.toInt() < mircColors.size) { editable.setSpan( - IrcForegroundColorSpan(foreground.toInt(), mircColors[foreground % 16]), from, to, + IrcForegroundColorSpan(foreground.toInt(), mircColors[foreground.toInt()]), from, to, Spanned.SPAN_INCLUSIVE_EXCLUSIVE ) } - if (background.toInt() != -1 && background.toInt() != 99) { + if (background.toInt() > 0 && background.toInt() < mircColors.size) { editable.setSpan( - IrcBackgroundColorSpan(background.toInt(), mircColors[background % 16]), from, to, + IrcBackgroundColorSpan(background.toInt(), mircColors[background.toInt()]), from, to, Spanned.SPAN_INCLUSIVE_EXCLUSIVE ) } @@ -282,8 +383,11 @@ class IrcFormatDeserializer(private val context: Context) { companion object { val CODE_BOLD = 0x02.toChar() val CODE_COLOR = 0x03.toChar() + val CODE_HEXCOLOR = 0x04.toChar() val CODE_ITALIC = 0x1D.toChar() val CODE_UNDERLINE = 0x1F.toChar() + val CODE_STRIKETHROUGH = 0x1E.toChar() + val CODE_MONOSPACE = 0x11.toChar() val CODE_SWAP = 0x16.toChar() val CODE_RESET = 0x0F.toChar() @@ -300,7 +404,23 @@ class IrcFormatDeserializer(private val context: Context) { return if (result.isEmpty()) -1 else - Integer.parseInt(result, 10).toByte() + result.toByteOrNull(10) ?: -1 + } + + /** + * Try to read a number from a String in specified bounds + * + * @param str String to be read from + * @param start Start index (inclusive) + * @param end End index (exclusive) + * @return The byte represented by the digits read from the string + */ + fun readHexNumber(str: String, start: Int, end: Int): Int { + val result = str.substring(start, end) + return if (result.isEmpty()) + -1 + else + result.toIntOrNull(16) ?: -1 } /** @@ -309,7 +429,7 @@ class IrcFormatDeserializer(private val context: Context) { * @return Index of first character that is not a digit */ private fun findEndOfNumber(str: String, start: Int): Int { - val validCharCodes = HashSet(Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) + val validCharCodes = setOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9') val searchFrame = str.substring(start) var i = 0 while (i < 2 && i < searchFrame.length) { @@ -321,11 +441,34 @@ class IrcFormatDeserializer(private val context: Context) { return start + i } + /** + * @param str String to be searched in + * @param start Start position (inclusive) + * @return Index of first character that is not a digit + */ + private fun findEndOfHexNumber(str: String, start: Int): Int { + val validCharCodes = setOf( + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', + 'c', 'd', 'e', 'f' + ) + val searchFrame = str.substring(start) + var i = 0 + while (i < 6 && i < searchFrame.length) { + if (!validCharCodes.contains(searchFrame[i])) { + break + } + i++ + } + return start + i + } + private fun fromId(id: Char) = when (id) { - CODE_BOLD -> BoldIrcFormat() - CODE_ITALIC -> ItalicIrcFormat() - CODE_UNDERLINE -> UnderlineIrcFormat() - else -> null + CODE_BOLD -> BoldIrcFormat() + CODE_ITALIC -> ItalicIrcFormat() + CODE_UNDERLINE -> UnderlineIrcFormat() + CODE_STRIKETHROUGH -> StrikethroughIrcFormat() + CODE_MONOSPACE -> MonospaceIrcFormat() + else -> null } } } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/IrcFormatSerializer.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/IrcFormatSerializer.kt index 5914434b0..70d7c4348 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/IrcFormatSerializer.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/IrcFormatSerializer.kt @@ -2,19 +2,44 @@ package de.kuschku.quasseldroid_ng.util.irc.format import android.content.Context import android.text.Spanned -import android.text.style.BackgroundColorSpan -import android.text.style.CharacterStyle -import android.text.style.ForegroundColorSpan -import android.text.style.UnderlineSpan +import android.text.style.* import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.util.helper.styledAttributes -import de.kuschku.quasseldroid_ng.util.irc.format.spans.IrcBackgroundColorSpan -import de.kuschku.quasseldroid_ng.util.irc.format.spans.IrcBoldSpan -import de.kuschku.quasseldroid_ng.util.irc.format.spans.IrcForegroundColorSpan -import de.kuschku.quasseldroid_ng.util.irc.format.spans.IrcItalicSpan +import de.kuschku.quasseldroid_ng.util.irc.format.spans.* import java.util.* class IrcFormatSerializer internal constructor(private val context: Context) { + val mircColors = context.theme.styledAttributes( + R.attr.mircColor00, R.attr.mircColor01, R.attr.mircColor02, R.attr.mircColor03, + R.attr.mircColor04, R.attr.mircColor05, R.attr.mircColor06, R.attr.mircColor07, + R.attr.mircColor08, R.attr.mircColor09, R.attr.mircColor10, R.attr.mircColor11, + R.attr.mircColor12, R.attr.mircColor13, R.attr.mircColor14, R.attr.mircColor15, + R.attr.mircColor16, R.attr.mircColor17, R.attr.mircColor18, R.attr.mircColor19, + R.attr.mircColor20, R.attr.mircColor21, R.attr.mircColor22, R.attr.mircColor23, + R.attr.mircColor24, R.attr.mircColor25, R.attr.mircColor26, R.attr.mircColor27, + R.attr.mircColor28, R.attr.mircColor29, R.attr.mircColor30, R.attr.mircColor31, + R.attr.mircColor32, R.attr.mircColor33, R.attr.mircColor34, R.attr.mircColor35, + R.attr.mircColor36, R.attr.mircColor37, R.attr.mircColor38, R.attr.mircColor39, + R.attr.mircColor40, R.attr.mircColor41, R.attr.mircColor42, R.attr.mircColor43, + R.attr.mircColor44, R.attr.mircColor45, R.attr.mircColor46, R.attr.mircColor47, + R.attr.mircColor48, R.attr.mircColor49, R.attr.mircColor50, R.attr.mircColor51, + R.attr.mircColor52, R.attr.mircColor53, R.attr.mircColor54, R.attr.mircColor55, + R.attr.mircColor56, R.attr.mircColor57, R.attr.mircColor58, R.attr.mircColor59, + R.attr.mircColor60, R.attr.mircColor61, R.attr.mircColor62, R.attr.mircColor63, + R.attr.mircColor64, R.attr.mircColor65, R.attr.mircColor66, R.attr.mircColor67, + R.attr.mircColor68, R.attr.mircColor69, R.attr.mircColor70, R.attr.mircColor71, + R.attr.mircColor72, R.attr.mircColor73, R.attr.mircColor74, R.attr.mircColor75, + R.attr.mircColor76, R.attr.mircColor77, R.attr.mircColor78, R.attr.mircColor79, + R.attr.mircColor80, R.attr.mircColor81, R.attr.mircColor82, R.attr.mircColor83, + R.attr.mircColor84, R.attr.mircColor85, R.attr.mircColor86, R.attr.mircColor87, + R.attr.mircColor88, R.attr.mircColor89, R.attr.mircColor90, R.attr.mircColor91, + R.attr.mircColor92, R.attr.mircColor93, R.attr.mircColor94, R.attr.mircColor95, + R.attr.mircColor96, R.attr.mircColor97, R.attr.mircColor98 + ) { + IntArray(99) { + getColor(it, 0) + } + } fun toEscapeCodes(text: Spanned): String { val out = StringBuilder() @@ -30,6 +55,8 @@ class IrcFormatSerializer internal constructor(private val context: Context) { var bold = false var underline = false var italic = false + var strikethrough = false + var monospace = false var i = start while (i < end) { @@ -41,6 +68,8 @@ class IrcFormatSerializer internal constructor(private val context: Context) { var afterBold = false var afterUnderline = false var afterItalic = false + var afterStrikethrough = false + var afterMonospace = false for (aStyle in style) { if (text.getSpanFlags(aStyle) and Spanned.SPAN_COMPOSING != 0) @@ -52,14 +81,18 @@ class IrcFormatSerializer internal constructor(private val context: Context) { afterItalic = true } else if (aStyle is UnderlineSpan) { afterUnderline = true + } else if (aStyle is StrikethroughSpan) { + afterStrikethrough = true + } else if (aStyle is IrcMonospaceSpan) { + afterMonospace = true } else if (aStyle is IrcForegroundColorSpan) { afterForeground = aStyle.mircColor } else if (aStyle is IrcBackgroundColorSpan) { afterBackground = aStyle.mircColor } else if (aStyle is ForegroundColorSpan) { - afterForeground = 0 + afterForeground = -1 } else if (aStyle is BackgroundColorSpan) { - afterBackground = 0 + afterBackground = -1 } } @@ -75,6 +108,14 @@ class IrcFormatSerializer internal constructor(private val context: Context) { out.append(CODE_ITALIC) } + if (afterStrikethrough != strikethrough) { + out.append(CODE_STRIKETHROUGH) + } + + if (afterMonospace != monospace) { + out.append(CODE_MONOSPACE) + } + if (afterForeground != foreground || afterBackground != background) { if (afterForeground == background && afterBackground == foreground) { out.append(CODE_SWAP) @@ -124,6 +165,8 @@ class IrcFormatSerializer internal constructor(private val context: Context) { bold = afterBold italic = afterItalic underline = afterUnderline + strikethrough = afterStrikethrough + monospace = afterMonospace background = afterBackground foreground = afterForeground i = next @@ -138,6 +181,8 @@ class IrcFormatSerializer internal constructor(private val context: Context) { val CODE_COLOR: Char = 0x03.toChar() val CODE_ITALIC: Char = 0x1D.toChar() val CODE_UNDERLINE: Char = 0x1F.toChar() + val CODE_STRIKETHROUGH = 0x1E.toChar() + val CODE_MONOSPACE = 0x11.toChar() val CODE_SWAP: Char = 0x16.toChar() val CODE_RESET: Char = 0x0F.toChar() } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcHexColorSpan.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcHexColorSpan.kt new file mode 100644 index 000000000..ef9e33e96 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcHexColorSpan.kt @@ -0,0 +1,9 @@ +package de.kuschku.quasseldroid_ng.util.irc.format.spans + +import android.support.annotation.ColorInt +import android.text.style.ForegroundColorSpan + +class IrcHexColorSpan(@ColorInt color: Int) : ForegroundColorSpan(color), + Copyable<IrcHexColorSpan> { + override fun copy() = IrcHexColorSpan(foregroundColor) +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcMonospaceSpan.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcMonospaceSpan.kt new file mode 100644 index 000000000..93be73ccf --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcMonospaceSpan.kt @@ -0,0 +1,7 @@ +package de.kuschku.quasseldroid_ng.util.irc.format.spans + +import android.text.style.TypefaceSpan + +class IrcMonospaceSpan : TypefaceSpan("monospace"), Copyable<IrcMonospaceSpan> { + override fun copy() = IrcMonospaceSpan() +} diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcStrikethroughSpan.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcStrikethroughSpan.kt new file mode 100644 index 000000000..7223229f3 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/irc/format/spans/IrcStrikethroughSpan.kt @@ -0,0 +1,7 @@ +package de.kuschku.quasseldroid_ng.util.irc.format.spans + +import android.text.style.StrikethroughSpan + +class IrcStrikethroughSpan : StrikethroughSpan(), Copyable<IrcStrikethroughSpan> { + override fun copy() = IrcStrikethroughSpan() +} diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 2d2d7219d..0af8785e4 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -18,22 +18,105 @@ <attr name="senderColorF" format="color" /> <!-- mirc colors --> - <attr name="mircColor0" format="color" /> - <attr name="mircColor1" format="color" /> - <attr name="mircColor2" format="color" /> - <attr name="mircColor3" format="color" /> - <attr name="mircColor4" format="color" /> - <attr name="mircColor5" format="color" /> - <attr name="mircColor6" format="color" /> - <attr name="mircColor7" format="color" /> - <attr name="mircColor8" format="color" /> - <attr name="mircColor9" format="color" /> - <attr name="mircColorA" format="color" /> - <attr name="mircColorB" format="color" /> - <attr name="mircColorC" format="color" /> - <attr name="mircColorD" format="color" /> - <attr name="mircColorE" format="color" /> - <attr name="mircColorF" format="color" /> + <attr name="mircColor00" format="color" /> + <attr name="mircColor01" format="color" /> + <attr name="mircColor02" format="color" /> + <attr name="mircColor03" format="color" /> + <attr name="mircColor04" format="color" /> + <attr name="mircColor05" format="color" /> + <attr name="mircColor06" format="color" /> + <attr name="mircColor07" format="color" /> + <attr name="mircColor08" format="color" /> + <attr name="mircColor09" format="color" /> + <attr name="mircColor10" format="color" /> + <attr name="mircColor11" format="color" /> + <attr name="mircColor12" format="color" /> + <attr name="mircColor13" format="color" /> + <attr name="mircColor14" format="color" /> + <attr name="mircColor15" format="color" /> + <attr name="mircColor16" format="color" /> + <attr name="mircColor17" format="color" /> + <attr name="mircColor18" format="color" /> + <attr name="mircColor19" format="color" /> + <attr name="mircColor20" format="color" /> + <attr name="mircColor21" format="color" /> + <attr name="mircColor22" format="color" /> + <attr name="mircColor23" format="color" /> + <attr name="mircColor24" format="color" /> + <attr name="mircColor25" format="color" /> + <attr name="mircColor26" format="color" /> + <attr name="mircColor27" format="color" /> + <attr name="mircColor28" format="color" /> + <attr name="mircColor29" format="color" /> + <attr name="mircColor30" format="color" /> + <attr name="mircColor31" format="color" /> + <attr name="mircColor32" format="color" /> + <attr name="mircColor33" format="color" /> + <attr name="mircColor34" format="color" /> + <attr name="mircColor35" format="color" /> + <attr name="mircColor36" format="color" /> + <attr name="mircColor37" format="color" /> + <attr name="mircColor38" format="color" /> + <attr name="mircColor39" format="color" /> + <attr name="mircColor40" format="color" /> + <attr name="mircColor41" format="color" /> + <attr name="mircColor42" format="color" /> + <attr name="mircColor43" format="color" /> + <attr name="mircColor44" format="color" /> + <attr name="mircColor45" format="color" /> + <attr name="mircColor46" format="color" /> + <attr name="mircColor47" format="color" /> + <attr name="mircColor48" format="color" /> + <attr name="mircColor49" format="color" /> + <attr name="mircColor50" format="color" /> + <attr name="mircColor51" format="color" /> + <attr name="mircColor52" format="color" /> + <attr name="mircColor53" format="color" /> + <attr name="mircColor54" format="color" /> + <attr name="mircColor55" format="color" /> + <attr name="mircColor56" format="color" /> + <attr name="mircColor57" format="color" /> + <attr name="mircColor58" format="color" /> + <attr name="mircColor59" format="color" /> + <attr name="mircColor60" format="color" /> + <attr name="mircColor61" format="color" /> + <attr name="mircColor62" format="color" /> + <attr name="mircColor63" format="color" /> + <attr name="mircColor64" format="color" /> + <attr name="mircColor65" format="color" /> + <attr name="mircColor66" format="color" /> + <attr name="mircColor67" format="color" /> + <attr name="mircColor68" format="color" /> + <attr name="mircColor69" format="color" /> + <attr name="mircColor70" format="color" /> + <attr name="mircColor71" format="color" /> + <attr name="mircColor72" format="color" /> + <attr name="mircColor73" format="color" /> + <attr name="mircColor74" format="color" /> + <attr name="mircColor75" format="color" /> + <attr name="mircColor76" format="color" /> + <attr name="mircColor77" format="color" /> + <attr name="mircColor78" format="color" /> + <attr name="mircColor79" format="color" /> + <attr name="mircColor80" format="color" /> + <attr name="mircColor81" format="color" /> + <attr name="mircColor82" format="color" /> + <attr name="mircColor83" format="color" /> + <attr name="mircColor84" format="color" /> + <attr name="mircColor85" format="color" /> + <attr name="mircColor86" format="color" /> + <attr name="mircColor87" format="color" /> + <attr name="mircColor88" format="color" /> + <attr name="mircColor89" format="color" /> + <attr name="mircColor90" format="color" /> + <attr name="mircColor91" format="color" /> + <attr name="mircColor92" format="color" /> + <attr name="mircColor93" format="color" /> + <attr name="mircColor94" format="color" /> + <attr name="mircColor95" format="color" /> + <attr name="mircColor96" format="color" /> + <attr name="mircColor97" format="color" /> + <attr name="mircColor98" format="color" /> <!-- Background and foreground colors for UI --> <attr name="colorForeground" format="color" /> diff --git a/app/src/main/res/values/themes_base.xml b/app/src/main/res/values/themes_base.xml index 6a519ac9a..5f41e0ace 100644 --- a/app/src/main/res/values/themes_base.xml +++ b/app/src/main/res/values/themes_base.xml @@ -61,22 +61,105 @@ <item name="cardStyle">@style/CardView.Dark</item> - <item name="mircColor0">#ffffff</item> - <item name="mircColor1">#000000</item> - <item name="mircColor2">#000080</item> - <item name="mircColor3">#008000</item> - <item name="mircColor4">#ff0000</item> - <item name="mircColor5">#800000</item> - <item name="mircColor6">#800080</item> - <item name="mircColor7">#ffa500</item> - <item name="mircColor8">#ffff00</item> - <item name="mircColor9">#00ff00</item> - <item name="mircColorA">#008080</item> - <item name="mircColorB">#00ffff</item> - <item name="mircColorC">#4169e1</item> - <item name="mircColorD">#ff00ff</item> - <item name="mircColorE">#808080</item> - <item name="mircColorF">#c0c0c0</item> + <item name="mircColor00">#ffffff</item> + <item name="mircColor01">#000000</item> + <item name="mircColor02">#000080</item> + <item name="mircColor03">#008000</item> + <item name="mircColor04">#ff0000</item> + <item name="mircColor05">#800000</item> + <item name="mircColor06">#800080</item> + <item name="mircColor07">#ffa500</item> + <item name="mircColor08">#ffff00</item> + <item name="mircColor09">#00ff00</item> + <item name="mircColor10">#008080</item> + <item name="mircColor11">#00ffff</item> + <item name="mircColor12">#4169e1</item> + <item name="mircColor13">#ff00ff</item> + <item name="mircColor14">#808080</item> + <item name="mircColor15">#c0c0c0</item> + <item name="mircColor16">#470000</item> + <item name="mircColor17">#472100</item> + <item name="mircColor18">#474700</item> + <item name="mircColor19">#324700</item> + <item name="mircColor20">#004700</item> + <item name="mircColor21">#00472c</item> + <item name="mircColor22">#004747</item> + <item name="mircColor23">#002747</item> + <item name="mircColor24">#000047</item> + <item name="mircColor25">#2e0047</item> + <item name="mircColor26">#470047</item> + <item name="mircColor27">#47002a</item> + <item name="mircColor28">#740000</item> + <item name="mircColor29">#743a00</item> + <item name="mircColor30">#747400</item> + <item name="mircColor31">#517400</item> + <item name="mircColor32">#007400</item> + <item name="mircColor33">#007449</item> + <item name="mircColor34">#007474</item> + <item name="mircColor35">#004074</item> + <item name="mircColor36">#000074</item> + <item name="mircColor37">#4b0074</item> + <item name="mircColor38">#740074</item> + <item name="mircColor39">#740045</item> + <item name="mircColor40">#b50000</item> + <item name="mircColor41">#b56300</item> + <item name="mircColor42">#b5b500</item> + <item name="mircColor43">#7db500</item> + <item name="mircColor44">#00b500</item> + <item name="mircColor45">#00b571</item> + <item name="mircColor46">#00b5b5</item> + <item name="mircColor47">#0063b5</item> + <item name="mircColor48">#0000b5</item> + <item name="mircColor49">#7500b5</item> + <item name="mircColor50">#b500b5</item> + <item name="mircColor51">#b5006b</item> + <item name="mircColor52">#ff0000</item> + <item name="mircColor53">#ff8c00</item> + <item name="mircColor54">#ffff00</item> + <item name="mircColor55">#b2ff00</item> + <item name="mircColor56">#00ff00</item> + <item name="mircColor57">#00ffa0</item> + <item name="mircColor58">#00ffff</item> + <item name="mircColor59">#008cff</item> + <item name="mircColor60">#0000ff</item> + <item name="mircColor61">#a500ff</item> + <item name="mircColor62">#ff00ff</item> + <item name="mircColor63">#ff0098</item> + <item name="mircColor64">#ff5959</item> + <item name="mircColor65">#ffb459</item> + <item name="mircColor66">#ffff71</item> + <item name="mircColor67">#cfff60</item> + <item name="mircColor68">#6fff6f</item> + <item name="mircColor69">#65ffc9</item> + <item name="mircColor70">#6dffff</item> + <item name="mircColor71">#59b4ff</item> + <item name="mircColor72">#5959ff</item> + <item name="mircColor73">#c459ff</item> + <item name="mircColor74">#ff66ff</item> + <item name="mircColor75">#ff59bc</item> + <item name="mircColor76">#ff9c9c</item> + <item name="mircColor77">#ffd39c</item> + <item name="mircColor78">#ffff9c</item> + <item name="mircColor79">#e2ff9c</item> + <item name="mircColor80">#9cff9c</item> + <item name="mircColor81">#9cffdb</item> + <item name="mircColor82">#9cffff</item> + <item name="mircColor83">#9cd3ff</item> + <item name="mircColor84">#9c9cff</item> + <item name="mircColor85">#dc9cff</item> + <item name="mircColor86">#ff9cff</item> + <item name="mircColor87">#ff94d3</item> + <item name="mircColor88">#000000</item> + <item name="mircColor89">#131313</item> + <item name="mircColor90">#282828</item> + <item name="mircColor91">#363636</item> + <item name="mircColor92">#4d4d4d</item> + <item name="mircColor93">#656565</item> + <item name="mircColor94">#818181</item> + <item name="mircColor95">#9f9f9f</item> + <item name="mircColor96">#bcbcbc</item> + <item name="mircColor97">#e2e2e2</item> + <item name="mircColor98">#ffffff</item> </style> <style name="Theme.ChatTheme.Auto" parent="Theme.ChatTheme"> @@ -110,22 +193,105 @@ <item name="cardStyle">@style/CardView.Light</item> - <item name="mircColor0">#ffffff</item> - <item name="mircColor1">#000000</item> - <item name="mircColor2">#000080</item> - <item name="mircColor3">#008000</item> - <item name="mircColor4">#ff0000</item> - <item name="mircColor5">#800000</item> - <item name="mircColor6">#800080</item> - <item name="mircColor7">#ffa500</item> - <item name="mircColor8">#ffff00</item> - <item name="mircColor9">#00ff00</item> - <item name="mircColorA">#008080</item> - <item name="mircColorB">#00ffff</item> - <item name="mircColorC">#4169e1</item> - <item name="mircColorD">#ff00ff</item> - <item name="mircColorE">#808080</item> - <item name="mircColorF">#c0c0c0</item> + <item name="mircColor00">#ffffff</item> + <item name="mircColor01">#000000</item> + <item name="mircColor02">#000080</item> + <item name="mircColor03">#008000</item> + <item name="mircColor04">#ff0000</item> + <item name="mircColor05">#800000</item> + <item name="mircColor06">#800080</item> + <item name="mircColor07">#ffa500</item> + <item name="mircColor08">#ffff00</item> + <item name="mircColor09">#00ff00</item> + <item name="mircColor10">#008080</item> + <item name="mircColor11">#00ffff</item> + <item name="mircColor12">#4169e1</item> + <item name="mircColor13">#ff00ff</item> + <item name="mircColor14">#808080</item> + <item name="mircColor15">#c0c0c0</item> + <item name="mircColor16">#470000</item> + <item name="mircColor17">#472100</item> + <item name="mircColor18">#474700</item> + <item name="mircColor19">#324700</item> + <item name="mircColor20">#004700</item> + <item name="mircColor21">#00472c</item> + <item name="mircColor22">#004747</item> + <item name="mircColor23">#002747</item> + <item name="mircColor24">#000047</item> + <item name="mircColor25">#2e0047</item> + <item name="mircColor26">#470047</item> + <item name="mircColor27">#47002a</item> + <item name="mircColor28">#740000</item> + <item name="mircColor29">#743a00</item> + <item name="mircColor30">#747400</item> + <item name="mircColor31">#517400</item> + <item name="mircColor32">#007400</item> + <item name="mircColor33">#007449</item> + <item name="mircColor34">#007474</item> + <item name="mircColor35">#004074</item> + <item name="mircColor36">#000074</item> + <item name="mircColor37">#4b0074</item> + <item name="mircColor38">#740074</item> + <item name="mircColor39">#740045</item> + <item name="mircColor40">#b50000</item> + <item name="mircColor41">#b56300</item> + <item name="mircColor42">#b5b500</item> + <item name="mircColor43">#7db500</item> + <item name="mircColor44">#00b500</item> + <item name="mircColor45">#00b571</item> + <item name="mircColor46">#00b5b5</item> + <item name="mircColor47">#0063b5</item> + <item name="mircColor48">#0000b5</item> + <item name="mircColor49">#7500b5</item> + <item name="mircColor50">#b500b5</item> + <item name="mircColor51">#b5006b</item> + <item name="mircColor52">#ff0000</item> + <item name="mircColor53">#ff8c00</item> + <item name="mircColor54">#ffff00</item> + <item name="mircColor55">#b2ff00</item> + <item name="mircColor56">#00ff00</item> + <item name="mircColor57">#00ffa0</item> + <item name="mircColor58">#00ffff</item> + <item name="mircColor59">#008cff</item> + <item name="mircColor60">#0000ff</item> + <item name="mircColor61">#a500ff</item> + <item name="mircColor62">#ff00ff</item> + <item name="mircColor63">#ff0098</item> + <item name="mircColor64">#ff5959</item> + <item name="mircColor65">#ffb459</item> + <item name="mircColor66">#ffff71</item> + <item name="mircColor67">#cfff60</item> + <item name="mircColor68">#6fff6f</item> + <item name="mircColor69">#65ffc9</item> + <item name="mircColor70">#6dffff</item> + <item name="mircColor71">#59b4ff</item> + <item name="mircColor72">#5959ff</item> + <item name="mircColor73">#c459ff</item> + <item name="mircColor74">#ff66ff</item> + <item name="mircColor75">#ff59bc</item> + <item name="mircColor76">#ff9c9c</item> + <item name="mircColor77">#ffd39c</item> + <item name="mircColor78">#ffff9c</item> + <item name="mircColor79">#e2ff9c</item> + <item name="mircColor80">#9cff9c</item> + <item name="mircColor81">#9cffdb</item> + <item name="mircColor82">#9cffff</item> + <item name="mircColor83">#9cd3ff</item> + <item name="mircColor84">#9c9cff</item> + <item name="mircColor85">#dc9cff</item> + <item name="mircColor86">#ff9cff</item> + <item name="mircColor87">#ff94d3</item> + <item name="mircColor88">#000000</item> + <item name="mircColor89">#131313</item> + <item name="mircColor90">#282828</item> + <item name="mircColor91">#363636</item> + <item name="mircColor92">#4d4d4d</item> + <item name="mircColor93">#656565</item> + <item name="mircColor94">#818181</item> + <item name="mircColor95">#9f9f9f</item> + <item name="mircColor96">#bcbcbc</item> + <item name="mircColor97">#e2e2e2</item> + <item name="mircColor98">#ffffff</item> </style> <style name="Theme.ChatTheme.Light.Auto" parent="Theme.ChatTheme.Light"> -- GitLab