Skip to content

Commit 0cba19c

Browse files
committed
Add pause feature
1 parent 1a21951 commit 0cba19c

5 files changed

Lines changed: 166 additions & 45 deletions

File tree

README.md

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ Simple Coding Time Tracker is a powerful extension for Visual Studio Code that h
1313
- **Tooltip on Status Bar**: Shows the total coding time weekly, monthly, and all time basis.
1414
- **Detailed Summaries**: View comprehensive reports of your coding activity. You can search your total time on a particular day or project.
1515
- **Data Persistence**: Safely stores your time data for long-term analysis.
16-
- **Configurable Save Interval**: Customize how often your coding time data is saved (default: 5 seconds). Adjust this in VS Code settings to balance between data accuracy and system performance.
17-
16+
- **Configurable Settings**:
17+
- Save Interval: Customize how often your coding time data is saved (default: 5 seconds)
18+
- Inactivity Timeout: Set how long to wait before stopping the timer when no activity is detected (default: 5 minutes)
1819

1920
## Screenshots
2021
### Status Bar
@@ -39,7 +40,6 @@ There are total 3 commands in the command palette available for this extension.
3940

4041
![All Command Palette Commands](./images/commands.png)
4142

42-
4343
## Installation
4444

4545
1. Open Visual Studio Code
@@ -51,37 +51,36 @@ There are total 3 commands in the command palette available for this extension.
5151

5252
Once installed, the extension will automatically start tracking your coding time. You can view your current session time in the status bar at the bottom of the VSCode window.
5353

54-
To access detailed summaries and reports, use the command palette (Ctrl+Shift+P or Cmd+Shift+P on macOS) and search for "Time Tracker" to see available commands.
54+
To access detailed summaries and reports, use the command palette (Ctrl+Shift+P or Cmd+Shift+P on macOS) and search for "SCTT" to see available commands.
5555

56-
### Configuring Save Interval
57-
You can customize how often the extension saves your coding time data:
58-
1. Open VS Code Settings (Ctrl+, or Cmd+, on macOS)
59-
2. Search for "Simple Coding Time Tracker"
60-
3. Find the "Save Interval" setting
61-
4. Enter your preferred interval in seconds (default is 5 seconds)
62-
- Lower values (e.g., 5-10 seconds) provide more frequent updates but may impact performance
63-
- Higher values (e.g., 30-60 seconds) are more efficient but update less frequently
56+
### Configuration Options
6457

65-
## Control Panel Commands
58+
You can customize the extension's behavior through VS Code settings:
6659

67-
The Simple Coding Time Tracker extension offers a range of commands accessible through the Command Palette, designed to streamline your coding time tracking experience. Here are the primary commands available:
68-
69-
To access these commands, open the Command Palette (Ctrl+Shift+P or Cmd+Shift+P on macOS).
60+
1. Open VS Code Settings (Ctrl+, or Cmd+, on macOS)
61+
2. Search for "Simple Coding Time Tracker"
62+
3. Available settings:
63+
- **Save Interval**: How often to save your coding time data (in seconds)
64+
- Default: 5 seconds
65+
- Lower values provide more frequent updates but may impact performance
66+
- Higher values are more efficient but update less frequently
67+
- **Inactivity Timeout**: How long to wait before stopping the timer when no activity is detected (in minutes)
68+
- Default: 5 minutes
69+
- Lower values will stop tracking sooner when you're not actively coding
70+
- Higher values will continue tracking for longer during breaks
7071

71-
- **Show Summary**:
72-
- Command Title: `SCTT: Show Coding Time Summary`
73-
- This command displays a comprehensive summary of your coding activity, including the total time invested in projects and a daily breakdown.
72+
### Available Commands
7473

75-
- **Reset Timer for Today**:
76-
- Command Title: `SCTT: Reset Coding Timer for Today`
77-
- This command resets the coding time tracker for the current day, allowing you to start anew without any previous data influencing your current session.
74+
The extension provides the following commands through the Command Palette:
7875

79-
- **Reset All Timers**:
80-
- Command Title: `SCTT: Reset All Coding Timers`
81-
- This command resets all coding time trackers. It includes a confirmation prompt to prevent unintended resets, ensuring you have full control over your data.
76+
- **Show Summary** (`SCTT: Show Coding Time Summary`):
77+
Displays a comprehensive summary of your coding activity, including total time invested in projects and a daily breakdown.
8278

83-
By using these commands, you can effectively manage your coding sessions and maintain precise records of your work.
79+
- **Reset Timer for Today** (`SCTT: Reset Coding Timer for Today`):
80+
Resets the coding time tracker for the current day, allowing you to start anew.
8481

82+
- **Reset All Timers** (`SCTT: Reset All Coding Timers`):
83+
Resets all coding time trackers with a confirmation prompt to prevent unintended resets.
8584

8685
## Changelog
8786

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@
2424
"type": "number",
2525
"default": 5,
2626
"description": "Interval in seconds to save the current coding session"
27+
},
28+
"simpleCodingTimeTracker.inactivityTimeout": {
29+
"type": "number",
30+
"default": 300,
31+
"description": "Time in seconds of inactivity before tracking stops (default: 300 seconds = 5 minutes)"
2732
}
2833
}
2934
},

src/extension.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ export function activate(context: vscode.ExtensionContext) {
1010
const statusBar = new StatusBar(timeTracker);
1111
const summaryView = new SummaryViewProvider(context, database, timeTracker);
1212

13+
// Register cursor tracking
14+
context.subscriptions.push(
15+
vscode.window.onDidChangeTextEditorSelection(() => {
16+
timeTracker.updateCursorActivity();
17+
})
18+
);
19+
1320
// Register the existing command
1421
let disposable = vscode.commands.registerCommand('simpleCodingTimeTracker.showSummary', () => {
1522
summaryView.show();

src/statusBar.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ export class StatusBar implements vscode.Disposable {
2020

2121
private updateStatusBar() {
2222
const todayTotal = this.timeTracker.getTodayTotal();
23-
this.statusBarItem.text = `💻 ${this.formatTime(todayTotal)}`;
24-
this.statusBarItem.tooltip = this.getTooltipText();
23+
const isActive = this.timeTracker.isActive();
24+
this.statusBarItem.text = `${isActive ? '💻' : '⏸️'} ${this.formatTime(todayTotal)}`;
25+
this.statusBarItem.tooltip = this.getTooltipText(isActive);
2526
}
2627

2728
private formatTime(minutes: number): string {
@@ -31,12 +32,12 @@ export class StatusBar implements vscode.Disposable {
3132
return `${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
3233
}
3334

34-
private getTooltipText(): string {
35+
private getTooltipText(isActive: boolean): string {
3536
const weeklyTotal = this.timeTracker.getWeeklyTotal();
3637
const monthlyTotal = this.timeTracker.getMonthlyTotal();
3738
const allTimeTotal = this.timeTracker.getAllTimeTotal();
3839

39-
return `Total Coding Time:
40+
return `${isActive ? 'Active' : 'Paused'} - Total Coding Time:
4041
This week: ${formatTime(weeklyTotal)}
4142
This month: ${formatTime(monthlyTotal)}
4243
All Time: ${formatTime(allTimeTotal)}

src/timeTracker.ts

Lines changed: 124 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,99 @@ export class TimeTracker implements vscode.Disposable {
99
private updateInterval: NodeJS.Timeout | null = null;
1010
private saveInterval: NodeJS.Timeout | null = null;
1111
private saveIntervalSeconds: number;
12+
private lastCursorActivity: number = Date.now();
13+
private cursorInactivityTimeout: NodeJS.Timeout | null = null;
14+
private inactivityTimeoutSeconds: number;
1215

1316
constructor(database: Database) {
1417
this.database = database;
15-
this.saveIntervalSeconds = vscode.workspace
16-
.getConfiguration('simpleCodingTimeTracker')
17-
.get('saveInterval', 5);
18+
const config = vscode.workspace.getConfiguration('simpleCodingTimeTracker');
19+
this.saveIntervalSeconds = config.get('saveInterval', 5);
20+
this.inactivityTimeoutSeconds = config.get('inactivityTimeout', 300); // Default 5 minutes in seconds
21+
22+
// Track cursor movements
23+
vscode.window.onDidChangeTextEditorSelection(() => {
24+
this.updateCursorActivity();
25+
});
26+
27+
// Track text changes
28+
vscode.workspace.onDidChangeTextDocument(() => {
29+
this.updateCursorActivity();
30+
});
31+
32+
// Track active editor changes
33+
vscode.window.onDidChangeActiveTextEditor(() => {
34+
this.updateCursorActivity();
35+
});
36+
37+
// Track hover events
38+
vscode.languages.registerHoverProvider({ scheme: '*' }, {
39+
provideHover: () => {
40+
this.updateCursorActivity();
41+
return null;
42+
}
43+
});
44+
45+
// Track type definition requests (triggered by mouse movement over symbols)
46+
vscode.languages.registerTypeDefinitionProvider({ scheme: '*' }, {
47+
provideTypeDefinition: () => {
48+
this.updateCursorActivity();
49+
return null;
50+
}
51+
});
52+
53+
// Track signature help requests (triggered by hovering over function calls)
54+
vscode.languages.registerSignatureHelpProvider({ scheme: '*' }, {
55+
provideSignatureHelp: () => {
56+
this.updateCursorActivity();
57+
return null;
58+
}
59+
}, '(', ',');
60+
61+
// Track when VS Code window gains focus
62+
vscode.window.onDidChangeWindowState((e) => {
63+
if (e.focused) {
64+
this.updateCursorActivity();
65+
}
66+
});
67+
}
68+
69+
private setupCursorTracking() {
70+
if (this.cursorInactivityTimeout) {
71+
clearTimeout(this.cursorInactivityTimeout);
72+
}
73+
74+
const currentTime = Date.now();
75+
const timeSinceLastActivity = currentTime - this.lastCursorActivity;
76+
77+
// Only setup new timeout if we haven't exceeded the inactivity threshold
78+
if (timeSinceLastActivity < this.inactivityTimeoutSeconds * 1000) {
79+
// Set up cursor activity tracking
80+
this.cursorInactivityTimeout = setTimeout(() => {
81+
const now = Date.now();
82+
const inactivityDuration = now - this.lastCursorActivity;
83+
84+
// Only stop tracking if we've truly been inactive
85+
if (this.isTracking && inactivityDuration >= this.inactivityTimeoutSeconds * 1000) {
86+
this.stopTracking();
87+
this.saveCurrentSession();
88+
}
89+
}, this.inactivityTimeoutSeconds * 1000); // Convert seconds to milliseconds
90+
}
91+
92+
this.lastCursorActivity = currentTime;
93+
}
94+
95+
public updateCursorActivity() {
96+
if (!this.isTracking) {
97+
this.startTracking();
98+
}
99+
100+
// Update the last activity timestamp
101+
this.lastCursorActivity = Date.now();
102+
103+
// Reset and setup the inactivity timer
104+
this.setupCursorTracking();
18105
}
19106

20107
startTracking() {
@@ -24,6 +111,7 @@ export class TimeTracker implements vscode.Disposable {
24111
this.currentProject = this.getCurrentProject();
25112
this.updateInterval = setInterval(() => this.updateCurrentSession(), 1000);
26113
this.saveInterval = setInterval(() => this.saveCurrentSession(), this.saveIntervalSeconds * 1000); // Convert seconds to milliseconds
114+
this.setupCursorTracking();
27115
}
28116
}
29117

@@ -38,6 +126,10 @@ export class TimeTracker implements vscode.Disposable {
38126
clearInterval(this.saveInterval);
39127
this.saveInterval = null;
40128
}
129+
if (this.cursorInactivityTimeout) {
130+
clearTimeout(this.cursorInactivityTimeout);
131+
this.cursorInactivityTimeout = null;
132+
}
41133
this.saveCurrentSession();
42134
}
43135
}
@@ -67,10 +159,14 @@ export class TimeTracker implements vscode.Disposable {
67159
.filter((entry: TimeEntry) => entry.date === today)
68160
.reduce((sum: number, entry: TimeEntry) => sum + entry.timeSpent, 0);
69161

70-
// Add the current session time if tracking is active
162+
// Add the current session time if tracking is active and we haven't exceeded inactivity threshold
71163
if (this.isTracking) {
72-
const currentSessionTime = (Date.now() - this.startTime) / 60000;
73-
return todayTotal + currentSessionTime;
164+
const timeSinceLastActivity = Date.now() - this.lastCursorActivity;
165+
// Only include current session if we're still within the activity window
166+
if (timeSinceLastActivity < this.inactivityTimeoutSeconds * 1000) {
167+
const currentSessionTime = (Date.now() - this.startTime) / 60000;
168+
return todayTotal + currentSessionTime;
169+
}
74170
}
75171

76172
return todayTotal;
@@ -84,10 +180,13 @@ export class TimeTracker implements vscode.Disposable {
84180
.filter((entry: TimeEntry) => entry.date === today && entry.project === currentProject)
85181
.reduce((sum: number, entry: TimeEntry) => sum + entry.timeSpent, 0);
86182

87-
// Add the current session time if tracking is active
183+
// Add the current session time if tracking is active and within activity window
88184
if (this.isTracking && this.currentProject === currentProject) {
89-
const currentSessionTime = (Date.now() - this.startTime) / 60000;
90-
return currentProjectTime + currentSessionTime;
185+
const timeSinceLastActivity = Date.now() - this.lastCursorActivity;
186+
if (timeSinceLastActivity < this.inactivityTimeoutSeconds * 1000) {
187+
const currentSessionTime = (Date.now() - this.startTime) / 60000;
188+
return currentProjectTime + currentSessionTime;
189+
}
91190
}
92191

93192
return currentProjectTime;
@@ -109,10 +208,13 @@ export class TimeTracker implements vscode.Disposable {
109208
const total = this.database.getEntries()
110209
.reduce((sum: number, entry: TimeEntry) => sum + entry.timeSpent, 0);
111210

112-
// Add current session if tracking is active
211+
// Add current session if tracking is active and within activity window
113212
if (this.isTracking) {
114-
const currentSessionTime = (Date.now() - this.startTime) / 60000;
115-
return total + currentSessionTime;
213+
const timeSinceLastActivity = Date.now() - this.lastCursorActivity;
214+
if (timeSinceLastActivity < this.inactivityTimeoutSeconds * 1000) {
215+
const currentSessionTime = (Date.now() - this.startTime) / 60000;
216+
return total + currentSessionTime;
217+
}
116218
}
117219

118220
return total;
@@ -129,10 +231,13 @@ export class TimeTracker implements vscode.Disposable {
129231

130232
const total = filteredEntries.reduce((sum, entry) => sum + entry.timeSpent, 0);
131233

132-
// Add current session if tracking is active
234+
// Add current session if tracking is active and within activity window
133235
if (this.isTracking) {
134-
const currentSessionTime = (Date.now() - this.startTime) / 60000;
135-
return total + currentSessionTime;
236+
const timeSinceLastActivity = Date.now() - this.lastCursorActivity;
237+
if (timeSinceLastActivity < this.inactivityTimeoutSeconds * 1000) {
238+
const currentSessionTime = (Date.now() - this.startTime) / 60000;
239+
return total + currentSessionTime;
240+
}
136241
}
137242

138243
return total;
@@ -159,4 +264,8 @@ export class TimeTracker implements vscode.Disposable {
159264
this.startTime = 0;
160265
this.database.resetAllTime();
161266
}
267+
268+
isActive(): boolean {
269+
return this.isTracking;
270+
}
162271
}

0 commit comments

Comments
 (0)