Skip to content

Commit 109e9d7

Browse files
authored
Develop (#93)
* fix: implement write lock for concurrent entry modifications and improve branch change handling (#90) * Feature/configurable statusbar icon and color (#91) * feat: add configurable status bar icon and color options * Refactor code structure for improved readability and maintainability * feat: apply background style selection to both status bar items * feat: add copilot instructions for coding time tracker * feat: update status bar to use a single item with configurable icon and improved tooltip * Pipeline/beta release (#92) * feat: add GitHub Actions workflow for beta release process * chore: update VSCode engine version to ^1.63.0 in package.json * feat: add verification step for develop branch commits in beta release workflow * feat: update version to 0.7.0 and enhance README with new features and settings
1 parent de112b6 commit 109e9d7

9 files changed

Lines changed: 692 additions & 116 deletions

File tree

.github/copilot-instructions.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Copilot Instructions for Simple Coding Time Tracker
2+
3+
## Project Overview
4+
VS Code extension that tracks coding time with visualization, health reminders, and git branch/language detection. Version 0.6.7, published to VS Code Marketplace and Open VSX.
5+
6+
## Architecture
7+
8+
### Core Components (all in `src/`)
9+
- **extension.ts**: Main entry point; activates on startup; registers commands, event listeners, and manages component lifecycle
10+
- **timeTracker.ts**: Tracks user activity (cursor, text edits, window focus); monitors git branches; manages inactivity/focus timeouts; coordinates with health notifications
11+
- **database.ts**: Persists time entries via VS Code's globalState; each entry stores: date, project, timeSpent (minutes), branch, language
12+
- **summaryView.ts**: Webview UI showing 4 chart types (project, timeline, heatmap, languages); handles search/filtering; ~2800 lines with HTML/CSS/JS embedded
13+
- **settingsView.ts**: User-friendly settings UI; updates all tracker configuration
14+
- **statusBar.ts**: Real-time timer display at bottom of editor; clickable to show summary
15+
- **healthNotifications.ts**: Manages 3 health reminders (20-20-20 eye rule, stretch, break intervals)
16+
- **logger.ts**: Centralized logging
17+
- **utils.ts**: 50+ language detection from file extensions and VS Code language IDs; time formatting
18+
19+
### Data Flow
20+
1. **Activity Detection** → Activity triggers cursor/text/hover event handlers in timeTracker
21+
2. **Activity Tracking** → Updates lastCursorActivity; resets inactivity timeout
22+
3. **Branch Monitoring** → Git watcher checks branch every 5 seconds; saves session and starts new one on branch change
23+
4. **Time Accumulation** → Save interval (5 sec) calculates elapsed time; validates against 24-hour ceiling
24+
5. **Database Persistence** → addEntry() to globalState; queried by summaryView for charts
25+
26+
### Configuration Management
27+
Settings stored in package.json `contributes.configuration`; read via `vscode.workspace.getConfiguration()`. Key settings:
28+
- `inactivityTimeout` (minutes): Stop tracking after inactivity in focused VS Code
29+
- `focusTimeout` (minutes): Continue tracking N minutes after VS Code loses focus
30+
- `statusBar.showSeconds`, `statusBar.icon`, `statusBar.backgroundStyle`
31+
- `health.enableNotifications`, `health.eyeRestInterval`, `health.stretchInterval`, `health.breakInterval`
32+
33+
**Pattern**: Settings changes trigger `onDidChangeConfiguration` listener in extension.ts; notify components to reload config via updateConfiguration() methods.
34+
35+
## Critical Workflows
36+
37+
### Building & Packaging
38+
```bash
39+
npm install # Install dependencies
40+
npm run compile # TypeScript → JavaScript to dist/
41+
npm run package # Create .vsix file via webpack
42+
```
43+
44+
### Testing (see CONTRIBUTING.md § Testing the Extension)
45+
1. **F5 in VS Code**: Launches Extension Development Host
46+
2. **Enable dev commands**: Search "enableDevCommands" in settings
47+
3. **Generate test data**: Command `SCTT: Generate Test Data (Dev)` creates 90-day dataset
48+
49+
### Release Process (TECHNICAL.md)
50+
- **Beta**: `git tag v<version>-beta.<number> && git push origin v<version>-beta.<number>`
51+
- **Production**: `git tag v<version> && git push origin v<version>`
52+
- GitHub Actions auto-builds, creates release, publishes to Marketplace
53+
54+
### Git Branch Strategy
55+
- `main`: Production releases → Marketplace
56+
- `develop`: Beta testing
57+
- `site`: GitHub Pages documentation (separate branch)
58+
- `stats-data`: Statistics only
59+
60+
## Key Patterns & Conventions
61+
62+
### Event Management
63+
- Use `vscode.* event listeners` for activity (onDidChangeTextEditorSelection, onDidChangeTextDocument, onDidChangeWindowState, onDidChangeActiveTextEditor)
64+
- Always call `this.updateCursorActivity()` on any editor activity
65+
- Store timers in private fields; clear with `clearTimeout()` / `clearInterval()`; clean up on deactivate
66+
67+
### Time Tracking Logic
68+
- **Cursor inactivity**: 2.5 min default (configurable); reset on any editor activity
69+
- **Focus timeout**: 3 min default; continues tracking N minutes after VS Code loses focus
70+
- **Branch changes**: Save current session before starting new one (prevents cross-branch mixing)
71+
- **Validation**: Reject time entries > 24 hours or <= 0
72+
73+
### Language Detection
74+
`detectLanguageFromFile(filePath)` uses file extension map (~50+ languages); fallback to VS Code's languageId via `detectLanguageFromLanguageId(languageId)`. See [utils.ts](src/utils.ts) for full map.
75+
76+
### Database Migrations
77+
If adding new TimeEntry fields, add migration logic in Database.migrateEntries() to backfill old entries (see branch/language migration pattern).
78+
79+
### Webview Communication
80+
Webviews (summaryView, settingsView) use `webview.postMessage()` to send and `onDidReceiveMessage()` to receive. Commands passed as JSON: `{ command: 'name', data: {...} }`.
81+
82+
### Error Handling
83+
- Wrap async operations in try-catch
84+
- Use vscode.window.showErrorMessage() for user-facing errors
85+
- Log via Logger.getInstance().log()
86+
- Never silently fail on persistence or git operations
87+
88+
## Important Files Reference
89+
- [package.json](package.json): Dependencies, extension config, scripts
90+
- [TECHNICAL.md](TECHNICAL.md): Release process, CI/CD pipelines
91+
- [CONTRIBUTING.md](CONTRIBUTING.md): Dev setup, testing commands
92+
- [src/timeTracker.ts](src/timeTracker.ts): Core tracking—understand inactivity/focus logic here first
93+
- [src/database.ts](src/database.ts): Understand TimeEntry schema and query patterns

.github/workflows/beta-release.yml

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
name: Beta Release
2+
on:
3+
push:
4+
branches:
5+
- develop
6+
paths-ignore:
7+
- '.github/workflows/**'
8+
- '**.md'
9+
- 'docs/**'
10+
workflow_dispatch:
11+
inputs:
12+
force_publish:
13+
description: 'Force beta publish (ignore checks)'
14+
required: false
15+
default: false
16+
type: boolean
17+
18+
jobs:
19+
# Build and create beta release
20+
build-beta:
21+
runs-on: ubuntu-latest
22+
outputs:
23+
version: ${{ steps.package.outputs.version }}
24+
beta_version: ${{ steps.package.outputs.beta_version }}
25+
vsix_name: ${{ steps.build.outputs.vsix_name }}
26+
should_publish: ${{ steps.verify.outputs.should_publish }}
27+
28+
steps:
29+
- name: Checkout code
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
34+
- name: Verify develop commits included
35+
run: |
36+
# Get current branch name
37+
CURRENT_BRANCH="${GITHUB_REF#refs/heads/}"
38+
echo "🔍 Current branch: $CURRENT_BRANCH"
39+
40+
# Skip check if we're on develop branch itself
41+
if [ "$CURRENT_BRANCH" = "develop" ]; then
42+
echo "✅ Running on develop branch - skipping verification"
43+
exit 0
44+
fi
45+
46+
# Fetch develop branch
47+
git fetch origin develop 2>/dev/null || true
48+
if ! git rev-parse --verify origin/develop >/dev/null 2>&1; then
49+
echo "⚠️ Develop branch not found - skipping verification"
50+
exit 0
51+
fi
52+
53+
# Check if develop is an ancestor of current branch (all develop commits are included)
54+
if git merge-base --is-ancestor origin/develop HEAD; then
55+
echo "✅ All commits from develop are included in $CURRENT_BRANCH"
56+
else
57+
echo "❌ ERROR: Current branch is missing commits from develop!"
58+
echo ""
59+
echo "Please merge or rebase develop into your feature branch:"
60+
echo " git checkout $CURRENT_BRANCH"
61+
echo " git merge origin/develop"
62+
echo " # or"
63+
echo " git rebase origin/develop"
64+
exit 1
65+
fi
66+
67+
- name: Setup Node.js
68+
uses: actions/setup-node@v4
69+
with:
70+
node-version: '20'
71+
72+
- name: Install dependencies
73+
run: npm ci
74+
75+
- name: Compile TypeScript
76+
run: npm run compile
77+
78+
- name: Lint code
79+
run: npm run lint
80+
81+
- name: Verify changes
82+
id: verify
83+
run: |
84+
# For manual triggers with force flag
85+
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ github.event.inputs.force_publish }}" = "true" ]; then
86+
echo "🚀 Manual workflow dispatch with force publish - proceeding with beta release"
87+
echo "should_publish=true" >> $GITHUB_OUTPUT
88+
exit 0
89+
fi
90+
91+
# Get changed files
92+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
93+
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD | tr '\n' ' ')
94+
elif [ -z "${{ github.event.before }}" ] || [ "${{ github.event.before }}" = "0000000000000000000000000000000000000000" ]; then
95+
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || git ls-files | tr '\n' ' ')
96+
else
97+
CHANGED_FILES=$(git diff --name-only ${{ github.event.before }} ${{ github.event.after }} | tr '\n' ' ')
98+
fi
99+
100+
echo "📋 Changed files: $CHANGED_FILES"
101+
102+
# Check if only documentation or workflow files were changed
103+
SKIP_PUBLISH=true
104+
for file in $CHANGED_FILES; do
105+
if [[ ! $file =~ \.(md|txt)$ ]] && [[ ! $file =~ ^docs/ ]] && [[ ! $file =~ ^\.github/workflows/ ]]; then
106+
SKIP_PUBLISH=false
107+
break
108+
fi
109+
done
110+
111+
if [[ "$SKIP_PUBLISH" == "true" ]]; then
112+
echo "📚 Only documentation or workflow files changed - skipping beta release"
113+
echo "should_publish=false" >> $GITHUB_OUTPUT
114+
else
115+
echo "✅ Code changes detected - proceeding with beta release"
116+
echo "should_publish=true" >> $GITHUB_OUTPUT
117+
fi
118+
119+
- name: Get package info and create beta version
120+
id: package
121+
run: |
122+
VERSION=$(node -p "require('./package.json').version")
123+
TIMESTAMP=$(date +'%Y%m%d%H%M%S')
124+
BETA_VERSION="${VERSION}-beta.${TIMESTAMP}"
125+
126+
echo "version=$VERSION" >> $GITHUB_OUTPUT
127+
echo "beta_version=$BETA_VERSION" >> $GITHUB_OUTPUT
128+
echo "timestamp=$TIMESTAMP" >> $GITHUB_OUTPUT
129+
echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
130+
131+
echo "📦 Base version: $VERSION"
132+
echo "🔬 Beta version: $BETA_VERSION"
133+
134+
- name: Update package.json with beta version
135+
if: steps.verify.outputs.should_publish == 'true'
136+
run: |
137+
node -e "
138+
const fs = require('fs');
139+
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
140+
pkg.version = '${{ steps.package.outputs.beta_version }}';
141+
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
142+
"
143+
echo "✅ Updated package.json to beta version"
144+
145+
- name: Build VSIX package
146+
id: build
147+
if: steps.verify.outputs.should_publish == 'true'
148+
run: |
149+
npm install -g @vscode/vsce@latest
150+
rm -f *.vsix
151+
vsce package --pre-release
152+
153+
VSIX_NAME="simple-coding-time-tracker-${{ steps.package.outputs.beta_version }}.vsix"
154+
echo "vsix_name=$VSIX_NAME" >> $GITHUB_OUTPUT
155+
156+
# Validate VSIX
157+
if [ ! -f "$VSIX_NAME" ]; then
158+
echo "❌ VSIX build failed"
159+
exit 1
160+
fi
161+
162+
# Get file size
163+
SIZE=$(stat -c%s "$VSIX_NAME" 2>/dev/null || stat -f%z "$VSIX_NAME")
164+
SIZE_MB=$((SIZE / 1024 / 1024))
165+
166+
echo "📦 Package size: ${SIZE_MB}MB"
167+
echo "✅ Beta VSIX built successfully - $VSIX_NAME"
168+
169+
- name: Upload VSIX artifact
170+
if: steps.verify.outputs.should_publish == 'true'
171+
uses: actions/upload-artifact@v4
172+
with:
173+
name: extension-vsix-beta-${{ steps.package.outputs.beta_version }}
174+
path: ${{ steps.build.outputs.vsix_name }}
175+
retention-days: 30
176+
177+
# Create GitHub Release for beta
178+
create-beta-release:
179+
needs: build-beta
180+
if: needs.build-beta.outputs.should_publish == 'true'
181+
runs-on: ubuntu-latest
182+
permissions:
183+
contents: write
184+
185+
steps:
186+
- name: Checkout code
187+
uses: actions/checkout@v4
188+
189+
- name: Download VSIX artifact
190+
uses: actions/download-artifact@v4
191+
with:
192+
name: extension-vsix-beta-${{ needs.build-beta.outputs.beta_version }}
193+
194+
- name: Create GitHub Beta Release
195+
uses: softprops/action-gh-release@v1
196+
with:
197+
tag_name: v${{ needs.build-beta.outputs.beta_version }}
198+
name: Beta Release v${{ needs.build-beta.outputs.beta_version }}
199+
body: |
200+
🔬 **Beta Release**
201+
202+
This is a pre-release build from the `develop` branch for testing purposes.
203+
204+
**Base Version:** ${{ needs.build-beta.outputs.version }}
205+
**Beta Version:** ${{ needs.build-beta.outputs.beta_version }}
206+
**Branch:** develop
207+
**Commit:** ${{ github.sha }}
208+
209+
### Installation
210+
Download the `.vsix` file and install manually:
211+
1. Download `${{ needs.build-beta.outputs.vsix_name }}`
212+
2. Open VS Code
213+
3. Go to Extensions view (Ctrl+Shift+X)
214+
4. Click on "..." menu → Install from VSIX...
215+
5. Select the downloaded file
216+
217+
### ⚠️ Warning
218+
This is a beta release and may contain bugs or incomplete features. Use at your own risk.
219+
220+
### Feedback
221+
Please report any issues or feedback on the [GitHub Issues](https://github.com/${{ github.repository }}/issues) page.
222+
files: ${{ needs.build-beta.outputs.vsix_name }}
223+
draft: false
224+
prerelease: true
225+
env:
226+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
227+
228+
- name: Summary
229+
run: |
230+
echo "### 🎉 Beta Release Created Successfully!" >> $GITHUB_STEP_SUMMARY
231+
echo "" >> $GITHUB_STEP_SUMMARY
232+
echo "**Version:** ${{ needs.build-beta.outputs.beta_version }}" >> $GITHUB_STEP_SUMMARY
233+
echo "**Tag:** v${{ needs.build-beta.outputs.beta_version }}" >> $GITHUB_STEP_SUMMARY
234+
echo "**VSIX:** ${{ needs.build-beta.outputs.vsix_name }}" >> $GITHUB_STEP_SUMMARY
235+
echo "" >> $GITHUB_STEP_SUMMARY
236+
echo "🔗 [View Release](https://github.com/${{ github.repository }}/releases/tag/v${{ needs.build-beta.outputs.beta_version }})" >> $GITHUB_STEP_SUMMARY

.vscode/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@
66
"simpleCodingTimeTracker.statusBar.showSeconds": true,
77
"simpleCodingTimeTracker.health.enableNotifications": false,
88
"simpleCodingTimeTracker.health.modalNotifications": true,
9-
"simpleCodingTimeTracker.health.breakThreshold": 90
9+
"simpleCodingTimeTracker.health.breakThreshold": 90,
10+
"simpleCodingTimeTracker.statusBar.icon": "$(clock)",
11+
"simpleCodingTimeTracker.statusBar.color": "#0bef5b",
12+
"simpleCodingTimeTracker.statusBar.backgroundStyle": "remote"
1013
}

0 commit comments

Comments
 (0)