| Age | Commit message (Collapse) | Author |
|
FindCardDirectory, FindOrCreateCardDirectory, GenerateCardID and the
ScanWords helper previously existed in both internal/utils.go (as
standalone functions) and were partially duplicated in
internal/gui/card_service.go (readWordFromDir, ScanExistingWords).
Introduce internal/store.CardStore as the single source of truth for
all on-disk card-directory operations. Both internal/processor and
internal/gui now hold a *store.CardStore field and delegate to it,
removing the last copy of the directory-scanning loop from
card_service.go. internal/utils.go keeps thin forwarding wrappers for
callers that import the root internal package.
Also adds table-driven unit tests for the new package covering
FindCardDirectory (including legacy _word.txt fallback),
FindOrCreateCardDirectory, and CardStore.ScanWords.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Define audio.ProviderFactory, image.PromptAwareClient,
image.OpenAIClientFactory, image.NanoBananaClientFactory, and
image.ClientFactories as the single source of truth for the three injectable
factory signatures that were previously duplicated across processor.Processor,
gui.Application, and gui.GenerationOrchestrator. Replace all three separate
function-type fields with imageFactories image.ClientFactories +
newAudioProvider audio.ProviderFactory, eliminating the parallel field
declarations and the local promptAwareImageClient interface in gui/generator.go.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Resolve all Viper config values once at startup in cmd/totalrecall/main.go
via the new newProcessorConfig() helper. The exported processor.Config struct
replaces the internal viperConfig type, and NewProcessor now accepts *Config
instead of querying Viper internally. The processor package no longer imports
Viper at all. Tests are updated to pass Config values directly, eliminating
the viper.Set/Reset boilerplate that coupled tests to the global singleton.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Extract audio coordination (voice selection, config assembly, attribution
writing) into audio_coordinator.go, card directory management into
card_store.go, and image downloading/searcher construction into
image_downloader.go. processor.go shrinks from ~1119 to ~575 lines,
each file now has a single clear responsibility. Also apply go fmt to
all touched files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
config, extract shared card-dir logic
task 00d: remove package-level var test seams from processor and gui packages;
factory functions (newAudioProvider, newOpenAIImageClient, newNanoBananaImageClient)
are now struct fields on Processor and Application, initialized with production
defaults in constructors and replaced in tests without global mutation.
task 006: add viperConfig struct captured once in NewProcessor; no method body
calls viper.GetString/IsSet/GetFloat64 directly any more — all config-file values
are accessed via p.viperCfg fields.
task 007: extract FindCardDirectory and FindOrCreateCardDirectory into
internal/utils.go; both Processor.findCardDirectory and
Application.findCardDirectory now delegate to the shared implementation,
which also handles the legacy _word.txt backward-compat fallback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Extend audio.Provider with Voices() []string and BuildAttribution() string
so all provider-specific behaviour is encapsulated in the implementation
rather than scattered as switch-cases across callers.
Add package-level VoicesFor(name) and BuildAttributionFor(name, params)
for callers (processor, GUI) that need these before constructing a
Provider instance. Add AttributionParamsFrom(config, word, ...) so
callers can build AttributionParams from the flat Config without a manual
provider switch. Implement both new interface methods in OpenAIProvider
and GeminiProvider. Update all Provider mock/fake types in tests.
Migrate audioVoicesForProvider() and saveAudioAttribution() in both
processor.go and gui/generator.go to use the new package-level helpers,
replacing the 10+ duplicated switch blocks.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Replace Processor.RunGUIMode() with a standalone runGUIMode() function in
the composition root (cmd/main.go) that calls proc.GUIConfig() to get the
GUI settings and then owns the gui.New()/Run() lifecycle. The processor
package still imports gui for the gui.Config return type; complete removal
of that import is deferred to task 000 (god-object decomposition) where
the Processor itself will be split up.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Add PhoneticFetcher and Translator fields to gui.Config so callers can
inject ready-to-use instances. gui.New() uses the injected values when
non-nil and falls back to constructing from provider/key fields otherwise.
The processor composition root now builds both dependencies and sets them
on gui.Config, keeping construction logic out of gui.New().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
batch timeout
- Thread ctx context.Context through generateAudio, generateAudioBgBg,
generateAudioWithVoice, generateAudioWithVoiceAndFilename,
generateAudioWithVoiceAndFilenameInDir, and downloadImagesWithTranslation.
Also add ctx to ProcessWordWithTranslationAndType so callers can control
the deadline for the full word-processing pipeline.
- In ProcessBatch, create a context.WithTimeout(5 * time.Minute) per word
so a single hung TTS or image API call cannot block the whole batch run.
Previously both functions created context.Background() internally, making
cancellation impossible.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Fix critical bug where generateAudioBgBg() was creating two separate
card directories (one for front audio, one for back audio)
- Root cause: generateAudioWithVoiceAndFilename() calls findOrCreateWordDirectory()
with both the front word AND the back word, creating separate directories
- Solution: Pass wordDir to both audio generation calls
- Create new generateAudioWithVoiceAndFilenameInDir() function
- Refactor generateAudioWithVoiceAndFilename() to use new function
- generateAudioBgBg() now finds directory ONCE and passes it to both calls
This fixes the issue where opening a bg-bg card showed 'no audio loaded'
because audio_front.mp3 and audio_back.mp3 were in different directories.
|
|
- Add debug logging to navigation.go to diagnose audio file loading issues
Prints paths being checked and whether files are found
- Improve AudioPlayer UI for Bulgarian-Bulgarian cards:
- Add labels showing 'Front' and 'Back' for bg-bg audio buttons
- Labels only show when audio files are actually loaded
- Better visual distinction between the two playable audios
- Reorganized button layout with VBox for cleaner appearance
- Track bg-bg state in AudioPlayer (isBgBg field)
- Automatically set when back audio file is loaded
- Used to determine when to show labels
This makes it clearer that Bulgarian-Bulgarian cards have two independently
playable audio outputs, and helps debug why audio isn't being loaded.
|
|
|
|
🤖 Generated with [opencode](https://opencode.ai)
Co-Authored-By: opencode <noreply@opencode.ai>
|
|
## Bulk Import Enhancements
- Added support for three flexible batch file formats:
- `BULGARIAN = ENGLISH` - Both provided, no translation needed
- `= ENGLISH` - Only English provided, auto-translated to Bulgarian
- `BULGARIAN` - Only Bulgarian provided, auto-translated to English
- Implemented smart file checking to skip already processed words
- Check all required files (word.txt, translation.txt, phonetic.txt, audio/image files and their attribution/metadata)
- Added batch processing summary with statistics
## Archive Functionality
- Renamed --clear flag to --archive for clarity
- Archive cards directory to ~/.local/state/totalrecall/archive/cards-TIMESTAMP
- Added archive button to GUI toolbar with folder icon
- Archive confirmation dialog supports keyboard shortcuts (y/n/c/ESC)
## Export Improvements
- Anki exports now show full file path in output
- Changed default export location to home directory (~) for both CLI and GUI
- Auto-adjust image size to 1024x1024 when DALL-E 3 is selected
## Other Improvements
- Added TranslateEnglishToBulgarian method for reverse translation
- Enhanced batch processing with better error handling and progress reporting
- Improved file integrity checking for complete word processing
🤖 Generated with [opencode](https://opencode.ai)
Co-Authored-By: opencode <noreply@opencode.ai>
|
|
Moves the phonetic information fetching to occur immediately after the word has been translated. This ensures that the phonetic data is available as early as possible in the processing pipeline.
Previously, the phonetic information was fetched after image generation, which caused an unnecessary delay. This change improves the logical flow of the word processing sequence.
|
|
- Fix batch mode to store cards in ~/.local/state/totalrecall/cards/ matching GUI behavior
- Add --no-auto-play flag to disable automatic audio playback (enabled by default)
- Simplify phonetic fetching in CLI to match GUI (IPA only, no detailed explanations)
- Remove redundant --gui flag as GUI is already the default mode
- Align image generation settings: both modes now use DALL-E 2 with 512x512 resolution
🤖 Generated with [opencode](https://opencode.ai)
Co-Authored-By: opencode <noreply@opencode.ai>
|
|
- Reduced main.go from 961 lines to 89 lines (91% reduction)
- Created new packages for better separation of concerns:
- cli: Command-line interface setup and configuration
- processor: Core word processing logic and orchestration
- batch: Batch file processing functionality
- translation: Bulgarian to English translation services
- models: OpenAI model listing functionality
- phonetic: Phonetic information fetching
- Each package has clear documentation in doc.go files
- Improved testability and maintainability
- All existing functionality preserved
- All tests passing and build successful
|