Styling up the LocationDetail
This commit is contained in:
parent
e3cd0bdd4b
commit
b9d14d12ff
11 changed files with 156 additions and 55 deletions
|
|
@ -100,7 +100,7 @@ fun LexiconItem(
|
||||||
true -> emptyList()
|
true -> emptyList()
|
||||||
else -> listOf(
|
else -> listOf(
|
||||||
AnnotatedString.Range(
|
AnnotatedString.Range(
|
||||||
item = typography.dropCapMediumSpan,
|
item = typography.bodyDropCapSpan,
|
||||||
start = 0,
|
start = 0,
|
||||||
end = 1,
|
end = 1,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ import androidx.compose.ui.unit.IntSize
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.pixelized.rplexicon.ui.composable.AsyncImage
|
import com.pixelized.rplexicon.ui.composable.AsyncImage
|
||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||||
import com.pixelized.rplexicon.ui.theme.colors.LexiconColors
|
|
||||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||||
import com.skydoves.landscapist.ImageOptions
|
import com.skydoves.landscapist.ImageOptions
|
||||||
|
|
||||||
|
|
@ -39,12 +38,13 @@ import com.skydoves.landscapist.ImageOptions
|
||||||
fun FantasyMap(
|
fun FantasyMap(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
state: FantasyMapState,
|
state: FantasyMapState,
|
||||||
|
model: () -> Any?,
|
||||||
imageOptions: ImageOptions = ImageOptions(),
|
imageOptions: ImageOptions = ImageOptions(),
|
||||||
@DrawableRes previewPlaceholder: Int,
|
@DrawableRes previewPlaceholder: Int,
|
||||||
item: State<LocationDetailUio>,
|
items: State<List<AnnotatedMarqueeUio>>,
|
||||||
highlight: State<Offset>,
|
highlight: State<Offset>,
|
||||||
selectedItem: State<Int>,
|
selectedItem: State<Int>,
|
||||||
onMarquee: (MarqueeUio) -> Unit,
|
onMarquee: (AnnotatedMarqueeUio) -> Unit,
|
||||||
onTap: (Offset) -> Unit,
|
onTap: (Offset) -> Unit,
|
||||||
) {
|
) {
|
||||||
val lexiconTheme = MaterialTheme.lexicon
|
val lexiconTheme = MaterialTheme.lexicon
|
||||||
|
|
@ -68,7 +68,7 @@ fun FantasyMap(
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(key1 = "CenterOnMarquee:${selectedItem.value}") {
|
LaunchedEffect(key1 = "CenterOnMarquee:${selectedItem.value}") {
|
||||||
item.value.marquees.getOrNull(selectedItem.value)?.position
|
items.value.getOrNull(selectedItem.value)?.position
|
||||||
?.let { state.pan(state.computeMarqueeOffset(it)) }
|
?.let { state.pan(state.computeMarqueeOffset(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +115,7 @@ fun FantasyMap(
|
||||||
.drawWithContent {
|
.drawWithContent {
|
||||||
drawContent()
|
drawContent()
|
||||||
if (animatedMarqueeAlpha.value > 0f) {
|
if (animatedMarqueeAlpha.value > 0f) {
|
||||||
item.value.marquees.forEachIndexed { index, item ->
|
items.value.forEachIndexed { index, item ->
|
||||||
if (item.position != Offset.Unspecified) {
|
if (item.position != Offset.Unspecified) {
|
||||||
drawMarque(
|
drawMarque(
|
||||||
theme = lexiconTheme,
|
theme = lexiconTheme,
|
||||||
|
|
@ -147,7 +147,7 @@ fun FantasyMap(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val marquee = item.value.marquees
|
val marquee = items.value
|
||||||
.asReversed()
|
.asReversed()
|
||||||
.firstOrNull { item ->
|
.firstOrNull { item ->
|
||||||
if (item.position != Offset.Unspecified) {
|
if (item.position != Offset.Unspecified) {
|
||||||
|
|
@ -163,7 +163,7 @@ fun FantasyMap(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
imageModel = { item.value.map },
|
imageModel = model,
|
||||||
imageOptions = imageOptions,
|
imageOptions = imageOptions,
|
||||||
previewPlaceholder = previewPlaceholder,
|
previewPlaceholder = previewPlaceholder,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.pixelized.rplexicon.ui.screens.location.detail
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.ScrollState
|
import androidx.compose.foundation.ScrollState
|
||||||
import androidx.compose.foundation.gestures.scrollBy
|
import androidx.compose.foundation.gestures.scrollBy
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
|
@ -36,6 +37,7 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
|
@ -43,13 +45,18 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.graphics.RectangleShape
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.IntOffset
|
import androidx.compose.ui.unit.IntOffset
|
||||||
|
|
@ -62,7 +69,6 @@ import com.pixelized.rplexicon.ui.composable.Handle
|
||||||
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
|
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
|
||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||||
import com.pixelized.rplexicon.utilitary.rememberTextSize
|
|
||||||
import com.skydoves.landscapist.ImageOptions
|
import com.skydoves.landscapist.ImageOptions
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
|
@ -77,6 +83,13 @@ data class LocationDetailUio(
|
||||||
val marquees: List<MarqueeUio>,
|
val marquees: List<MarqueeUio>,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
data class AnnotatedLocationDetailUio(
|
||||||
|
val name: AnnotatedString,
|
||||||
|
val map: Uri,
|
||||||
|
val marquees: List<AnnotatedMarqueeUio>,
|
||||||
|
)
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun LocationDetail(
|
fun LocationDetail(
|
||||||
|
|
@ -94,6 +107,7 @@ fun LocationDetail(
|
||||||
|
|
||||||
val ok = stringResource(id = android.R.string.ok)
|
val ok = stringResource(id = android.R.string.ok)
|
||||||
|
|
||||||
|
val location = rememberAnnotation(item = viewModel.location)
|
||||||
val snackJob = remember { mutableStateOf<Job?>(null) }
|
val snackJob = remember { mutableStateOf<Job?>(null) }
|
||||||
val mapHighlight = remember { mutableStateOf(Offset.Unspecified) }
|
val mapHighlight = remember { mutableStateOf(Offset.Unspecified) }
|
||||||
val selectedIndex = remember { mutableStateOf(0) }
|
val selectedIndex = remember { mutableStateOf(0) }
|
||||||
|
|
@ -107,7 +121,7 @@ fun LocationDetail(
|
||||||
scrollState = scroll,
|
scrollState = scroll,
|
||||||
pagerState = pager,
|
pagerState = pager,
|
||||||
fantasyMapState = fantasy,
|
fantasyMapState = fantasy,
|
||||||
item = viewModel.location,
|
item = location,
|
||||||
selectedIndex = selectedIndex,
|
selectedIndex = selectedIndex,
|
||||||
mapHighlight = mapHighlight,
|
mapHighlight = mapHighlight,
|
||||||
onBack = {
|
onBack = {
|
||||||
|
|
@ -115,7 +129,7 @@ fun LocationDetail(
|
||||||
},
|
},
|
||||||
onMarquee = {
|
onMarquee = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val index = max(viewModel.location.value.marquees.indexOf(it), 0)
|
val index = max(location.value.marquees.indexOf(it), 0)
|
||||||
selectedIndex.value = index
|
selectedIndex.value = index
|
||||||
pager.animateScrollToPage(page = index)
|
pager.animateScrollToPage(page = index)
|
||||||
}
|
}
|
||||||
|
|
@ -195,18 +209,19 @@ private fun LocationContent(
|
||||||
scrollState: ScrollState,
|
scrollState: ScrollState,
|
||||||
pagerState: PagerState,
|
pagerState: PagerState,
|
||||||
fantasyMapState: FantasyMapState,
|
fantasyMapState: FantasyMapState,
|
||||||
item: State<LocationDetailUio>,
|
item: State<AnnotatedLocationDetailUio>,
|
||||||
selectedIndex: State<Int>,
|
selectedIndex: State<Int>,
|
||||||
mapHighlight: State<Offset>,
|
mapHighlight: State<Offset>,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onMarquee: (MarqueeUio) -> Unit,
|
onMarquee: (AnnotatedMarqueeUio) -> Unit,
|
||||||
onMapTap: (Offset) -> Unit,
|
onMapTap: (Offset) -> Unit,
|
||||||
onTouch: (Boolean) -> Unit,
|
onTouch: (Boolean) -> Unit,
|
||||||
onCenter: () -> Unit,
|
onCenter: () -> Unit,
|
||||||
onZoomIn: () -> Unit,
|
onZoomIn: () -> Unit,
|
||||||
onZoomOut: () -> Unit,
|
onZoomOut: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val itemNameSize = rememberTextSize(style = MaterialTheme.typography.headlineSmall)
|
val density = LocalDensity.current
|
||||||
|
val itemNameSize = remember { mutableStateOf(0.dp) }
|
||||||
|
|
||||||
val filledIconButtonColors = IconButtonDefaults.filledIconButtonColors(
|
val filledIconButtonColors = IconButtonDefaults.filledIconButtonColors(
|
||||||
containerColor = MaterialTheme.colorScheme.surface,
|
containerColor = MaterialTheme.colorScheme.surface,
|
||||||
|
|
@ -261,9 +276,10 @@ private fun LocationContent(
|
||||||
.align(alignment = Alignment.Center)
|
.align(alignment = Alignment.Center)
|
||||||
.offset { IntOffset(x = 0, y = scrollState.value / 2) },
|
.offset { IntOffset(x = 0, y = scrollState.value / 2) },
|
||||||
state = fantasyMapState,
|
state = fantasyMapState,
|
||||||
|
model = { item.value.map },
|
||||||
previewPlaceholder = R.drawable.im_brulkhai,
|
previewPlaceholder = R.drawable.im_brulkhai,
|
||||||
imageOptions = ImageOptions(contentScale = ContentScale.Fit),
|
imageOptions = ImageOptions(contentScale = ContentScale.Fit),
|
||||||
item = item,
|
items = remember { derivedStateOf { item.value.marquees } },
|
||||||
selectedItem = selectedIndex,
|
selectedItem = selectedIndex,
|
||||||
highlight = mapHighlight,
|
highlight = mapHighlight,
|
||||||
onMarquee = onMarquee,
|
onMarquee = onMarquee,
|
||||||
|
|
@ -323,18 +339,32 @@ private fun LocationContent(
|
||||||
Handle(
|
Handle(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(alignment = Alignment.CenterHorizontally)
|
.align(alignment = Alignment.CenterHorizontally)
|
||||||
.padding(top = 16.dp)
|
.padding(vertical = 16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(alignment = Alignment.CenterHorizontally)
|
.onSizeChanged { itemNameSize.value = with(density) { it.height.toDp() } }
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
.padding(top = 16.dp),
|
.fillMaxWidth(),
|
||||||
textAlign = TextAlign.Center,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
) {
|
||||||
text = item.value.name,
|
Text(
|
||||||
)
|
textAlign = TextAlign.Center,
|
||||||
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
|
text = item.value.name,
|
||||||
|
)
|
||||||
|
Image(
|
||||||
|
modifier = Modifier
|
||||||
|
.height(24.dp)
|
||||||
|
.graphicsLayer { rotationZ = 180f },
|
||||||
|
painter = painterResource(id = R.drawable.art_divider_1),
|
||||||
|
contentScale = ContentScale.FillWidth,
|
||||||
|
alignment = Alignment.Center,
|
||||||
|
colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.onSurface),
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -350,7 +380,7 @@ private fun LocationContent(
|
||||||
MarqueeItem(
|
MarqueeItem(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(this@constraint.maxHeight - 32.dp - itemNameSize.height),
|
.height(this@constraint.maxHeight - 32.dp - itemNameSize.value),
|
||||||
marquee = marquee,
|
marquee = marquee,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -378,6 +408,31 @@ private fun HandlePagerScroll(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Stable
|
||||||
|
fun rememberAnnotation(item: State<LocationDetailUio>): State<AnnotatedLocationDetailUio> {
|
||||||
|
val typography = MaterialTheme.lexicon.typography
|
||||||
|
|
||||||
|
return remember(item) {
|
||||||
|
derivedStateOf {
|
||||||
|
AnnotatedLocationDetailUio(
|
||||||
|
name = AnnotatedString(
|
||||||
|
text = item.value.name,
|
||||||
|
spanStyles = listOf(
|
||||||
|
AnnotatedString.Range(
|
||||||
|
item = typography.titleDropCapSpan,
|
||||||
|
start = 0,
|
||||||
|
end = Integer.min(1, item.value.name.length),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
map = item.value.map,
|
||||||
|
marquees = item.value.marquees.map { it.annotate(typography) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@Stable
|
@Stable
|
||||||
private fun rememberSnapConnection(
|
private fun rememberSnapConnection(
|
||||||
|
|
@ -437,7 +492,7 @@ private fun LocationPreview() {
|
||||||
scrollState = rememberScrollState(),
|
scrollState = rememberScrollState(),
|
||||||
pagerState = rememberPagerState(),
|
pagerState = rememberPagerState(),
|
||||||
fantasyMapState = rememberFantasyMapState(),
|
fantasyMapState = rememberFantasyMapState(),
|
||||||
item = remember {
|
item = rememberAnnotation(item = remember {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
LocationDetailUio(
|
LocationDetailUio(
|
||||||
name = "Daggerfall",
|
name = "Daggerfall",
|
||||||
|
|
@ -456,7 +511,7 @@ private fun LocationPreview() {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
}),
|
||||||
selectedIndex = remember { mutableStateOf(0) },
|
selectedIndex = remember { mutableStateOf(0) },
|
||||||
mapHighlight = remember { mutableStateOf(Offset(0.5f, 0.5f)) },
|
mapHighlight = remember { mutableStateOf(Offset(0.5f, 0.5f)) },
|
||||||
onBack = { },
|
onBack = { },
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package com.pixelized.rplexicon.ui.screens.location.detail
|
||||||
|
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.geometry.Offset
|
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.pixelized.rplexicon.repository.LocationRepository
|
import com.pixelized.rplexicon.repository.LocationRepository
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@ package com.pixelized.rplexicon.ui.screens.location.detail
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
|
@ -14,11 +13,16 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||||
|
import com.pixelized.rplexicon.ui.theme.typography.LexiconTypography
|
||||||
|
import com.pixelized.rplexicon.utilitary.LOS_HOLLOW
|
||||||
|
import com.pixelized.rplexicon.utilitary.extentions.annotateWithDropCap
|
||||||
|
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
data class MarqueeUio(
|
data class MarqueeUio(
|
||||||
|
|
@ -27,23 +31,49 @@ data class MarqueeUio(
|
||||||
val description: String?,
|
val description: String?,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
data class AnnotatedMarqueeUio(
|
||||||
|
val name: AnnotatedString,
|
||||||
|
val position: Offset,
|
||||||
|
val description: AnnotatedString?,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
fun MarqueeUio.annotate(
|
||||||
|
typography: LexiconTypography
|
||||||
|
): AnnotatedMarqueeUio {
|
||||||
|
return AnnotatedMarqueeUio(
|
||||||
|
name = name.annotateWithDropCap(style = typography.bodyDropCapSpan),
|
||||||
|
position = position,
|
||||||
|
description = description?.annotateWithDropCap(style = typography.bodyDropCapSpan),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MarqueeItem(
|
fun MarqueeItem(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
marquee: MarqueeUio,
|
marquee: AnnotatedMarqueeUio,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
verticalArrangement = Arrangement.spacedBy(space = 8.dp)
|
verticalArrangement = Arrangement.spacedBy(space = 8.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
textAlign = TextAlign.Center,
|
) {
|
||||||
overflow = TextOverflow.Ellipsis,
|
Text(
|
||||||
maxLines = 1,
|
modifier = Modifier.alignByBaseline(),
|
||||||
style = MaterialTheme.typography.titleMedium,
|
text = LOS_HOLLOW,
|
||||||
text = marquee.name,
|
)
|
||||||
)
|
Text(
|
||||||
|
modifier = Modifier.alignByBaseline(),
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
maxLines = 3,
|
||||||
|
text = marquee.name,
|
||||||
|
)
|
||||||
|
}
|
||||||
marquee.description?.let {
|
marquee.description?.let {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.verticalScroll(rememberScrollState()),
|
modifier = Modifier.verticalScroll(rememberScrollState()),
|
||||||
|
|
@ -65,6 +95,8 @@ private fun MarqueeItemPreview() {
|
||||||
name = "Name",
|
name = "Name",
|
||||||
position = Offset.Zero,
|
position = Offset.Zero,
|
||||||
description = "description",
|
description = "description",
|
||||||
|
).annotate(
|
||||||
|
typography = MaterialTheme.lexicon.typography,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ fun LocationItem(
|
||||||
true -> emptyList()
|
true -> emptyList()
|
||||||
else -> listOf(
|
else -> listOf(
|
||||||
AnnotatedString.Range(
|
AnnotatedString.Range(
|
||||||
item = typography.dropCapMediumSpan,
|
item = typography.bodyDropCapSpan,
|
||||||
start = 0,
|
start = 0,
|
||||||
end = 1,
|
end = 1,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.graphics.ColorMatrix
|
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
|
@ -129,7 +128,7 @@ private fun QuestDetailUio.QuestStep.annotate(): AnnotatedQuestDetailUio.Annotat
|
||||||
text = description,
|
text = description,
|
||||||
spanStyles = listOf(
|
spanStyles = listOf(
|
||||||
AnnotatedString.Range(
|
AnnotatedString.Range(
|
||||||
item = typography.dropCapLargeSpan,
|
item = typography.bodyDropCapSpan,
|
||||||
start = 0,
|
start = 0,
|
||||||
end = min(1, description.length),
|
end = min(1, description.length),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ fun QuestItem(
|
||||||
true -> emptyList()
|
true -> emptyList()
|
||||||
else -> listOf(
|
else -> listOf(
|
||||||
AnnotatedString.Range(
|
AnnotatedString.Range(
|
||||||
item = typography.dropCapMediumSpan,
|
item = typography.bodyDropCapSpan,
|
||||||
start = 0,
|
start = 0,
|
||||||
end = 1,
|
end = 1,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ fun lexiconDimen(
|
||||||
thickness = 4.dp,
|
thickness = 4.dp,
|
||||||
),
|
),
|
||||||
map: LexiconDimens.Map = LexiconDimens.Map(
|
map: LexiconDimens.Map = LexiconDimens.Map(
|
||||||
mapSnapPx = with(density) { 64.dp.roundToPx() },
|
mapSnapPx = with(density) { 128.dp.roundToPx() },
|
||||||
marqueeRadiusPx = with(density) { 12.dp.roundToPx() },
|
marqueeRadiusPx = with(density) { 12.dp.roundToPx() },
|
||||||
marqueeStrokePx = with(density) { 2.dp.roundToPx() },
|
marqueeStrokePx = with(density) { 2.dp.roundToPx() },
|
||||||
crossRadiusPx = with(density) { 12.dp.roundToPx() / sqrt(2f) }.toInt(),
|
crossRadiusPx = with(density) { 12.dp.roundToPx() / sqrt(2f) }.toInt(),
|
||||||
|
|
|
||||||
|
|
@ -24,22 +24,19 @@ val stampFontFamily = FontFamily(
|
||||||
@Stable
|
@Stable
|
||||||
class LexiconTypography(
|
class LexiconTypography(
|
||||||
val base: Typography = Typography(),
|
val base: Typography = Typography(),
|
||||||
val dropCapMedium: TextStyle = base.displaySmall.copy(
|
val stamp: TextStyle = base.headlineLarge.copy(
|
||||||
|
fontFamily = stampFontFamily,
|
||||||
|
),
|
||||||
|
val bodyDropCapSpan: SpanStyle = base.displaySmall.copy(
|
||||||
fontFamily = regalFontFamily,
|
fontFamily = regalFontFamily,
|
||||||
baselineShift = BaselineShift(-0.3f),
|
baselineShift = BaselineShift(-0.3f),
|
||||||
letterSpacing = (-6).sp
|
letterSpacing = (-6).sp
|
||||||
),
|
).toSpanStyle(),
|
||||||
val dropCapLarge: TextStyle = base.displayMedium.copy(
|
val titleDropCapSpan: SpanStyle = base.displayLarge.copy(
|
||||||
fontFamily = regalFontFamily,
|
fontFamily = regalFontFamily,
|
||||||
baselineShift = BaselineShift.Subscript,
|
baselineShift = BaselineShift(-0.3f),
|
||||||
letterSpacing = (-8).sp
|
letterSpacing = (-8).sp
|
||||||
),
|
).toSpanStyle()
|
||||||
val stamp: TextStyle = base.headlineLarge.copy(
|
)
|
||||||
fontFamily = stampFontFamily,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
val dropCapMediumSpan: SpanStyle = dropCapMedium.toSpanStyle()
|
|
||||||
val dropCapLargeSpan: SpanStyle = dropCapLarge.toSpanStyle()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun lexiconTypography() = LexiconTypography()
|
fun lexiconTypography() = LexiconTypography()
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
package com.pixelized.rplexicon.utilitary.extentions
|
package com.pixelized.rplexicon.utilitary.extentions
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.view.accessibility.AccessibilityNodeInfo
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
|
||||||
val String.ARG: String get() = "$this={$this}"
|
val String.ARG: String get() = "$this={$this}"
|
||||||
|
|
@ -24,3 +28,18 @@ fun String?.toUriOrNull(): Uri? = try {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val dropCapRegex = Regex("(?:\n\n)(.)")
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
fun String.annotateWithDropCap(
|
||||||
|
style: SpanStyle,
|
||||||
|
) = AnnotatedString(
|
||||||
|
text = this,
|
||||||
|
spanStyles = listOf(
|
||||||
|
AnnotatedString.Range(
|
||||||
|
item = style,
|
||||||
|
start = 0,
|
||||||
|
end = Integer.min(1, this.length),
|
||||||
|
),
|
||||||
|
) + dropCapRegex.annotatedSpan(input = this, spanStyle = style)
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue