mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-08-29 07:16:08 +00:00
Stabilize globe quality selector layout
This commit is contained in:
parent
8602db88de
commit
6fc4583a15
@ -95,13 +95,18 @@ class GeohashPickerActivity : OrientationAwareActivity() {
|
||||
BitchatTheme {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val initialRenderQuality = remember(context) {
|
||||
GlobeRenderQualityPreference.load(context)
|
||||
}
|
||||
var renderQuality by remember { mutableStateOf(initialRenderQuality) }
|
||||
|
||||
val globeState = remember {
|
||||
GlobeState(
|
||||
targetLat = targetLat,
|
||||
targetLon = targetLon,
|
||||
initialPrecision = initialPrecision,
|
||||
startZoomedOut = true
|
||||
startZoomedOut = true,
|
||||
initialRenderQuality = initialRenderQuality
|
||||
).apply {
|
||||
introTarget = Triple(targetLat, targetLon, initialPrecision)
|
||||
}
|
||||
@ -157,9 +162,6 @@ class GeohashPickerActivity : OrientationAwareActivity() {
|
||||
|
||||
val labelTypeface = remember { ResourcesCompat.getFont(context, R.font.geist_mono_medium) }
|
||||
val labelTypefaceBold = remember { ResourcesCompat.getFont(context, R.font.geist_mono_semibold) }
|
||||
var renderQuality by remember {
|
||||
mutableStateOf(GlobeRenderQualityPreference.load(context))
|
||||
}
|
||||
|
||||
Box(
|
||||
Modifier
|
||||
@ -173,7 +175,6 @@ class GeohashPickerActivity : OrientationAwareActivity() {
|
||||
land = rings,
|
||||
borders = borders,
|
||||
cities = cities,
|
||||
renderQuality = renderQuality,
|
||||
labelTypeface = labelTypeface,
|
||||
labelTypefaceBold = labelTypefaceBold,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
@ -210,9 +211,11 @@ class GeohashPickerActivity : OrientationAwareActivity() {
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
qualities.forEachIndexed { index, quality ->
|
||||
val selected = renderQuality == quality
|
||||
SegmentedButton(
|
||||
selected = renderQuality == quality,
|
||||
selected = selected,
|
||||
onClick = {
|
||||
globeState.setRenderQuality(quality)
|
||||
renderQuality = quality
|
||||
GlobeRenderQualityPreference.save(context, quality)
|
||||
},
|
||||
@ -220,12 +223,27 @@ class GeohashPickerActivity : OrientationAwareActivity() {
|
||||
index = index,
|
||||
count = qualities.size
|
||||
),
|
||||
icon = {},
|
||||
label = {
|
||||
Text(
|
||||
text = stringResource(quality.labelResource),
|
||||
fontSize = 11.sp,
|
||||
fontFamily = BitchatFontFamily
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (selected) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Check,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.size(18.dp)
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = stringResource(quality.labelResource),
|
||||
fontSize = 11.sp,
|
||||
fontFamily = BitchatFontFamily
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@ -28,7 +28,8 @@ class GlobeState(
|
||||
targetLat: Double,
|
||||
targetLon: Double,
|
||||
initialPrecision: Int,
|
||||
startZoomedOut: Boolean
|
||||
startZoomedOut: Boolean,
|
||||
initialRenderQuality: GlobeRenderQuality = GlobeRenderQuality.MEDIUM
|
||||
) {
|
||||
var centerLat by mutableFloatStateOf(if (startZoomedOut) (targetLat * 0.4).toFloat() else targetLat.toFloat())
|
||||
private set
|
||||
@ -47,6 +48,8 @@ class GlobeState(
|
||||
|
||||
internal var baseRadiusPx by mutableFloatStateOf(0f)
|
||||
internal var screenMinPx by mutableFloatStateOf(0f)
|
||||
internal var renderQuality = initialRenderQuality
|
||||
private set
|
||||
|
||||
private var scope: CoroutineScope? = null
|
||||
private var animJob: Job? = null
|
||||
@ -68,6 +71,14 @@ class GlobeState(
|
||||
this.scope = scope
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering quality only affects moving frames. This is deliberately not snapshot state:
|
||||
* changing it must not invalidate the expensive stationary globe beneath the selector.
|
||||
*/
|
||||
fun setRenderQuality(quality: GlobeRenderQuality) {
|
||||
renderQuality = quality
|
||||
}
|
||||
|
||||
fun setViewport(baseRadiusPx: Float, screenMinPx: Float) {
|
||||
if (baseRadiusPx <= 0f || screenMinPx <= 0f) return
|
||||
this.baseRadiusPx = baseRadiusPx
|
||||
|
||||
@ -119,7 +119,6 @@ fun GlobeView(
|
||||
land: List<LandData.Ring>,
|
||||
borders: List<LandData.Ring>,
|
||||
cities: List<LandData.City>,
|
||||
renderQuality: GlobeRenderQuality,
|
||||
labelTypeface: Typeface?,
|
||||
labelTypefaceBold: Typeface?,
|
||||
modifier: Modifier = Modifier
|
||||
@ -324,7 +323,7 @@ fun GlobeView(
|
||||
|
||||
val clip = ClipRect(-size.width, -size.height, size.width * 2f, size.height * 2f)
|
||||
|
||||
val frameDetail = globeFrameDetail(renderQuality, state.isInMotion)
|
||||
val frameDetail = globeFrameDetail(state.renderQuality, state.isInMotion)
|
||||
|
||||
// Graticule
|
||||
drawGraticule(
|
||||
|
||||
@ -14,6 +14,21 @@ class GlobeRenderQualityTest {
|
||||
assertEquals(GlobeRenderQuality.MEDIUM, GlobeRenderQuality.fromStoredValue("UNKNOWN"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun globeState_usesAndUpdatesRenderQualityWithoutReplacingState() {
|
||||
val state = GlobeState(
|
||||
targetLat = 0.0,
|
||||
targetLon = 0.0,
|
||||
initialPrecision = 2,
|
||||
startZoomedOut = false,
|
||||
initialRenderQuality = GlobeRenderQuality.FAST
|
||||
)
|
||||
|
||||
assertEquals(GlobeRenderQuality.FAST, state.renderQuality)
|
||||
state.setRenderQuality(GlobeRenderQuality.HIGH)
|
||||
assertEquals(GlobeRenderQuality.HIGH, state.renderQuality)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun stationaryFrame_alwaysUsesFullDetail() {
|
||||
GlobeRenderQuality.entries.forEach { quality ->
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user