Skip to content

Commit ed3093f

Browse files
version 1.0.0
1 parent 2f64254 commit ed3093f

7 files changed

Lines changed: 399 additions & 0 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/node_modules
2+
/package-lock.json

github-contributions.desktop

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[Desktop Entry]
2+
Name=GitHub Contributions
3+
Comment=GitHub Contributions Tracker
4+
Exec=/usr/bin/github-contributions
5+
Icon=/usr/share/icons/github-contributions.png
6+
Type=Application
7+
Categories=Utility;Development;
8+
StartupNotify=true
9+
StartupWMClass=GitHub Contributions

icon.png

364 KB
Loading

index.html

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>GitHub Contributions</title>
7+
<style>
8+
body { font-family: Arial, sans-serif; margin: 5px; border-radius: 10px; background-color: rgba(255, 255, 255, 0); }
9+
.settings { margin-bottom: 5px; -webkit-app-region: no-drag; background-color: rgba(255, 255, 255, 0.9); padding: 10px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.2); }
10+
.settings label { display: block; margin-bottom: 5px; font-weight: bold; }
11+
.settings input, .settings select { width: 100%; padding: 5px; margin-bottom: 10px; border: 1px solid #ccc; border-radius: 3px; }
12+
.settings button { padding: 5px 10px; background-color: #007bff; color: white; border: none; border-radius: 3px; cursor: pointer; }
13+
.settings button:hover { background-color: #0056b3; }
14+
.graph { display: grid; grid-template-columns: repeat(53, 10px); grid-template-rows: repeat(7, 10px); gap: 2px; grid-auto-flow: column; }
15+
.day { width: 10px; height: 10px; border-radius: 2px; }
16+
.level-0 { background-color: #ebedf0; }
17+
.level-1 { background-color: #9be9a8; }
18+
.level-2 { background-color: #40c463; }
19+
.level-3 { background-color: #30a14e; }
20+
.level-4 { background-color: #216e39; }
21+
.dark { background-color: rgba(13, 17, 23, 0.8); color: white; }
22+
.dark .level-0 { background-color: #161b22; }
23+
.dark .settings { background-color: rgba(43, 43, 43, 1); }
24+
.dark .settings input, .dark .settings select { background-color: #2b2b2b; color: white; border-color: #555; width: 300px; align-self: center;}
25+
.dark .settings button { background-color: #007bff; }
26+
#year-label { margin-bottom: 10px; font-weight: bold; }
27+
</style>
28+
</head>
29+
<body>
30+
31+
<div class="settings" id="settings-panel" style="display: none;">
32+
<label>Username: <input type="text" id="username"></label>
33+
<label>Token (create a simple token in https://github.com/settings/tokens with no scope): <input type="password" id="token"></label>
34+
<label>Theme: <select id="theme"><option>Light</option><option>Dark</option></select></label>
35+
<button id="save">Save</button>
36+
</div>
37+
<div id="year-label"></div>
38+
<div id="graph" class="graph"></div>
39+
<script src="renderer.js"></script>
40+
</body>
41+
</html>

main.js

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
const { app, BrowserWindow, ipcMain, Menu, Tray, nativeImage } = require('electron');
2+
const path = require('path');
3+
const fs = require('fs');
4+
5+
app.commandLine.appendSwitch('--no-sandbox');
6+
app.commandLine.appendSwitch('--disable-setuid-sandbox');
7+
8+
let win;
9+
let dragOffset = { x: 0, y: 0 };
10+
const boundsFile = path.join(app.getPath('userData'), 'bounds.json');
11+
12+
function saveBounds() {
13+
if (win) {
14+
const bounds = win.getBounds();
15+
fs.writeFileSync(boundsFile, JSON.stringify(bounds));
16+
}
17+
}
18+
19+
function loadBounds() {
20+
try {
21+
return JSON.parse(fs.readFileSync(boundsFile, 'utf8'));
22+
} catch {
23+
return { width: 655, height: 150, x: 100, y: 100 };
24+
}
25+
}
26+
27+
ipcMain.on('close-window', () => {
28+
if (win) win.close();
29+
});
30+
31+
ipcMain.on('show-context-menu', (event) => {
32+
const menu = Menu.buildFromTemplate([
33+
{
34+
label: 'Settings',
35+
click: () => event.sender.send('toggle-settings')
36+
},
37+
{
38+
label: 'Close',
39+
click: () => win.close()
40+
}
41+
]);
42+
menu.popup();
43+
});
44+
45+
ipcMain.on('start-drag', (event, pos) => {
46+
const bounds = win.getBounds();
47+
dragOffset.x = pos.x - bounds.x;
48+
dragOffset.y = pos.y - bounds.y;
49+
});
50+
51+
ipcMain.on('drag', (event, pos) => {
52+
const newX = pos.x - dragOffset.x;
53+
const newY = pos.y - dragOffset.y;
54+
win.setBounds({ x: newX, y: newY, width: 655, height: win.getBounds().height });
55+
});
56+
57+
ipcMain.on('resize-window', (event, height) => {
58+
const bounds = win.getBounds();
59+
win.setBounds({ ...bounds, height });
60+
});
61+
62+
ipcMain.on('save-bounds', saveBounds);
63+
64+
function createWindow() {
65+
const bounds = loadBounds();
66+
win = new BrowserWindow({
67+
...bounds,
68+
webPreferences: {
69+
nodeIntegration: true,
70+
contextIsolation: false,
71+
enableRemoteModule: true
72+
},
73+
resizable: false,
74+
frame: false,
75+
transparent: true,
76+
show: false,
77+
skipTaskbar: true,
78+
type: process.platform === 'linux' ? 'toolbar' : undefined,
79+
alwaysOnTop: false,
80+
icon:"./icon.png",
81+
title: 'GitHub Contributions',
82+
name: 'GitHub Contributions'
83+
});
84+
85+
win.loadFile('index.html');
86+
win.on('close', saveBounds);
87+
88+
const icon = nativeImage.createFromPath(path.join(__dirname, 'icon.png'));
89+
const tray = new Tray(icon);
90+
tray.setToolTip('GitHub Contributions');
91+
92+
const trayMenu = Menu.buildFromTemplate([
93+
{
94+
label: 'Settings',
95+
click: () => win.webContents.send('toggle-settings')
96+
},
97+
{
98+
label: 'Close',
99+
click: () => win.close()
100+
}
101+
]);
102+
103+
tray.on('click', () => {
104+
if (win.isVisible()) {
105+
win.hide();
106+
} else {
107+
win.show();
108+
setTimeout(() => {
109+
win.setSkipTaskbar(true);
110+
}, 100);
111+
}
112+
});
113+
114+
tray.setContextMenu(trayMenu);
115+
116+
win.once('ready-to-show', () => {
117+
win.show();
118+
119+
// Force hide from taskbar on Linux
120+
if (process.platform === 'linux') {
121+
setTimeout(() => {
122+
win.setSkipTaskbar(true);
123+
// Additional Linux-specific method
124+
win.blur();
125+
}, 100);
126+
127+
// Try multiple times for Linux
128+
setTimeout(() => win.setSkipTaskbar(true), 500);
129+
setTimeout(() => win.setSkipTaskbar(true), 1000);
130+
} else {
131+
win.setSkipTaskbar(true);
132+
}
133+
});
134+
}
135+
136+
app.whenReady().then(createWindow);
137+
138+
app.on('window-all-closed', () => {
139+
if (process.platform !== 'darwin') app.quit();
140+
});

package.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "github-contributions",
3+
"version": "1.0.0",
4+
"main": "main.js",
5+
"scripts": {
6+
"start": "electron . --no-sandbox",
7+
"build": "electron-builder",
8+
"test": "echo \"Error: no test specified\" && exit 1"
9+
},
10+
"repository": {
11+
"type": "git",
12+
"url": "git+https://github.com/mohammad-hassani/github-contributions.git"
13+
},
14+
"keywords": [],
15+
"author": "Mohammad Hassani <hasani9821.mh@gmail.com>",
16+
"license": "ISC",
17+
"type": "commonjs",
18+
"bugs": {
19+
"url": "https://github.com/mohammad-hassani/github-contributions/issues"
20+
},
21+
"homepage": "https://github.com/mohammad-hassani/github-contributions#readme",
22+
"description": "GitHub Contributions Tracker - A minimal desktop app to track your GitHub contributions",
23+
"devDependencies": {
24+
"electron": "^33.0.0",
25+
"electron-builder": "^26.0.0"
26+
},
27+
"icon": "icon.png",
28+
"build": {
29+
"appId": "com.github-contributions.app",
30+
"icon": "icon.png",
31+
"linux": {
32+
"target": "deb",
33+
"category": "Utility",
34+
"synopsis": "GitHub Contributions Tracker"
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)