Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ Thumbs.db

# Claude specific
**/.claude/settings.local.json
private-dev/
58 changes: 58 additions & 0 deletions docs/features/screenshot-export.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Screenshot Export Feature

## Overview
The Screenshot Export feature allows users to capture screenshots of the BERT system diagrams and save them to disk. This feature is essential for documentation, presentations, and sharing visual system models with others.

## Implementation
The feature uses a two-part architecture:
1. **Tauri Backend**: Handles file save dialogs and file operations
2. **Leptos Frontend**: Provides UI controls and event coordination

**Note:** This initial implementation provides the UI and dialog workflow but contains a placeholder for the actual screenshot capture functionality, which will be fully implemented in a future update.

### Key Components

#### Backend (Tauri)
- **Dependencies**: `chrono` for timestamp generation
- **Commands**:
- `take_screenshot`: Captures a screenshot without saving
- `save_screenshot_with_dialog`: Captures and opens a save dialog

#### Frontend (Leptos)
- **UI Component**: `ScreenshotControls` - Floating controls in the bottom-right corner
- **Events**: `ScreenshotEvent` for Bevy-Leptos communication
- **Hooks**: `use_screenshot` for programmatic screenshot capture

### User Interface
The UI provides two buttons:
- **Save Screenshot**: Captures and shows a save dialog
- **Quick Screenshot**: Captures without saving (for quick preview)

A status message appears below the buttons to show the result of the screenshot operation.

## User Experience
1. Click "Save Screenshot" or "Quick Screenshot" button
2. For "Save Screenshot":
- A save dialog appears with a default filename including timestamp
- User selects location and confirms
- Status message confirms successful save with path
3. For "Quick Screenshot":
- Status message confirms capture (screenshot is not saved to disk)

## Technical Details

### Event Flow
1. User clicks screenshot button in Leptos UI
2. Tauri command is invoked via WASM bindings
3. Screenshot is captured by `tauri-plugin-screenshots`
4. Result is returned to Leptos UI
5. Status message is updated accordingly

### File Format
Screenshots are saved as PNG images with the naming format: `bert_screenshot_YYYYMMDD_HHMMSS.png`

## Future Enhancements
- Add keyboard shortcuts (e.g., Ctrl+S for Save Screenshot)
- Implement image format options (PNG, JPG, SVG)
- Add annotation capabilities
- Provide option to copy to clipboard
61 changes: 61 additions & 0 deletions src/bevy_app/systems/screenshot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//! This module contains the systems for taking and saving screenshots.
use bevy::{
prelude::*,
render::view::screenshot::{Screenshot, ScreenshotFinished},
window::PrimaryWindow,
};
use std::path::PathBuf;

/// A resource to hold the path for the next screenshot.
#[derive(Resource, Deref, DerefMut)]
pub struct ScreenshotFile(PathBuf);

/// Takes a screenshot when the user presses the appropriate key combination.
///
/// This system follows the pattern of other direct keyboard shortcuts in the application.
pub fn take_screenshot(
input: Res<ButtonInput<KeyCode>>,
main_window: Query<Entity, With<PrimaryWindow>>,
mut commands: Commands,
) {
// Using Command on macs, Control on windows/linux.
let modifier = if cfg!(target_os = "macos") {
KeyCode::SuperLeft
} else {
KeyCode::ControlLeft
};

if input.pressed(modifier) && input.just_pressed(KeyCode::KeyP) {
let timestamp = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S");
let path = PathBuf::from(format!("bert_screenshot_{}.png", timestamp));
commands.insert_resource(ScreenshotFile(path));
let screenshot_entity = commands.spawn(Screenshot::window(main_window.single())).id();
info!("Taking screenshot, saving to entity {:?}", screenshot_entity);
}
}

/// Saves the screenshot to the path specified in the `ScreenshotFile` resource
/// once the `ScreenshotFinished` event is received.
pub fn save_screenshot_to_disk(
mut screenshot_events: EventReader<ScreenshotFinished>,
mut commands: Commands,
screenshot_file: Option<Res<ScreenshotFile>>,
) {
if let Some(screenshot_file) = screenshot_file {
for event in screenshot_events.read() {
if let Some(image_data) = &event.image_data {
let path = &screenshot_file.0;
match std::fs::write(path, image_data) {
Ok(_) => {
info!("Screenshot saved to {}", path.display());
}
Err(e) => {
error!("Failed to save screenshot: {}", e);
}
}
// Remove the resource so we don't try to save again.
commands.remove_resource::<ScreenshotFile>();
}
}
}
}