| Age | Commit message (Collapse) | Author |
|
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
GetActiveJobs previously drained and refilled q.jobs while holding RLock,
racing with AddWordWithPrompt and ProcessNextJob on the same channel.
Derive queued jobs from q.results (StatusQueued) and processing jobs from
q.processing, matching the authoritative state already updated under the
mutex elsewhere.
Made-with: Cursor
|
|
Add internal/config/defaults.go with shared model IDs, output format, OpenAI/Gemini
audio literals, and speed defaults. Wire audio.DefaultProviderConfig, CLI flags,
GUI defaulting paths, and image package re-exports to these constants. Update
command_test to use the public config identifiers.
Made-with: Cursor
|
|
KeyboardShortcuts
Move navigation, export dialog, queue processing, and keyboard wiring out of
Application into focused types with app *Application for shared state.
Add ensureHandlers() for lazy init so tests that build Application literals
still work. Wire queue callbacks to QueueManager; keep thin Application
delegates for entry points used across the GUI.
Made-with: Cursor
|
|
Use time.NewTimer with defer Stop in the delayed tooltip goroutine so the
timer is not left pending when ctx wins the select. After the delay, check
ctx before and inside fyne.Do so SetToolTip never runs after shutdown
cancels the application context.
Made-with: Cursor
|
|
Define Archiver, ModelLister, and StoryRunner interfaces in their packages.
gui.New returns App; Application carries an injectable Archiver from Config.
cmd/totalrecall wires default implementations via runDeps for tests and DI.
Made-with: Cursor
|
|
Add internal/registry generic Registry[K,T] for keyed factory registration.
Wire audio.NewProvider via registered per-provider constructors; GUI and
processor newImageSearcher use registries of *Orchestrator/*Processor methods.
Export image.ImageProviderOpenAI and ImageProviderNanoBanana from search.go
and use them across gui to avoid duplicate string constants.
Made-with: Cursor
|
|
Split orchestrator audio resolution, voice selection, and parallel material
generation into dedicated types in separate files. GenerationOrchestrator
wires AudioConfigResolver and VoiceSelector from NewGenerationOrchestrator
and delegates GenerateMaterials to ParallelRunner; public behaviour unchanged.
Made-with: Cursor
|
|
Adds showGalleryVideoDialog in internal/gui/dialogs.go: a multi-checkbox
list (all pre-selected) lets the user choose which gallery PNGs to animate,
then calls cli.GenerateSelectedVideos in a goroutine while a progress dialog
indicates background work.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Fire-and-forget goroutines in the tooltip setup, word-change handler, and
audio playback could write to freed Fyne widgets after the window was closed.
All four patterns are now fixed:
- setupTooltips() and the secondary-toolbar tooltip block: replaced
time.AfterFunc(500ms) with wg-tracked goroutines using select/ctx.Done().
- handleWordChange(): replaced time.AfterFunc(100ms) with the same pattern.
- onWindowClosed(): added wordChangeTimer.Stop() to prevent its AfterFunc
callback from firing after context cancellation.
- AudioPlayer: added ctx context.Context field + SetContext(); the
post-playback goroutine now guards fyne.Do with ctx.Err() == nil, and the
auto-play AfterFunc is replaced with a ctx-aware goroutine.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
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>
|
|
Extract CardService (file I/O, persistence, card directory management) and
GenerationOrchestrator (audio/image/phonetics generation) from the 2852-line
Application struct. Application is now thin UI event-wiring. Also split all
functions over 50 lines into focused helpers throughout app.go.
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>
|
|
Two issues prevented the IPA from being fully displayed:
1. audio_player.go: switched the bottom bar from NewHBox to NewBorder so the
phonetic label fills the centre column instead of being squeezed to its
minimum width between the stop button and the status label. Also enabled
TextWrapWord so very long IPA strings wrap rather than being clipped.
2. phonetic/fetcher.go: raised MaxOutputTokens from 50 to 200 so Gemini 2.5
Flash has enough budget to emit the full IPA bracket pair without truncation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- audio/fallbacks.go: lowercase error string per Go convention
- gui/app.go: remove empty else branch in keyboard shortcut handler
- audio/provider_test.go: remove unused mockProvider type
- update test assertions in voices_test.go and processor_test.go to match
the corrected lowercase error string
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- startFileCheckTicker: add wg.Add(1)/wg.Done() so the app shutdown handler
waits for the ticker goroutine to exit (it already uses ctx.Done() to stop).
- post-delete cleanup goroutine: add wg.Add(1)/wg.Done() and a ctx.Done()
case so a shutdown during the 5-second polling window terminates cleanly
instead of leaking the goroutine.
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>
|
|
audio_player.go: use time.AfterFunc instead of goroutine+sleep for the
100ms auto-play delay — no goroutine is blocked waiting.
app.go (setupUI, setupTooltips): replace goroutine+sleep with time.AfterFunc
for both 500ms tooltip initialization delays.
navigation.go: replace fixed 500ms sleep in the delete-cleanup goroutine with
a ticker+select loop that polls hasActiveOperations(). The goroutine now
proceeds as soon as all in-flight operations for the deleted word finish
(or after a 5-second safety timeout), rather than waiting a fixed interval
that may be too short or too long.
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>
|
|
shared prompt
- task 00g: fix gofmt violations (trailing whitespace, missing newlines,
indentation) in 8 files; all pass gofmt -l now
- task 00k: remove unused ProviderWithFallback and its tests (YAGNI — no
production caller existed; voice-level fallback via RunWithVoiceFallbacks
already covers the real use case)
- task 00h: replace private splitLines/trimSpace/isSpace helpers in
internal/batch/processor.go with strings.Split+ReplaceAll and
strings.TrimSpace from the stdlib; remove the now-redundant tests
- task 008: extract buildEducationalPrompt into internal/image/prompt.go so
the prompt-assembly policy (scene truncation cascade, char limit) lives in
one place; both OpenAIClient and NanoBananaClient delegate to it
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Removed duplicate fyne.KeyA handler that was triggering both front and back audio
- Added SetAudioFileNoAutoPlay() method for controlled playback
- Front audio (a key) now auto-plays only front audio
- Back audio (A key) now auto-plays only back audio
- Refactored startPlayback to use startPlaybackForFile for better control
- Fixed icon reset when playback finishes for each audio type separately
|