summaryrefslogtreecommitdiff
path: root/internal/gui
AgeCommit message (Collapse)Author
2026-04-21Audit stripped comicgen leftoversPaul Buetow
2026-04-13Release v0.29.0: display card counter (Card X / N) in the GUI status barv0.29.0Paul Buetow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08fix(gui): make GetActiveJobs concurrency-safe without channel access under lockPaul Buetow
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
2026-04-08config: centralize NanoBanana and audio defaults in defaults.goPaul Buetow
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
2026-04-08refactor(gui): extract NavigationHandler, ExportHandler, QueueManager, ↵Paul Buetow
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
2026-04-08fix(gui): avoid tooltip init race after window closePaul Buetow
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
2026-04-08refactor(dip): inject archive, models, story, and gui at composition rootsPaul Buetow
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
2026-04-08refactor: registry pattern for audio and image provider factoriesPaul Buetow
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
2026-04-08refactor(gui): extract AudioConfigResolver, VoiceSelector, ParallelRunnerPaul Buetow
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
2026-04-06feat: add Fyne GUI dialog for gallery video generationPaul Buetow
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>
2026-04-06fix: track all GUI goroutines with WaitGroup and ctx.Done() (Go Mistake #62)Paul Buetow
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>
2026-04-06refactor: extract shared CardStore into internal/store to eliminate duplicationPaul Buetow
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>
2026-04-06refactor: consolidate provider factory test seams into shared named typesPaul Buetow
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>
2026-04-06refactor: decompose gui.Application god object into focused servicesPaul Buetow
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>
2026-04-06refactor: decompose Processor god object into focused files (SRP)Paul Buetow
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>
2026-04-03fix: show full phonetic IPA in audio player barPaul Buetow
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>
2026-04-03fix: resolve all golangci-lint issuesPaul Buetow
- 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>
2026-04-03task 00a: track background goroutines in WaitGroup and respect ctx.Done()Paul Buetow
- 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>
2026-04-03tasks 00d, 006, 007: move test seams to struct fields, centralize Viper ↵Paul Buetow
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>
2026-04-02task zz: add Voices()/BuildAttribution() to Provider interface [OCP]Paul Buetow
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>
2026-04-02task 004: replace time.Sleep goroutine synchronization with proper primitivesPaul Buetow
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>
2026-04-02task 00e: inject phonetic.Fetcher and translation.Translator into gui.New()Paul Buetow
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>
2026-04-02task 00g/00k/00h/008: gofmt, remove ProviderWithFallback, stdlib helpers, ↵Paul Buetow
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>
2026-04-02task 003: handle home-dir and APKG marshal errorsPaul Buetow
2026-04-02task 002: restore Gemini warning outputPaul Buetow
2026-04-02task 002: centralize Gemini voice fallbacksPaul Buetow
2026-04-02task 001: remove committed debug printf tracesPaul Buetow
2026-04-02Release v0.9.0v0.9.0Paul Buetow
2026-04-02Fix verification gate lint and test issuesPaul Buetow
2026-04-02Centralize audio sidecar generationPaul Buetow
2026-04-02Align GUI and CLI provider wiringPaul Buetow
2026-04-02Fix GUI selector sync and audio metadata modelPaul Buetow
2026-04-02Fix GUI audio reload and bg-bg session statePaul Buetow
2026-04-02Fix GUI voice-suffixed audio discoveryPaul Buetow
2026-04-02Harden GUI audio loading for GeminiPaul Buetow
2026-04-01Wire Gemini audio into GUIPaul Buetow
2026-04-01zg: add gui front-back voice coveragePaul Buetow
2026-04-01zg: add bg-bg consumer coveragePaul Buetow
2026-04-01zg: add consumer coverage for shared voice listsPaul Buetow
2026-04-01zg: extract shared audio voice listsPaul Buetow
2026-04-01z9: wire Nano Banana into GUIPaul Buetow
2026-04-01zt: align GUI translation defaults with shared translatorPaul Buetow
2026-04-01zt: route GUI translations through shared translatorPaul Buetow
2026-04-01zu: switch GUI phonetics to shared fetcherPaul Buetow
2026-03-08refactor(task-376): share audio attribution builderPaul Buetow
2026-03-08test(task-374): fix errcheck issues in tests and support codePaul Buetow
2026-03-08fix(task-373): handle runtime cleanup errors in production pathsPaul Buetow
2026-03-08fix: complete code-quality task queue (373-378)Paul Buetow
2026-03-05chore: release v0.8.1v0.8.1Paul Buetow
2026-01-21Fix: Auto-play only regenerated audio (front or back, not both) for bg-bg cardsv0.8.0Paul Buetow
- 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