From 201a5ec550e718341e114c753203f78f5ddb230a Mon Sep 17 00:00:00 2001 From: tshasan Date: Sun, 27 Apr 2025 20:01:34 -0700 Subject: [PATCH 01/12] Refactor CI workflow: remove commented-out steps and clean up linting section --- .github/workflows/ci.yml | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d35654..c947365 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,25 +26,4 @@ jobs: run: npm ci - name: Lint (ESLint) - run: npm run lint - - # We dont have any test yet - # - name: Run tests (Jest) - # run: npm test - - - name: Build (Webpack) - run: npm run build - - # This doesnt really work yet we need to figure this out - # - name: Package Firefox Extension - # run: npm run build:ext - - - name: Generate docs (JSDoc) - run: npm run docs - - # This doesnt work yet need to figure this out - # - name: Upload extension artifact - # uses: actions/upload-artifact@v3 - # with: - # name: firefox-recap-extension - # path: web-ext-artifacts/*.zip \ No newline at end of file + run: npm run lint \ No newline at end of file From b7f2d12384168eb9c2530b183211c11a14c2a526 Mon Sep 17 00:00:00 2001 From: Kate Date: Sun, 27 Apr 2025 21:56:42 -0700 Subject: [PATCH 02/12] manifest was not in dist --- webpack.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/webpack.config.js b/webpack.config.js index 9493fd3..dfc94fe 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -30,6 +30,7 @@ module.exports = { plugins: [ new CopyWebpackPlugin({ patterns: [ + { from: 'src/manifest.json', to: 'manifest.json' }, { from: 'src/popup/popup.html', to: 'popup.html' }, { from: 'src/popup/recap.html', to: 'recap.html' } ] From 87dedb3cad1999a5d71f9909e926002ffc9204cc Mon Sep 17 00:00:00 2001 From: tshasan Date: Sun, 27 Apr 2025 22:36:06 -0700 Subject: [PATCH 03/12] Update build command to overwrite destination and clean up background script handlers --- package.json | 2 +- src/background/background.js | 43 +++++++++++++++++++---------------- src/background/services/ml.js | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) 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 From 7352edf14180f327c712a2848e11b3ba0e224469 Mon Sep 17 00:00:00 2001 From: tshasan Date: Sun, 27 Apr 2025 22:42:52 -0700 Subject: [PATCH 04/12] Update manifest.json: set background script to persistent and add browser-specific settings --- .DS_Store | Bin 6148 -> 0 bytes src/manifest.json | 7 ++++++- 2 files changed, 6 insertions(+), 1 deletion(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index d871d82946bd2bb9d98f20038fb6b61a1c6ca179..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}N774E|#GP_Ty{JN%r}!s zHZ$L0vH>8QeR~V60W7JC_|jo6y01EutFSag(Qmx8!|ti?J1))@jcw546$3tx<5ze` z&y8n1;LT=xbX*OSlV(^j>H|Bb?WVk8n!J8+lyi@qe#t;GkPIXP$-qT35Vdi6ebKkb z!zTmDz;7_1??a&~*1*xxo(>My0uc2#-h^}OC5S~0#2Pp{(n1jrC3>htiy7V0B)68f4u2P?%yE5%%BDZV-KD>~ Date: Sun, 27 Apr 2025 22:51:48 -0700 Subject: [PATCH 05/12] Improve UX by showing a fallback screen to handle empty or insufficient data (#37) * Improve UX by showing a fallback screen to handle empty or insufficient browsing history * Add .DS_Store to .gitignore * Remove accidentally committed .DS_Store file --- .gitignore | 1 + src/popup/SlideShow.jsx | 30 +++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) 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/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 (
From f6e4835f8c66284dc49b984b2b3fd1a7b382a206 Mon Sep 17 00:00:00 2001 From: tshasan Date: Sun, 27 Apr 2025 23:04:23 -0700 Subject: [PATCH 06/12] Update CI workflow: improve Node.js setup and caching steps --- .github/workflows/ci.yml | 25 +++++++++++++++++++++++-- src/manifest.json | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c947365..4519cad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,14 +16,35 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - - name: Use Node.js 18.x + - name: Set up Node.js uses: actions/setup-node@v3 with: node-version: '18.x' cache: 'npm' + - name: Cache node_modules + uses: actions/cache@v3 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install dependencies run: npm ci - name: Lint (ESLint) - run: npm run lint \ No newline at end of file + run: npm run lint + + # What tests ! + # - name: Run Tests + # run: npm test + + - name: Build Extension + run: npm run build:ext + + - name: Upload Extension Artifact + uses: actions/upload-artifact@v4 + with: + name: firefox-recap-extension + path: web-ext-artifacts/ \ No newline at end of file diff --git a/src/manifest.json b/src/manifest.json index d8e5139..fd325e9 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Firefox Recap", - "version": "2.0.0", + "version": "1.0.0", "description": "Categorize and analyze browsing history for productivity insights.", "permissions": [ "history", From f4804dc7fb3df40fe250b96eeb6af4d9569c0c80 Mon Sep 17 00:00:00 2001 From: tshasan Date: Sun, 27 Apr 2025 23:08:48 -0700 Subject: [PATCH 07/12] remove artifacts --- .github/workflows/ci.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4519cad..695829a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,12 +39,4 @@ jobs: # What tests ! # - name: Run Tests # run: npm test - - - name: Build Extension - run: npm run build:ext - - - name: Upload Extension Artifact - uses: actions/upload-artifact@v4 - with: - name: firefox-recap-extension - path: web-ext-artifacts/ \ No newline at end of file + From 7d9b5cacbcbf6a9bd4115cf37d6a21aeed4fa507 Mon Sep 17 00:00:00 2001 From: Kate Date: Mon, 28 Apr 2025 12:34:50 -0700 Subject: [PATCH 08/12] backgrounds working --- src/manifest.json | 3 ++- src/popup/SlideShow.jsx | 2 +- webpack.config.js | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/manifest.json b/src/manifest.json index fd325e9..ae7e559 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -32,7 +32,8 @@ "128": "assets/icon128.png" }, "web_accessible_resources": [ - "recap.html" + "recap.html", + "assets/videos/*.mp4" ], "browser_specific_settings": { "gecko": { diff --git a/src/popup/SlideShow.jsx b/src/popup/SlideShow.jsx index 065da69..04f5963 100644 --- a/src/popup/SlideShow.jsx +++ b/src/popup/SlideShow.jsx @@ -55,7 +55,7 @@ const SlideShow = ({ setView, timeRange }) => { return array; }; - useEffect(() => { + useEffect(() => { const loadSlides = async () => { setLoading(true); const daysMap = { day: 1, week: 7, month: 30 }; diff --git a/webpack.config.js b/webpack.config.js index dfc94fe..1cb3f85 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -32,7 +32,8 @@ module.exports = { patterns: [ { from: 'src/manifest.json', to: 'manifest.json' }, { from: 'src/popup/popup.html', to: 'popup.html' }, - { from: 'src/popup/recap.html', to: 'recap.html' } + { from: 'src/popup/recap.html', to: 'recap.html' }, + { from: 'src/assets', to: 'assets' } ] }) ], From 71d8cc31aeff3aea9ac042e4a5d86d72862a126d Mon Sep 17 00:00:00 2001 From: Kate Date: Mon, 28 Apr 2025 12:43:15 -0700 Subject: [PATCH 09/12] centered --- src/popup/SlideShow.jsx | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/popup/SlideShow.jsx b/src/popup/SlideShow.jsx index 04f5963..d3ee653 100644 --- a/src/popup/SlideShow.jsx +++ b/src/popup/SlideShow.jsx @@ -231,22 +231,15 @@ const SlideShow = ({ setView, timeRange }) => { // 🚀 LOADING SCREEN while slides are being fetched if (loading || progress < 100) { return ( -
-

Preparing your recap...

+
+

Preparing your recap...

{ {slides[index]?.video && } - -
{slides[index]?.chart ? ( <> From 1b80d60ec805424d6ed4e4bcfa1754d32b19419c Mon Sep 17 00:00:00 2001 From: katesawtell <125850781+katesawtell@users.noreply.github.com> Date: Mon, 28 Apr 2025 12:44:22 -0700 Subject: [PATCH 10/12] Feature/cooler loading screen (#38) * backgrounds working * centered --- src/manifest.json | 3 ++- src/popup/SlideShow.jsx | 21 ++++++--------------- webpack.config.js | 3 ++- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/manifest.json b/src/manifest.json index fd325e9..ae7e559 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -32,7 +32,8 @@ "128": "assets/icon128.png" }, "web_accessible_resources": [ - "recap.html" + "recap.html", + "assets/videos/*.mp4" ], "browser_specific_settings": { "gecko": { diff --git a/src/popup/SlideShow.jsx b/src/popup/SlideShow.jsx index 065da69..d3ee653 100644 --- a/src/popup/SlideShow.jsx +++ b/src/popup/SlideShow.jsx @@ -55,7 +55,7 @@ const SlideShow = ({ setView, timeRange }) => { return array; }; - useEffect(() => { + useEffect(() => { const loadSlides = async () => { setLoading(true); const daysMap = { day: 1, week: 7, month: 30 }; @@ -231,22 +231,15 @@ const SlideShow = ({ setView, timeRange }) => { // 🚀 LOADING SCREEN while slides are being fetched if (loading || progress < 100) { return ( -
-

Preparing your recap...

+
+

Preparing your recap...

{ {slides[index]?.video && } - -
{slides[index]?.chart ? ( <> diff --git a/webpack.config.js b/webpack.config.js index dfc94fe..1cb3f85 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -32,7 +32,8 @@ module.exports = { patterns: [ { from: 'src/manifest.json', to: 'manifest.json' }, { from: 'src/popup/popup.html', to: 'popup.html' }, - { from: 'src/popup/recap.html', to: 'recap.html' } + { from: 'src/popup/recap.html', to: 'recap.html' }, + { from: 'src/assets', to: 'assets' } ] }) ], From 6e0fbd771e3516086208158851982fa66222f88d Mon Sep 17 00:00:00 2001 From: Kate Date: Mon, 28 Apr 2025 13:41:17 -0700 Subject: [PATCH 11/12] centered load with animation --- src/popup/SlideShow.jsx | 8 ++++--- src/popup/WavyText.jsx | 33 ++++++++++++++++++++++++++ src/popup/popup.css | 51 ++++++++++++++++++++++++----------------- 3 files changed, 68 insertions(+), 24 deletions(-) create mode 100644 src/popup/WavyText.jsx diff --git a/src/popup/SlideShow.jsx b/src/popup/SlideShow.jsx index d3ee653..a2f3958 100644 --- a/src/popup/SlideShow.jsx +++ b/src/popup/SlideShow.jsx @@ -4,6 +4,7 @@ import { FaArrowRight, FaArrowLeft } from 'react-icons/fa'; import promptsData from "./prompts.json"; import RadarCategoryChart from './RadarCategoryChart'; import TimeOfDayHistogram from './TimeOfDayHistogram'; +import WavyText from './WavyText'; import CategoryTrendsLineChart from './CategoryTrendsLineChart'; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer as LineContainer } from 'recharts'; @@ -232,15 +233,16 @@ const SlideShow = ({ setView, timeRange }) => { if (loading || progress < 100) { return (
-

Preparing your recap...

-
+ +
+ }}>
{ + return ( +
+ {text.split(/(\s+)/).map((segment, index) => { + if (segment.trim() === '') { + // Render spaces without animation + return {segment}; + } else { + // Render each character in the word with animation + return ( + + {segment.split('').map((char, charIndex) => ( + + {char} + + ))} + + ); + } + })} +
+ ); + }; + + export default WavyText; \ No newline at end of file diff --git a/src/popup/popup.css b/src/popup/popup.css index b704a03..3cacf68 100644 --- a/src/popup/popup.css +++ b/src/popup/popup.css @@ -119,7 +119,7 @@ body { padding: 15px; font-size: 30px; background-color: #6F84B3; - color: white; + color: #fff; border: none; margin-bottom: 15px; border-radius: 15px; @@ -138,26 +138,35 @@ button:disabled { display: none; } -.spinner-overlay { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - background-color: black; - opacity: 20%; - display: flex; - align-items: center; - justify-content: center; - z-index: 9999; /* ensures it stays on top */ +.wavy-text { + display: inline-block; + font-size: 2rem; + font-weight: bold; + color: white; + text-align: center; + border: 2px solid white; +} + +.wavy-char { + display: inline-block; + animation: wave 1.5s infinite; + animation-delay: calc(0.1s * var(--i)); } -.spinner { - border: 6px solid #fff; - border-top: 6px solid #444; - border-radius: 50%; - width: 60px; - height: 60px; - animation: spin 1s linear infinite; +@keyframes wave { + 0%, 100% { + transform: translateY(0); + } + 50% { + transform: translateY(-10px); + } +} + +.center-container { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; /* Full viewport height */ + width: 100vw; /* Full viewport width */ + background-color: black; /* Optional: set background color */ } -@keyframes spin { to { transform: rotate(360deg); } } \ No newline at end of file From 19e9b1edd2225c559c3f67e83b58a09aeec6d8d4 Mon Sep 17 00:00:00 2001 From: Kate Date: Mon, 28 Apr 2025 13:46:35 -0700 Subject: [PATCH 12/12] loading bar is back --- src/popup/SlideShow.jsx | 23 ++++++---------------- src/popup/popup.css | 42 +++++++++++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/popup/SlideShow.jsx b/src/popup/SlideShow.jsx index a2f3958..49dffbe 100644 --- a/src/popup/SlideShow.jsx +++ b/src/popup/SlideShow.jsx @@ -229,31 +229,20 @@ const SlideShow = ({ setView, timeRange }) => { return () => clearTimeout(timer); }, [index, slides.length, loading, notEnoughData]); - // 🚀 LOADING SCREEN while slides are being fetched + // LOADING SCREEN if (loading || progress < 100) { return ( -
+
-
-
+
+
+
); } - + if (notEnoughData) { return (
diff --git a/src/popup/popup.css b/src/popup/popup.css index 3cacf68..831d467 100644 --- a/src/popup/popup.css +++ b/src/popup/popup.css @@ -137,14 +137,34 @@ body { button:disabled { display: none; } +/* Container that covers the entire viewport */ +.loading-screen { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: black; /* Optional: set background color */ + display: flex; + justify-content: center; + align-items: center; +} +/* Container that centers its content vertically */ +.center-container { + display: flex; + flex-direction: column; + align-items: center; +} + +/* Wavy text styling */ .wavy-text { display: inline-block; font-size: 2rem; font-weight: bold; color: white; text-align: center; - border: 2px solid white; + margin-bottom: 20px; /* Space between text and progress bar */ } .wavy-char { @@ -162,11 +182,17 @@ button:disabled { } } -.center-container { - display: flex; - justify-content: center; - align-items: center; - height: 100vh; /* Full viewport height */ - width: 100vw; /* Full viewport width */ - background-color: black; /* Optional: set background color */ +/* Progress bar styling */ +.progress-bar { + width: 100%; + height: 8px; + background-color: #555; + border-radius: 5px; + overflow: hidden; +} + +.progress-bar-fill { + height: 100%; + background-color: #00C853; + transition: width 0.5s ease-in-out; }