Skip to content

Commit ed9ed6c

Browse files
author
Lalit Sharma
committed
feat: update changelog for version 1.1.47, fix Google Maps short-link parse failures on Android, add regression coverage for fallback parsing, and bump mobile version
1 parent e04334a commit ed9ed6c

4 files changed

Lines changed: 81 additions & 2 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.47] — 2026-02-27
9+
10+
### Fixed
11+
- Fixed Google Maps short-link parse failures on Android when the initial short-link fetch returns a final URL but no usable body for coordinate extraction by re-fetching the expanded Maps URL page and re-attempting preview-payload coordinate parsing.
12+
13+
### Added
14+
- Added regression coverage for short-link parsing fallback that requires a second fetch against the expanded Google Maps URL.
15+
16+
### Changed
17+
- Bumped `apps/mobile` version to `1.1.47`.
18+
819
## [1.1.46] — 2026-02-27
920

1021
### Fixed

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

apps/mobile/src/utils/sharedMapLink.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,39 @@ async function expandShortMapUrlWithResponse(
218218
}
219219
}
220220

221+
async function fetchMapPageText(
222+
url: string,
223+
options: ExpandShortMapUrlOptions = {},
224+
): Promise<string | null> {
225+
const parsed = parseUrl(url);
226+
if (!parsed || !isSupportedMapHost(parsed)) return null;
227+
228+
const fetchImpl =
229+
options.fetchImpl ??
230+
(typeof fetch === "function" ? (fetch as unknown as FetchLike) : undefined);
231+
if (!fetchImpl) return null;
232+
233+
const timeoutMs =
234+
typeof options.timeoutMs === "number" && Number.isFinite(options.timeoutMs)
235+
? Math.max(1, Math.floor(options.timeoutMs))
236+
: DEFAULT_EXPAND_TIMEOUT_MS;
237+
238+
try {
239+
const response = await withTimeout(
240+
fetchImpl(parsed.toString(), {
241+
method: "GET",
242+
redirect: "follow",
243+
}),
244+
timeoutMs,
245+
);
246+
247+
if (typeof response.text !== "function") return null;
248+
return await withTimeout(Promise.resolve(response.text()), timeoutMs);
249+
} catch {
250+
return null;
251+
}
252+
}
253+
221254
export function extractFirstUrl(input: string): string | null {
222255
const text = input.trim();
223256
if (!text) return null;
@@ -307,7 +340,12 @@ export async function parseSharedMapLinkAsync(
307340
if (parsedExpandedLink) return parsedExpandedLink;
308341
}
309342

310-
const parsedFromPreviewPayload = parseGooglePreviewCoordinatesFromText(responseText ?? "");
343+
let parsedFromPreviewPayload = parseGooglePreviewCoordinatesFromText(responseText ?? "");
344+
if (!parsedFromPreviewPayload && expandedUrl !== extracted) {
345+
const expandedPageText = await fetchMapPageText(expandedUrl, options);
346+
parsedFromPreviewPayload = parseGooglePreviewCoordinatesFromText(expandedPageText ?? "");
347+
}
348+
311349
if (!parsedFromPreviewPayload) return null;
312350

313351
return {

apps/mobile/tests/shared-map-link.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,36 @@ describe("shared map link parser", () => {
185185
});
186186
});
187187

188+
it("re-fetches expanded url page when short-link response body is unavailable", async () => {
189+
const fetchImpl = vi.fn(async (input: string) => {
190+
if (input === "https://maps.app.goo.gl/abc123") {
191+
return {
192+
url: "https://www.google.com/maps/place/Somewhere",
193+
};
194+
}
195+
196+
if (input === "https://www.google.com/maps/place/Somewhere") {
197+
return {
198+
url: input,
199+
text: async () =>
200+
'<a href="/maps/preview/place?pb=%211m3%212d-1.55405635%213d52.276200949999996">Preview</a>',
201+
};
202+
}
203+
204+
return { url: input };
205+
});
206+
207+
const parsed = await parseSharedMapLinkAsync("https://maps.app.goo.gl/abc123", { fetchImpl });
208+
209+
expect(parsed).toEqual({
210+
provider: "google",
211+
lat: 52.276200949999996,
212+
lon: -1.55405635,
213+
rawUrl: "https://maps.app.goo.gl/abc123",
214+
});
215+
expect(fetchImpl).toHaveBeenCalledTimes(2);
216+
});
217+
188218
it("returns null when expansion cannot produce parseable map coordinates", async () => {
189219
const fetchImpl = vi.fn(async () => ({
190220
url: "https://www.google.com/maps/place/Somewhere",

0 commit comments

Comments
 (0)