Conversation
- docs: update metadata - refactor: remove unused code - feat: add moods ai tool - chore: rename dashboard -> charts - refactor: add a moods keys array - refactor: run prettier - refactor: extract svg charts into a separate module - refactor: extract data functions - feat: implement dashboard view - feat: implement mood search - feat: implement mood recording - feat: initial commit
|
Congratulations on your new Raycast extension! 🚀 Due to our current reduced availability, the initial review may take up to 10-15 business days Once the PR is approved and merged, the extension will be available on our Store. |
|
@greptileai can you help check this |
There was a problem hiding this comment.
PR Summary
This PR adds a comprehensive Mood Tracker extension that enables users to record, search, and visualize their emotional well-being with AI-powered insights.
- The
metadatafolder with screenshots is missing but required since there areviewcommands inpackage.json- refer to https://developers.raycast.com/basics/prepare-an-extension-for-store#how-to-use-it - Error handling in
search-moods.tsxcould be simplified usingshowFailureToastfrom@raycast/utilsinstead ofshowToast - Lists in
search-moods.tsxandview-charts.tsxshould useisLoadingto avoid empty state flicker per https://developers.raycast.com/basics/prepare-an-extension-for-store#empty-states getSelectedText()inrecord-mood.tsxshould be wrapped in try-catch for graceful error handling- Consider adding subtitles to commands in
package.jsonto indicate they are part of "Mood Tracker"
💡 (1/5) You can manually trigger the bot by mentioning @greptileai in a comment!
13 file(s) reviewed, 13 comment(s)
Edit PR Review Bot Settings | Greptile
extensions/mood/src/lib/charts.ts
Outdated
| const chartWidth = width - margin.right; | ||
| const chartHeight = height - margin.top - margin.bottom; |
There was a problem hiding this comment.
logic: margin.left not accounted for in chartWidth calculation, could cause alignment issues
| const chartWidth = width - margin.right; | |
| const chartHeight = height - margin.top - margin.bottom; | |
| const chartWidth = width - margin.right - margin.left; | |
| const chartHeight = height - margin.top - margin.bottom; |
There was a problem hiding this comment.
This chart actually doesn't have a left margin. But I've made an additional pass on margins and now actually removed most of them, only adding the ones necessary for the labels
extensions/mood/src/lib/charts.ts
Outdated
|
|
||
| // Calculate points for sparkline | ||
| const points = values.map((value, index) => { | ||
| const x = (index / (values.length - 1 || 1)) * chartWidth; |
There was a problem hiding this comment.
logic: division by zero possible if values.length is 1 (|| 1 only helps if length is 0)
| const x = (index / (values.length - 1 || 1)) * chartWidth; | |
| const x = (index / Math.max(1, values.length - 1)) * chartWidth; |
There was a problem hiding this comment.
No, actually if length is 1, then length - 1 is 0 that gets replaced with || 1. But Math.max is more readable, I've adopted it. Thanks
| return svgToBase64(` | ||
| <svg width="${width}" height="${height + 30}" xmlns="http://www.w3.org/2000/svg"> | ||
| ${xAxis} | ||
| ${bars} | ||
| </svg> | ||
| `); |
There was a problem hiding this comment.
logic: height + 30 adjustment not accounted for in y-coordinate calculations
There was a problem hiding this comment.
This was strictly for the labels, but I agree it's confusing, removed
| if (fs.existsSync(ENTRIES_FILE)) { | ||
| const data = await fs.promises.readFile(ENTRIES_FILE, "utf-8"); | ||
| let entries = JSON.parse(data) as MoodEntry[]; |
There was a problem hiding this comment.
logic: fs operations should be wrapped in try/catch to handle potential file system errors gracefully
| if (fs.existsSync(ENTRIES_FILE)) { | |
| const data = await fs.promises.readFile(ENTRIES_FILE, "utf-8"); | |
| let entries = JSON.parse(data) as MoodEntry[]; | |
| if (fs.existsSync(ENTRIES_FILE)) { | |
| try { | |
| const data = await fs.promises.readFile(ENTRIES_FILE, "utf-8"); | |
| let entries = JSON.parse(data) as MoodEntry[]; | |
| } catch (error) { | |
| console.error('Failed to load entries:', error); | |
| return []; | |
| } |
There was a problem hiding this comment.
I actually wrap these calls at the place of use, where more context can be provided to the user. Everywhere loadEntries/saveEntries is called, they are wrapped in try/catch
| /** | ||
| * Returns the list of user's moods with timestamp, notes and tags | ||
| */ | ||
| export default async function () { |
There was a problem hiding this comment.
style: Function should have a descriptive name like getMoods instead of being anonymous
There was a problem hiding this comment.
This was actually generated by Raycast when I added a new tool using the "Manage Extensions" action. Might need to edit the template if that's a problem 😄 Fixed it manually here, though I don't see the need for a descriptive name here personally.
| try { | ||
| const newEntry: MoodEntry = { | ||
| id: crypto.randomUUID(), | ||
| mood: values.mood, | ||
| tags: values.tags, | ||
| notes: values.notes, | ||
| date: values.date || new Date(), | ||
| }; | ||
|
|
There was a problem hiding this comment.
logic: loadEntries() could throw an error but is outside the try block. Move the loadEntries() call inside the try block to properly catch any file system errors
| try { | |
| const newEntry: MoodEntry = { | |
| id: crypto.randomUUID(), | |
| mood: values.mood, | |
| tags: values.tags, | |
| notes: values.notes, | |
| date: values.date || new Date(), | |
| }; | |
| try { | |
| const entries = await loadEntries(); | |
| const newEntry: MoodEntry = { | |
| id: crypto.randomUUID(), | |
| mood: values.mood, | |
| tags: values.tags, | |
| notes: values.notes, | |
| date: values.date || new Date(), | |
| }; |
There was a problem hiding this comment.
This seems like a hallucination, loadEntries already is inside this try/catch block
extensions/mood/src/view-charts.tsx
Outdated
| // Generate charts | ||
| const sparklineSvg = generateSparkline(filteredEntries); | ||
| const distributionSvg = generateMoodDistribution(filteredEntries); |
There was a problem hiding this comment.
style: Chart generation on every render could impact performance with large datasets. Consider using useMemo for sparklineSvg and distributionSvg
|
@pernielsentikaer done with the initial batch of comments except for #17428 (comment) because I'm honestly not sure what is being suggested |
pernielsentikaer
left a comment
There was a problem hiding this comment.
Hi 👋
Looks good to me, approved 🔥
|
Published to the Raycast Store: |
|
🎉 🎉 🎉 We've rewarded your Raycast account with some credits. You will soon be able to exchange them for some swag. |
Description
Mood Tracker extension helps users monitor their emotional well-being by providing a simple and efficient way to record, track, and analyze your moods over time.
It includes actions that let user record their mood, view and search the list of recordings and view glanceable charts of mood trend and distribution over a specific timeframe.
It also includes a tool that lets Raycast AI work with the data and provide additional insights (I found this especially fun).
Screenshots
Checklist
npm run buildand tested this distribution build in Raycastassetsfolder are used by the extension itselfREADMEare placed outside of themetadatafolder