2018-01-04 19:52:25 +01:00
|
|
|
package jp.juggler.subwaytooter
|
|
|
|
|
|
|
|
import android.content.Context
|
2023-01-13 13:22:25 +01:00
|
|
|
import android.content.res.ColorStateList
|
2019-12-15 20:12:57 +01:00
|
|
|
import android.content.res.Configuration
|
2023-01-13 13:22:25 +01:00
|
|
|
import android.graphics.Color
|
2019-01-16 13:33:07 +01:00
|
|
|
import android.graphics.PorterDuff
|
|
|
|
import android.graphics.drawable.Drawable
|
2023-01-13 13:22:25 +01:00
|
|
|
import android.os.Build
|
2018-01-04 19:52:25 +01:00
|
|
|
import android.text.SpannableStringBuilder
|
|
|
|
import android.text.Spanned
|
|
|
|
import android.view.View
|
|
|
|
import android.view.ViewGroup
|
2023-01-13 13:22:25 +01:00
|
|
|
import android.view.WindowManager
|
2018-01-04 19:52:25 +01:00
|
|
|
import android.widget.ImageButton
|
|
|
|
import android.widget.ImageView
|
2021-06-20 15:12:25 +02:00
|
|
|
import androidx.annotation.DrawableRes
|
2023-01-13 13:22:25 +01:00
|
|
|
import androidx.appcompat.app.AppCompatActivity
|
|
|
|
import androidx.appcompat.widget.SwitchCompat
|
2020-09-09 21:46:50 +02:00
|
|
|
import androidx.core.content.ContextCompat
|
2018-01-04 19:52:25 +01:00
|
|
|
import jp.juggler.subwaytooter.api.entity.TootAccount
|
2018-08-20 19:37:42 +02:00
|
|
|
import jp.juggler.subwaytooter.api.entity.TootVisibility
|
2021-11-08 10:29:11 +01:00
|
|
|
import jp.juggler.subwaytooter.emoji.EmojiMap
|
|
|
|
import jp.juggler.subwaytooter.pref.PrefB
|
2021-11-06 04:00:29 +01:00
|
|
|
import jp.juggler.subwaytooter.pref.PrefI
|
2023-02-04 21:52:26 +01:00
|
|
|
import jp.juggler.subwaytooter.pref.lazyContext
|
2018-01-04 19:52:25 +01:00
|
|
|
import jp.juggler.subwaytooter.span.EmojiImageSpan
|
2019-09-14 22:09:52 +02:00
|
|
|
import jp.juggler.subwaytooter.span.createSpan
|
2018-08-20 19:37:42 +02:00
|
|
|
import jp.juggler.subwaytooter.table.UserRelation
|
2023-01-13 13:22:25 +01:00
|
|
|
import jp.juggler.util.*
|
|
|
|
import jp.juggler.util.data.notZero
|
|
|
|
import jp.juggler.util.log.LogCategory
|
|
|
|
import jp.juggler.util.ui.*
|
|
|
|
import org.xmlpull.v1.XmlPullParser
|
2019-12-15 20:12:57 +01:00
|
|
|
import kotlin.math.max
|
2019-09-14 22:09:52 +02:00
|
|
|
import kotlin.math.min
|
2018-01-04 19:52:25 +01:00
|
|
|
|
2019-12-15 20:12:57 +01:00
|
|
|
private val log = LogCategory("Styler")
|
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
fun defaultColorIcon(context: Context, iconId: Int): Drawable? =
|
|
|
|
ContextCompat.getDrawable(context, iconId)?.also {
|
2023-01-14 21:37:23 +01:00
|
|
|
it.setTint(context.attrColor(R.attr.colorTextContent))
|
2023-01-13 13:22:25 +01:00
|
|
|
it.setTintMode(PorterDuff.Mode.SRC_IN)
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-02-04 21:52:26 +01:00
|
|
|
fun TootVisibility.getVisibilityIconId(isMisskeyData: Boolean): Int {
|
|
|
|
val isMisskey = when (PrefI.ipVisibilityStyle.value) {
|
2023-01-13 13:22:25 +01:00
|
|
|
PrefI.VS_MASTODON -> false
|
|
|
|
PrefI.VS_MISSKEY -> true
|
|
|
|
else -> isMisskeyData
|
|
|
|
}
|
|
|
|
return when {
|
2023-02-04 21:52:26 +01:00
|
|
|
isMisskey -> when (this) {
|
2023-01-13 13:22:25 +01:00
|
|
|
TootVisibility.Public -> R.drawable.ic_public
|
|
|
|
TootVisibility.UnlistedHome -> R.drawable.ic_home
|
|
|
|
TootVisibility.PrivateFollowers -> R.drawable.ic_lock_open
|
|
|
|
TootVisibility.DirectSpecified -> R.drawable.ic_mail
|
|
|
|
TootVisibility.DirectPrivate -> R.drawable.ic_lock
|
|
|
|
TootVisibility.WebSetting -> R.drawable.ic_question
|
|
|
|
TootVisibility.AccountSetting -> R.drawable.ic_question
|
|
|
|
|
|
|
|
TootVisibility.LocalPublic -> R.drawable.ic_local_ltl
|
|
|
|
TootVisibility.LocalHome -> R.drawable.ic_local_home
|
|
|
|
TootVisibility.LocalFollowers -> R.drawable.ic_local_lock_open
|
|
|
|
|
|
|
|
TootVisibility.Unknown -> R.drawable.ic_question
|
|
|
|
TootVisibility.Limited -> R.drawable.ic_account_circle
|
|
|
|
TootVisibility.Mutual -> R.drawable.ic_bidirectional
|
2021-06-20 15:12:25 +02:00
|
|
|
}
|
2023-02-04 21:52:26 +01:00
|
|
|
else -> when (this) {
|
2023-01-13 13:22:25 +01:00
|
|
|
TootVisibility.Public -> R.drawable.ic_public
|
|
|
|
TootVisibility.UnlistedHome -> R.drawable.ic_lock_open
|
|
|
|
TootVisibility.PrivateFollowers -> R.drawable.ic_lock
|
|
|
|
TootVisibility.DirectSpecified -> R.drawable.ic_mail
|
|
|
|
TootVisibility.DirectPrivate -> R.drawable.ic_mail
|
|
|
|
TootVisibility.WebSetting -> R.drawable.ic_question
|
|
|
|
TootVisibility.AccountSetting -> R.drawable.ic_question
|
|
|
|
|
|
|
|
TootVisibility.LocalPublic -> R.drawable.ic_local_ltl
|
|
|
|
TootVisibility.LocalHome -> R.drawable.ic_local_lock_open
|
|
|
|
TootVisibility.LocalFollowers -> R.drawable.ic_local_lock
|
|
|
|
|
|
|
|
TootVisibility.Unknown -> R.drawable.ic_question
|
|
|
|
TootVisibility.Limited -> R.drawable.ic_account_circle
|
|
|
|
TootVisibility.Mutual -> R.drawable.ic_bidirectional
|
2021-06-20 15:12:25 +02:00
|
|
|
}
|
2023-01-13 13:22:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-04 21:52:26 +01:00
|
|
|
fun TootVisibility.getVisibilityString(isMisskeyData: Boolean): String {
|
|
|
|
val isMisskey = when (PrefI.ipVisibilityStyle.value) {
|
2023-01-13 13:22:25 +01:00
|
|
|
PrefI.VS_MASTODON -> false
|
|
|
|
PrefI.VS_MISSKEY -> true
|
|
|
|
else -> isMisskeyData
|
|
|
|
}
|
2023-02-04 21:52:26 +01:00
|
|
|
return lazyContext.getString(
|
2023-01-13 13:22:25 +01:00
|
|
|
when {
|
2023-02-04 21:52:26 +01:00
|
|
|
isMisskey -> when (this) {
|
2023-01-13 13:22:25 +01:00
|
|
|
TootVisibility.Public -> R.string.visibility_public
|
|
|
|
TootVisibility.UnlistedHome -> R.string.visibility_home
|
|
|
|
TootVisibility.PrivateFollowers -> R.string.visibility_followers
|
|
|
|
TootVisibility.DirectSpecified -> R.string.visibility_direct
|
|
|
|
TootVisibility.DirectPrivate -> R.string.visibility_private
|
|
|
|
TootVisibility.WebSetting -> R.string.visibility_web_setting
|
|
|
|
TootVisibility.AccountSetting -> R.string.visibility_account_setting
|
|
|
|
|
|
|
|
TootVisibility.LocalPublic -> R.string.visibility_local_public
|
|
|
|
TootVisibility.LocalHome -> R.string.visibility_local_home
|
|
|
|
TootVisibility.LocalFollowers -> R.string.visibility_local_followers
|
|
|
|
|
|
|
|
TootVisibility.Unknown -> R.string.visibility_unknown
|
|
|
|
TootVisibility.Limited -> R.string.visibility_limited
|
|
|
|
TootVisibility.Mutual -> R.string.visibility_mutual
|
2021-06-20 15:12:25 +02:00
|
|
|
}
|
2023-02-04 21:52:26 +01:00
|
|
|
else -> when (this) {
|
2023-01-13 13:22:25 +01:00
|
|
|
TootVisibility.Public -> R.string.visibility_public
|
|
|
|
TootVisibility.UnlistedHome -> R.string.visibility_unlisted
|
|
|
|
TootVisibility.PrivateFollowers -> R.string.visibility_followers
|
|
|
|
TootVisibility.DirectSpecified -> R.string.visibility_direct
|
|
|
|
TootVisibility.DirectPrivate -> R.string.visibility_direct
|
|
|
|
TootVisibility.WebSetting -> R.string.visibility_web_setting
|
|
|
|
TootVisibility.AccountSetting -> R.string.visibility_account_setting
|
|
|
|
|
|
|
|
TootVisibility.LocalPublic -> R.string.visibility_local_public
|
|
|
|
TootVisibility.LocalHome -> R.string.visibility_local_unlisted
|
|
|
|
TootVisibility.LocalFollowers -> R.string.visibility_local_followers
|
|
|
|
|
|
|
|
TootVisibility.Unknown -> R.string.visibility_unknown
|
|
|
|
TootVisibility.Limited -> R.string.visibility_limited
|
|
|
|
TootVisibility.Mutual -> R.string.visibility_mutual
|
2021-06-20 15:12:25 +02:00
|
|
|
}
|
|
|
|
}
|
2023-01-13 13:22:25 +01:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// アイコン付きの装飾テキストを返す
|
|
|
|
fun getVisibilityCaption(
|
|
|
|
context: Context,
|
|
|
|
isMisskeyData: Boolean,
|
|
|
|
visibility: TootVisibility,
|
|
|
|
): CharSequence {
|
|
|
|
|
2023-02-04 21:52:26 +01:00
|
|
|
val iconId = visibility.getVisibilityIconId(isMisskeyData)
|
|
|
|
val sv = visibility.getVisibilityString(isMisskeyData)
|
2023-01-14 21:37:23 +01:00
|
|
|
val color = context.attrColor(R.attr.colorTextContent)
|
2023-01-13 13:22:25 +01:00
|
|
|
val sb = SpannableStringBuilder()
|
|
|
|
|
|
|
|
// アイコン部分
|
|
|
|
val start = sb.length
|
|
|
|
sb.append(" ")
|
|
|
|
val end = sb.length
|
|
|
|
sb.setSpan(
|
|
|
|
EmojiImageSpan(
|
|
|
|
context,
|
2023-01-14 11:19:01 +01:00
|
|
|
iconId,
|
2023-01-13 13:22:25 +01:00
|
|
|
useColorShader = true,
|
|
|
|
color = color
|
|
|
|
),
|
|
|
|
start,
|
|
|
|
end,
|
|
|
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
|
|
)
|
|
|
|
|
|
|
|
// 文字列部分
|
|
|
|
sb.append(' ')
|
|
|
|
sb.append(sv)
|
|
|
|
|
|
|
|
return sb
|
|
|
|
}
|
|
|
|
|
|
|
|
fun setFollowIcon(
|
|
|
|
context: Context,
|
|
|
|
ibFollow: ImageButton,
|
|
|
|
ivDot: ImageView,
|
|
|
|
relation: UserRelation,
|
|
|
|
who: TootAccount,
|
|
|
|
defaultColor: Int,
|
|
|
|
alphaMultiplier: Float,
|
|
|
|
) {
|
2023-01-14 21:37:23 +01:00
|
|
|
val colorFollowed =
|
2023-02-04 21:52:26 +01:00
|
|
|
PrefI.ipButtonFollowingColor.value.notZero()
|
2023-01-13 13:22:25 +01:00
|
|
|
?: context.attrColor(R.attr.colorButtonAccentFollow)
|
|
|
|
|
2023-01-14 21:37:23 +01:00
|
|
|
val colorFollowRequest =
|
2023-02-04 21:52:26 +01:00
|
|
|
PrefI.ipButtonFollowRequestColor.value.notZero()
|
2023-01-13 13:22:25 +01:00
|
|
|
?: context.attrColor(R.attr.colorButtonAccentFollowRequest)
|
|
|
|
|
2023-01-14 21:37:23 +01:00
|
|
|
val colorError = context.attrColor(R.attr.colorRegexFilterError)
|
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
// 被フォロー状態
|
|
|
|
when {
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
relation.blocked_by -> {
|
|
|
|
ivDot.visibility = View.VISIBLE
|
|
|
|
setIconDrawableId(
|
|
|
|
context,
|
|
|
|
ivDot,
|
|
|
|
R.drawable.ic_blocked_by,
|
2023-01-14 21:37:23 +01:00
|
|
|
color = colorError,
|
2023-01-13 13:22:25 +01:00
|
|
|
alphaMultiplier = alphaMultiplier
|
|
|
|
)
|
2021-06-20 15:12:25 +02:00
|
|
|
}
|
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
relation.requested_by -> {
|
|
|
|
ivDot.visibility = View.VISIBLE
|
|
|
|
setIconDrawableId(
|
2021-06-20 15:12:25 +02:00
|
|
|
context,
|
2023-01-13 13:22:25 +01:00
|
|
|
ivDot,
|
|
|
|
R.drawable.ic_requested_by,
|
2023-01-14 21:37:23 +01:00
|
|
|
color = colorFollowRequest,
|
2023-01-13 13:22:25 +01:00
|
|
|
alphaMultiplier = alphaMultiplier
|
|
|
|
)
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
relation.followed_by -> {
|
|
|
|
ivDot.visibility = View.VISIBLE
|
|
|
|
setIconDrawableId(
|
|
|
|
context,
|
|
|
|
ivDot,
|
|
|
|
R.drawable.ic_follow_dot,
|
2023-01-14 21:37:23 +01:00
|
|
|
color = colorFollowed,
|
2023-01-13 13:22:25 +01:00
|
|
|
alphaMultiplier = alphaMultiplier
|
|
|
|
)
|
|
|
|
// 被フォローリクエスト状態の時に followed_by が 真と偽の両方がありえるようなので
|
|
|
|
// Relationshipだけを見ても被フォローリクエスト状態は分からないっぽい
|
|
|
|
// 仕方ないので馬鹿正直に「 followed_byが真ならバッジをつける」しかできない
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
else -> {
|
|
|
|
ivDot.visibility = View.GONE
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
}
|
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
// フォローボタン
|
|
|
|
// follow button
|
|
|
|
val color: Int
|
|
|
|
val iconId: Int
|
|
|
|
val contentDescription: String
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
when {
|
|
|
|
relation.blocking -> {
|
|
|
|
iconId = R.drawable.ic_block
|
|
|
|
color = defaultColor
|
|
|
|
contentDescription = context.getString(R.string.follow)
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
relation.muting -> {
|
|
|
|
iconId = R.drawable.ic_volume_off
|
|
|
|
color = defaultColor
|
|
|
|
contentDescription = context.getString(R.string.follow)
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
relation.getFollowing(who) -> {
|
|
|
|
iconId = R.drawable.ic_follow_cross
|
2023-01-14 21:37:23 +01:00
|
|
|
color = colorFollowed
|
2023-01-13 13:22:25 +01:00
|
|
|
contentDescription = context.getString(R.string.unfollow)
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
relation.getRequested(who) -> {
|
|
|
|
iconId = R.drawable.ic_follow_wait
|
2023-01-14 21:37:23 +01:00
|
|
|
color = colorFollowRequest
|
2023-01-13 13:22:25 +01:00
|
|
|
contentDescription = context.getString(R.string.unfollow)
|
2021-06-20 15:12:25 +02:00
|
|
|
}
|
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
else -> {
|
|
|
|
iconId = R.drawable.ic_follow_plus
|
|
|
|
color = defaultColor
|
|
|
|
contentDescription = context.getString(R.string.follow)
|
|
|
|
}
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
setIconDrawableId(
|
|
|
|
context,
|
|
|
|
ibFollow,
|
|
|
|
iconId,
|
|
|
|
color = color,
|
|
|
|
alphaMultiplier = alphaMultiplier
|
|
|
|
)
|
|
|
|
ibFollow.contentDescription = contentDescription
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
private fun getHorizontalPadding(v: View, dpDelta: Float): Int {
|
|
|
|
// Essential Phone PH-1は 短辺439dp
|
|
|
|
val formWidthMax = 460f
|
|
|
|
val dm = v.resources.displayMetrics
|
|
|
|
val screenW = dm.widthPixels
|
|
|
|
val contentW = (0.5f + formWidthMax * dm.density).toInt()
|
|
|
|
val padW = max(0, (screenW - contentW) / 2)
|
|
|
|
return padW + (0.5f + dpDelta * dm.density).toInt()
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
private fun getOrientationString(orientation: Int?) = when (orientation) {
|
|
|
|
null -> "null"
|
|
|
|
Configuration.ORIENTATION_LANDSCAPE -> "landscape"
|
|
|
|
Configuration.ORIENTATION_PORTRAIT -> "portrait"
|
|
|
|
Configuration.ORIENTATION_UNDEFINED -> "undefined"
|
|
|
|
else -> orientation.toString()
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
fun fixHorizontalPadding(v: View, dpDelta: Float = 12f) {
|
2023-01-14 11:19:01 +01:00
|
|
|
val padT = v.paddingTop
|
|
|
|
val padB = v.paddingBottom
|
2023-01-13 13:22:25 +01:00
|
|
|
|
|
|
|
val dm = v.resources.displayMetrics
|
|
|
|
val widthDp = dm.widthPixels / dm.density
|
|
|
|
if (widthDp >= 640f && v.resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
2023-01-14 11:19:01 +01:00
|
|
|
val padLr = (0.5f + dpDelta * dm.density).toInt()
|
2023-02-04 21:52:26 +01:00
|
|
|
when (PrefI.ipJustifyWindowContentPortrait.value) {
|
2023-01-13 13:22:25 +01:00
|
|
|
PrefI.JWCP_START -> {
|
2023-01-14 11:19:01 +01:00
|
|
|
v.setPaddingRelative(padLr, padT, padLr + dm.widthPixels / 2, padB)
|
2023-01-13 13:22:25 +01:00
|
|
|
return
|
2021-06-20 15:12:25 +02:00
|
|
|
}
|
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
PrefI.JWCP_END -> {
|
2023-01-14 11:19:01 +01:00
|
|
|
v.setPaddingRelative(padLr + dm.widthPixels / 2, padT, padLr, padB)
|
2023-01-13 13:22:25 +01:00
|
|
|
return
|
2021-06-20 15:12:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-14 11:19:01 +01:00
|
|
|
val padLr = getHorizontalPadding(v, dpDelta)
|
|
|
|
v.setPaddingRelative(padLr, padT, padLr, padB)
|
2023-01-13 13:22:25 +01:00
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
fun fixHorizontalPadding0(v: View) = fixHorizontalPadding(v, 0f)
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
fun fixHorizontalMargin(v: View) {
|
|
|
|
val lp = v.layoutParams
|
|
|
|
if (lp is ViewGroup.MarginLayoutParams) {
|
2021-06-20 15:12:25 +02:00
|
|
|
|
|
|
|
val dm = v.resources.displayMetrics
|
2023-01-13 13:22:25 +01:00
|
|
|
val orientationString = getOrientationString(v.resources?.configuration?.orientation)
|
2021-06-20 15:12:25 +02:00
|
|
|
val widthDp = dm.widthPixels / dm.density
|
2023-01-13 13:22:25 +01:00
|
|
|
log.d("fixHorizontalMargin: orientation=$orientationString, w=${widthDp}dp, h=${dm.heightPixels / dm.density}")
|
|
|
|
|
2021-06-20 15:12:25 +02:00
|
|
|
if (widthDp >= 640f && v.resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
2023-02-04 21:52:26 +01:00
|
|
|
when (PrefI.ipJustifyWindowContentPortrait.value) {
|
2021-06-22 10:31:51 +02:00
|
|
|
PrefI.JWCP_START -> {
|
2023-01-13 13:22:25 +01:00
|
|
|
lp.marginStart = 0
|
|
|
|
lp.marginEnd = dm.widthPixels / 2
|
2021-06-20 15:12:25 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-06-22 10:31:51 +02:00
|
|
|
PrefI.JWCP_END -> {
|
2023-01-13 13:22:25 +01:00
|
|
|
lp.marginStart = dm.widthPixels / 2
|
|
|
|
lp.marginEnd = 0
|
2021-06-20 15:12:25 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-14 11:19:01 +01:00
|
|
|
val padLr = getHorizontalPadding(v, 0f)
|
|
|
|
lp.leftMargin = padLr
|
|
|
|
lp.rightMargin = padLr
|
2021-06-20 15:12:25 +02:00
|
|
|
}
|
2023-01-13 13:22:25 +01:00
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
// ActMainの初期化時に更新される
|
2023-01-14 21:37:23 +01:00
|
|
|
var stylerRoundRatio: Float = 0.33f * 0.5f
|
|
|
|
var stylerBoostAlpha: Float = 1f
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-14 21:37:23 +01:00
|
|
|
fun calcIconRound(wh: Int) = wh.toFloat() * stylerRoundRatio
|
2021-06-20 15:12:25 +02:00
|
|
|
|
2023-01-13 13:22:25 +01:00
|
|
|
fun calcIconRound(lp: ViewGroup.LayoutParams) =
|
2023-01-14 21:37:23 +01:00
|
|
|
min(lp.width, lp.height).toFloat() * stylerRoundRatio
|
2018-04-21 01:16:44 +02:00
|
|
|
|
|
|
|
fun SpannableStringBuilder.appendColorShadeIcon(
|
2021-06-20 15:12:25 +02:00
|
|
|
context: Context,
|
|
|
|
@DrawableRes drawableId: Int,
|
|
|
|
text: String,
|
2023-01-13 13:22:25 +01:00
|
|
|
color: Int? = null,
|
2021-06-20 15:12:25 +02:00
|
|
|
): SpannableStringBuilder {
|
|
|
|
val start = this.length
|
|
|
|
this.append(text)
|
|
|
|
val end = this.length
|
|
|
|
this.setSpan(
|
|
|
|
EmojiImageSpan(context, drawableId, useColorShader = true, color = color),
|
|
|
|
start,
|
|
|
|
end,
|
|
|
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
|
|
)
|
|
|
|
return this
|
2018-08-21 03:53:52 +02:00
|
|
|
}
|
|
|
|
|
2019-09-14 22:09:52 +02:00
|
|
|
fun SpannableStringBuilder.appendMisskeyReaction(
|
2021-06-20 15:12:25 +02:00
|
|
|
context: Context,
|
|
|
|
emojiUtf16: String,
|
2023-01-13 13:22:25 +01:00
|
|
|
text: String,
|
2021-06-20 15:12:25 +02:00
|
|
|
): SpannableStringBuilder {
|
|
|
|
|
2021-11-08 10:29:11 +01:00
|
|
|
val emoji = EmojiMap.unicodeMap[emojiUtf16]
|
|
|
|
when {
|
|
|
|
emoji == null ->
|
|
|
|
append("text")
|
|
|
|
|
2023-02-04 21:52:26 +01:00
|
|
|
PrefB.bpUseTwemoji.value -> {
|
2021-11-08 10:29:11 +01:00
|
|
|
val start = this.length
|
|
|
|
append(text)
|
|
|
|
val end = this.length
|
|
|
|
this.setSpan(
|
|
|
|
emoji.createSpan(context),
|
|
|
|
start, end,
|
|
|
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
|
|
)
|
|
|
|
}
|
|
|
|
else ->
|
|
|
|
this.append(emoji.unifiedCode)
|
|
|
|
}
|
2021-06-20 15:12:25 +02:00
|
|
|
return this
|
2018-04-21 01:16:44 +02:00
|
|
|
}
|
2023-01-13 13:22:25 +01:00
|
|
|
|
|
|
|
fun Context.setSwitchColor(root: View?) {
|
2023-02-04 21:52:26 +01:00
|
|
|
root ?: return
|
2023-01-13 13:22:25 +01:00
|
|
|
val colorBg = attrColor(R.attr.colorWindowBackground)
|
|
|
|
val colorOff = attrColor(R.attr.colorSwitchOff)
|
2023-02-04 21:52:26 +01:00
|
|
|
val colorOn = PrefI.ipSwitchOnColor.value
|
2023-01-13 13:22:25 +01:00
|
|
|
|
|
|
|
val colorDisabled = mixColor(colorBg, colorOff)
|
|
|
|
|
|
|
|
val colorTrackDisabled = mixColor(colorBg, colorDisabled)
|
|
|
|
val colorTrackOn = mixColor(colorBg, colorOn)
|
|
|
|
val colorTrackOff = mixColor(colorBg, colorOff)
|
|
|
|
|
|
|
|
// https://stackoverflow.com/a/25635526/9134243
|
|
|
|
val thumbStates = ColorStateList(
|
|
|
|
arrayOf(
|
|
|
|
intArrayOf(-android.R.attr.state_enabled),
|
|
|
|
intArrayOf(android.R.attr.state_checked),
|
|
|
|
intArrayOf()
|
|
|
|
),
|
|
|
|
intArrayOf(
|
|
|
|
colorDisabled,
|
|
|
|
colorOn,
|
|
|
|
colorOff
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
val trackStates = ColorStateList(
|
|
|
|
arrayOf(
|
|
|
|
intArrayOf(-android.R.attr.state_enabled),
|
|
|
|
intArrayOf(android.R.attr.state_checked),
|
|
|
|
intArrayOf()
|
|
|
|
),
|
|
|
|
intArrayOf(
|
|
|
|
colorTrackDisabled,
|
|
|
|
colorTrackOn,
|
|
|
|
colorTrackOff
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2023-02-04 21:52:26 +01:00
|
|
|
root.scan {
|
2023-01-13 13:22:25 +01:00
|
|
|
(it as? SwitchCompat)?.apply {
|
|
|
|
thumbTintList = thumbStates
|
|
|
|
trackTintList = trackStates
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun ViewGroup.generateLayoutParamsEx(): ViewGroup.LayoutParams? =
|
|
|
|
try {
|
|
|
|
val parser = resources.getLayout(R.layout.generate_params)
|
|
|
|
// Skip everything until the view tag.
|
|
|
|
while (true) {
|
|
|
|
val token = parser.nextToken()
|
|
|
|
if (token == XmlPullParser.START_TAG) break
|
|
|
|
}
|
|
|
|
generateLayoutParams(parser)
|
|
|
|
} catch (ex: Throwable) {
|
|
|
|
log.e(ex, "generateLayoutParamsEx failed")
|
|
|
|
null
|
|
|
|
}
|
|
|
|
|
|
|
|
fun AppCompatActivity.setStatusBarColor(forceDark: Boolean = false) {
|
|
|
|
window?.apply {
|
|
|
|
if (Build.VERSION.SDK_INT < 30) {
|
|
|
|
@Suppress("DEPRECATION")
|
|
|
|
clearFlags(
|
|
|
|
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS or
|
|
|
|
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
|
|
|
|
|
|
|
var c = when {
|
|
|
|
forceDark -> Color.BLACK
|
2023-02-04 21:52:26 +01:00
|
|
|
else -> PrefI.ipStatusBarColor.value.notZero()
|
|
|
|
?: attrColor(R.attr.colorPrimaryDark)
|
2023-01-13 13:22:25 +01:00
|
|
|
}
|
|
|
|
setStatusBarColorCompat(c)
|
|
|
|
|
|
|
|
c = when {
|
|
|
|
forceDark -> Color.BLACK
|
2023-02-04 21:52:26 +01:00
|
|
|
else -> PrefI.ipNavigationBarColor.value
|
2023-01-13 13:22:25 +01:00
|
|
|
}
|
|
|
|
setNavigationBarColorCompat(c)
|
|
|
|
}
|
|
|
|
}
|