she worksish!!

This commit is contained in:
End 2025-10-19 22:10:41 -07:00
parent 233d5237ca
commit a644654906
4 changed files with 485 additions and 287 deletions

View file

@ -7,57 +7,353 @@
</head>
<body>
<div class="container">
<h2>How are you feeling?</h2>
<div class="moods">
<button class="mood-btn" onclick="saveMood('😊')">😊</button>
<button class="mood-btn" onclick="saveMood('😐')">😐</button>
<button class="mood-btn" onclick="saveMood('😔')">😔</button>
<button class="mood-btn" onclick="saveMood('😫')">😫</button>
<button class="mood-btn" onclick="saveMood('😴')">😴</button>
<div class="nav-tabs">
<div class="nav-tab active" onclick="showView('mood')">Log Mood</div>
<div class="nav-tab" onclick="showView('history')">History</div>
</div>
<div class="controls">
<button onclick="dismiss()">Dismiss</button>
<button onclick="toggleSettings()">⚙️ Settings</button>
<!-- mood logging view -->
<div class="view active" id="mood-view">
<h2>How are you feeling?</h2>
<div class="mood-categories">
<div class="category-title">Happy</div>
<div class="mood-row">
<button class="mood-btn" onclick="selectMood('😊', 'good', this)">
<span>😊</span>
<span class="mood-label">good</span>
</button>
<button class="mood-btn" onclick="selectMood('😄', 'joyful', this)">
<span>😄</span>
<span class="mood-label">joyful</span>
</button>
<button class="mood-btn" onclick="selectMood('🥰', 'loved', this)">
<span>🥰</span>
<span class="mood-label">loved</span>
</button>
<button
class="mood-btn"
onclick="selectMood('😌', 'peaceful', this)"
>
<span>😌</span>
<span class="mood-label">peaceful</span>
</button>
<button
class="mood-btn"
onclick="selectMood('🤗', 'grateful', this)"
>
<span>🤗</span>
<span class="mood-label">grateful</span>
</button>
</div>
<div class="category-title">Calm</div>
<div class="mood-row">
<button
class="mood-btn"
onclick="selectMood('😐', 'neutral', this)"
>
<span>😐</span>
<span class="mood-label">neutral</span>
</button>
<button
class="mood-btn"
onclick="selectMood('🙂', 'content', this)"
>
<span>🙂</span>
<span class="mood-label">content</span>
</button>
<button class="mood-btn" onclick="selectMood('😶', 'blank', this)">
<span>😶</span>
<span class="mood-label">blank</span>
</button>
<button
class="mood-btn"
onclick="selectMood('🤔', 'thoughtful', this)"
>
<span>🤔</span>
<span class="mood-label">thinking</span>
</button>
<button class="mood-btn" onclick="selectMood('😴', 'sleepy', this)">
<span>😴</span>
<span class="mood-label">sleepy</span>
</button>
</div>
<div class="category-title">Sad</div>
<div class="mood-row">
<button class="mood-btn" onclick="selectMood('😔', 'down', this)">
<span>😔</span>
<span class="mood-label">down</span>
</button>
<button class="mood-btn" onclick="selectMood('😢', 'sad', this)">
<span>😢</span>
<span class="mood-label">sad</span>
</button>
<button
class="mood-btn"
onclick="selectMood('😞', 'disappointed', this)"
>
<span>😞</span>
<span class="mood-label">let down</span>
</button>
<button class="mood-btn" onclick="selectMood('😭', 'crying', this)">
<span>😭</span>
<span class="mood-label">crying</span>
</button>
<button class="mood-btn" onclick="selectMood('🥺', 'hurt', this)">
<span>🥺</span>
<span class="mood-label">hurt</span>
</button>
</div>
<div class="category-title">Anxious</div>
<div class="mood-row">
<button
class="mood-btn"
onclick="selectMood('😰', 'worried', this)"
>
<span>😰</span>
<span class="mood-label">worried</span>
</button>
<button
class="mood-btn"
onclick="selectMood('😨', 'anxious', this)"
>
<span>😨</span>
<span class="mood-label">anxious</span>
</button>
<button
class="mood-btn"
onclick="selectMood('😖', 'overwhelmed', this)"
>
<span>😖</span>
<span class="mood-label">stressed</span>
</button>
<button class="mood-btn" onclick="selectMood('😣', 'tense', this)">
<span>😣</span>
<span class="mood-label">tense</span>
</button>
<button
class="mood-btn"
onclick="selectMood('😓', 'exhausted', this)"
>
<span>😓</span>
<span class="mood-label">drained</span>
</button>
</div>
<div class="category-title">Angry</div>
<div class="mood-row">
<button
class="mood-btn"
onclick="selectMood('😠', 'annoyed', this)"
>
<span>😠</span>
<span class="mood-label">annoyed</span>
</button>
<button class="mood-btn" onclick="selectMood('😡', 'angry', this)">
<span>😡</span>
<span class="mood-label">angry</span>
</button>
<button
class="mood-btn"
onclick="selectMood('🤬', 'furious', this)"
>
<span>🤬</span>
<span class="mood-label">furious</span>
</button>
<button
class="mood-btn"
onclick="selectMood('😤', 'frustrated', this)"
>
<span>😤</span>
<span class="mood-label">frustrated</span>
</button>
<button
class="mood-btn"
onclick="selectMood('😒', 'irritated', this)"
>
<span>😒</span>
<span class="mood-label">irritated</span>
</button>
</div>
<div class="category-title">Excited</div>
<div class="mood-row">
<button class="mood-btn" onclick="selectMood('🤩', 'amazed', this)">
<span>🤩</span>
<span class="mood-label">amazed</span>
</button>
<button
class="mood-btn"
onclick="selectMood('😆', 'excited', this)"
>
<span>😆</span>
<span class="mood-label">excited</span>
</button>
<button
class="mood-btn"
onclick="selectMood('🥳', 'celebratory', this)"
>
<span>🥳</span>
<span class="mood-label">pumped</span>
</button>
<button
class="mood-btn"
onclick="selectMood('😎', 'confident', this)"
>
<span>😎</span>
<span class="mood-label">confident</span>
</button>
<button
class="mood-btn"
onclick="selectMood('🤓', 'focused', this)"
>
<span>🤓</span>
<span class="mood-label">focused</span>
</button>
</div>
</div>
<!-- energy level slider -->
<div class="energy-section" id="energy-section">
<div class="energy-label">
<span>Energy Level</span>
<span id="energy-value">5</span>
</div>
<input
type="range"
min="1"
max="10"
class="energy-slider"
id="energy-slider"
oninput="updateEnergyValue()"
/>
</div>
<!-- journal textarea -->
<div class="journal-section" id="journal-section">
<textarea
id="note"
placeholder="What's on your mind? (optional)"
></textarea>
</div>
<div class="controls">
<button onclick="dismiss()">Dismiss</button>
<button class="primary" onclick="saveMood()" id="save-btn" disabled>
Save
</button>
</div>
<div class="settings" id="settings">
<div class="setting-row">
<label>Position:</label>
<select id="position" onchange="updateConfig()">
<option value="top-left">Top Left</option>
<option value="top-right">Top Right</option>
<option value="bottom-left">Bottom Left</option>
<option value="bottom-right">Bottom Right</option>
</select>
</div>
<div class="setting-row">
<label>Idle time (minutes):</label>
<select id="idleMinutes" onchange="updateConfig()">
<option value="1">1</option>
<option value="2">2</option>
<option value="5">5</option>
<option value="10">10</option>
</select>
</div>
<button onclick="toggleSettings()">Close Settings</button>
</div>
<button
onclick="toggleSettings()"
style="margin-top: 12px; width: 100%"
>
⚙️ Settings
</button>
</div>
<div class="settings" id="settings">
<div class="setting-row">
<label>Position:</label>
<select id="position" onchange="updateConfig()">
<option value="top-left">Top Left</option>
<option value="top-right">Top Right</option>
<option value="bottom-left">Bottom Left</option>
<option value="bottom-right">Bottom Right</option>
</select>
</div>
<div class="setting-row">
<label>Idle time (minutes):</label>
<select id="idleMinutes" onchange="updateConfig()">
<option value="1">1</option>
<option value="2">2</option>
<option value="5">5</option>
<option value="10">10</option>
</select>
<!-- history view -->
<div class="view" id="history-view">
<h2>Your Mood History</h2>
<div class="history-list" id="history-list">
<div class="no-history">Loading...</div>
</div>
<button onclick="showView('mood')" style="width: 100%">← Back</button>
</div>
</div>
<script>
const { ipcRenderer } = require("electron");
// load config when started
let selectedMood = null;
let selectedMoodLabel = null;
// load saved config
const config = ipcRenderer.sendSync("get-config");
document.getElementById("position").value = config.position;
document.getElementById("idleMinutes").value = config.idleMinutes;
function saveMood(mood) {
ipcRenderer.send("save-mood", mood);
function selectMood(emoji, label, btn) {
selectedMood = emoji;
selectedMoodLabel = label;
// clear previous selection
document
.querySelectorAll(".mood-btn")
.forEach((b) => b.classList.remove("selected"));
btn.classList.add("selected");
// show energy + journal sections
document.getElementById("energy-section").classList.add("active");
document.getElementById("journal-section").classList.add("active");
document.getElementById("save-btn").disabled = false;
}
function updateEnergyValue() {
const value = document.getElementById("energy-slider").value;
document.getElementById("energy-value").value = value;
}
function saveMood() {
if (!selectedMood) return;
const note = document.getElementById("note").value.trim();
const energy = parseInt(document.getElementById("energy-slider").value);
ipcRenderer.send("save-mood", {
mood: `${selectedMood} ${selectedMoodLabel}`,
energy,
note,
});
// reset form
resetForm();
}
function dismiss() {
ipcRenderer.send("dismiss");
resetForm();
}
function resetForm() {
selectedMood = null;
selectedMoodLabel = null;
document.getElementById("note").value = "";
document.getElementById("energy-slider").value = 5;
document.getElementById("energy-value").textContent = "5";
document
.querySelectorAll(".mood-btn")
.forEach((b) => b.classList.remove("selected"));
document.getElementById("energy-section").classList.remove("active");
document.getElementById("journal-section").classList.remove("active");
document.getElementById("save-btn").disabled = true;
}
function toggleSettings() {
@ -71,6 +367,74 @@
};
ipcRenderer.send("save-config", config);
}
function showView(viewName) {
// update active tab
document
.querySelectorAll(".nav-tab")
.forEach((tab) => tab.classList.remove("active"));
event.target.classList.add("active");
// switch views
document
.querySelectorAll(".view")
.forEach((view) => view.classList.remove("active"));
document.getElementById(viewName + "-view").classList.add("active");
if (viewName === "history") {
loadHistory();
}
}
function loadHistory() {
ipcRenderer.send("get-moods", 30);
}
// render history items
ipcRenderer.on("moods-data", (event, moods) => {
const historyList = document.getElementById("history-list");
if (moods.length === 0) {
historyList.innerHTML =
'<div class="no-history">No entries yet. Start tracking!</div>';
return;
}
historyList.innerHTML = moods
.map((mood) => {
const date = new Date(mood.timestamp);
const timeStr =
date.toLocaleDateString() +
" " +
date.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
});
return `
<div class="history-item">
<div class="history-header">
<div class="history-mood">
${mood.mood}
${
mood.energy
? `<span class="history-energy">⚡ ${mood.energy}/10</span>`
: ""
}
</div>
<span class="history-time">${timeStr}</span>
</div>
${mood.note ? `<div class="history-note">${mood.note}</div>` : ""}
</div>
`;
})
.join("");
});
// handle tray menu click
ipcRenderer.on("show-history", () => {
showView("history");
});
</script>
</body>
</html>

50
main.js
View file

@ -15,24 +15,23 @@ const sqlite3 = require("sqlite3").verbose();
let mainWindow;
let tray;
let db;
const IDLE_THRESHOLD = 120; // seconds (2 minutes)
const IDLE_THRESHOLD = 120; // TODO: change back to 120 for prod
const CONFIG_PATH = path.join(app.getPath("userData"), "config.json");
const DB_PATH = path.join(app.getPath("userData"), "moods.db");
// Initialize database
function initDatabase() {
db = new sqlite3.Database(DB_PATH);
db.run(`
CREATE TABLE IF NOT EXISTS moods (
id INTEGER PRIMARY KEY AUTOINCREMENT,
mood TEXT NOT NULL,
energy INTEGER,
note TEXT,
timestamp INTEGER NOT NULL
)
`);
}
// Load/create config
function loadConfig() {
try {
return JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8"));
@ -45,11 +44,10 @@ function saveConfig(config) {
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
}
// Calculate window position based on config
function getWindowPosition(position) {
const { width, height } = screen.getPrimaryDisplay().workAreaSize;
const windowWidth = 400;
const windowHeight = 350;
const windowWidth = 450;
const windowHeight = 550;
const padding = 20;
const positions = {
@ -70,8 +68,8 @@ function createWindow() {
const position = getWindowPosition(config.position);
mainWindow = new BrowserWindow({
width: 400,
height: 350,
width: 450,
height: 550,
x: position.x,
y: position.y,
frame: false,
@ -89,12 +87,8 @@ function createWindow() {
mainWindow.loadFile("index.html");
}
// Create system tray icon
function createTray() {
// Create a simple icon
const iconPath = path.join(__dirname, "icon.png");
// For testing
// fallback icon - replace with actual icon.png in prod
tray = new Tray(createDefaultIcon());
const contextMenu = Menu.buildFromTemplate([
@ -119,28 +113,21 @@ function createTray() {
tray.setToolTip("Mood Tracker");
tray.setContextMenu(contextMenu);
// Double click to open
tray.on("double-click", () => {
mainWindow.show();
});
}
// Create a simple icon for testing
function createDefaultIcon() {
const { nativeImage } = require("electron");
const canvas = require("canvas");
const canvasObj = canvas.createCanvas(16, 16);
const ctx = canvasObj.getContext("2d");
ctx.fillStyle = "#667eea";
ctx.beginPath();
ctx.arc(8, 8, 7, 0, Math.PI * 2);
ctx.fill();
// simple 16x16 purple circle as base64 PNG
const iconData =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAdgAAAHYBTnsmCAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAE3SURBVDiNpdI7S0JRHMDx3+WRD8pHZhAUFQRBDdHQ0NQc0hINLU1Bc0NzRB9BaGhoaQyRoqWGhqYgCHoQBEEQRGPYC1+ZXb2Xbl4qcODC/Z/fOZxz/keQJAnDMGAYBpIkIQgCer0e0WhU8TidTkVhNBolnU5Ld3f38nq9XgRBIJvNks/nlU6n0zidTuXz+ZQsy1xeXtLr9chkMvh8Pnw+H+VyWbm6uiKRSJBKpUgmk1QqFer1OtVqlUajQavVolwuK81mk3a7TafTodvt0uv16Pf7DAYDBu+Dh8mQYcgH2u02s9mM6XSKKIrMZjPm8zmLxYLlcsl4PGY0GimSJCGKIpPJhOFwyGAw4O3tTZFl+U9Zlvl8nyGfzyuKoqxRVVX0L9frrVar1W9UVWU+n/Pw+Mher4eqqmxsbPANK8aErL8MfjYAAAAASUVORK5CYII=";
return nativeImage.createFromDataURL(canvasObj.toDataURL());
return nativeImage.createFromDataURL(iconData);
}
// Check for idle state
function checkIdleState() {
const idleTime = powerMonitor.getSystemIdleTime();
const config = loadConfig();
@ -156,13 +143,13 @@ app.whenReady().then(() => {
createWindow();
createTray();
// Testing shortcutw
// dev shortcut
globalShortcut.register("CommandOrControl+Shift+M", () => {
console.log("Manual trigger - showing window");
console.log("Manual trigger");
mainWindow.show();
});
// Check idle state every 30 seconds
// check every 30s
setInterval(checkIdleState, 30000);
app.on("activate", () => {
@ -173,8 +160,7 @@ app.whenReady().then(() => {
});
app.on("window-all-closed", (e) => {
// Prevent quit - keep running in tray
e.preventDefault();
e.preventDefault(); // keep running in tray
});
app.on("before-quit", () => {
@ -183,10 +169,10 @@ app.on("before-quit", () => {
// IPC handlers
ipcMain.on("save-mood", (event, data) => {
const { mood, note } = data;
const { mood, energy, note } = data;
db.run(
"INSERT INTO moods (mood, note, timestamp) VALUES (?, ?, ?)",
[mood, note || null, Date.now()],
"INSERT INTO moods (mood, energy, note, timestamp) VALUES (?, ?, ?, ?)",
[mood, energy, note || null, Date.now()],
(err) => {
if (err) console.error(err);
mainWindow.hide();

277
package-lock.json generated
View file

@ -7,9 +7,9 @@
"": {
"name": "mood-tracker",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"canvas": "^2.11.2",
"electron": "^35.7.5",
"electron": "^28.0.0",
"sqlite3": "^5.1.6"
}
},
@ -41,86 +41,6 @@
"license": "MIT",
"optional": true
},
"node_modules/@mapbox/node-pre-gyp": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
"integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
"license": "BSD-3-Clause",
"dependencies": {
"detect-libc": "^2.0.0",
"https-proxy-agent": "^5.0.0",
"make-dir": "^3.1.0",
"node-fetch": "^2.6.7",
"nopt": "^5.0.0",
"npmlog": "^5.0.1",
"rimraf": "^3.0.2",
"semver": "^7.3.5",
"tar": "^6.1.11"
},
"bin": {
"node-pre-gyp": "bin/node-pre-gyp"
}
},
"node_modules/@mapbox/node-pre-gyp/node_modules/are-we-there-yet": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
"integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
"deprecated": "This package is no longer supported.",
"license": "ISC",
"dependencies": {
"delegates": "^1.0.0",
"readable-stream": "^3.6.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@mapbox/node-pre-gyp/node_modules/gauge": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
"integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
"deprecated": "This package is no longer supported.",
"license": "ISC",
"dependencies": {
"aproba": "^1.0.3 || ^2.0.0",
"color-support": "^1.1.2",
"console-control-strings": "^1.0.0",
"has-unicode": "^2.0.1",
"object-assign": "^4.1.1",
"signal-exit": "^3.0.0",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1",
"wide-align": "^1.1.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@mapbox/node-pre-gyp/node_modules/npmlog": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
"integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
"deprecated": "This package is no longer supported.",
"license": "ISC",
"dependencies": {
"are-we-there-yet": "^2.0.0",
"console-control-strings": "^1.1.0",
"gauge": "^3.0.0",
"set-blocking": "^2.0.0"
}
},
"node_modules/@mapbox/node-pre-gyp/node_modules/semver": {
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@npmcli/fs": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
@ -253,13 +173,15 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"license": "ISC"
"license": "ISC",
"optional": true
},
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"license": "MIT",
"optional": true,
"dependencies": {
"debug": "4"
},
@ -299,6 +221,7 @@
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=8"
}
@ -307,7 +230,8 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz",
"integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==",
"license": "ISC"
"license": "ISC",
"optional": true
},
"node_modules/are-we-there-yet": {
"version": "3.0.1",
@ -328,7 +252,8 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"license": "MIT"
"license": "MIT",
"optional": true
},
"node_modules/base64-js": {
"version": "1.5.1",
@ -383,6 +308,7 @@
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"license": "MIT",
"optional": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -478,56 +404,6 @@
"node": ">=8"
}
},
"node_modules/canvas": {
"version": "2.11.2",
"resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz",
"integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.0",
"nan": "^2.17.0",
"simple-get": "^3.0.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/canvas/node_modules/decompress-response": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
"license": "MIT",
"dependencies": {
"mimic-response": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/canvas/node_modules/mimic-response": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/canvas/node_modules/simple-get": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
"integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
"license": "MIT",
"dependencies": {
"decompress-response": "^4.2.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"node_modules/chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
@ -564,6 +440,7 @@
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
"license": "ISC",
"optional": true,
"bin": {
"color-support": "bin.js"
}
@ -572,13 +449,15 @@
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"license": "MIT"
"license": "MIT",
"optional": true
},
"node_modules/console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
"license": "ISC"
"license": "ISC",
"optional": true
},
"node_modules/debug": {
"version": "4.4.3",
@ -682,7 +561,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
"license": "MIT"
"license": "MIT",
"optional": true
},
"node_modules/detect-libc": {
"version": "2.1.2",
@ -701,14 +581,14 @@
"optional": true
},
"node_modules/electron": {
"version": "35.7.5",
"resolved": "https://registry.npmjs.org/electron/-/electron-35.7.5.tgz",
"integrity": "sha512-dnL+JvLraKZl7iusXTVTGYs10TKfzUi30uEDTqsmTm0guN9V2tbOjTzyIZbh9n3ygUjgEYyo+igAwMRXIi3IPw==",
"version": "28.3.3",
"resolved": "https://registry.npmjs.org/electron/-/electron-28.3.3.tgz",
"integrity": "sha512-ObKMLSPNhomtCOBAxFS8P2DW/4umkh72ouZUlUKzXGtYuPzgr1SYhskhFWgzAsPtUzhL2CzyV2sfbHcEW4CXqw==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@electron/get": "^2.0.0",
"@types/node": "^22.7.7",
"@types/node": "^18.11.18",
"extract-zip": "^2.0.1"
},
"bin": {
@ -718,11 +598,27 @@
"node": ">= 12.20.55"
}
},
"node_modules/electron/node_modules/@types/node": {
"version": "18.19.130",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
"integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/electron/node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"license": "MIT"
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"license": "MIT"
"license": "MIT",
"optional": true
},
"node_modules/encoding": {
"version": "0.1.13",
@ -879,7 +775,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"license": "ISC"
"license": "ISC",
"optional": true
},
"node_modules/gauge": {
"version": "4.0.4",
@ -929,6 +826,7 @@
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"license": "ISC",
"optional": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -1053,7 +951,8 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
"license": "ISC"
"license": "ISC",
"optional": true
},
"node_modules/http-cache-semantics": {
"version": "4.2.0",
@ -1094,6 +993,7 @@
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"license": "MIT",
"optional": true,
"dependencies": {
"agent-base": "6",
"debug": "4"
@ -1178,6 +1078,7 @@
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"license": "ISC",
"optional": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@ -1210,6 +1111,7 @@
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=8"
}
@ -1281,21 +1183,6 @@
"node": ">=10"
}
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"license": "MIT",
"dependencies": {
"semver": "^6.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/make-fetch-happen": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
@ -1351,6 +1238,7 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"license": "ISC",
"optional": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@ -1486,12 +1374,6 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/nan": {
"version": "2.23.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz",
"integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==",
"license": "MIT"
},
"node_modules/napi-build-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
@ -1538,26 +1420,6 @@
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"license": "MIT"
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"license": "MIT",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-gyp": {
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz",
@ -1601,6 +1463,7 @@
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
"license": "ISC",
"optional": true,
"dependencies": {
"abbrev": "1"
},
@ -1640,15 +1503,6 @@
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@ -1698,6 +1552,7 @@
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=0.10.0"
}
@ -1849,6 +1704,7 @@
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"license": "ISC",
"optional": true,
"dependencies": {
"glob": "^7.1.3"
},
@ -1940,13 +1796,15 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
"license": "ISC"
"license": "ISC",
"optional": true
},
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"license": "ISC"
"license": "ISC",
"optional": true
},
"node_modules/simple-concat": {
"version": "1.0.1",
@ -2092,6 +1950,7 @@
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"license": "MIT",
"optional": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@ -2106,6 +1965,7 @@
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"license": "MIT",
"optional": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@ -2194,12 +2054,6 @@
"node": ">=8"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT"
},
"node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@ -2266,22 +2120,6 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"license": "MIT",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -2303,6 +2141,7 @@
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
"license": "ISC",
"optional": true,
"dependencies": {
"string-width": "^1.0.2 || 2 || 3 || 4"
}

View file

@ -1,13 +1,22 @@
{
"name": "mood-tracker",
"version": "1.0.0",
"description": "Desktop mood tracking app with idle detection",
"main": "main.js",
"scripts": {
"start": "electron ."
"start": "electron .",
"dev": "electron . --dev"
},
"keywords": [
"mood",
"tracker",
"journal",
"electron"
],
"author": "",
"license": "MIT",
"dependencies": {
"electron": "^35.7.5",
"sqlite3": "^5.1.6",
"canvas": "^2.11.2"
"electron": "^28.0.0",
"sqlite3": "^5.1.6"
}
}