Skip to content

Commit b00ae2a

Browse files
author
Lalit Sharma
committed
Add debug overlay functionality: enable/disable overlay and display coordinates and UTC time
1 parent 40b1c47 commit b00ae2a

2 files changed

Lines changed: 183 additions & 1 deletion

File tree

apps/mobile/android/wear/src/main/java/com/lallimaven/eclipsetimer/wear/EclipseRenderView.kt

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@ import android.content.Context
44
import android.graphics.Canvas
55
import android.graphics.Color
66
import android.graphics.Paint
7+
import android.graphics.RectF
8+
import android.graphics.Typeface
79
import android.util.AttributeSet
810
import android.view.View
11+
import java.time.Instant
12+
import java.time.ZoneOffset
13+
import java.time.format.DateTimeFormatter
14+
import java.util.Locale
915
import kotlin.math.hypot
1016
import kotlin.math.max
1117
import kotlin.math.min
@@ -45,12 +51,49 @@ class EclipseRenderView @JvmOverloads constructor(
4551
style = Paint.Style.STROKE
4652
color = Color.rgb(230, 243, 255)
4753
}
54+
private val debugPanelPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
55+
style = Paint.Style.FILL
56+
color = Color.parseColor("#8A000000")
57+
}
58+
private val debugPanelStrokePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
59+
style = Paint.Style.STROKE
60+
color = Color.parseColor("#66FFFFFF")
61+
}
62+
private val debugTextPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
63+
style = Paint.Style.FILL
64+
color = Color.WHITE
65+
textAlign = Paint.Align.CENTER
66+
typeface = Typeface.MONOSPACE
67+
}
4868

4969
private var showMoon = false
5070
private var sunRadiusNorm = DEFAULT_SUN_RADIUS_NORM
5171
private var moonRadiusNorm = 0f
5272
private var moonCenterXNorm = DEFAULT_CENTER_NORM
5373
private var moonCenterYNorm = DEFAULT_CENTER_NORM
74+
private var debugOverlayEnabled = false
75+
private var debugLatitudeDeg: Double? = null
76+
private var debugLongitudeDeg: Double? = null
77+
private var debugEpochMillis: Long = System.currentTimeMillis()
78+
79+
fun setDebugOverlayEnabled(enabled: Boolean) {
80+
if (debugOverlayEnabled == enabled) {
81+
return
82+
}
83+
debugOverlayEnabled = enabled
84+
invalidate()
85+
}
86+
87+
fun updateDebugOverlay(
88+
latitudeDeg: Double?,
89+
longitudeDeg: Double?,
90+
epochMillis: Long,
91+
) {
92+
debugLatitudeDeg = latitudeDeg
93+
debugLongitudeDeg = longitudeDeg
94+
debugEpochMillis = epochMillis
95+
invalidate()
96+
}
5497

5598
fun renderSunOnly(sunRadiusNorm: Float = DEFAULT_SUN_RADIUS_NORM) {
5699
showMoon = false
@@ -126,6 +169,7 @@ class EclipseRenderView @JvmOverloads constructor(
126169
canvas.drawCircle(centerX, centerY, max(1f, sunRadius - 1.5f), sunRingPaint)
127170

128171
if (!showMoon) {
172+
drawDebugOverlay(canvas, centerX, centerY, minDimension)
129173
return
130174
}
131175

@@ -154,6 +198,8 @@ class EclipseRenderView @JvmOverloads constructor(
154198
(moonRadius + minDimension * TOTALITY_RING_OFFSET_NORM) * totalityRingScale
155199
canvas.drawCircle(moonCenterX, moonCenterY, totalityRingRadius, totalityRingPaint)
156200
}
201+
202+
drawDebugOverlay(canvas, centerX, centerY, minDimension)
157203
}
158204

159205
private fun calculateTotalityBlend(
@@ -182,7 +228,61 @@ class EclipseRenderView @JvmOverloads constructor(
182228
return t * t * (3f - 2f * t)
183229
}
184230

231+
private fun drawDebugOverlay(
232+
canvas: Canvas,
233+
centerX: Float,
234+
centerY: Float,
235+
minDimension: Float,
236+
) {
237+
if (!debugOverlayEnabled) {
238+
return
239+
}
240+
241+
val coordinateText = if (debugLatitudeDeg != null && debugLongitudeDeg != null) {
242+
String.format(
243+
Locale.US,
244+
"LAT %.4f LON %.4f",
245+
debugLatitudeDeg,
246+
debugLongitudeDeg,
247+
)
248+
} else {
249+
"LAT --.-- LON --.--"
250+
}
251+
val utcText = "UTC ${DEBUG_TIME_FORMATTER.format(Instant.ofEpochMilli(debugEpochMillis))}"
252+
253+
val textSize = max(9f, minDimension * DEBUG_TEXT_SIZE_RATIO)
254+
debugTextPaint.textSize = textSize
255+
val lineHeight = textSize * DEBUG_LINE_HEIGHT_MULTIPLIER
256+
val panelPaddingX = textSize * 0.7f
257+
val panelPaddingY = textSize * 0.5f
258+
val panelWidth = max(
259+
debugTextPaint.measureText(coordinateText),
260+
debugTextPaint.measureText(utcText),
261+
) + panelPaddingX * 2f
262+
val panelHeight = lineHeight * 2f + panelPaddingY * 2f
263+
val panelRect = RectF(
264+
centerX - panelWidth / 2f,
265+
centerY - panelHeight / 2f,
266+
centerX + panelWidth / 2f,
267+
centerY + panelHeight / 2f,
268+
)
269+
val cornerRadius = max(8f, textSize * 0.7f)
270+
debugPanelStrokePaint.strokeWidth = max(1f, textSize * 0.08f)
271+
272+
canvas.drawRoundRect(panelRect, cornerRadius, cornerRadius, debugPanelPaint)
273+
canvas.drawRoundRect(panelRect, cornerRadius, cornerRadius, debugPanelStrokePaint)
274+
275+
val firstLineBaseline =
276+
panelRect.top + panelPaddingY - debugTextPaint.fontMetrics.ascent
277+
val secondLineBaseline = firstLineBaseline + lineHeight
278+
279+
canvas.drawText(coordinateText, centerX, firstLineBaseline, debugTextPaint)
280+
canvas.drawText(utcText, centerX, secondLineBaseline, debugTextPaint)
281+
}
282+
185283
companion object {
284+
private val DEBUG_TIME_FORMATTER: DateTimeFormatter =
285+
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC)
186286
private const val DEFAULT_SUN_RADIUS_NORM = 0.24f
187287
private const val SUN_GLOW_MULTIPLIER = 1.65f
188288
private const val RENDER_ZOOM_MULTIPLIER = 1.9f
@@ -199,5 +299,7 @@ class EclipseRenderView @JvmOverloads constructor(
199299
private const val TOTALITY_RING_STROKE_NORM = 4f / 300f
200300
private const val TOTALITY_CORONA_STROKE_NORM = 16f / 300f
201301
private const val MIN_VISIBLE_TOTALITY_BLEND = 0.002f
302+
private const val DEBUG_TEXT_SIZE_RATIO = 0.041f
303+
private const val DEBUG_LINE_HEIGHT_MULTIPLIER = 1.2f
202304
}
203305
}

apps/mobile/android/wear/src/main/java/com/lallimaven/eclipsetimer/wear/MainActivity.kt

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class MainActivity : ComponentActivity(), MessageClient.OnMessageReceivedListene
8484
private var activePreviewPayload: PreviewRenderPayload? = null
8585
private var activePreviewSessionId: String? = null
8686
private var previewProgressNorm = 0f
87+
private var debugOverlayEnabled = false
8788
private var connectedPhoneNodeId: String? = null
8889
private var lastSentPreviewScrubProgressNorm = Float.NaN
8990
private var lastSentPreviewScrubElapsedRealtimeMs = 0L
@@ -122,6 +123,12 @@ class MainActivity : ComponentActivity(), MessageClient.OnMessageReceivedListene
122123
setContentView(R.layout.activity_main)
123124
eclipseRenderView = findViewById(R.id.eclipse_render_view)
124125
statusText = findViewById(R.id.status_text)
126+
eclipseRenderView.setDebugOverlayEnabled(debugOverlayEnabled)
127+
eclipseRenderView.updateDebugOverlay(
128+
latitudeDeg = null,
129+
longitudeDeg = null,
130+
epochMillis = System.currentTimeMillis(),
131+
)
125132
eclipseRenderView.renderSunOnly()
126133
showErrorStatus(R.string.status_acquiring_location)
127134
applyDeepLink(intent)
@@ -354,17 +361,28 @@ class MainActivity : ComponentActivity(), MessageClient.OnMessageReceivedListene
354361
return
355362
}
356363

364+
val nowMs = System.currentTimeMillis()
357365
val location = latestObservedLocation
358366
if (location == null) {
367+
eclipseRenderView.updateDebugOverlay(
368+
latitudeDeg = null,
369+
longitudeDeg = null,
370+
epochMillis = nowMs,
371+
)
359372
eclipseRenderView.renderSunOnly()
360373
showErrorStatus(R.string.status_acquiring_location)
361374
return
362375
}
363376

377+
eclipseRenderView.updateDebugOverlay(
378+
latitudeDeg = location.latitude,
379+
longitudeDeg = location.longitude,
380+
epochMillis = nowMs,
381+
)
364382
val localGeometry = LocalSunMoonCalculator.calculateLiveGeometry(
365383
latitudeDeg = location.latitude,
366384
longitudeDeg = location.longitude,
367-
epochMillis = System.currentTimeMillis(),
385+
epochMillis = nowMs,
368386
)
369387
val payload = LiveRenderPayload(
370388
showMoon = localGeometry.showMoon,
@@ -489,6 +507,13 @@ class MainActivity : ComponentActivity(), MessageClient.OnMessageReceivedListene
489507

490508
private fun renderPreviewFrame() {
491509
val payload = activePreviewPayload ?: return
510+
val nowMs = System.currentTimeMillis()
511+
val location = latestObservedLocation
512+
eclipseRenderView.updateDebugOverlay(
513+
latitudeDeg = location?.latitude,
514+
longitudeDeg = location?.longitude,
515+
epochMillis = nowMs,
516+
)
492517

493518
val axisOffsetNorm = interpolatePreviewAxisOffset(
494519
progressNorm = previewProgressNorm,
@@ -847,10 +872,65 @@ class MainActivity : ComponentActivity(), MessageClient.OnMessageReceivedListene
847872
return
848873
}
849874

875+
parseDebugOverlayEnabled(data)?.let { enabled ->
876+
setDebugOverlayEnabled(
877+
enabled = enabled,
878+
source = "deep_link",
879+
)
880+
}
881+
850882
val label = formatDeepLinkLabel(data)
851883
activeDeepLinkLabel = label
852884
}
853885

886+
private fun setDebugOverlayEnabled(
887+
enabled: Boolean,
888+
source: String,
889+
) {
890+
if (debugOverlayEnabled == enabled) {
891+
return
892+
}
893+
debugOverlayEnabled = enabled
894+
eclipseRenderView.setDebugOverlayEnabled(enabled)
895+
logInfo(
896+
"debug_overlay_toggled",
897+
"enabled" to enabled,
898+
"source" to source,
899+
)
900+
}
901+
902+
private fun parseDebugOverlayEnabled(uri: Uri): Boolean? {
903+
val keyCandidates = listOf("debugOverlay", "overlay", "debug", "enabled")
904+
for (key in keyCandidates) {
905+
val rawValue = uri.getQueryParameter(key) ?: continue
906+
parseBooleanToggle(rawValue)?.let { return it }
907+
}
908+
909+
val normalizedPath = uri.path.orEmpty().lowercase()
910+
if (
911+
normalizedPath.endsWith("/debug-overlay/on") ||
912+
normalizedPath.endsWith("/overlay/on")
913+
) {
914+
return true
915+
}
916+
if (
917+
normalizedPath.endsWith("/debug-overlay/off") ||
918+
normalizedPath.endsWith("/overlay/off")
919+
) {
920+
return false
921+
}
922+
923+
return null
924+
}
925+
926+
private fun parseBooleanToggle(rawValue: String): Boolean? {
927+
return when (rawValue.trim().lowercase()) {
928+
"1", "true", "on", "yes", "enabled" -> true
929+
"0", "false", "off", "no", "disabled" -> false
930+
else -> null
931+
}
932+
}
933+
854934
private fun showErrorStatus(messageResId: Int, vararg formatArgs: Any) {
855935
statusText.visibility = View.VISIBLE
856936
statusText.text = if (formatArgs.isNotEmpty()) {

0 commit comments

Comments
 (0)