165 lines
4.6 KiB
Go
165 lines
4.6 KiB
Go
// Package main provides screenshot functionality for EMLy.
|
|
// This file contains methods for capturing, saving, and exporting screenshots
|
|
// of the application window.
|
|
package main
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"emly/backend/utils"
|
|
|
|
"github.com/wailsapp/wails/v2/pkg/runtime"
|
|
)
|
|
|
|
// =============================================================================
|
|
// Screenshot Types
|
|
// =============================================================================
|
|
|
|
// ScreenshotResult contains the captured screenshot data and metadata.
|
|
type ScreenshotResult struct {
|
|
// Data is the base64-encoded PNG image data
|
|
Data string `json:"data"`
|
|
// Width is the image width in pixels
|
|
Width int `json:"width"`
|
|
// Height is the image height in pixels
|
|
Height int `json:"height"`
|
|
// Filename is the suggested filename for saving
|
|
Filename string `json:"filename"`
|
|
}
|
|
|
|
// =============================================================================
|
|
// Screenshot Methods
|
|
// =============================================================================
|
|
|
|
// TakeScreenshot captures the current EMLy application window and returns it as base64 PNG.
|
|
// This uses Windows GDI API to capture the window contents, handling DWM composition
|
|
// for proper rendering of modern Windows applications.
|
|
//
|
|
// The method automatically detects whether the app is in main mode or viewer mode
|
|
// and captures the appropriate window.
|
|
//
|
|
// Returns:
|
|
// - *ScreenshotResult: Contains base64 PNG data, dimensions, and suggested filename
|
|
// - error: Error if window capture or encoding fails
|
|
func (a *App) TakeScreenshot() (*ScreenshotResult, error) {
|
|
// Determine window title based on current mode
|
|
windowTitle := "EMLy - EML Viewer for 3gIT"
|
|
|
|
// Check if running in viewer mode
|
|
for _, arg := range os.Args {
|
|
if strings.Contains(arg, "--view-image") {
|
|
windowTitle = "EMLy Image Viewer"
|
|
break
|
|
}
|
|
if strings.Contains(arg, "--view-pdf") {
|
|
windowTitle = "EMLy PDF Viewer"
|
|
break
|
|
}
|
|
}
|
|
|
|
// Capture the window using Windows GDI API
|
|
img, err := utils.CaptureWindowByTitle(windowTitle)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to capture window: %w", err)
|
|
}
|
|
|
|
// Encode to PNG and convert to base64
|
|
base64Data, err := utils.ScreenshotToBase64PNG(img)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to encode screenshot: %w", err)
|
|
}
|
|
|
|
// Build result with metadata
|
|
bounds := img.Bounds()
|
|
timestamp := time.Now().Format("20060102_150405")
|
|
|
|
return &ScreenshotResult{
|
|
Data: base64Data,
|
|
Width: bounds.Dx(),
|
|
Height: bounds.Dy(),
|
|
Filename: fmt.Sprintf("emly_screenshot_%s.png", timestamp),
|
|
}, nil
|
|
}
|
|
|
|
// SaveScreenshot captures and saves the screenshot to the system temp directory.
|
|
// This is a convenience method that captures and saves in one step.
|
|
//
|
|
// Returns:
|
|
// - string: The full path to the saved screenshot file
|
|
// - error: Error if capture or save fails
|
|
func (a *App) SaveScreenshot() (string, error) {
|
|
// Capture the screenshot
|
|
result, err := a.TakeScreenshot()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Decode base64 data
|
|
data, err := base64.StdEncoding.DecodeString(result.Data)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to decode screenshot data: %w", err)
|
|
}
|
|
|
|
// Save to temp directory
|
|
tempDir := os.TempDir()
|
|
filePath := filepath.Join(tempDir, result.Filename)
|
|
|
|
if err := os.WriteFile(filePath, data, 0644); err != nil {
|
|
return "", fmt.Errorf("failed to save screenshot: %w", err)
|
|
}
|
|
|
|
return filePath, nil
|
|
}
|
|
|
|
// SaveScreenshotAs captures a screenshot and opens a save dialog for the user
|
|
// to choose where to save it.
|
|
//
|
|
// Returns:
|
|
// - string: The selected save path, or empty string if cancelled
|
|
// - error: Error if capture, dialog, or save fails
|
|
func (a *App) SaveScreenshotAs() (string, error) {
|
|
// Capture the screenshot first
|
|
result, err := a.TakeScreenshot()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Open save dialog with PNG filter
|
|
savePath, err := runtime.SaveFileDialog(a.ctx, runtime.SaveDialogOptions{
|
|
DefaultFilename: result.Filename,
|
|
Title: "Save Screenshot",
|
|
Filters: []runtime.FileFilter{
|
|
{
|
|
DisplayName: "PNG Images (*.png)",
|
|
Pattern: "*.png",
|
|
},
|
|
},
|
|
})
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to open save dialog: %w", err)
|
|
}
|
|
|
|
// User cancelled
|
|
if savePath == "" {
|
|
return "", nil
|
|
}
|
|
|
|
// Decode base64 data
|
|
data, err := base64.StdEncoding.DecodeString(result.Data)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to decode screenshot data: %w", err)
|
|
}
|
|
|
|
// Save to selected location
|
|
if err := os.WriteFile(savePath, data, 0644); err != nil {
|
|
return "", fmt.Errorf("failed to save screenshot: %w", err)
|
|
}
|
|
|
|
return savePath, nil
|
|
}
|