diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index d871d82..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore index 2d6fd38..887de55 100644 --- a/.gitignore +++ b/.gitignore @@ -705,3 +705,4 @@ fabric.properties # Exclude web-ext build artifacts /web-ext-artifacts/ /*.zip +.DS_Store diff --git a/package.json b/package.json index b07ab3d..4b91ac0 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "dev": "webpack --mode development", "build": "webpack --mode production", "test": "jest --env=jsdom", - "build:ext": "npm run build && web-ext build --source-dir ./dist/" + "build:ext": "npm run build && web-ext build --overwrite-dest --source-dir ./dist/" }, "repository": { "type": "git", diff --git a/src/background/background.js b/src/background/background.js index c35dab9..62b5c2a 100644 --- a/src/background/background.js +++ b/src/background/background.js @@ -8,7 +8,23 @@ */ import { initDB } from './initdb.js'; -import handlers from './handlers/index.js'; +import handlers from './handlers/index.js'; // Keep the default import for window assignment + +// Destructure the specific handlers needed for the message listener +const { + fetchAndStoreHistory, + getMostVisitedSites, + getVisitsPerHour, + getLabelCounts, + //getTimeSpentPerSite, + getCategoryTrends, + getCOCounts, + getDailyVisitCounts, + getRecencyFrequency, + getTransitionPatterns, + getUniqueWebsites +} = handlers; + /** * Initialize the extension’s database on startup. @@ -54,10 +70,11 @@ browser.runtime.onMessage.addListener((message, sender, sendResponse) => { return true; } - if (action === "getTimeSpentPerSite") { - getTimeSpentPerSite(days, limit).then(sendResponse); - return true; - } + // Note: 'getTimeSpentPerSite' is not defined in handlers/index.js + // if (action === "getTimeSpentPerSite") { + // getTimeSpentPerSite(days, limit).then(sendResponse); + // return true; + // } if (action === "getCategoryTrends") { getCategoryTrends(days).then(sendResponse); @@ -91,19 +108,5 @@ browser.runtime.onMessage.addListener((message, sender, sendResponse) => { console.warn("[Background] No handler for action:", action); sendResponse(null); - return true; + return true; // Keep true here for async sendResponse }); - - -/** - * Expose background handler functions on the global `window` object. - * - * This allows you to call e.g. - * ``` - * getMostVisitedSites(7).then(console.log) - * ``` - * directly from the console for debugging or ad‐hoc testing. - * - * @type {Object.} - */ -Object.assign(window, handlers); diff --git a/src/background/services/ml.js b/src/background/services/ml.js index 16f5e25..33354f8 100644 --- a/src/background/services/ml.js +++ b/src/background/services/ml.js @@ -110,7 +110,7 @@ export async function classifyURLAndTitle( console.log('ML classify:', textToClassify); const result = await mlApi.runEngine({ args: [textToClassify], - options: { top_k: null }, + options: { top_k: null }, // mutli-label classification we apply threshold later this might be better at 2 }); const mapped = result diff --git a/src/manifest.json b/src/manifest.json index 4a7d369..d8e5139 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -18,7 +18,7 @@ "scripts": [ "background.js" ], - "persistent": false + "persistent": true }, "browser_action": { "default_popup": "popup.html", @@ -34,5 +34,10 @@ "web_accessible_resources": [ "recap.html" ], + "browser_specific_settings": { + "gecko": { + "id": "firefoxrecap@gmail.com" + } + }, "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'; connect-src https://big.oisd.nl blob:;" } \ No newline at end of file diff --git a/src/popup/SlideShow.jsx b/src/popup/SlideShow.jsx index 3f4fe73..065da69 100644 --- a/src/popup/SlideShow.jsx +++ b/src/popup/SlideShow.jsx @@ -17,11 +17,13 @@ const safeCallBackground = async (action, payload = {}) => { } }; + const SlideShow = ({ setView, timeRange }) => { const [slides, setSlides] = useState([]); const [index, setIndex] = useState(0); const [loading, setLoading] = useState(true); const [progress, setProgress] = useState(0); + const [notEnoughData, setNotEnoughData] = useState(false); const videoRef = useRef(null); const backgroundVideos = [ @@ -81,6 +83,16 @@ const SlideShow = ({ setView, timeRange }) => { }); const totalUnique = await safeCallBackground("getUniqueWebsites", { days }); + + // see if theres any data, if not skip slides + if (!totalUnique || totalUnique === 0) { + console.log("[SlideShow] Not enough data (totalUnique=0)."); + setNotEnoughData(true); + setLoading(false); + setProgress(100); + return; + } + slides.push({ id: 'totalWebsites', video: videos[2], @@ -179,12 +191,12 @@ const SlideShow = ({ setView, timeRange }) => { video: videos[7], prompt: pickPrompt("recapOutro", { x: timeRangeMap[timeRange] }) }); - setSlides(slides); + setNotEnoughData(false); setLoading(false); setProgress(100); }; - + loadSlides(); }, [timeRange]); @@ -207,11 +219,14 @@ const SlideShow = ({ setView, timeRange }) => { }, [index]); useEffect(() => { + if (loading || notEnoughData) return; + const timer = setTimeout(() => { setIndex(prev => (prev < slides.length - 1 ? prev + 1 : prev)); }, 5000); + return () => clearTimeout(timer); - }, [index, slides.length]); + }, [index, slides.length, loading, notEnoughData]); // 🚀 LOADING SCREEN while slides are being fetched if (loading || progress < 100) { @@ -244,6 +259,15 @@ const SlideShow = ({ setView, timeRange }) => { ); } + if (notEnoughData) { + return ( +
+

Not enough browsing history yet. Your recap will be ready once you’ve explored a bit more!

+
+ ); + } + + // 🚀 SLIDESHOW UI after loading return (