Skip to content

Commit ffd8ba4

Browse files
author
Lalit Sharma
committed
feat: add Photography Guide functionality with scheduling and landscape composite
- Updated TimerScreen to include a new Photography Guide button and corresponding handler. - Implemented photography guide logic in a new utils file, allowing for shot scheduling and moon geometry calculations. - Created unit tests for the photography guide schedule and landscape composite layout to ensure correct functionality. - Enhanced documentation to reflect the current status and implementation details of the Photography Guide feature.
1 parent 4aee346 commit ffd8ba4

9 files changed

Lines changed: 1572 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@ 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.33] — 2026-02-26
9+
10+
### Added
11+
- Added a new timer-linked `Photography Guide` flow with a split `Preview` / `Photo Guide` action row on the Timer screen.
12+
- Added schedule generation helpers for photo timing distribution across eclipse phases (`3/5/7/9` shots), including phase buckets and preview-progress anchors.
13+
- Added in-guide shot schedule table rows with UTC/local timestamps, phase labels, and generated eclipse preview thumbnails per shot.
14+
- Added landscape composite simulation modal with 24mm framing, fixed `MAX` anchor placement, clamped edge indicators, and moon rendering only during occlusion windows.
15+
- Added regression tests for photography guide schedule logic and composite anchor/clamping behavior.
16+
17+
### Changed
18+
- Updated navigation wiring to include a dedicated `PhotographyGuide` route with timer circumstance payload (including contact bearings for preview direction).
19+
- Bumped `apps/mobile` version to `1.1.33`.
20+
21+
### Tests
22+
- Verified mobile checks pass: `pnpm -C apps/mobile typecheck`, `pnpm -C apps/mobile lint`, and `pnpm -C apps/mobile test`.
23+
824
## [1.1.32] — 2026-02-26
925

1026
### 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.32",
3+
"version": "1.1.33",
44
"private": true,
55
"main": "index.js",
66
"scripts": {

apps/mobile/src/navigation/RootNavigator.tsx

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ import HelpScreen from "../screens/HelpScreen";
4848
import LandingScreen from "../screens/LandingScreen";
4949
import LocationSettingsScreen from "../screens/LocationSettingsScreen";
5050
import NotificationSettingsScreen from "../screens/NotificationSettingsScreen";
51+
import PhotographyGuideScreen, {
52+
type PhotographyGuidePayload,
53+
} from "../screens/PhotographyGuideScreen";
5154
import SettingsScreen from "../screens/SettingsScreen";
5255
import ThemeSettingsScreen from "../screens/ThemeSettingsScreen";
5356
import TimerScreen from "../screens/TimerScreen";
@@ -67,6 +70,7 @@ type RootStackParamList = {
6770
Landing: undefined;
6871
Timer: undefined;
6972
Preview: { payload: PreviewPayload };
73+
PhotographyGuide: { payload: PhotographyGuidePayload };
7074
Settings: undefined;
7175
Help: undefined;
7276
ThemeSettings: undefined;
@@ -80,6 +84,7 @@ const linking: LinkingOptions<RootStackParamList> = {
8084
screens: {
8185
Landing: "landing",
8286
Timer: "timer",
87+
PhotographyGuide: "photography-guide",
8388
Settings: "settings",
8489
Help: "settings/help",
8590
ThemeSettings: "settings/theme",
@@ -105,6 +110,10 @@ type PreviewRouteProps = NativeStackScreenProps<RootStackParamList, "Preview"> &
105110
onOpenMenu: () => void;
106111
};
107112

113+
type PhotographyGuideRouteProps = NativeStackScreenProps<RootStackParamList, "PhotographyGuide"> & {
114+
onOpenMenu: () => void;
115+
};
116+
108117
type SettingsRouteProps = NativeStackScreenProps<RootStackParamList, "Settings"> & {
109118
onOpenMenu: () => void;
110119
};
@@ -170,7 +179,8 @@ function StartupLoadingScreen({
170179
}
171180

172181
function toMenuRouteName(route: keyof RootStackParamList): MenuRouteName | null {
173-
if (route === "Landing" || route === "Timer") return route;
182+
if (route === "Landing") return "Landing";
183+
if (route === "Timer" || route === "PhotographyGuide") return "Timer";
174184
if (
175185
route === "Settings" ||
176186
route === "Help" ||
@@ -410,6 +420,30 @@ function TimerRoute({ navigation, catalog, onOpenMenu }: TimerRouteProps) {
410420
},
411421
[activeEclipse?.dateYmd, activeEclipse?.id, navigation],
412422
);
423+
const openPhotographyGuide = useCallback(
424+
(result: Circumstances, observer: Observer) => {
425+
const payload: PhotographyGuidePayload = {
426+
eclipseId: activeEclipse?.id ?? result.eclipseId,
427+
eclipseDateYmd: activeEclipse?.dateYmd ?? "",
428+
visible: result.visible,
429+
kindAtLocation: result.kindAtLocation,
430+
magnitude: result.magnitude,
431+
c1Utc: result.c1Utc,
432+
c2Utc: result.c2Utc,
433+
maxUtc: result.maxUtc,
434+
c3Utc: result.c3Utc,
435+
c4Utc: result.c4Utc,
436+
c1BearingDeg: result.c1BearingDeg,
437+
c2BearingDeg: result.c2BearingDeg,
438+
c3BearingDeg: result.c3BearingDeg,
439+
c4BearingDeg: result.c4BearingDeg,
440+
observer,
441+
};
442+
443+
navigation.navigate("PhotographyGuide", { payload });
444+
},
445+
[activeEclipse?.dateYmd, activeEclipse?.id, navigation],
446+
);
413447

414448
const useFavoriteLocation = useCallback(
415449
(location: FavoriteLocation) => {
@@ -456,6 +490,7 @@ function TimerRoute({ navigation, catalog, onOpenMenu }: TimerRouteProps) {
456490
onSelectEclipse={selectEclipse}
457491
onOpenMenu={onOpenMenu}
458492
onOpenPreview={openPreview}
493+
onOpenPhotographyGuide={openPhotographyGuide}
459494
/>
460495
);
461496
}
@@ -470,6 +505,16 @@ function PreviewRoute({ navigation, route, onOpenMenu }: PreviewRouteProps) {
470505
);
471506
}
472507

508+
function PhotographyGuideRoute({ navigation, route, onOpenMenu }: PhotographyGuideRouteProps) {
509+
return (
510+
<PhotographyGuideScreen
511+
payload={route.params.payload}
512+
onBack={() => navigation.goBack()}
513+
onOpenMenu={onOpenMenu}
514+
/>
515+
);
516+
}
517+
473518
function SettingsRoute({ navigation, onOpenMenu }: SettingsRouteProps) {
474519
return (
475520
<SettingsScreen
@@ -803,6 +848,9 @@ export default function RootNavigator() {
803848
<Stack.Screen name="Preview">
804849
{(props) => <PreviewRoute {...props} onOpenMenu={openMenu} />}
805850
</Stack.Screen>
851+
<Stack.Screen name="PhotographyGuide">
852+
{(props) => <PhotographyGuideRoute {...props} onOpenMenu={openMenu} />}
853+
</Stack.Screen>
806854
<Stack.Screen name="Settings">
807855
{(props) => <SettingsRoute {...props} onOpenMenu={openMenu} />}
808856
</Stack.Screen>

0 commit comments

Comments
 (0)