Make project Windows-only compatible
- Remove xcap dependency (Linux-focused) - Add Windows crate with Win32 APIs support - Implement native Windows window capture using GetForegroundWindow - Implement process name retrieval using GetModuleBaseNameW - Update all paths to use Windows backslash separators - Update README to specify Windows-only platform - Add Windows badge and requirements - Update installation instructions for PowerShell - Add error handling for non-Windows platforms 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9c46beb11c
commit
9eea0199bb
12
Cargo.toml
12
Cargo.toml
@ -3,7 +3,7 @@ name = "activity-tracker"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Activity Tracker Team"]
|
authors = ["Activity Tracker Team"]
|
||||||
description = "Backend de suivi d'activité pour reconstruire l'historique de travail"
|
description = "Backend de suivi d'activité pour reconstruire l'historique de travail (Windows uniquement)"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Core dependencies
|
# Core dependencies
|
||||||
@ -17,7 +17,15 @@ env_logger = "0.11"
|
|||||||
screenshots = "0.6"
|
screenshots = "0.6"
|
||||||
image = "0.24"
|
image = "0.24"
|
||||||
webp = "0.2"
|
webp = "0.2"
|
||||||
xcap = "0.0.10"
|
|
||||||
|
# Windows APIs
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
windows = { version = "0.52", features = [
|
||||||
|
"Win32_Foundation",
|
||||||
|
"Win32_UI_WindowsAndMessaging",
|
||||||
|
"Win32_System_Threading",
|
||||||
|
"Win32_System_ProcessStatus",
|
||||||
|
] }
|
||||||
|
|
||||||
# Storage (SQLite + Encryption)
|
# Storage (SQLite + Encryption)
|
||||||
rusqlite = { version = "0.31", features = ["bundled"] }
|
rusqlite = { version = "0.31", features = ["bundled"] }
|
||||||
|
|||||||
36
README.md
36
README.md
@ -3,12 +3,14 @@
|
|||||||

|

|
||||||

|

|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
**Activity Tracker** est un système de suivi d'activité conçu pour aider les utilisateurs à reconstruire leur historique de travail via une analyse automatisée des actions numériques.
|
**Activity Tracker** est un système de suivi d'activité **Windows uniquement** conçu pour aider les utilisateurs à reconstruire leur historique de travail via une analyse automatisée des actions numériques.
|
||||||
|
|
||||||
## Caractéristiques (MVP)
|
## Caractéristiques (MVP)
|
||||||
|
|
||||||
- **Capture passive** : Screenshots toutes les 5 minutes + métadonnées fenêtres
|
- **Capture passive** : Screenshots toutes les 5 minutes + métadonnées fenêtres Windows
|
||||||
|
- **API Windows native** : Utilise GetForegroundWindow et les APIs Win32
|
||||||
- **Stockage sécurisé** : Base SQLite avec chiffrement AES-256-GCM
|
- **Stockage sécurisé** : Base SQLite avec chiffrement AES-256-GCM
|
||||||
- **Analyse intelligente** : Classification automatique en 5 catégories
|
- **Analyse intelligente** : Classification automatique en 5 catégories
|
||||||
- **Rapports journaliers** : Export JSON avec statistiques détaillées
|
- **Rapports journaliers** : Export JSON avec statistiques détaillées
|
||||||
@ -18,28 +20,27 @@
|
|||||||
|
|
||||||
### Prérequis
|
### Prérequis
|
||||||
|
|
||||||
- Rust 1.70+
|
- **Windows 10 ou supérieur** (requis)
|
||||||
- Cargo
|
- Rust 1.70+ et Cargo (installer via [rustup](https://rustup.rs/))
|
||||||
- SQLite3
|
- SQLite3 (inclus automatiquement via Cargo)
|
||||||
|
|
||||||
### Compilation
|
### Compilation
|
||||||
|
|
||||||
```bash
|
```powershell
|
||||||
git clone https://gitea.legion-muyue.fr/Muyue/activity-tracker.git
|
git clone https://gitea.legion-muyue.fr/Muyue/activity-tracker.git
|
||||||
cd activity-tracker
|
cd activity-tracker
|
||||||
cargo build --release
|
cargo build --release
|
||||||
```
|
```
|
||||||
|
|
||||||
Le binaire compilé sera disponible dans `target/release/activity-tracker`.
|
Le binaire compilé sera disponible dans `target\release\activity-tracker.exe`.
|
||||||
|
|
||||||
### Installation système
|
### Installation système
|
||||||
|
|
||||||
```bash
|
```powershell
|
||||||
# Linux/macOS
|
# Ajoutez le répertoire à votre PATH ou copiez le binaire
|
||||||
sudo cp target/release/activity-tracker /usr/local/bin/
|
copy target\release\activity-tracker.exe C:\Program Files\ActivityTracker\
|
||||||
|
|
||||||
# Ou ajoutez le chemin à votre PATH
|
# Ou utilisez directement depuis le dossier target\release
|
||||||
export PATH=$PATH:$(pwd)/target/release
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Utilisation
|
## Utilisation
|
||||||
@ -173,7 +174,7 @@ inactivity_threshold = 600 # 10 minutes
|
|||||||
[storage]
|
[storage]
|
||||||
max_storage_mb = 500
|
max_storage_mb = 500
|
||||||
retention_days = 30
|
retention_days = 30
|
||||||
db_path = "data/activity_tracker.db"
|
db_path = "data\\activity_tracker.db"
|
||||||
|
|
||||||
[ai]
|
[ai]
|
||||||
categories = ["Development", "Meeting", "Research", "Design", "Other"]
|
categories = ["Development", "Meeting", "Research", "Design", "Other"]
|
||||||
@ -277,11 +278,12 @@ Pattern::new(vec!["slack", "discord", "telegram"], 0.9),
|
|||||||
- [ ] **Détection audio** de réunions
|
- [ ] **Détection audio** de réunions
|
||||||
- [ ] **Intégrations** (Trello, Jira, calendriers)
|
- [ ] **Intégrations** (Trello, Jira, calendriers)
|
||||||
|
|
||||||
## Problèmes connus
|
## Plateforme supportée
|
||||||
|
|
||||||
- **Linux** : L'accès aux métadonnées de fenêtres nécessite X11 (Wayland non supporté)
|
- **Windows uniquement** : Fonctionne avec Windows 10 et supérieur
|
||||||
- **macOS** : Nécessite autorisations Accessibilité (voir documentation officielle)
|
- Utilise les APIs Windows natives pour la capture de fenêtres
|
||||||
- **Windows** : Fonctionne avec les privilèges standards
|
- Aucune autorisation spéciale requise (privilèges standards suffisants)
|
||||||
|
- Les plateformes Linux et macOS ne sont **pas supportées**
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# Activity Tracker MVP Configuration
|
# Activity Tracker MVP Configuration (Windows uniquement)
|
||||||
|
|
||||||
[capture]
|
[capture]
|
||||||
interval_seconds = 300 # 5 minutes (as per MVP spec)
|
interval_seconds = 300 # 5 minutes (as per MVP spec)
|
||||||
@ -8,7 +8,7 @@ inactivity_threshold = 600 # 10 minutes
|
|||||||
[storage]
|
[storage]
|
||||||
max_storage_mb = 500
|
max_storage_mb = 500
|
||||||
retention_days = 30
|
retention_days = 30
|
||||||
db_path = "data/activity_tracker.db"
|
db_path = "data\\activity_tracker.db" # Chemin Windows
|
||||||
|
|
||||||
[ai]
|
[ai]
|
||||||
categories = ["Development", "Meeting", "Research", "Design", "Other"]
|
categories = ["Development", "Meeting", "Research", "Design", "Other"]
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
/// Window metadata extraction
|
/// Window metadata extraction (Windows uniquement)
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::error::{AppError, Result};
|
use crate::error::{AppError, Result};
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(windows)]
|
||||||
use xcap::Window;
|
use windows::{
|
||||||
|
core::PWSTR,
|
||||||
|
Win32::Foundation::{HWND, MAX_PATH},
|
||||||
|
Win32::System::ProcessStatus::GetModuleBaseNameW,
|
||||||
|
Win32::System::Threading::{OpenProcess, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ},
|
||||||
|
Win32::UI::WindowsAndMessaging::{GetForegroundWindow, GetWindowTextW, GetWindowThreadProcessId},
|
||||||
|
};
|
||||||
|
|
||||||
/// Window metadata structure
|
/// Window metadata structure
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -81,39 +87,72 @@ impl WindowMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get metadata for the currently active window
|
/// Get metadata for the currently active window (Windows implementation)
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(windows)]
|
||||||
pub fn get_active_window_metadata() -> Result<WindowMetadata> {
|
pub fn get_active_window_metadata() -> Result<WindowMetadata> {
|
||||||
let windows = Window::all()
|
unsafe {
|
||||||
.map_err(|e| AppError::Capture(format!("Failed to get windows: {}", e)))?;
|
// Get the foreground window handle
|
||||||
|
let hwnd = GetForegroundWindow();
|
||||||
|
if hwnd.0 == 0 {
|
||||||
|
return Ok(WindowMetadata::inactive());
|
||||||
|
}
|
||||||
|
|
||||||
// Find the active/focused window
|
// Get window title
|
||||||
// For MVP, we'll use the first window as a fallback
|
let mut title_buffer = [0u16; 512];
|
||||||
let active_window = windows.first()
|
let title_len = GetWindowTextW(hwnd, &mut title_buffer);
|
||||||
.ok_or_else(|| AppError::Capture("No windows found".to_string()))?;
|
let title = if title_len > 0 {
|
||||||
|
String::from_utf16_lossy(&title_buffer[..title_len as usize])
|
||||||
|
} else {
|
||||||
|
"Unknown".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get process ID
|
||||||
|
let mut process_id: u32 = 0;
|
||||||
|
GetWindowThreadProcessId(hwnd, Some(&mut process_id));
|
||||||
|
|
||||||
|
// Get process name
|
||||||
|
let process_name = get_process_name(process_id).unwrap_or_else(|| "unknown".to_string());
|
||||||
|
|
||||||
Ok(WindowMetadata {
|
Ok(WindowMetadata {
|
||||||
title: active_window.title().to_string(),
|
title,
|
||||||
process_name: active_window.app_name().to_string(),
|
process_name,
|
||||||
process_id: active_window.id() as u32,
|
process_id,
|
||||||
is_active: true,
|
is_active: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get metadata for the currently active window (Windows implementation)
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub fn get_active_window_metadata() -> Result<WindowMetadata> {
|
|
||||||
// Simplified implementation for MVP
|
|
||||||
// In production, would use Windows API to get active window
|
|
||||||
Ok(WindowMetadata::unknown())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get metadata for the currently active window (macOS implementation)
|
/// Get process name from process ID (Windows)
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(windows)]
|
||||||
|
fn get_process_name(process_id: u32) -> Option<String> {
|
||||||
|
unsafe {
|
||||||
|
let process_handle = OpenProcess(
|
||||||
|
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
||||||
|
false,
|
||||||
|
process_id,
|
||||||
|
).ok()?;
|
||||||
|
|
||||||
|
let mut name_buffer = [0u16; MAX_PATH as usize];
|
||||||
|
let name_len = GetModuleBaseNameW(
|
||||||
|
process_handle,
|
||||||
|
None,
|
||||||
|
&mut name_buffer,
|
||||||
|
);
|
||||||
|
|
||||||
|
if name_len > 0 {
|
||||||
|
Some(String::from_utf16_lossy(&name_buffer[..name_len as usize]))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fallback for non-Windows platforms (not supported)
|
||||||
|
#[cfg(not(windows))]
|
||||||
pub fn get_active_window_metadata() -> Result<WindowMetadata> {
|
pub fn get_active_window_metadata() -> Result<WindowMetadata> {
|
||||||
// Simplified implementation for MVP
|
Err(AppError::Capture(
|
||||||
// In production, would use macOS APIs to get active window
|
"This application only supports Windows".to_string()
|
||||||
Ok(WindowMetadata::unknown())
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -77,7 +77,7 @@ impl Config {
|
|||||||
storage: StorageConfig {
|
storage: StorageConfig {
|
||||||
max_storage_mb: 500,
|
max_storage_mb: 500,
|
||||||
retention_days: 30,
|
retention_days: 30,
|
||||||
db_path: "data/activity_tracker.db".to_string(),
|
db_path: "data\\activity_tracker.db".to_string(),
|
||||||
},
|
},
|
||||||
ai: AiConfig {
|
ai: AiConfig {
|
||||||
categories: vec![
|
categories: vec![
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user