VideoTools/REFACTORING_PROMPT_FOR_OPENCODE.md
Stu Leak 0bad7d858f Add comprehensive refactoring guide for opencode
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 <noreply@anthropic.com>
2025-12-23 21:30:17 -05:00

11 KiB

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

  1. 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
  2. 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

  1. 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()
  2. benchmark_module.go (~326 lines)

    • Lines: ~1938-2264 + config persistence at ~700-729
    • Functions: showBenchmark(), showBenchmarkHistory(), benchmark helpers
    • Types: benchmarkConfig, benchmarkRun
  3. queue_module.go (~scattered functions)

    • Functions: showQueue(), refreshQueueView(), jobExecutor(), buildFFmpegCommandFromJob()
    • Lines: Various, needs gathering

Phase 4: Most Critical (Do Last)

  1. 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:

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

# 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

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)

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)

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)

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:

# 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.