package jp.juggler.subwaytooter.util import android.content.Context import android.text.Spannable import android.text.SpannableStringBuilder import android.text.style.ReplacementSpan import jp.juggler.subwaytooter.api.entity.* import jp.juggler.subwaytooter.emoji.CustomEmoji import jp.juggler.subwaytooter.table.HighlightWord import jp.juggler.util.WordTrieTree import org.jetbrains.anko.collections.forEachReversedByIndex import java.util.* class DecodeOptions( val context: Context? = null, var linkHelper: LinkHelper? = null, var short: Boolean = false, var decodeEmoji: Boolean = false, var attachmentList: ArrayList? = null, var linkTag: Any? = null, var emojiMapCustom: HashMap? = null, var emojiMapProfile: HashMap? = null, var highlightTrie: WordTrieTree? = null, var unwrapEmojiImageTag: Boolean = false, var enlargeCustomEmoji: Float = 1f, var enlargeEmoji: Float = 1f, var forceHtml: Boolean = false, // force use HTML instead of Misskey Markdown var mentionFullAcct: Boolean = false, var mentions: ArrayList? = null, // Account.note などmentionsがない状況でメンションリンクをfull acct化するにはアカウント等からapDomainを補う必要がある var mentionDefaultHostDomain: HostAndDomain = linkHelper ?: unknownHostAndDomain, ) { internal fun isMediaAttachment(url: String?): Boolean = url?.let { u -> attachmentList?.any { it.hasUrl(u) } } ?: false // OUTPUT var highlightSound: HighlightWord? = null var highlightSpeech: HighlightWord? = null var highlightAny: HighlightWord? = null //////////////////////// // decoder // AndroidのStaticLayoutはパラグラフ中に絵文字が沢山あると異常に遅いので、絵文字が連続して登場したら改行文字を挿入する private fun SpannableStringBuilder.workaroundForEmojiLineBreak(): SpannableStringBuilder { val maxEmojiPerLine = if (linkHelper?.isMisskey == true) 5 else 12 val spans = getSpans(0, length, ReplacementSpan::class.java) if (spans != null && spans.size > maxEmojiPerLine) { val insertList = ArrayList() var emojiCount = 1 var preEnd: Int? = null for (span in spans.sortedBy { getSpanStart(it) }) { val start = getSpanStart(span) if (preEnd != null) { // true if specified range includes line feed fun containsLineFeed(start: Int, end: Int): Boolean { for (i in start until end) { if (get(i) == '\n') return true } return false } if (containsLineFeed(preEnd, start)) { emojiCount = 1 } else if (++emojiCount > maxEmojiPerLine) { insertList.add(start) emojiCount = 1 } } preEnd = getSpanEnd(span) } // 後ろから順に挿入する insertList.forEachReversedByIndex { insert(it, "\n") } } return this } fun decodeHTML(html: String?) = HTMLDecoder.decodeHTML(this, html).workaroundForEmojiLineBreak() fun decodeEmoji(s: String?): Spannable = EmojiDecoder.decodeEmoji(this, s ?: "").workaroundForEmojiLineBreak() // fun decodeEmojiNullable(s : String?) = when(s) { // null -> null // else -> EmojiDecoder.decodeEmoji(this, s) // } }