Documentation
¶
Index ¶
- func GetAppIcon() fyne.Resource
- func ResourceFromPath(path string) (fyne.Resource, error)
- type App
- type Application
- type AudioConfigResolver
- func (r *AudioConfigResolver) BaseConfigForAttribution() *audio.Config
- func (r *AudioConfigResolver) ConfigForGeneration(voice string, speed float64) audio.Config
- func (r *AudioConfigResolver) OutputFormat() string
- func (r *AudioConfigResolver) ProviderName() string
- func (r *AudioConfigResolver) Voices() []string
- type AudioPlayer
- func (p *AudioPlayer) Clear()
- func (p *AudioPlayer) CreateRenderer() fyne.WidgetRenderer
- func (p *AudioPlayer) Play()
- func (p *AudioPlayer) PlayBack()
- func (p *AudioPlayer) SetAudioFile(audioFile string)
- func (p *AudioPlayer) SetAudioFileNoAutoPlay(audioFile string)
- func (p *AudioPlayer) SetAutoPlayEnabled(autoPlayEnabled *bool)
- func (p *AudioPlayer) SetBackAudioFile(audioFile string)
- func (p *AudioPlayer) SetContext(ctx context.Context)
- func (p *AudioPlayer) SetPhonetic(phonetic string)
- type CardFiles
- type CardService
- func (cs *CardService) CheckMissingFiles(word string, ...) *CardFiles
- func (cs *CardService) DeleteWord(word string, existingWords []string, savedCards []anki.Card) ([]string, []anki.Card, error)
- func (cs *CardService) EnsureCardDirectory(word string) (string, error)
- func (cs *CardService) EnsureWordDirectoryAndMetadata(word string) (string, error)
- func (cs *CardService) FindCardDirectory(word string) string
- func (cs *CardService) LoadCardFiles(word string) *CardFiles
- func (cs *CardService) LoadImagePromptForWord(word string) string
- func (cs *CardService) LoadPhoneticInfo(word string) string
- func (cs *CardService) SavePhoneticInfo(word, phoneticText string) error
- func (cs *CardService) SaveTranslation(word, translation string) error
- func (cs *CardService) ScanExistingWords() []string
- type Config
- type CustomEntry
- type CustomMultiLineEntry
- type ExportHandler
- type GenerateResult
- type GenerationOrchestrator
- func (o *GenerationOrchestrator) GenerateAudio(ctx context.Context, word, cardDir string) (string, error)
- func (o *GenerationOrchestrator) GenerateAudioBack(ctx context.Context, text, cardDir string) (string, error)
- func (o *GenerationOrchestrator) GenerateAudioBgBg(ctx context.Context, front, back, cardDir string) (string, string, error)
- func (o *GenerationOrchestrator) GenerateAudioFront(ctx context.Context, word, cardDir string) (string, error)
- func (o *GenerationOrchestrator) GenerateImagesWithPrompt(ctx context.Context, word, customPrompt, translation, cardDir string) (string, error)
- func (o *GenerationOrchestrator) GenerateMaterials(ctx context.Context, word, translation, cardDir string, isBgBg bool, ...) (GenerateResult, error)
- func (o *GenerationOrchestrator) GetPhoneticInfo(word string) (string, error)
- func (o *GenerationOrchestrator) TranslateEnglishToBulgarian(word string) (string, error)
- func (o *GenerationOrchestrator) TranslateWord(word string) (string, error)
- type ImageDisplay
- type JobStatus
- type KeyboardShortcuts
- type LogViewer
- type LogWriter
- type NavigationHandler
- type ParallelRunner
- type QueueManager
- type VoiceSelector
- type WordJob
- type WordQueue
- func (q *WordQueue) AddWord(word string) *WordJob
- func (q *WordQueue) AddWordWithPrompt(word, customPrompt string) *WordJob
- func (q *WordQueue) CompleteJob(jobID int, translation, audioFile, audioFileBack, imageFile string)
- func (q *WordQueue) FailJob(jobID int, err error)
- func (q *WordQueue) GetActiveJobs() []*WordJob
- func (q *WordQueue) GetCompletedJobs() []*WordJob
- func (q *WordQueue) GetJob(id int) *WordJob
- func (q *WordQueue) GetQueueStatus() (queued, processing, completed, failed int)
- func (q *WordQueue) IsWordProcessing(word string) bool
- func (q *WordQueue) ProcessNextJob() *WordJob
- func (q *WordQueue) RemoveCompletedJobByWord(word string)
- func (q *WordQueue) SetCallbacks(onStatusUpdate func(*WordJob), onJobComplete func(*WordJob))
- func (q *WordQueue) Stop()
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetAppIcon ¶
GetAppIcon returns the application icon as a Fyne resource
Types ¶
type App ¶
type App interface {
Run()
}
App is the runnable GUI application constructed at the composition root (cmd/totalrecall). Callers invoke Run() to start the Fyne event loop.
type Application ¶
type Application struct {
// contains filtered or unexported fields
}
Application represents the main GUI application
type AudioConfigResolver ¶
type AudioConfigResolver struct {
// contains filtered or unexported fields
}
AudioConfigResolver derives effective TTS provider settings from the GUI config and the shared audio.Config. It centralizes provider name, voice list, output format, and per-run audio.Config construction so orchestration code does not repeat string handling and defaults.
func NewAudioConfigResolver ¶
func NewAudioConfigResolver(guiConfig *Config, audioConfig *audio.Config) *AudioConfigResolver
NewAudioConfigResolver builds a resolver for the given GUI and audio settings. Either pointer may be nil; defaults match the previous GenerationOrchestrator behaviour.
func (*AudioConfigResolver) BaseConfigForAttribution ¶
func (r *AudioConfigResolver) BaseConfigForAttribution() *audio.Config
BaseConfigForAttribution returns the configured audio.Config pointer, or the package default when unset — matching how attribution sidecars resolve the base parameters before per-run voice/speed overrides.
func (*AudioConfigResolver) ConfigForGeneration ¶
func (r *AudioConfigResolver) ConfigForGeneration(voice string, speed float64) audio.Config
ConfigForGeneration builds an audio.Config for a single generation call, overriding the voice and speed with the values selected for this run.
func (*AudioConfigResolver) OutputFormat ¶
func (r *AudioConfigResolver) OutputFormat() string
OutputFormat resolves the effective output format (e.g. "mp3" or "wav").
func (*AudioConfigResolver) ProviderName ¶
func (r *AudioConfigResolver) ProviderName() string
ProviderName returns the lowercase provider name from config, defaulting to the shared audio default when none is set.
func (*AudioConfigResolver) Voices ¶
func (r *AudioConfigResolver) Voices() []string
Voices returns the configured provider's voice list.
type AudioPlayer ¶
type AudioPlayer struct {
widget.BaseWidget
// contains filtered or unexported fields
}
AudioPlayer is a custom widget for playing audio files
func NewAudioPlayer ¶
func NewAudioPlayer() *AudioPlayer
NewAudioPlayer creates a new audio player widget. Call SetContext before use so that post-playback UI updates are guarded against the app shutting down.
func (*AudioPlayer) CreateRenderer ¶
func (p *AudioPlayer) CreateRenderer() fyne.WidgetRenderer
CreateRenderer implements fyne.Widget
func (*AudioPlayer) PlayBack ¶
func (p *AudioPlayer) PlayBack()
PlayBack triggers back audio playback (for bg-bg cards)
func (*AudioPlayer) SetAudioFile ¶
func (p *AudioPlayer) SetAudioFile(audioFile string)
SetAudioFile sets the audio file to play and optionally auto-plays it
func (*AudioPlayer) SetAudioFileNoAutoPlay ¶
func (p *AudioPlayer) SetAudioFileNoAutoPlay(audioFile string)
SetAudioFileNoAutoPlay sets the audio file without auto-playing Used when regenerating audio on bg-bg cards - we only want to play when explicitly requested
func (*AudioPlayer) SetAutoPlayEnabled ¶
func (p *AudioPlayer) SetAutoPlayEnabled(autoPlayEnabled *bool)
SetAutoPlayEnabled sets the reference to the auto-play state
func (*AudioPlayer) SetBackAudioFile ¶
func (p *AudioPlayer) SetBackAudioFile(audioFile string)
SetBackAudioFile sets the back audio file for bg-bg cards
func (*AudioPlayer) SetContext ¶
func (p *AudioPlayer) SetContext(ctx context.Context)
SetContext wires the application lifecycle context into the player. The post-playback UI update goroutine checks this context before calling fyne.Do, preventing writes to freed widgets after the window is closed (Go Mistake #62). Must be called before the first playback attempt.
func (*AudioPlayer) SetPhonetic ¶
func (p *AudioPlayer) SetPhonetic(phonetic string)
SetPhonetic sets the phonetic transcription text
type CardFiles ¶
type CardFiles struct {
WordDir string
Translation string
AudioFile string
AudioBack string
ImageFile string
PhoneticInfo string
ImagePrompt string
CardType internal.CardType
}
CardFiles holds the paths to all files loaded for a single card.
type CardService ¶
type CardService struct {
// contains filtered or unexported fields
}
CardService manages card file discovery, directory creation, persistence, and state loading from the output directory. It is responsible for all non-UI file I/O related to cards, decoupled from UI event-wiring. Directory-scanning and creation are delegated to a store.CardStore so the underlying algorithm is shared with the processor package (DRY).
func NewCardService ¶
func NewCardService(config *Config) *CardService
NewCardService constructs a CardService for the given configuration. It initialises an internal store.CardStore rooted at config.OutputDir.
func (*CardService) CheckMissingFiles ¶
func (cs *CardService) CheckMissingFiles(word string, existingAudio, existingAudioBack, existingImage, existingTranslation, existingPrompt, existingPhonetic string, cardType string) *CardFiles
CheckMissingFiles inspects a card directory for any files that have appeared since the last load and returns a partial CardFiles with only the newly found fields populated. Callers should merge with existing state.
func (*CardService) DeleteWord ¶
func (cs *CardService) DeleteWord(word string, existingWords []string, savedCards []anki.Card) ([]string, []anki.Card, error)
DeleteWord moves the card directory for a word to the trash bin directory. Returns the updated existingWords slice and updatedSavedCards slice.
func (*CardService) EnsureCardDirectory ¶
func (cs *CardService) EnsureCardDirectory(word string) (string, error)
EnsureCardDirectory ensures a card directory exists for the given word and returns its path. Creates it with metadata if it does not exist yet.
func (*CardService) EnsureWordDirectoryAndMetadata ¶
func (cs *CardService) EnsureWordDirectoryAndMetadata(word string) (string, error)
EnsureWordDirectoryAndMetadata creates a new card directory and writes word metadata to word.txt inside it. Returns the directory path. Uses store.FindOrCreateCardDirectory so the creation logic is not duplicated.
func (*CardService) FindCardDirectory ¶
func (cs *CardService) FindCardDirectory(word string) string
FindCardDirectory finds the directory for a given Bulgarian word. Delegates to the shared store.CardStore which also handles the legacy _word.txt fallback for backward compatibility.
func (*CardService) LoadCardFiles ¶
func (cs *CardService) LoadCardFiles(word string) *CardFiles
LoadCardFiles loads all available files for the given word from disk. Returns nil if no card directory exists for the word.
func (*CardService) LoadImagePromptForWord ¶
func (cs *CardService) LoadImagePromptForWord(word string) string
LoadImagePromptForWord reads the image_prompt.txt file for the given word. Returns empty string if not found.
func (*CardService) LoadPhoneticInfo ¶
func (cs *CardService) LoadPhoneticInfo(word string) string
LoadPhoneticInfo reads phonetic information from disk for the given word. Returns empty string if not found.
func (*CardService) SavePhoneticInfo ¶
func (cs *CardService) SavePhoneticInfo(word, phoneticText string) error
SavePhoneticInfo persists phonetic information for the given word to disk.
func (*CardService) SaveTranslation ¶
func (cs *CardService) SaveTranslation(word, translation string) error
SaveTranslation persists the translation for the given word to disk. It finds or creates the card directory as necessary.
func (*CardService) ScanExistingWords ¶
func (cs *CardService) ScanExistingWords() []string
ScanExistingWords scans the output directory for existing card subdirectories and returns a sorted list of the Bulgarian words found. A directory counts only if it contains at least one of: an audio file, an image, or a translation file. Delegates iteration and word-file reading to the shared store.CardStore so that logic is not duplicated here.
type Config ¶
type Config struct {
OutputDir string
AudioFormat string
// AudioProvider selects the TTS backend used by the GUI.
AudioProvider string
ImageProvider string
OpenAIKey string
GoogleAPIKey string
// NanoBananaModel selects the Gemini image model for Nano Banana generation.
NanoBananaModel string
// NanoBananaTextModel selects the Gemini text model for Nano Banana prompt generation.
NanoBananaTextModel string
// GeminiTTSModel selects the Gemini TTS model when Gemini audio is active.
GeminiTTSModel string
// GeminiVoice selects a specific Gemini voice; empty picks a random Gemini voice.
GeminiVoice string
TranslationProvider translation.Provider
PhoneticProvider phonetic.Provider
AutoPlay bool // Whether to automatically play audio when generated or navigated to
// Injectable dependencies — when non-nil, New() uses them directly instead of
// constructing new instances from the provider/key fields above.
PhoneticFetcher *phonetic.Fetcher
Translator *translation.Translator
// Archiver moves the cards directory to a timestamped archive; nil uses
// archive.DefaultArchiver.
Archiver archive.Archiver
}
Config holds GUI application configuration
type CustomEntry ¶
CustomEntry extends widget.Entry to handle Escape key (single-line version)
func NewCustomEntry ¶
func NewCustomEntry() *CustomEntry
NewCustomEntry creates a new custom single-line entry
func (*CustomEntry) SetOnEscape ¶
func (e *CustomEntry) SetOnEscape(f func())
SetOnEscape sets the callback for when Escape is pressed
func (*CustomEntry) TypedKey ¶
func (e *CustomEntry) TypedKey(key *fyne.KeyEvent)
TypedKey handles key events
type CustomMultiLineEntry ¶
CustomMultiLineEntry extends widget.Entry to handle Escape key
func NewCustomMultiLineEntry ¶
func NewCustomMultiLineEntry() *CustomMultiLineEntry
NewCustomMultiLineEntry creates a new custom multi-line entry
func (*CustomMultiLineEntry) SetOnEscape ¶
func (e *CustomMultiLineEntry) SetOnEscape(f func())
SetOnEscape sets the callback for when Escape is pressed
func (*CustomMultiLineEntry) TypedKey ¶
func (e *CustomMultiLineEntry) TypedKey(key *fyne.KeyEvent)
TypedKey handles key events
type ExportHandler ¶
type ExportHandler struct {
// contains filtered or unexported fields
}
ExportHandler owns the Export to Anki dialog and APKG/CSV export paths (SRP).
type GenerateResult ¶
type GenerateResult struct {
AudioFile string
AudioFileBack string
ImageFile string
PhoneticInfo string
}
GenerateResult holds the outcome of a parallel generation run.
type GenerationOrchestrator ¶
type GenerationOrchestrator struct {
// contains filtered or unexported fields
}
GenerationOrchestrator coordinates audio, image, and phonetics generation for a single card. It holds all injectable factory functions so tests can substitute fakes without touching the UI layer. image.ClientFactories groups the two image-factory functions so the field definitions are not duplicated between this type and processor.Processor.
func NewGenerationOrchestrator ¶
func NewGenerationOrchestrator( config *Config, audioCfg *audio.Config, phonetics *phonetic.Fetcher, translator *translation.Translator, imageFactories image.ClientFactories, newAudio audio.ProviderFactory, ) *GenerationOrchestrator
NewGenerationOrchestrator constructs an orchestrator wired to the given app configuration and service dependencies. imageFactories and newAudio are the injectable test seams — pass image.DefaultClientFactories() and audio.NewProvider for production behaviour.
func (*GenerationOrchestrator) GenerateAudio ¶
func (o *GenerationOrchestrator) GenerateAudio(ctx context.Context, word, cardDir string) (string, error)
GenerateAudio generates audio for an en-bg card's single audio file. Returns the path to the generated file.
func (*GenerationOrchestrator) GenerateAudioBack ¶
func (o *GenerationOrchestrator) GenerateAudioBack(ctx context.Context, text, cardDir string) (string, error)
GenerateAudioBack generates the back audio file for a bg-bg card.
func (*GenerationOrchestrator) GenerateAudioBgBg ¶
func (o *GenerationOrchestrator) GenerateAudioBgBg(ctx context.Context, front, back, cardDir string) (string, string, error)
GenerateAudioBgBg generates audio for both sides of a bg-bg card in a single call, using the same voice for both to maintain consistency.
func (*GenerationOrchestrator) GenerateAudioFront ¶
func (o *GenerationOrchestrator) GenerateAudioFront(ctx context.Context, word, cardDir string) (string, error)
GenerateAudioFront generates the front audio file for a bg-bg card.
func (*GenerationOrchestrator) GenerateImagesWithPrompt ¶
func (o *GenerationOrchestrator) GenerateImagesWithPrompt(ctx context.Context, word, customPrompt, translation, cardDir string) (string, error)
GenerateImagesWithPrompt downloads a single image for a word, using an optional custom prompt and translation hint.
func (*GenerationOrchestrator) GenerateMaterials ¶
func (o *GenerationOrchestrator) GenerateMaterials( ctx context.Context, word, translation, cardDir string, isBgBg bool, imagePrompt string, promptUI func(prompt string), ) (GenerateResult, error)
GenerateMaterials generates audio, image, and phonetics in parallel for a word. translation is the existing translation (may be empty). isBgBg flags bg-bg card type. imagePrompt is an optional custom prompt; imageTranslation is the translation hint for image prompts. The promptUI callback is called on the generating goroutine when the image prompt becomes known so callers can update the UI. Returns a GenerateResult or an error if any mandatory step fails.
func (*GenerationOrchestrator) GetPhoneticInfo ¶
func (o *GenerationOrchestrator) GetPhoneticInfo(word string) (string, error)
GetPhoneticInfo fetches phonetic information for a Bulgarian word.
func (*GenerationOrchestrator) TranslateEnglishToBulgarian ¶
func (o *GenerationOrchestrator) TranslateEnglishToBulgarian(word string) (string, error)
TranslateEnglishToBulgarian translates an English word to Bulgarian.
func (*GenerationOrchestrator) TranslateWord ¶
func (o *GenerationOrchestrator) TranslateWord(word string) (string, error)
TranslateWord translates a Bulgarian word to English.
type ImageDisplay ¶
type ImageDisplay struct {
widget.BaseWidget
// contains filtered or unexported fields
}
ImageDisplay is a custom widget for displaying images
func NewImageDisplay ¶
func NewImageDisplay() *ImageDisplay
NewImageDisplay creates a new image display widget
func (*ImageDisplay) CreateRenderer ¶
func (d *ImageDisplay) CreateRenderer() fyne.WidgetRenderer
CreateRenderer implements fyne.Widget
func (*ImageDisplay) SetGenerating ¶
func (d *ImageDisplay) SetGenerating()
SetGenerating shows a generating status
func (*ImageDisplay) SetImage ¶
func (d *ImageDisplay) SetImage(imagePath string)
SetImage sets a single image to display
func (*ImageDisplay) SetImages ¶
func (d *ImageDisplay) SetImages(images []string)
SetImages sets multiple images but only displays the first one
type KeyboardShortcuts ¶
type KeyboardShortcuts struct {
// contains filtered or unexported fields
}
KeyboardShortcuts wires global canvas shortcuts and the hotkey help dialog (SRP).
type LogViewer ¶
type LogViewer struct {
widget.BaseWidget
// contains filtered or unexported fields
}
LogViewer is a widget that displays log messages
func (*LogViewer) AddMessage ¶
AddMessage adds a message to the log
func (*LogViewer) CreateRenderer ¶
func (v *LogViewer) CreateRenderer() fyne.WidgetRenderer
CreateRenderer implements fyne.Widget
func (*LogViewer) StartCapture ¶
func (v *LogViewer) StartCapture()
StartCapture starts capturing stdout and stderr
func (*LogViewer) StopCapture ¶
func (v *LogViewer) StopCapture()
StopCapture stops capturing stdout and stderr
type LogWriter ¶
type LogWriter struct {
// contains filtered or unexported fields
}
LogWriter is a custom writer that captures log output
type NavigationHandler ¶
type NavigationHandler struct {
// contains filtered or unexported fields
}
NavigationHandler owns word list navigation, loading card files from disk or queue state, file-check polling, and delete-to-trash. It holds a reference to Application for shared UI state and services (SRP: navigation vs generation).
type ParallelRunner ¶
type ParallelRunner struct{}
ParallelRunner coordinates parallel audio, image, and phonetics work for material generation. It is stateless; the orchestrator supplies all behaviour via the first method argument.
func (ParallelRunner) GenerateMaterials ¶
func (ParallelRunner) GenerateMaterials( o *GenerationOrchestrator, ctx context.Context, word, translation, cardDir string, isBgBg bool, imagePrompt string, promptUI func(prompt string), ) (GenerateResult, error)
GenerateMaterials generates audio, image, and phonetics in parallel for a word. translation is the existing translation (may be empty). isBgBg flags bg-bg card type. imagePrompt is an optional custom prompt; imageTranslation is the translation hint for image prompts. The promptUI callback is called on the generating goroutine when the image prompt becomes known so callers can update the UI. Returns a GenerateResult or an error if any mandatory step fails.
type QueueManager ¶
type QueueManager struct {
// contains filtered or unexported fields
}
QueueManager owns background word-job processing: card contexts, active operation counts, queue draining, and the queue status label (SRP).
type VoiceSelector ¶
type VoiceSelector struct {
// contains filtered or unexported fields
}
VoiceSelector picks voice and speed for a generation run from an AudioConfigResolver. For Gemini with a pinned voice the configured voice is used; otherwise a random voice is selected from the available list.
func NewVoiceSelector ¶
func NewVoiceSelector(resolver *AudioConfigResolver) *VoiceSelector
NewVoiceSelector constructs a VoiceSelector backed by the given resolver.
func (*VoiceSelector) GeminiSpeed ¶
func (v *VoiceSelector) GeminiSpeed() float64
GeminiSpeed returns the configured Gemini TTS speed or the default.
func (*VoiceSelector) GeminiVoicePinned ¶
func (v *VoiceSelector) GeminiVoicePinned() bool
GeminiVoicePinned reports whether a specific Gemini voice is locked in config, meaning fallback voice selection should be skipped.
func (*VoiceSelector) VoiceAndSpeed ¶
func (v *VoiceSelector) VoiceAndSpeed() (string, float64)
VoiceAndSpeed selects the voice and speed for a generation run.
type WordJob ¶
type WordJob struct {
ID int
Word string
Translation string
AudioFile string
AudioFileBack string // Back audio file (only for bg-bg cards)
ImageFile string // Changed from ImageFiles []string to single image
Status JobStatus
Error error
StartedAt time.Time
CompletedAt time.Time
CustomPrompt string // Custom prompt for image generation
NeedsTranslation bool // Whether translation is needed
CardType string // Card type: "en-bg" or "bg-bg"
}
WordJob represents a single word processing job
type WordQueue ¶
type WordQueue struct {
// contains filtered or unexported fields
}
WordQueue manages the queue of words to be processed
func NewWordQueue ¶
NewWordQueue creates a new word processing queue
func (*WordQueue) AddWordWithPrompt ¶
AddWordWithPrompt adds a word to the processing queue with a custom prompt
func (*WordQueue) CompleteJob ¶
CompleteJob marks a job as completed with results
func (*WordQueue) GetActiveJobs ¶
GetActiveJobs returns all jobs that are currently queued or processing. It uses only q.processing and q.results under the read lock; it does not touch q.jobs, because channel operations must not run while holding the mutex (other goroutines send/receive on q.jobs without the lock).
func (*WordQueue) GetCompletedJobs ¶
GetCompletedJobs returns all completed jobs
func (*WordQueue) GetQueueStatus ¶
GetQueueStatus returns the current queue statistics
func (*WordQueue) IsWordProcessing ¶
IsWordProcessing checks if a word is currently being processed or queued
func (*WordQueue) ProcessNextJob ¶
ProcessNextJob should be called by the GUI to process the next job in queue
func (*WordQueue) RemoveCompletedJobByWord ¶
RemoveCompletedJobByWord removes a completed job for a specific word
func (*WordQueue) SetCallbacks ¶
SetCallbacks sets the callback functions for UI updates