no usage display notice implemented

remembering the last known position implemented
This commit is contained in:
Slavomir Durej 2025-12-17 08:41:19 +00:00
parent 5680558060
commit 2cfa69cc5d
5 changed files with 107 additions and 12 deletions

View file

@ -117,8 +117,8 @@ const UPDATE_INTERVAL = 5 * 60 * 1000; // Change to your preference (in millisec
- Try re-logging in from the system tray menu - Try re-logging in from the system tray menu
### Widget position not saving ### Widget position not saving
- Position is reset on each launch - Window position is now saved automatically when you drag it
- Future version will include position memory - Position will be restored when you restart the app
### Build errors ### Build errors
```bash ```bash
@ -158,7 +158,7 @@ https://claude.ai/api/organizations/{org_id}/usage
- [ ] Linux support - [ ] Linux support
- [ ] Custom themes - [ ] Custom themes
- [ ] Notification alerts at usage thresholds - [ ] Notification alerts at usage thresholds
- [ ] Remember window position - [x] Remember window position
- [ ] Settings panel - [ ] Settings panel
- [ ] Usage history graphs - [ ] Usage history graphs
- [ ] Multiple account support - [ ] Multiple account support

20
main.js
View file

@ -16,7 +16,9 @@ const WIDGET_WIDTH = 480;
const WIDGET_HEIGHT = 140; const WIDGET_HEIGHT = 140;
function createMainWindow() { function createMainWindow() {
mainWindow = new BrowserWindow({ // Load saved position or use defaults
const savedPosition = store.get('windowPosition');
const windowOptions = {
width: WIDGET_WIDTH, width: WIDGET_WIDTH,
height: WIDGET_HEIGHT, height: WIDGET_HEIGHT,
frame: false, frame: false,
@ -30,7 +32,15 @@ function createMainWindow() {
contextIsolation: true, contextIsolation: true,
preload: path.join(__dirname, 'preload.js') preload: path.join(__dirname, 'preload.js')
} }
}); };
// Apply saved position if it exists
if (savedPosition) {
windowOptions.x = savedPosition.x;
windowOptions.y = savedPosition.y;
}
mainWindow = new BrowserWindow(windowOptions);
mainWindow.loadFile('src/renderer/index.html'); mainWindow.loadFile('src/renderer/index.html');
@ -38,6 +48,12 @@ function createMainWindow() {
mainWindow.setAlwaysOnTop(true, 'floating'); mainWindow.setAlwaysOnTop(true, 'floating');
mainWindow.setVisibleOnAllWorkspaces(true); mainWindow.setVisibleOnAllWorkspaces(true);
// Save position when window is moved
mainWindow.on('move', () => {
const position = mainWindow.getBounds();
store.set('windowPosition', { x: position.x, y: position.y });
});
mainWindow.on('closed', () => { mainWindow.on('closed', () => {
mainWindow = null; mainWindow = null;
}); });

View file

@ -9,6 +9,7 @@ const UPDATE_INTERVAL = 5 * 60 * 1000; // 5 minutes
const elements = { const elements = {
loadingContainer: document.getElementById('loadingContainer'), loadingContainer: document.getElementById('loadingContainer'),
loginContainer: document.getElementById('loginContainer'), loginContainer: document.getElementById('loginContainer'),
noUsageContainer: document.getElementById('noUsageContainer'),
mainContent: document.getElementById('mainContent'), mainContent: document.getElementById('mainContent'),
loginBtn: document.getElementById('loginBtn'), loginBtn: document.getElementById('loginBtn'),
refreshBtn: document.getElementById('refreshBtn'), refreshBtn: document.getElementById('refreshBtn'),
@ -130,17 +131,30 @@ async function fetchUsageData() {
} }
} }
// Update UI with usage data // Check if there's no usage data
function hasNoUsage(data) {
const sessionUtilization = data.five_hour?.utilization || 0;
const sessionResetsAt = data.five_hour?.resets_at;
const weeklyUtilization = data.seven_day?.utilization || 0;
const weeklyResetsAt = data.seven_day?.resets_at;
return sessionUtilization === 0 && !sessionResetsAt &&
weeklyUtilization === 0 && !weeklyResetsAt;
}
// Update UI with usage data // Update UI with usage data
function updateUI(data) { function updateUI(data) {
latestUsageData = data; latestUsageData = data;
// Check if there's no usage data
if (hasNoUsage(data)) {
showNoUsage();
return;
}
showMainContent();
refreshTimers(); refreshTimers();
startCountdown(); startCountdown();
// Update timestamp
// Update timestamp
// const now = new Date();
// elements.lastUpdate.textContent = `Updated ${now.toLocaleTimeString()}`;
} }
// Track if we've already triggered a refresh for expired timers // Track if we've already triggered a refresh for expired timers
@ -301,19 +315,29 @@ function updateTimer(timerElement, textElement, resetsAt, totalMinutes) {
function showLoading() { function showLoading() {
elements.loadingContainer.style.display = 'block'; elements.loadingContainer.style.display = 'block';
elements.loginContainer.style.display = 'none'; elements.loginContainer.style.display = 'none';
elements.noUsageContainer.style.display = 'none';
elements.mainContent.style.display = 'none'; elements.mainContent.style.display = 'none';
} }
function showLoginRequired() { function showLoginRequired() {
elements.loadingContainer.style.display = 'none'; elements.loadingContainer.style.display = 'none';
elements.loginContainer.style.display = 'flex'; // Use flex to preserve centering elements.loginContainer.style.display = 'flex'; // Use flex to preserve centering
elements.noUsageContainer.style.display = 'none';
elements.mainContent.style.display = 'none'; elements.mainContent.style.display = 'none';
stopAutoUpdate(); stopAutoUpdate();
} }
function showNoUsage() {
elements.loadingContainer.style.display = 'none';
elements.loginContainer.style.display = 'none';
elements.noUsageContainer.style.display = 'flex';
elements.mainContent.style.display = 'none';
}
function showMainContent() { function showMainContent() {
elements.loadingContainer.style.display = 'none'; elements.loadingContainer.style.display = 'none';
elements.loginContainer.style.display = 'none'; elements.loginContainer.style.display = 'none';
elements.noUsageContainer.style.display = 'none';
elements.mainContent.style.display = 'block'; elements.mainContent.style.display = 'block';
} }

View file

@ -56,6 +56,19 @@
</div> </div>
</div> </div>
<!-- No Usage State -->
<div class="no-usage-container" id="noUsageContainer" style="display: none;">
<div class="no-usage-content">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
</svg>
<div class="no-usage-text-group">
<h3>No Usage Yet</h3>
<p>Start chatting with Claude to see your usage stats</p>
</div>
</div>
</div>
<!-- Main Content --> <!-- Main Content -->
<div class="content" id="mainContent" style="display: none;"> <div class="content" id="mainContent" style="display: none;">
<!-- Session Usage --> <!-- Session Usage -->

View file

@ -56,7 +56,7 @@ body {
} }
.app-logo { .app-logo {
width: 19px; width: 19px;npm
height: 19px; height: 19px;
border-radius: 6px; border-radius: 6px;
opacity: 0.8; opacity: 0.8;
@ -188,6 +188,48 @@ body {
box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3); box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);
} }
/* No Usage State */
.no-usage-container {
padding: 0 16px;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.no-usage-content {
display: flex;
align-items: center;
gap: 16px;
text-align: left;
width: 100%;
}
.no-usage-content svg {
color: #8b5cf6;
width: 32px;
height: 32px;
flex-shrink: 0;
}
.no-usage-text-group {
display: flex;
flex-direction: column;
justify-content: center;
}
.no-usage-content h3 {
color: #e0e0e0;
font-size: 14px;
margin-bottom: 2px;
}
.no-usage-content p {
color: #a0a0a0;
font-size: 11px;
margin-bottom: 0;
}
/* Main Content */ /* Main Content */
.content { .content {
padding: 20px; padding: 20px;