From feb10fdb8bff09defdd7baad4e0d98cbb3df4aae Mon Sep 17 00:00:00 2001 From: Paul Huliganga Date: Wed, 25 Mar 2026 00:37:18 -0400 Subject: [PATCH] feat(extension): send page URL to import API from context menu --- TODO.md | 2 +- browser-extension/background.js | 55 +++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/TODO.md b/TODO.md index 56aa24c..f45a68c 100644 --- a/TODO.md +++ b/TODO.md @@ -43,7 +43,7 @@ MVP is functionally complete (core app + docs + tests). ### Phase 4: Browser Extension (after URL import stable) - [x] Scaffold browser extension project (Manifest v3) -- [ ] Add “Send to Recipe Manager” action to call import API +- [x] Add “Send to Recipe Manager” action to call import API - [ ] Add extension settings for Recipe Manager base URL --- diff --git a/browser-extension/background.js b/browser-extension/background.js index 472f562..b1255fc 100644 --- a/browser-extension/background.js +++ b/browser-extension/background.js @@ -1,8 +1,46 @@ +const DEFAULT_BASE_URL = 'http://localhost:3000'; + +function normalizeBaseUrl(rawBaseUrl) { + if (typeof rawBaseUrl !== 'string' || rawBaseUrl.trim().length === 0) { + return DEFAULT_BASE_URL; + } + + return rawBaseUrl.trim().replace(/\/+$/, ''); +} + +async function getRecipeManagerBaseUrl() { + const { recipeManagerBaseUrl } = await chrome.storage.sync.get({ + recipeManagerBaseUrl: DEFAULT_BASE_URL, + }); + + return normalizeBaseUrl(recipeManagerBaseUrl); +} + +async function sendUrlToRecipeManager(pageUrl) { + const baseUrl = await getRecipeManagerBaseUrl(); + const importUrl = `${baseUrl}/api/import/url`; + + const response = await fetch(importUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ url: pageUrl }), + }); + + if (!response.ok) { + const responseText = await response.text(); + throw new Error(`Import request failed (${response.status}): ${responseText}`); + } + + return response.json(); +} + chrome.runtime.onInstalled.addListener(() => { chrome.contextMenus.create({ id: 'send-to-recipe-manager', title: 'Send to Recipe Manager', - contexts: ['page'] + contexts: ['page'], }); }); @@ -11,6 +49,17 @@ chrome.contextMenus.onClicked.addListener((info, tab) => { return; } - // Placeholder for task: "Add 'Send to Recipe Manager' action to call import API" - console.info('[Recipe Manager Extension] Context menu clicked for URL:', tab.url); + sendUrlToRecipeManager(tab.url) + .then((payload) => { + console.info('[Recipe Manager Extension] Import request sent successfully', { + sourceUrl: tab.url, + success: payload?.success ?? true, + }); + }) + .catch((error) => { + console.error('[Recipe Manager Extension] Failed to import URL', { + sourceUrl: tab.url, + error: error instanceof Error ? error.message : String(error), + }); + }); });