SubwayTooter-Android-App/app/src/main/java/jp/juggler/subwaytooter/actmain/ActMainAutoCW.kt

115 lines
3.8 KiB
Kotlin

package jp.juggler.subwaytooter.actmain
import android.text.SpannableStringBuilder
import android.view.View
import android.widget.LinearLayout
import jp.juggler.subwaytooter.ActMain
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.api.entity.TootStatus
import jp.juggler.subwaytooter.pref.PrefS
import jp.juggler.subwaytooter.span.NetworkEmojiSpan
import jp.juggler.subwaytooter.view.MyTextView
import java.lang.ref.WeakReference
/**
* 各カラムの各投稿のコンテンツ部分の幅を覚える
*/
fun ActMain.saveContentTextWidth(columnW: Int) {
val lvPad = (0.5f + 12 * density).toInt()
val iconWidth = avatarIconSize
val iconEnd = (0.5f + 4 * density).toInt()
val contentTextWidth = columnW - lvPad * 2 - iconWidth - iconEnd
// CW部分の絵文字とか、リアクションなら数字と枠を避けたサイズとか
val maxEmojiWidth = contentTextWidth - (64f * density + 0.5f)
// NetworkEmojiSpanに覚える
NetworkEmojiSpan.maxEmojiWidth = maxEmojiWidth
// 自動CW用の値に覚える
val sv = PrefS.spAutoCWLines.value
nAutoCwLines = sv.toIntOrNull() ?: -1
if (nAutoCwLines > 0) {
nAutoCwCellWidth = contentTextWidth
}
// この後各カラムは再描画される
}
// 与えられたステータスのTootStatus.AutoCWオブジェクトを更新する
// TextViewを作って実際にレイアウトさせて表示行数を数える黒魔術
fun ActMain.checkAutoCW(status: TootStatus, text: CharSequence) {
if (nAutoCwCellWidth <= 0) {
// 設定が無効
status.auto_cw = null
return
}
var autoCw = status.auto_cw
if (autoCw != null &&
autoCw.refActivity?.get() === this &&
autoCw.cellWidth == nAutoCwCellWidth
) {
// 以前に計算した値がまだ使える
return
}
if (autoCw == null) {
autoCw = TootStatus.AutoCW()
status.auto_cw = autoCw
}
// 計算時の条件(文字フォント、文字サイズ、カラム幅)を覚えておいて、再利用時に同じか確認する
autoCw.refActivity = WeakReference(this)
autoCw.cellWidth = nAutoCwCellWidth
autoCw.decodedSpoilerText = null
// テキストをレイアウトして行数を測定
val tv = MyTextView(this).apply {
layoutParams =
LinearLayout.LayoutParams(nAutoCwCellWidth, LinearLayout.LayoutParams.WRAP_CONTENT)
if (!timelineFontSizeSp.isNaN()) {
textSize = timelineFontSizeSp
}
val fv = timelineSpacing
if (fv != null) setLineSpacing(0f, fv)
typeface = ActMain.timelineFont
this.text = text
}
tv.measure(
View.MeasureSpec.makeMeasureSpec(nAutoCwCellWidth, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
)
val l = tv.layout
if (l != null) {
autoCw.originalLineCount = l.lineCount
val lineCount = autoCw.originalLineCount
if ((nAutoCwLines > 0 && lineCount > nAutoCwLines) &&
status.spoiler_text.isEmpty() &&
(status.mentions?.size ?: 0) <= nAutoCwLines
) {
val sb = SpannableStringBuilder()
sb.append(getString(R.string.auto_cw_prefix))
sb.append(text, 0, l.getLineEnd(nAutoCwLines - 1))
var last = sb.length
while (last > 0) {
val c = sb[last - 1]
if (c == '\n' || Character.isWhitespace(c)) {
--last
continue
}
break
}
if (last < sb.length) {
sb.delete(last, sb.length)
}
sb.append('…')
autoCw.decodedSpoilerText = sb
}
}
}