Skip to content

Commit 0b98114

Browse files
authored
Fix MAX View sun/moon sizing ratios (#8)
1 parent fc3f699 commit 0b98114

5 files changed

Lines changed: 84 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.1.19] — 2026-02-23
9+
10+
### Fixed
11+
- Corrected Timer screen compact `MAX View` moon/sun sizing so moon-size ratios now match the full preview geometry instead of using oversized fixed moon radii.
12+
13+
### Changed
14+
- Bumped `apps/mobile` version to `1.1.19`.
15+
16+
### Tests
17+
- Added regression tests to verify compact-stage moon/sun ratio scaling and C1/C4 tangency distance in the Timer screen `MAX View` size profile.
18+
819
## [1.1.18] — 2026-02-23
920

1021
### Added

apps/mobile/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@eclipse-timer/mobile",
3-
"version": "1.1.18",
3+
"version": "1.1.19",
44
"private": true,
55
"main": "index.js",
66
"scripts": {

apps/mobile/src/screens/TimerScreen.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import { eclipseCenterForRecord, kindCodeForRecord } from "../utils/eclipse";
2727
import {
2828
calculatePreviewMoonGeometry,
2929
determinePreviewTravelVector,
30+
PREVIEW_STAGE_SIZE,
31+
PREVIEW_SUN_RADIUS,
3032
} from "../utils/previewGeometry";
3133

3234
const VISIBLE_PATH_COLOR = "rgba(79, 195, 247, 0.22)";
@@ -36,7 +38,8 @@ const FAVORITE_COORD_EPSILON = 0.0001;
3638
const DEG2RAD = Math.PI / 180;
3739
const RAD2DEG = 180 / Math.PI;
3840
const TIMER_HERO_PREVIEW_STAGE_SIZE = 84;
39-
const TIMER_HERO_PREVIEW_SUN_RADIUS = 19;
41+
const TIMER_HERO_PREVIEW_SUN_RADIUS =
42+
(TIMER_HERO_PREVIEW_STAGE_SIZE * PREVIEW_SUN_RADIUS) / PREVIEW_STAGE_SIZE;
4043
const TIMER_HERO_PREVIEW_GLOW_SIZE = 118;
4144

4245
function localKindLabel(kind: "none" | "partial" | "total" | "annular") {

apps/mobile/src/utils/previewGeometry.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ import type { EclipseKindAtLocation } from "@eclipse-timer/shared";
22

33
export const PREVIEW_SUN_RADIUS = 72;
44
export const PREVIEW_STAGE_SIZE = 300;
5+
const ANNULAR_RADIUS_RATIO = 58 / PREVIEW_SUN_RADIUS;
6+
const TOTAL_RADIUS_RATIO = 76 / PREVIEW_SUN_RADIUS;
7+
const PARTIAL_RADIUS_RATIO = 68 / PREVIEW_SUN_RADIUS;
8+
const NONE_RADIUS_RATIO = 66 / PREVIEW_SUN_RADIUS;
9+
const NONE_GAP_RATIO = 14 / PREVIEW_SUN_RADIUS;
10+
const PARTIAL_INTERNAL_MARGIN_RATIO = 6 / PREVIEW_SUN_RADIUS;
511

612
export type PreviewMotionContacts = {
713
c1?: number;
@@ -98,11 +104,14 @@ export function describePreviewTravelDirection(vector: PreviewTravelVector): str
98104
return `${vertical}, ${horizontal}`;
99105
}
100106

101-
export function determineMoonRadius(kindAtLocation: EclipseKindAtLocation) {
102-
if (kindAtLocation === "annular") return 58;
103-
if (kindAtLocation === "total") return 76;
104-
if (kindAtLocation === "partial") return 68;
105-
return 66;
107+
export function determineMoonRadius(
108+
kindAtLocation: EclipseKindAtLocation,
109+
sunRadius = PREVIEW_SUN_RADIUS,
110+
) {
111+
if (kindAtLocation === "annular") return sunRadius * ANNULAR_RADIUS_RATIO;
112+
if (kindAtLocation === "total") return sunRadius * TOTAL_RADIUS_RATIO;
113+
if (kindAtLocation === "partial") return sunRadius * PARTIAL_RADIUS_RATIO;
114+
return sunRadius * NONE_RADIUS_RATIO;
106115
}
107116

108117
export function determineApproachOffset(
@@ -112,13 +121,13 @@ export function determineApproachOffset(
112121
sunRadius = PREVIEW_SUN_RADIUS,
113122
) {
114123
if (kindAtLocation === "none") {
115-
return sunRadius + moonRadius + 14;
124+
return sunRadius + moonRadius + sunRadius * NONE_GAP_RATIO;
116125
}
117126

118127
if (kindAtLocation === "partial") {
119128
const safeMag =
120129
typeof magnitude === "number" && Number.isFinite(magnitude) ? clamp01(magnitude) : 0.6;
121-
return (1 - safeMag) * (sunRadius + moonRadius - 6);
130+
return (1 - safeMag) * (sunRadius + moonRadius - sunRadius * PARTIAL_INTERNAL_MARGIN_RATIO);
122131
}
123132

124133
return 0;
@@ -196,7 +205,7 @@ export function calculatePreviewMoonGeometry(params: {
196205
}): PreviewMoonGeometry {
197206
const stageSize = params.stageSize ?? PREVIEW_STAGE_SIZE;
198207
const sunRadius = params.sunRadius ?? PREVIEW_SUN_RADIUS;
199-
const moonRadius = determineMoonRadius(params.kindAtLocation);
208+
const moonRadius = determineMoonRadius(params.kindAtLocation, sunRadius);
200209
const moonClosestOffset = determineApproachOffset(
201210
params.kindAtLocation,
202211
params.magnitude,

apps/mobile/tests/preview-geometry.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
calculatePreviewMoonGeometry,
55
describePreviewTravelDirection,
66
determinePreviewTravelVector,
7+
PREVIEW_STAGE_SIZE,
78
PREVIEW_SUN_RADIUS,
89
} from "../src/utils/previewGeometry";
910

@@ -130,4 +131,54 @@ describe("preview moon geometry", () => {
130131
expect(c1Distance).toBeCloseTo(PREVIEW_SUN_RADIUS + c1Geometry.moonRadius, 6);
131132
expect(c4Distance).toBeCloseTo(PREVIEW_SUN_RADIUS + c4Geometry.moonRadius, 6);
132133
});
134+
135+
it("keeps moon-size ratio consistent when rendered in compact max-view stage", () => {
136+
const compactStageSize = 84;
137+
const compactSunRadius = (compactStageSize * PREVIEW_SUN_RADIUS) / PREVIEW_STAGE_SIZE;
138+
const fullGeometry = calculatePreviewMoonGeometry({
139+
progress: 0.5,
140+
kindAtLocation: "total",
141+
contacts: { c1: 0, c2: 0.25, max: 0.5, c3: 0.75, c4: 1 },
142+
});
143+
const compactGeometry = calculatePreviewMoonGeometry({
144+
progress: 0.5,
145+
kindAtLocation: "total",
146+
contacts: { c1: 0, c2: 0.25, max: 0.5, c3: 0.75, c4: 1 },
147+
stageSize: compactStageSize,
148+
sunRadius: compactSunRadius,
149+
});
150+
151+
const fullRatio = fullGeometry.moonRadius / PREVIEW_SUN_RADIUS;
152+
const compactRatio = compactGeometry.moonRadius / compactSunRadius;
153+
expect(compactRatio).toBeCloseTo(fullRatio, 10);
154+
});
155+
156+
it("preserves C1/C4 tangency distance in compact max-view stage", () => {
157+
const compactStageSize = 84;
158+
const compactSunRadius = (compactStageSize * PREVIEW_SUN_RADIUS) / PREVIEW_STAGE_SIZE;
159+
const stageCenter = compactStageSize / 2;
160+
const contacts = { c1: 0, c2: 0.25, max: 0.5, c3: 0.75, c4: 1 };
161+
162+
const c1Geometry = calculatePreviewMoonGeometry({
163+
progress: 0,
164+
kindAtLocation: "annular",
165+
contacts,
166+
stageSize: compactStageSize,
167+
sunRadius: compactSunRadius,
168+
});
169+
const c4Geometry = calculatePreviewMoonGeometry({
170+
progress: 1,
171+
kindAtLocation: "annular",
172+
contacts,
173+
stageSize: compactStageSize,
174+
sunRadius: compactSunRadius,
175+
});
176+
177+
const c1Distance = Math.abs(c1Geometry.moonCenterX - stageCenter);
178+
const c4Distance = Math.abs(c4Geometry.moonCenterX - stageCenter);
179+
const expectedDistance = compactSunRadius + c1Geometry.moonRadius;
180+
181+
expect(c1Distance).toBeCloseTo(expectedDistance, 6);
182+
expect(c4Distance).toBeCloseTo(expectedDistance, 6);
183+
});
133184
});

0 commit comments

Comments
 (0)