summaryrefslogtreecommitdiff
path: root/internal/gui/generator.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-07-18 14:00:13 +0300
committerPaul Buetow <paul@buetow.org>2025-07-18 14:00:13 +0300
commita6e9947b904406ec5b49e88c77689d5c6ef6d04b (patch)
treefc89df6a57d6ee3e8ef3487d9d07d01797b4c696 /internal/gui/generator.go
parente2f45921c45c9322c2ddb679d0511ba20772dcae (diff)
feat: major refactor - APKG export support and subdirectory organization
Major Features: - Added native .apkg (Anki package) export format with embedded media - Reorganized file structure to use subdirectories per word - Enhanced GUI export dialog with format selection (APKG/CSV) APKG Export Implementation: - Created apkg_generator.go with full SQLite-based Anki package generation - Includes custom card templates with professional CSS styling - Front side: Image + English word - Back side: Image + Bulgarian word + Audio + Notes - All media files automatically embedded in package - Custom deck names supported via --deck-name flag Directory Structure Changes: - Each word now gets its own subdirectory (e.g., anki_cards/ябълка/) - All related files (audio, images, translations, prompts) stored together - Cleaner organization and easier management - Prevents file naming conflicts GUI Updates: - Export dialog no longer shows file browser, exports directly to anki_cards - Format selection between APKG (recommended) and CSV (legacy) - Fixed navigation to properly load image prompts from subdirectories - Delete function now moves entire word directory to trash CLI Updates: - --anki flag now generates APKG by default - --anki-csv flag for legacy CSV format - All file generation uses subdirectory structure Bug Fixes: - Fixed handling of multi-word entries (e.g., "картоф картофи") - Fixed GenerateFromDirectory to properly handle words with underscores - Fixed phonetic files being treated as separate cards - Fixed image prompt preservation during navigation Breaking Changes: - File structure changed from flat to subdirectory-based - Existing files need to be reorganized into subdirectories 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'internal/gui/generator.go')
-rw-r--r--internal/gui/generator.go22
1 files changed, 17 insertions, 5 deletions
diff --git a/internal/gui/generator.go b/internal/gui/generator.go
index d26bb81..16ea7cf 100644
--- a/internal/gui/generator.go
+++ b/internal/gui/generator.go
@@ -99,9 +99,15 @@ func (a *Application) generateAudio(word string) (string, error) {
return "", err
}
- // Generate filename
+ // Create subdirectory for this word
filename := sanitizeFilename(word)
- outputFile := filepath.Join(a.config.OutputDir, fmt.Sprintf("%s.%s", filename, a.config.AudioFormat))
+ wordDir := filepath.Join(a.config.OutputDir, filename)
+ if err := os.MkdirAll(wordDir, 0755); err != nil {
+ return "", fmt.Errorf("failed to create word directory: %w", err)
+ }
+
+ // Generate filename in subdirectory
+ outputFile := filepath.Join(wordDir, fmt.Sprintf("%s.%s", filename, a.config.AudioFormat))
// Generate audio
err = provider.GenerateAudio(a.ctx, word, outputFile)
@@ -150,9 +156,16 @@ func (a *Application) generateImagesWithPrompt(word string, customPrompt string,
return "", fmt.Errorf("unknown image provider: %s", a.config.ImageProvider)
}
+ // Create subdirectory for this word
+ filename := sanitizeFilename(word)
+ wordDir := filepath.Join(a.config.OutputDir, filename)
+ if err := os.MkdirAll(wordDir, 0755); err != nil {
+ return "", fmt.Errorf("failed to create word directory: %w", err)
+ }
+
// Create downloader
downloadOpts := &image.DownloadOptions{
- OutputDir: a.config.OutputDir,
+ OutputDir: wordDir,
OverwriteExisting: true,
CreateDir: true,
FileNamePattern: "{word}",
@@ -182,8 +195,7 @@ func (a *Application) generateImagesWithPrompt(word string, customPrompt string,
usedPrompt := openaiClient.GetLastPrompt()
if usedPrompt != "" {
// Save the prompt to disk immediately for this word
- filename := sanitizeFilename(word)
- promptFile := filepath.Join(a.config.OutputDir, fmt.Sprintf("%s_prompt.txt", filename))
+ promptFile := filepath.Join(wordDir, fmt.Sprintf("%s_prompt.txt", filename))
os.WriteFile(promptFile, []byte(usedPrompt), 0644)
// Only update UI if this word is still the current word