diff options
| author | Paul Buetow <paul@buetow.org> | 2025-07-18 08:34:16 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-07-18 08:34:16 +0300 |
| commit | e2f45921c45c9322c2ddb679d0511ba20772dcae (patch) | |
| tree | 85e13d7d4127bd1fdc4821427782475095c6f289 | |
| parent | 85ee3559fcdee46a21c4e9a5ef9ec519d997c447 (diff) | |
gui improvements
| -rw-r--r-- | internal/gui/app.go | 91 | ||||
| -rw-r--r-- | internal/gui/audio_player.go | 18 | ||||
| -rwxr-xr-x | test_all_ui_elements.sh | 33 | ||||
| -rwxr-xr-x | test_bidirectional_translation.sh | 31 | ||||
| -rwxr-xr-x | test_image_prompt_persistence.sh | 31 | ||||
| -rwxr-xr-x | test_no_mixup.sh | 23 | ||||
| -rwxr-xr-x | test_phonetic_gui.sh | 21 | ||||
| -rwxr-xr-x | test_prompt_persistence.sh | 26 | ||||
| -rwxr-xr-x | test_scene_generation.sh | 20 | ||||
| -rwxr-xr-x | test_single_image.sh | 13 | ||||
| -rwxr-xr-x | test_translation_edit.sh | 17 | ||||
| -rwxr-xr-x | test_translation_fix.sh | 23 |
12 files changed, 88 insertions, 259 deletions
diff --git a/internal/gui/app.go b/internal/gui/app.go index 46141d6..2caffe4 100644 --- a/internal/gui/app.go +++ b/internal/gui/app.go @@ -15,6 +15,7 @@ import ( "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/storage" + "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" "github.com/sashabaranov/go-openai" @@ -192,9 +193,18 @@ func (a *Application) setupUI() { a.window.Canvas().Unfocus() } - a.submitButton = widget.NewButton("Generate (g)", a.onSubmit) - a.prevWordBtn = widget.NewButton("◀ Prev (←)", a.onPrevWord) - a.nextWordBtn = widget.NewButton("Next (→) ▶", a.onNextWord) + // Create navigation buttons with tooltips + a.submitButton = widget.NewButtonWithIcon("", theme.ConfirmIcon(), a.onSubmit) + submitLabel := widget.NewLabelWithStyle("Generate (g)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}) + submitBtn := container.NewVBox(a.submitButton, submitLabel) + + a.prevWordBtn = widget.NewButtonWithIcon("", theme.NavigateBackIcon(), a.onPrevWord) + prevLabel := widget.NewLabelWithStyle("Previous (←)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}) + prevBtn := container.NewVBox(a.prevWordBtn, prevLabel) + + a.nextWordBtn = widget.NewButtonWithIcon("", theme.NavigateNextIcon(), a.onNextWord) + nextLabel := widget.NewLabelWithStyle("Next (→)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}) + nextBtn := container.NewVBox(a.nextWordBtn, nextLabel) // Create a grid layout for inputs inputGrid := container.New(layout.NewGridLayout(2), @@ -204,8 +214,8 @@ func (a *Application) setupUI() { inputSection := container.NewBorder( nil, nil, - a.prevWordBtn, - container.NewHBox(a.submitButton, a.nextWordBtn), + prevBtn, + container.NewHBox(submitBtn, nextBtn), inputGrid, ) @@ -269,27 +279,44 @@ func (a *Application) setupUI() { imageSection, ) - // Create action buttons - a.keepButton = widget.NewButton("New Word (n)", a.onKeepAndContinue) - a.regenerateImageBtn = widget.NewButton("Regenerate Image (i)", a.onRegenerateImage) - a.regenerateRandomImageBtn = widget.NewButton("Random Image (m)", a.onRegenerateRandomImage) - a.regenerateAudioBtn = widget.NewButton("Regenerate Audio (a)", a.onRegenerateAudio) - a.regenerateAllBtn = widget.NewButton("Regenerate All (r)", a.onRegenerateAll) - a.deleteButton = widget.NewButton("Delete (d)", a.onDelete) + // Create action buttons with icons and tooltips + a.keepButton = widget.NewButtonWithIcon("", theme.DocumentCreateIcon(), a.onKeepAndContinue) + keepLabel := widget.NewLabelWithStyle("New Word (n)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}) + keepBtn := container.NewVBox(a.keepButton, keepLabel) + + a.regenerateImageBtn = widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), a.onRegenerateImage) + imageLabel := widget.NewLabelWithStyle("Regenerate Image (i)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}) + regenerateImageBtn := container.NewVBox(a.regenerateImageBtn, imageLabel) + + a.regenerateRandomImageBtn = widget.NewButtonWithIcon("", theme.MediaPhotoIcon(), a.onRegenerateRandomImage) + randomLabel := widget.NewLabelWithStyle("Random Image (m)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}) + regenerateRandomBtn := container.NewVBox(a.regenerateRandomImageBtn, randomLabel) + + a.regenerateAudioBtn = widget.NewButtonWithIcon("", theme.MediaPlayIcon(), a.onRegenerateAudio) + audioLabel := widget.NewLabelWithStyle("Regenerate Audio (a)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}) + regenerateAudioBtn := container.NewVBox(a.regenerateAudioBtn, audioLabel) + + a.regenerateAllBtn = widget.NewButtonWithIcon("", theme.ViewFullScreenIcon(), a.onRegenerateAll) + allLabel := widget.NewLabelWithStyle("Regenerate All (r)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}) + regenerateAllBtn := container.NewVBox(a.regenerateAllBtn, allLabel) + + a.deleteButton = widget.NewButtonWithIcon("", theme.DeleteIcon(), a.onDelete) a.deleteButton.Importance = widget.DangerImportance + deleteLabel := widget.NewLabelWithStyle("Delete (d)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}) + deleteBtn := container.NewVBox(a.deleteButton, deleteLabel) // Initially disable action buttons a.setActionButtonsEnabled(false) actionSection := container.NewHBox( - a.keepButton, + keepBtn, layout.NewSpacer(), - a.deleteButton, + deleteBtn, widget.NewSeparator(), - a.regenerateImageBtn, - a.regenerateRandomImageBtn, - a.regenerateAudioBtn, - a.regenerateAllBtn, + regenerateImageBtn, + regenerateRandomBtn, + regenerateAudioBtn, + regenerateAllBtn, ) // Create status section @@ -344,6 +371,8 @@ func (a *Application) setupUI() { // Run starts the GUI application func (a *Application) Run() { + // Focus the Bulgarian word input on startup + a.window.Canvas().Focus(a.wordInput) a.window.ShowAndRun() } @@ -1237,6 +1266,12 @@ func (a *Application) setupKeyboardShortcuts() { return } + // Handle Tab key for custom focus navigation + if ev.Name == fyne.KeyTab { + a.handleTabNavigation() + return + } + // Check if input field is focused focused := a.window.Canvas().Focused() isInputFocused := focused == a.wordInput || focused == a.imagePromptEntry || focused == a.translationEntry @@ -1255,6 +1290,26 @@ func (a *Application) setupKeyboardShortcuts() { }) } +// handleTabNavigation manages custom Tab navigation order +func (a *Application) handleTabNavigation() { + focused := a.window.Canvas().Focused() + + switch focused { + case a.wordInput: + // From Bulgarian -> English + a.window.Canvas().Focus(a.translationEntry) + case a.translationEntry: + // From English -> Image prompt + a.window.Canvas().Focus(a.imagePromptEntry) + case a.imagePromptEntry: + // From Image prompt -> Bulgarian (cycle back) + a.window.Canvas().Focus(a.wordInput) + default: + // If nothing focused, start with Bulgarian + a.window.Canvas().Focus(a.wordInput) + } +} + // handleShortcutKey handles the actual shortcut action func (a *Application) handleShortcutKey(key fyne.KeyName) { // Don't process if we're in delete confirmation mode diff --git a/internal/gui/audio_player.go b/internal/gui/audio_player.go index f36eddf..63428bd 100644 --- a/internal/gui/audio_player.go +++ b/internal/gui/audio_player.go @@ -9,6 +9,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/layout" + "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) @@ -39,10 +40,21 @@ func NewAudioPlayer() *AudioPlayer { p.playButton.Disable() p.stopButton.Disable() - // Create container - p.container = container.NewHBox( + // Create containers with tooltips + playContainer := container.NewVBox( p.playButton, + widget.NewLabelWithStyle("Play (p)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}), + ) + + stopContainer := container.NewVBox( p.stopButton, + widget.NewLabelWithStyle("Stop", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}), + ) + + // Create main container + p.container = container.NewHBox( + playContainer, + stopContainer, layout.NewSpacer(), p.statusLabel, ) @@ -164,7 +176,7 @@ func (p *AudioPlayer) startPlayback() error { // Playback finished normally fyne.Do(func() { p.isPlaying = false - p.playButton.SetText("▶ Play (p)") + p.playButton.SetIcon(theme.MediaPlayIcon()) p.stopButton.Disable() p.statusLabel.SetText("Finished: " + filepath.Base(p.audioFile)) }) diff --git a/test_all_ui_elements.sh b/test_all_ui_elements.sh deleted file mode 100755 index ddaa627..0000000 --- a/test_all_ui_elements.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -# Test script to verify all UI elements are preserved during rapid navigation - -echo "Starting totalrecall GUI to test all UI element preservation..." -echo "" -echo "Test procedure:" -echo "1. Enter multiple words rapidly in different ways:" -echo " - Word 1: Enter 'apple' in English field only" -echo " - Word 2: Enter 'котка' in Bulgarian field only" -echo " - Word 3: Enter 'куче' in Bulgarian with custom prompt 'brown dog running'" -echo " - Word 4: Enter 'car' in English with custom prompt 'red sports car'" -echo "" -echo "2. While processing is happening, rapidly navigate using arrow keys" -echo "3. Verify that for each word:" -echo " - Bulgarian text stays correct" -echo " - English translation stays correct" -echo " - Custom image prompts are preserved" -echo " - Phonetic information is displayed correctly" -echo " - Audio files play the correct word" -echo "" -echo "4. Check the anki_cards folder for:" -echo " - *_translation.txt files with correct translations" -echo " - *_prompt.txt files with correct prompts" -echo " - *_phonetic.txt files with correct phonetic info" -echo " - Audio files that match the word names" -echo "" -echo "5. Restart the app and navigate through the words again" -echo "6. Verify all data is correctly loaded from disk" -echo "" -echo "Press Ctrl+C to exit when testing is complete." -echo "" - -./totalrecall gui
\ No newline at end of file diff --git a/test_bidirectional_translation.sh b/test_bidirectional_translation.sh deleted file mode 100755 index 1a04bd8..0000000 --- a/test_bidirectional_translation.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# Test script to verify the bidirectional translation functionality - -echo "Starting totalrecall GUI with bidirectional translation feature..." -echo "" -echo "Test scenarios:" -echo "" -echo "1. Bulgarian -> English translation:" -echo " - Enter 'ябълка' in Bulgarian field, leave English empty" -echo " - Click 'Generate' or press 'g'" -echo " - English translation 'apple' appears IMMEDIATELY in English field" -echo " - Then audio and images are generated" -echo "" -echo "2. English -> Bulgarian translation:" -echo " - Enter 'apple' in English field, leave Bulgarian empty" -echo " - Click 'Generate' or press 'g'" -echo " - Bulgarian translation 'ябълка' appears IMMEDIATELY in Bulgarian field" -echo " - Then audio and images are generated" -echo "" -echo "3. Both fields provided (no translation):" -echo " - Enter 'котка' in Bulgarian and 'cat' in English" -echo " - Click 'Generate' - no translation should occur" -echo "" -echo "4. Edit translations:" -echo " - You can manually edit the English translation at any time" -echo " - Changes are saved automatically" -echo "" -echo "Press Ctrl+C to exit when testing is complete." -echo "" - -./totalrecall gui
\ No newline at end of file diff --git a/test_image_prompt_persistence.sh b/test_image_prompt_persistence.sh deleted file mode 100755 index adc311a..0000000 --- a/test_image_prompt_persistence.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# Test script to verify image prompt persistence functionality - -echo "Testing image prompt persistence in totalrecall GUI..." -echo "" -echo "Test scenarios:" -echo "" -echo "1. Create card with custom prompt:" -echo " - Enter 'котка' in Bulgarian field" -echo " - Enter custom prompt: 'cute fluffy cat playing with yarn'" -echo " - Generate the card" -echo " - The prompt is automatically saved" -echo "" -echo "2. Navigate away and back:" -echo " - Use navigation arrows to go to another word" -echo " - Navigate back to 'котка'" -echo " - The custom prompt should be restored" -echo "" -echo "3. Regenerate image:" -echo " - Click 'Regenerate Image'" -echo " - The saved prompt will be used automatically" -echo "" -echo "4. Edit and save prompt:" -echo " - Modify the prompt text" -echo " - Changes are saved automatically" -echo " - Regenerate to see the new prompt in action" -echo "" -echo "Press Ctrl+C to exit when testing is complete." -echo "" - -./totalrecall gui
\ No newline at end of file diff --git a/test_no_mixup.sh b/test_no_mixup.sh deleted file mode 100755 index 863977d..0000000 --- a/test_no_mixup.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# Test script to verify that rapid word entry doesn't cause mix-ups - -echo "Starting totalrecall GUI to test rapid word entry..." -echo "" -echo "Test procedure:" -echo "1. Enter a word (e.g., 'ябълка') and click Generate" -echo "2. While it's still processing, immediately enter a new word (e.g., 'котка')" -echo "3. Click Generate for the second word" -echo "4. Verify that:" -echo " - The first word's image/audio appears correctly when it completes" -echo " - The second word's image/audio appears correctly when it completes" -echo " - No mix-ups occur between the two words" -echo "5. Check the anki_cards folder to ensure files are correctly named" -echo "" -echo "Additional tests:" -echo "- Try entering 'rocket launcher' in English, then quickly enter another word" -echo "- Verify the translation doesn't get mixed up" -echo "" -echo "Press Ctrl+C to exit when testing is complete." -echo "" - -./totalrecall gui
\ No newline at end of file diff --git a/test_phonetic_gui.sh b/test_phonetic_gui.sh deleted file mode 100755 index 0ceaf6b..0000000 --- a/test_phonetic_gui.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -# Test script for the phonetic information GUI feature - -echo "Testing TotalRecall GUI with phonetic information feature..." -echo "" -echo "Features to test:" -echo "1. Enter Bulgarian words like: ябълка (apple), котка (cat), куче (dog)" -echo "2. Phonetic info shows detailed IPA with pronunciation examples for EACH letter" -echo "3. Examples compare to English sounds (e.g., '/a/ like in father')" -echo "4. Phonetic info is saved automatically and persists after restart" -echo "5. Use arrow keys or prev/next buttons to navigate between cards" -echo "6. Info fetches concurrently with audio/image for faster processing" -echo "" -echo "The phonetic text area is located between the image section and audio controls." -echo "" -echo "Press Enter to start the GUI..." -read - -# Run the GUI -./totalrecall gui
\ No newline at end of file diff --git a/test_prompt_persistence.sh b/test_prompt_persistence.sh deleted file mode 100755 index 33c4b7e..0000000 --- a/test_prompt_persistence.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -# Test script to verify that image prompts are preserved during rapid navigation - -echo "Starting totalrecall GUI to test prompt persistence..." -echo "" -echo "Test procedure:" -echo "1. Enter multiple words quickly with custom prompts:" -echo " - Word 1: 'ябълка' with prompt 'red apple on wooden table'" -echo " - Word 2: 'котка' with prompt 'orange cat sleeping on sofa'" -echo " - Word 3: 'куче' with prompt 'golden retriever playing in park'" -echo "" -echo "2. While images are still generating, navigate rapidly using arrow keys" -echo "3. Verify that:" -echo " - Each word retains its correct custom prompt" -echo " - Prompts don't get mixed up between words" -echo " - Prompts are saved to disk (*_prompt.txt files)" -echo "" -echo "4. After all processing completes, navigate through words again" -echo "5. Verify prompts are correctly loaded from disk" -echo "" -echo "Check the anki_cards folder for *_prompt.txt files" -echo "" -echo "Press Ctrl+C to exit when testing is complete." -echo "" - -./totalrecall gui
\ No newline at end of file diff --git a/test_scene_generation.sh b/test_scene_generation.sh deleted file mode 100755 index 0355167..0000000 --- a/test_scene_generation.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# Test scene generation with Bulgarian words -echo "Testing scene generation for Bulgarian flashcards..." - -# Test words -words=("ябълка" "котка" "куче" "хляб" "вода" "книга") - -for word in "${words[@]}"; do - echo "" - echo "====================" - echo "Testing word: $word" - echo "====================" - go run ./cmd/totalrecall "$word" --provider openai - echo "" - echo "Press Enter to continue to next word..." - read -done - -echo "Scene generation test complete!"
\ No newline at end of file diff --git a/test_single_image.sh b/test_single_image.sh deleted file mode 100755 index 3dde0de..0000000 --- a/test_single_image.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -# Test script to verify single image functionality - -echo "Building totalrecall..." -go build -o totalrecall ./cmd/totalrecall || exit 1 - -echo "Testing CLI mode with a single word..." -./totalrecall "котка" || exit 1 - -echo "Checking generated files..." -ls -la output/котка* - -echo "Test completed successfully!"
\ No newline at end of file diff --git a/test_translation_edit.sh b/test_translation_edit.sh deleted file mode 100755 index 79b501a..0000000 --- a/test_translation_edit.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# Test script to verify the translation editing functionality - -echo "Starting totalrecall GUI with translation editing feature..." -echo "" -echo "Test instructions:" -echo "1. Enter a Bulgarian word (e.g., 'ябълка')" -echo "2. Click 'Generate' or press 'g'" -echo "3. Wait for translation to appear" -echo "4. Try editing the translation in the text field" -echo "5. Navigate away and back to verify the translation was saved" -echo "6. The edited translation should persist" -echo "" -echo "Press Ctrl+C to exit when testing is complete." -echo "" - -./totalrecall gui
\ No newline at end of file diff --git a/test_translation_fix.sh b/test_translation_fix.sh deleted file mode 100755 index 8be4aeb..0000000 --- a/test_translation_fix.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# Test script to verify the translation fix - -echo "Testing totalrecall translation fix..." -echo "=======================================" -echo "" -echo "This test verifies that when a Bulgarian word is translated to English," -echo "the English translation is used for image generation without re-translating." -echo "" -echo "To test manually:" -echo "1. Run: ./totalrecall" -echo "2. Enter a Bulgarian word (e.g., ябълка)" -echo "3. Wait for it to be translated to English (e.g., apple)" -echo "4. Optionally edit the English translation" -echo "5. Click Generate or press Enter" -echo "6. Watch the console output - it should show:" -echo " 'Using provided translation: ябълка -> apple'" -echo " instead of translating again" -echo "" -echo "Expected behavior:" -echo "- The image generation uses the translation shown in the UI" -echo "- No additional translation happens during image generation" -echo "- Console shows 'Using provided translation' message"
\ No newline at end of file |
