Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
package io.homeassistant.companion.android.settings.wear.views

import android.graphics.Typeface
import android.text.style.AbsoluteSizeSpan
import android.text.style.CharacterStyle
import android.text.style.ForegroundColorSpan
import android.text.style.RelativeSizeSpan
import android.text.style.StyleSpan
import android.text.style.UnderlineSpan
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand All @@ -26,24 +19,17 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY
import androidx.core.text.HtmlCompat.fromHtml
import com.mikepenz.iconics.compose.Image
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import io.homeassistant.companion.android.common.R as commonR
import io.homeassistant.companion.android.util.compose.parseHtml
import io.homeassistant.companion.android.util.intervalToString
import io.homeassistant.companion.android.util.safeBottomPaddingValues

Expand Down Expand Up @@ -130,35 +116,6 @@ fun SettingsWearTemplateTile(
}
}

private fun parseHtml(renderedText: String) = buildAnnotatedString {
// Replace control char \r\n, \r, \n and also \r\n, \r, \n as text literals in strings to <br>
val renderedSpanned =
fromHtml(renderedText.replace("(\r\n|\r|\n)|(\\\\r\\\\n|\\\\r|\\\\n)".toRegex(), "<br>"), FROM_HTML_MODE_LEGACY)
append(renderedSpanned.toString())
renderedSpanned.getSpans(0, renderedSpanned.length, CharacterStyle::class.java).forEach { span ->
val start = renderedSpanned.getSpanStart(span)
val end = renderedSpanned.getSpanEnd(span)
when (span) {
is AbsoluteSizeSpan -> addStyle(SpanStyle(fontSize = span.size.sp), start, end)
is ForegroundColorSpan -> addStyle(SpanStyle(color = Color(span.foregroundColor)), start, end)
is RelativeSizeSpan -> {
val defaultSize = 12
addStyle(SpanStyle(fontSize = (span.sizeChange * defaultSize).sp), start, end)
}
is StyleSpan -> when (span.style) {
Typeface.BOLD -> addStyle(SpanStyle(fontWeight = FontWeight.Bold), start, end)
Typeface.ITALIC -> addStyle(SpanStyle(fontStyle = FontStyle.Italic), start, end)
Typeface.BOLD_ITALIC -> addStyle(
SpanStyle(fontWeight = FontWeight.Bold, fontStyle = FontStyle.Italic),
start,
end,
)
}
is UnderlineSpan -> addStyle(SpanStyle(textDecoration = TextDecoration.Underline), start, end)
}
}
}

@Preview
@Composable
private fun PreviewSettingsWearTemplateTile() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package io.homeassistant.companion.android.util.compose

import android.graphics.Typeface
import android.text.style.AbsoluteSizeSpan
import android.text.style.CharacterStyle
import android.text.style.ForegroundColorSpan
import android.text.style.RelativeSizeSpan
import android.text.style.StyleSpan
import android.text.style.UnderlineSpan
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.sp
import androidx.core.text.HtmlCompat

private val LINE_BREAK_REGEX = "(\r\n|\r|\n)|(\\\\r\\\\n|\\\\r|\\\\n)".toRegex()
private const val DEFAULT_RELATIVE_SIZE_SP = 12

/**
* Converts HTML, as returned by a rendered Home Assistant template, into an [AnnotatedString] by
* translating the [android.text.Spanned] styles produced by [HtmlCompat.fromHtml] into Compose
* [SpanStyle]s. Shared by every screen that displays a rendered template.
*/
fun parseHtml(renderedText: String): AnnotatedString = buildAnnotatedString {
// Replace both actual and literal (escaped) line break characters with <br>
val renderedSpanned = HtmlCompat.fromHtml(
renderedText.replace(LINE_BREAK_REGEX, "<br>"),
HtmlCompat.FROM_HTML_MODE_LEGACY,
)
append(renderedSpanned.toString())
renderedSpanned.getSpans(0, renderedSpanned.length, CharacterStyle::class.java).forEach { span ->
val start = renderedSpanned.getSpanStart(span)
val end = renderedSpanned.getSpanEnd(span)
when (span) {
is AbsoluteSizeSpan -> addStyle(SpanStyle(fontSize = span.size.sp), start, end)
is ForegroundColorSpan -> addStyle(SpanStyle(color = Color(span.foregroundColor)), start, end)
is RelativeSizeSpan -> {
addStyle(SpanStyle(fontSize = (span.sizeChange * DEFAULT_RELATIVE_SIZE_SP).sp), start, end)
}
is StyleSpan -> when (span.style) {
Typeface.BOLD -> addStyle(SpanStyle(fontWeight = FontWeight.Bold), start, end)
Typeface.ITALIC -> addStyle(SpanStyle(fontStyle = FontStyle.Italic), start, end)
Typeface.BOLD_ITALIC -> addStyle(
SpanStyle(fontWeight = FontWeight.Bold, fontStyle = FontStyle.Italic),
start,
end,
)
}
is UnderlineSpan -> addStyle(SpanStyle(textDecoration = TextDecoration.Underline), start, end)
}
}
}
Loading
Loading