Skip to content

Commit 227eeca

Browse files
committed
feat: initial project setup with Electron, React, Vite, and CI/CD
0 parents  commit 227eeca

28 files changed

Lines changed: 1189 additions & 0 deletions

‎.github/workflows/release.yml‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Build & Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
jobs:
9+
build:
10+
runs-on: windows-latest
11+
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- name: Use Node.js
16+
uses: actions/setup-node@v4
17+
with:
18+
node-version: '20.x'
19+
cache: 'npm'
20+
21+
- name: Install dependencies
22+
run: npm ci
23+
24+
- name: Type check
25+
run: npx tsc --noEmit
26+
27+
- name: Run tests
28+
run: npm test
29+
30+
- name: Build
31+
run: npm run build
32+
33+
- name: Build Electron
34+
run: npm run dist
35+
36+
- name: Create Release
37+
uses: softprops/action-gh-release@v1
38+
with:
39+
files: |
40+
dist/DiskOH-Setup.exe
41+
dist/DiskOH-*.exe
42+
env:
43+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

‎.github/workflows/test.yml‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Test & Build
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main, develop]
8+
9+
jobs:
10+
test:
11+
runs-on: windows-latest
12+
13+
strategy:
14+
matrix:
15+
node-version: [18.x, 20.x]
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Use Node.js ${{ matrix.node-version }}
21+
uses: actions/setup-node@v4
22+
with:
23+
node-version: ${{ matrix.node-version }}
24+
cache: 'npm'
25+
26+
- name: Install dependencies
27+
run: npm ci
28+
29+
- name: Type check
30+
run: npx tsc --noEmit
31+
32+
- name: Run smoke tests
33+
run: npm test
34+
35+
- name: Build
36+
run: npm run build
37+
38+
- name: Test Electron build
39+
run: npm run electron-build
40+
continue-on-error: true

‎.gitignore‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Archives
2+
*.zip
3+
*.tar.gz
4+
*.rar
5+
*.7z
6+
7+
# Dependencies
8+
node_modules/
9+
.pnp/
10+
.pnp.js
11+
12+
# Environment & secrets
13+
.env
14+
.env.local
15+
.env.*.local
16+
17+
# Build output
18+
dist/
19+
build/
20+
out/
21+
.next/
22+
23+
# OS files
24+
.DS_Store
25+
Thumbs.db
26+
desktop.ini
27+
28+
# Editor
29+
.vscode/
30+
.idea/
31+
*.suo
32+
*.user
33+
34+
# Logs
35+
*.log
36+
npm-debug.log*
37+
38+
# Misc
39+
.cache/
40+
*.tmp
41+
42+
# Electron
43+
**/node_modules

‎README.md‎

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# DiskOH - Modern Disk Space Analyzer
2+
3+
[![Build Status](https://github.com/BeardedTech0o/DISK-OH/actions/workflows/test.yml/badge.svg)](https://github.com/BeardedTech0o/DISK-OH/actions)
4+
5+
A modern, beautiful disk space analyzer for Windows built with Electron, React, and TypeScript.
6+
7+
## Features
8+
9+
- **Interactive Treemap Visualization** - See your disk usage at a glance with drill-down exploration
10+
- **Dark Mode Support** - System theme detection and manual toggle
11+
- **Multi-Drive Analysis** - Compare usage across multiple drives
12+
- **File Deletion** - Safely delete folders with confirmation dialogs
13+
- **Auto-Updates** - Automatic dependency and app updates with safety checks
14+
- **Windows Native** - NSIS installer, UAC elevation, full drive access
15+
16+
## Installation
17+
18+
Download the latest `DiskOH-Setup.exe` from [Releases](https://github.com/BeardedTech0o/DISK-OH/releases) and run it.
19+
20+
## Development
21+
22+
### Prerequisites
23+
- Node.js 18+
24+
- npm or yarn
25+
26+
### Setup
27+
```bash
28+
npm install
29+
```
30+
31+
### Commands
32+
```bash
33+
# Start development server with hot reload
34+
npm run dev
35+
36+
# Build React bundle
37+
npm run build
38+
39+
# Run Electron app with built bundle
40+
npm run electron-dev
41+
42+
# Run smoke tests
43+
npm test
44+
45+
# Build Windows installer (.exe)
46+
npm run dist
47+
```
48+
49+
## Architecture
50+
51+
- **Main Process** (Node.js) - Handles file system access, disk scanning, updates
52+
- **Renderer Process** (React) - UI with treemap visualization and settings
53+
- **IPC Communication** - Safe bridge between main and renderer processes
54+
55+
## Project Structure
56+
57+
```
58+
src/
59+
├── main/ # Electron main process
60+
│ ├── main.ts # App entry point
61+
│ ├── preload.ts # IPC bridge
62+
│ ├── scanner.ts # Disk scanning logic
63+
│ ├── drive-utils.ts # Windows drive enumeration
64+
│ ├── file-ops.ts # File deletion
65+
│ ├── updater.ts # Auto-updates
66+
│ └── smoke-tests.ts # Post-update validation
67+
├── renderer/ # React UI
68+
│ ├── App.tsx
69+
│ ├── components/ # UI components
70+
│ └── main.tsx # React entry
71+
└── shared/ # Shared types & constants
72+
```
73+
74+
## Update Strategy
75+
76+
**npm Dependencies**: Uses caret ranges (^) allowing minor/patch updates only. Major versions are pinned and require manual updates.
77+
78+
**App Updates**: electron-updater checks GitHub releases on startup. Updates are silent and installed on next launch.
79+
80+
**Safety**: Smoke tests run after updates validate core functionality.
81+
82+
## CI/CD
83+
84+
- **test.yml** - Runs on every push: type checking, tests, build
85+
- **release.yml** - Runs on version tags: builds installer and creates GitHub release
86+
87+
## License
88+
89+
MIT

‎index.html‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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>DiskOH - Disk Space Analyzer</title>
7+
</head>
8+
<body>
9+
<div id="root"></div>
10+
<script type="module" src="/src/renderer/main.tsx"></script>
11+
</body>
12+
</html>

‎package.json‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"name": "disk-oh",
3+
"version": "0.1.0",
4+
"description": "Modern disk space analyzer for Windows",
5+
"main": "dist/main/main.js",
6+
"type": "module",
7+
"scripts": {
8+
"dev": "vite",
9+
"build": "vite build",
10+
"test": "node --test src/main/smoke-tests.ts",
11+
"preview": "vite preview",
12+
"electron-dev": "electron .",
13+
"electron-build": "vite build && electron .",
14+
"dist": "electron-builder",
15+
"dist:win": "electron-builder --win"
16+
},
17+
"dependencies": {
18+
"react": "^18.3.0",
19+
"react-dom": "^18.3.0",
20+
"recharts": "^2.10.0",
21+
"tailwindcss": "^3.4.0",
22+
"electron-updater": "^6.1.0",
23+
"lucide-react": "^0.263.1"
24+
},
25+
"devDependencies": {
26+
"@tauri-apps/cli": "^2.2.0",
27+
"@types/node": "^20.10.0",
28+
"@types/react": "^18.2.43",
29+
"@types/react-dom": "^18.2.17",
30+
"@vitejs/plugin-react": "^4.2.1",
31+
"autoprefixer": "^10.4.16",
32+
"electron": "^30.0.0",
33+
"electron-builder": "^24.9.0",
34+
"postcss": "^8.4.31",
35+
"typescript": "^5.3.3",
36+
"vite": "^5.0.7"
37+
},
38+
"build": {
39+
"appId": "com.beardedtech.diskoh",
40+
"productName": "DiskOH",
41+
"directories": {
42+
"buildResources": "public"
43+
},
44+
"files": [
45+
"dist/**/*"
46+
],
47+
"win": {
48+
"target": [
49+
{
50+
"target": "nsis",
51+
"arch": [
52+
"x64"
53+
]
54+
}
55+
]
56+
},
57+
"nsis": {
58+
"oneClick": false,
59+
"allowToChangeInstallationDirectory": true,
60+
"createDesktopShortcut": true,
61+
"createStartMenuShortcut": true
62+
}
63+
}
64+
}

‎postcss.config.js‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default {
2+
plugins: {
3+
tailwindcss: {},
4+
autoprefixer: {},
5+
},
6+
}

‎src/main/drive-utils.ts‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { execSync } from 'child_process'
2+
import { DriveInfo } from '../shared/types.js'
3+
4+
export function getDrives(): DriveInfo[] {
5+
const drives: DriveInfo[] = []
6+
7+
try {
8+
// Windows: use wmic to get drive info
9+
const output = execSync(
10+
'wmic logicaldisk get name,size,freespace /csv',
11+
{ encoding: 'utf-8' }
12+
)
13+
14+
const lines = output.trim().split('\n')
15+
// Skip header
16+
for (let i = 1; i < lines.length; i++) {
17+
const parts = lines[i].split(',')
18+
if (parts.length >= 3) {
19+
const letter = parts[0].trim()
20+
const total = parseInt(parts[1].trim()) || 0
21+
const free = parseInt(parts[2].trim()) || 0
22+
const used = total - free
23+
24+
if (letter && total > 0) {
25+
drives.push({
26+
letter: letter.replace(':', ''),
27+
name: letter,
28+
total,
29+
used,
30+
free,
31+
})
32+
}
33+
}
34+
}
35+
} catch (err) {
36+
console.error('Failed to get drives:', err)
37+
}
38+
39+
return drives
40+
}

‎src/main/file-ops.ts‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import fs from 'fs/promises'
2+
import path from 'path'
3+
4+
export async function deleteFile(filePath: string): Promise<void> {
5+
try {
6+
const stat = await fs.stat(filePath)
7+
8+
if (stat.isDirectory()) {
9+
// Recursively delete directory
10+
await deleteDirectory(filePath)
11+
} else {
12+
// Delete file
13+
await fs.unlink(filePath)
14+
}
15+
} catch (err) {
16+
throw new Error(`Failed to delete ${filePath}: ${err}`)
17+
}
18+
}
19+
20+
async function deleteDirectory(dirPath: string): Promise<void> {
21+
try {
22+
const entries = await fs.readdir(dirPath, { withFileTypes: true })
23+
24+
for (const entry of entries) {
25+
const fullPath = path.join(dirPath, entry.name)
26+
27+
if (entry.isDirectory()) {
28+
await deleteDirectory(fullPath)
29+
} else {
30+
await fs.unlink(fullPath)
31+
}
32+
}
33+
34+
await fs.rmdir(dirPath)
35+
} catch (err) {
36+
throw new Error(`Failed to delete directory ${dirPath}: ${err}`)
37+
}
38+
}

0 commit comments

Comments
 (0)