From 0bad7d858f804ed6df4b51525194d55ec7182f76 Mon Sep 17 00:00:00 2001 From: Stu Leak Date: Tue, 23 Dec 2025 21:30:17 -0500 Subject: [PATCH] Add comprehensive refactoring guide for opencode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created step-by-step guide for modularizing main.go: - 9 modules to extract in priority order (least → most important) - Filters first (easiest), Convert last (most critical) - Clear instructions for each extraction - Reference patterns from existing modules - Success criteria and testing steps - Emergency rollback procedures Module extraction order: 1. filters_module.go (~236 lines) - Simple UI 2. upscale_module.go (~1200 lines) - AI integration 3. thumb_module.go (~400 lines) - Thumbnail generation 4. player_module.go (~800 lines) - Playback system 5. compare_module.go (~550 lines) - File comparison 6. merge_module.go (~700 lines) - File merging 7. benchmark_module.go (~400 lines) - Encoder benchmarks 8. queue_module.go (~500 lines) - Job queue 9. convert_module.go (~6400 lines) - Most critical, do last Goal: Reduce main.go from 14,116 → ~4,000 lines Expected: Windows build time 5+ min → <2 min Each module extraction is independent and testable. Pattern established with inspect_module.go (already done). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- REFACTORING_PROMPT_FOR_OPENCODE.md | 411 +++++++++++++++++++++++++++++ 1 file changed, 411 insertions(+) create mode 100644 REFACTORING_PROMPT_FOR_OPENCODE.md diff --git a/REFACTORING_PROMPT_FOR_OPENCODE.md b/REFACTORING_PROMPT_FOR_OPENCODE.md new file mode 100644 index 0000000..2fc72d8 --- /dev/null +++ b/REFACTORING_PROMPT_FOR_OPENCODE.md @@ -0,0 +1,411 @@ +# Main.go Modularization - Incremental Refactoring Prompt + +## Current State + +**Problem:** main.go is 14,116 lines (420KB) causing: +- 5+ minute builds on Windows +- Poor code maintainability +- Difficult to navigate and modify + +**Goal:** Extract modules into separate files following established patterns + +**Already Extracted:** +- ✅ `author_module.go` (1,421 lines) - Pattern reference +- ✅ `subtitles_module.go` (756 lines) - Pattern reference +- ✅ `inspect_module.go` (292 lines) - Pattern reference + +**Remaining:** 9 modules to extract (~10,000 lines) + +--- + +## Extraction Order (Least Important → Most Important) + +Work through these **one module at a time**, testing after each extraction: + +### Phase 1: Simple Modules (Start Here) + +1. **filters_module.go** (~236 lines) + - Lines: ~13261-13497 + - Functions: `showFiltersView()`, `buildFiltersView()` + - State fields: `filtersFile`, `filterBrightness`, `filterContrast`, etc. + - Why first: Simple UI-only, no job execution + +2. **upscale_module.go** (~889 lines + job executor) + - Lines: ~13498-14387 + job executor at ~4568-5023 + - Functions: `showUpscaleView()`, `buildUpscaleView()`, `executeUpscaleJob()`, AI helpers + - State fields: All `upscale*` fields (~25 fields) + - Includes: AI backend detection, model helpers + +3. **thumb_module.go** (~335 lines + job executor) + - Lines: ~12837-13172 + executeThumbJob at ~4222-4264 + - Functions: `showThumbView()`, `buildThumbView()`, `executeThumbJob()` + - State fields: `thumbFile`, `thumbCount`, `thumbWidth`, etc. + +### Phase 2: Moderate Complexity + +4. **player_module.go** (~87 lines + playSession ~450 lines) + - Lines: ~13173-13260 + playSession at ~8929-9329 + - Functions: `showPlayerView()`, `buildPlayerView()`, `stopPlayer()`, entire `playSession` type + - State fields: `playerFile`, `player`, `playerReady`, `playerVolume`, etc. + - Types: `playSession`, `playerSurface`, `playSession` methods + - Note: Includes recent performance improvements + +5. **compare_module.go** (~503 lines + fullscreen) + - Lines: ~12068-12571 + fullscreen at ~14277-14387 + - Functions: `showCompareView()`, `buildCompareView()`, `buildCompareFullscreenView()`, `showCompareFullscreen()` + - State fields: `compareFile1`, `compareFile2`, `autoCompare` + +### Phase 3: Complex Infrastructure + +6. **merge_module.go** (~374 lines + job executor) + - Lines: ~2752-3126 + executeMergeJob at ~3232-3564 + - Functions: `showMergeView()` (inline UI builder), `addMergeToQueue()`, `executeMergeJob()` + - State fields: `mergeClips`, `mergeFormat`, `mergeOutput`, etc. + - Types: `mergeClip` struct + - Note: UI builder is inline, needs extraction to `buildMergeView()` + +7. **benchmark_module.go** (~326 lines) + - Lines: ~1938-2264 + config persistence at ~700-729 + - Functions: `showBenchmark()`, `showBenchmarkHistory()`, benchmark helpers + - Types: `benchmarkConfig`, `benchmarkRun` + +8. **queue_module.go** (~scattered functions) + - Functions: `showQueue()`, `refreshQueueView()`, `jobExecutor()`, `buildFFmpegCommandFromJob()` + - Lines: Various, needs gathering + +### Phase 4: Most Critical (Do Last) + +9. **convert_module.go** (~6,384 lines - THE BIG ONE) + - Lines: ~5683-12067 + - Functions: 50+ functions including `buildConvertView()`, `showConvertView()`, all convert helpers + - State fields: All `convert*` fields, `source`, `loadedVideos`, etc. + - Types: `convertConfig`, `formatOption` + - Shared components: `buildMetadataPanel()`, `buildVideoPane()` (used by other modules) + - May need to split into multiple files if > 3000 lines + +--- + +## Instructions for Each Module Extraction + +### Step-by-Step Process + +For each module (do ONE at a time): + +#### 1. Create the Module File + +**File:** `{module}_module.go` (e.g., `filters_module.go`) + +**Template:** +```go +package main + +import ( + // Copy imports from main.go that this module needs + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/container" + // ... etc +) + +// Move the show{Module}View() method here +func (s *appState) show{Module}View() { + s.stopPreview() + s.lastModule = s.active + s.active = "{module}" + s.setContent(build{Module}View(s)) +} + +// Move the build{Module}View() function here +func build{Module}View(state *appState) fyne.CanvasObject { + // ... entire function body ... +} + +// Move any helper functions specific to this module +// Move any job executor functions (execute{Module}Job) +``` + +#### 2. Remove from main.go + +Delete the exact same functions you just moved. Use line numbers as guide. + +**IMPORTANT:** Do NOT remove: +- Shared functions used by multiple modules (e.g., `moduleColor()`, `probeVideo()`) +- State fields in `appState` struct (leave all state in main.go) +- Type definitions used across modules + +#### 3. Build and Test + +```bash +# Must succeed +go build -o VideoTools . + +# Check line count reduction +wc -l main.go {module}_module.go + +# Test the module works +./VideoTools # Navigate to the module and test basic functionality +``` + +#### 4. Commit + +```bash +git add {module}_module.go main.go +git commit -m "Extract {module} module from main.go + +- Create {module}_module.go (XXX lines) +- Move show{Module}View() and build{Module}View() +- Reduce main.go by XXX lines +- All tests pass, module functions correctly +" +``` + +#### 5. Move to Next Module + +Repeat the process for the next module in the order above. + +--- + +## Reference Patterns + +Look at these existing extracted modules for the pattern: + +### Pattern 1: Simple Module (inspect_module.go) +```go +package main + +import ( + // Necessary imports +) + +func (s *appState) showInspectView() { + s.stopPreview() + s.lastModule = s.active + s.active = "inspect" + s.setContent(buildInspectView(s)) +} + +func buildInspectView(state *appState) fyne.CanvasObject { + // UI building code +} +``` + +### Pattern 2: Module with Job Executor (subtitles_module.go) +```go +package main + +import ( + // Necessary imports +) + +func (s *appState) showSubtitlesView() { + // ... +} + +func buildSubtitlesView(state *appState) fyne.CanvasObject { + // ... +} + +func (s *appState) executeSubtitlesJob(ctx context.Context, job *queue.Job, progressCallback func(float64)) error { + // Job execution logic +} + +// Helper functions specific to subtitles +``` + +### Pattern 3: Module with Types (author_module.go) +```go +package main + +import ( + // ... +) + +// Types specific to this module +type authorClip struct { + // ... +} + +func (s *appState) showAuthorView() { + // ... +} + +// Many helper functions specific to author module +``` + +--- + +## What Stays in main.go + +**DO NOT MOVE these to module files:** + +### Core Application +- `main()` function +- `runGUI()` function +- `type appState struct` definition (all fields stay) +- Window setup and initialization + +### Shared Utilities (Used by 3+ modules) +- `moduleColor()` - Color scheme helper +- `moduleFooter()` - Footer bar builder +- `statusStrip()` - Status bar +- `probeVideo()` - Video file analysis (CRITICAL - used everywhere) +- `buildMetadataPanel()` - Used by convert and other modules +- `buildVideoPane()` - Video preview pane (used by many modules) +- `formatBitrate()`, `formatClock()`, etc. - Format helpers + +### Navigation & State +- `showMainMenu()` - Main menu builder +- `setContent()` - Content switcher +- History sidebar code +- Stats bar updates +- Drop handlers + +### Shared Types +- `videoSource` type and methods +- Shared constants and enums + +--- + +## Special Cases & Gotchas + +### Convert Module (Do Last!) + +The convert module is massive and may need splitting: + +**Option A: Single File** (if < 3000 lines after extraction) +- `convert_module.go` + +**Option B: Split into Multiple Files** (if > 3000 lines) +- `convert_module.go` - Main UI and show function +- `convert_config.go` - Configuration types and persistence +- `convert_job.go` - Job execution logic +- `convert_helpers.go` - Codec/format helpers + +**Shared Components:** +- `buildMetadataPanel()` and `buildVideoPane()` might need to move to `shared_ui.go` if used by many modules + +### Merge Module Inline UI + +The merge module has UI building inline in `showMergeView()`. You'll need to: + +1. Extract inline UI to `buildMergeView()` function +2. Then follow standard pattern + +### Player Module with playSession + +The `playSession` type and all its methods should move to `player_module.go` together. + +### Import Adjustments + +Some modules might need internal package imports that aren't in main.go: +- Check for missing imports after extraction +- Run `go build` to catch import errors +- Add necessary imports to the module file + +--- + +## Success Criteria for Each Extraction + +Before moving to next module, verify: + +- ✅ `go build` succeeds with no errors +- ✅ Module file has clear structure (show function, build function, helpers) +- ✅ main.go reduced by expected lines +- ✅ Module works when tested in GUI +- ✅ No duplicate code between main.go and module file +- ✅ Git commit created with clear message +- ✅ Can navigate to module and use basic features + +--- + +## Tracking Progress + +After each extraction, update this checklist: + +- [ ] 1. filters_module.go (~236 lines) +- [ ] 2. upscale_module.go (~1200 lines) +- [ ] 3. thumb_module.go (~400 lines) +- [ ] 4. player_module.go (~800 lines) +- [ ] 5. compare_module.go (~550 lines) +- [ ] 6. merge_module.go (~700 lines) +- [ ] 7. benchmark_module.go (~400 lines) +- [ ] 8. queue_module.go (~500 lines) +- [ ] 9. convert_module.go (~6400 lines - may split) + +**Target:** main.go from 14,116 lines → ~4,000 lines + +--- + +## Expected Timeline + +- **Simple modules (1-3):** 20-30 min each +- **Moderate modules (4-5):** 30-45 min each +- **Complex modules (6-8):** 45-60 min each +- **Convert module (9):** 2-3 hours (largest, most critical) + +**Total:** ~8-12 hours of incremental work + +--- + +## Final Build Performance Goal + +After all extractions: + +**Before:** +- main.go: 14,329 lines (426KB) +- Build time (Windows): 5+ minutes + +**After:** +- main.go: ~4,000 lines (~120KB) +- Module files: 10-12 files (~800-1500 lines each) +- Build time (Windows): < 2 minutes (hopefully < 1 minute) + +--- + +## Questions to Ask If Stuck + +1. **"Does this function use state from multiple modules?"** + - Yes → Keep in main.go + - No → Move to module file + +2. **"Is this function called by 3+ different modules?"** + - Yes → Keep in main.go as shared utility + - No → Move to the module that uses it + +3. **"Is this a type used across modules?"** + - Yes → Keep type definition in main.go + - No → Move to module file + +4. **"Where are the line numbers for this module?"** + - Check this document's module listing + - Use grep to find function: `grep -n "func buildXView" main.go` + +--- + +## Emergency Rollback + +If an extraction breaks the build: + +```bash +# Restore main.go from backup +git checkout HEAD -- main.go + +# Remove the broken module file +rm {module}_module.go + +# Try again with more care +``` + +--- + +## Start Here + +**First module to extract:** `filters_module.go` + +1. Find lines ~13261-13497 in main.go +2. Create `filters_module.go` +3. Copy `showFiltersView()` and `buildFiltersView()` +4. Remove from main.go +5. Build, test, commit +6. Move to next module + +Good luck! Take it one module at a time, test after each extraction, and the convert module will be much easier once you've established the pattern with the simpler modules.