feat: Refactor of Go backend code
This commit is contained in:
164
app_screenshot.go
Normal file
164
app_screenshot.go
Normal file
@@ -0,0 +1,164 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user