d41761d6e9
Rewrites oxker from Rust/ratatui to Go/Bubbletea, migrated to the Bubbletea v2 API (charm.land/bubbletea/v2). Removes all original Rust source files and legacy Go modules (internal/ui, internal/input, bubbles). Key changes: - View() returns tea.View with declarative AltScreen and MouseMode - KeyMsg → KeyPressMsg, MouseMsg → MouseClickMsg/WheelMsg/MotionMsg/ReleaseMsg - execWriteKey rewritten for v2 key fields (Code/Mod/Text) - Mouse toggle via View field instead of imperative commands - Filter/search text input uses msg.Text for v2 space key compat Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
18 KiB
18 KiB
Oxker Go Rewrite — Review Findings
Systematischer Vergleich aller Original-Rust-Dateien mit der Go-Reimplementierung. 6 parallele Review-Agenten, ~130 Findings gesamt.
CRITICAL (App funktioniert falsch)
C1. CPU immer 0 — ContainerStatsOneShot liefert leere precpu_stats
- Source: Docker Integration Review #11
- Rust:
docker_data/mod.rs:136-143—stream: false, one_shot: false+.take(1) - Go:
docker/client.go:70—ContainerStatsOneShotsetztone-shot=true - Problem: Mit
one-shot=trueliefert Docker leereprecpu_stats, CPU-Berechnung ergibt 0 - Fix:
ContainerStatsmitstream=falsestattContainerStatsOneShotverwenden - Status: [x] FIXED
C2. uint64 Underflow bei CPU-Berechnung
- Source: Docker Integration Review #6/#7
- Rust:
docker_data/mod.rs:86-91—saturating_subverhindert Underflow - Go:
app.go:1120-1121— plain uint64 Subtraktion, kann wrappen - Fix: Guard:
if TotalUsage < PreTotalUsage { return 0 } - Status: [x] FIXED
C3. --host Flag wird ignoriert
- Source: Docker Integration Review #1
- Rust:
main.rs:47-57— Config Host > DOCKER_HOST env > default socket - Go:
docker/client.go:17-22— nurFromEnv, ignoriertConfig.Host - Fix:
docker.New()soll optionalen Host akzeptieren,client.WithHost(host)verwenden - Status: [x] FIXED
C4. Logs ShowStderr Config ignoriert
- Source: Docker Integration Review #8
- Rust:
docker_data/mod.rs:256-258—config.show_std_err - Go:
app.go:1089-1091— hardcodedShowStderr: true - Fix:
ShowStderr: a.Config.ShowStdErr - Status: [x] FIXED
C5. Bandwidth-Chart zeigt kumulative Bytes statt Rate
- Source: Data Model Review #8
- Rust:
container_state.rs:627-672—NetworkBandwidth.to_vec_f64berechnet Deltas - Go:
app.go:1493-1508—fmtRate(c.RxBytes)auf kumulative Rohwerte - Fix: Bandwidth als Differenz zwischen aufeinanderfolgenden Einträgen berechnen
- Status: [x] FIXED
C6. RunningUnhealthy — fehlt pause/restart in Commands
- Source: Data Model Review #2, Main UI Review #6
- Rust:
container_state.rs:451—Running(_) => [Pause, Restart, Stop, Delete] - Go:
app.go:1749-1750—RunningUnhealthynur["stop", "delete"] - Fix: Gleiche Commands wie RunningHealthy
- Status: [x] FIXED
C7. Enter führt immer ersten Command aus — kein Command-Selection
- Source: Input Review #6, Data Model Review #4, Main UI Review #8
- Rust:
input_handler/mod.rs:267— prüftpanel == Commands, nutztselected_docker_controls() - Go:
app.go:922—cmds[0]immer, unabhängig von Panel - Fix:
CmdSelectedIdxFeld, nur beiActivePanel == PanelCommandsausführen - Status: [x] FIXED
C8. Ctrl+C quit nicht in Filter/Search-Modus
- Source: Input Review #9
- Rust:
input_handler/mod.rs:762-763— Ctrl+C immer quit - Go:
app.go:360-367— Filter/Search early return, Ctrl+C wird nie erreicht - Fix: Ctrl+C Check vor Mode-Dispatch
- Status: [x] FIXED
C9. Mouse-Events nicht blockiert in Overlay-Modi
- Source: Input Review #10
- Rust:
input_handler/mod.rs:74-84— blockiert Mouse in Error/Help/Filter/Search/DeleteConfirm - Go:
app.go:638— keine Mode-Checks, Mouse immer aktiv - Fix: Mode-Checks am Anfang von
handleMouse - Status: [x] FIXED
C10. Info-Popup Auto-Dismiss fehlt (4 Sekunden)
- Source: Popups Review #9
- Rust:
info.rs:52-54—instant.elapsed() > 4000ms - Go:
app.go:1003-1006— Kommentar sagt "handled by tick", aber kein Timer - Fix:
tea.Tick(4*time.Second)→InfoDismissMsg - Status: [x] FIXED
HIGH (UI sieht falsch aus)
H1. CPU-Format ohne Zero-Padding
- Source: Main UI Review #2
- Rust:
container_state.rs:521—{:05.2}%→00.00%,05.34% - Go:
app.go:1325—%.2f%%→0.00%,5.34% - Fix:
fmt.Sprintf("%05.2f%%", c.CPUPercent) - Status: [x] FIXED
H2. Container-Spalten ohne Farben (Name/ID/Image/RX/TX)
- Source: Main UI Review #10/#11
- Rust:
containers.rs:26-33— Name/ID/Image mitcontainers.text(Blue), RX/TX eigene Farben - Go:
app.go:1321-1332— kein Styling - Fix: lipgloss.Foreground für Name/ID/Image und separate Farben für RX/TX
- Status: [x] FIXED
H3. Command-Farben falsch
- Source: Main UI Review #5
- Rust: restart=Magenta, delete=Gray, resume=Blue, start=Green, stop=Red, pause=Yellow
- Go: restart/resume/start=Green, stop/delete=Red, pause=Yellow
- Fix: Jeder Command eigene Farbe
- Status: [x] FIXED
H4. Layout-Proportionen falsch
- Source: Main UI Review #17
- Rust:
ui/mod.rs:400— 75%/25% (oben/unten) - Go:
app.go:1664-1686— 30% Container, 22% Charts, Rest Logs - Fix: 75%/25% Split, dann Container/Logs innerhalb der 75%
- Status: [x] FIXED
H5. Ports: :: und 0 statt leer
- Source: Charts/Ports Review #15/#16
- Rust:
container_state.rs:156-160— None → leerer String - Go:
app.go:1522-1523—::für leere IP,0für fehlenden Public Port - Fix: Leere Strings statt
::und0 - Status: [x] FIXED
H6. Falsches Highlight-Symbol
- Source: Main UI Review #12
- Rust:
mod.rs:47—⚪(offener Kreis) - Go:
app.go:1315—●(gefüllter Kreis, blau) - Fix:
⚪verwenden - Status: [x] FIXED
H7. Default-Sort fehlt (nach CreatedAt)
- Source: Data Model Review #13
- Rust:
mod.rs:492-499— sort bycreated+ Name als Tiebreaker - Go:
app.go:829-831— kein Sort beiSortNone - Fix: Bei
SortNonenachCreatedAtsortieren, Name als Tiebreaker - Status: [x] FIXED
H8. Sort verliert Selection
- Source: Data Model Review #6
- Rust:
mod.rs:377-387— re-selects Container by ID nach Sort - Go:
app.go:812-827— SelectedIdx bleibt gleich, Container an Position ändert sich - Fix: Nach Sort alten Container per ID finden und SelectedIdx aktualisieren
- Status: [x] FIXED
H9. Sort Tiebreaker by Name fehlt
- Source: Data Model Review #15
- Rust:
mod.rs:437-484—.then_with(|| name.cmp(name)) - Go:
app.go:834-866— kein Tiebreaker - Fix: Name-Vergleich als Tiebreaker bei Gleichheit
- Status: [x] FIXED
H10. State-Reihenfolge beim Sort falsch
- Source: Data Model Review #14
- Rust:
container_state.rs:316-327— Healthy=0, Unhealthy=1, Paused=2, Restarting=3, etc. - Go: iota-Reihenfolge weicht ab (Exited vor Restarting)
- Fix:
order()Methode mit Rust-Mapping - Status: [x] FIXED
H11. Search-Highlight: ganze Zeile statt Substring
- Source: Charts/Ports Review #22
- Rust: Substring-Level Highlighting
- Go:
app.go:1422-1423— ganze Zeile gelb - Fix: Nur gematchten Substring highlighten
- Status: [x] FIXED
H12. Help wird als Vollbild gerendert statt Overlay
- Source: Popups Review #11
- Rust:
mod.rs:477-480— Overlay auf Base View - Go:
app.go:1175-1177— ersetzt komplett den View - Fix: Base View rendern, dann Help darüber legen
- Status: [x] FIXED
H13. Log-Zeilen: Byte-Length statt Rune-Length für UTF-8
- Source: Main UI Review #28
- Rust:
.chars().count()für Width - Go:
app.go:1409-1414—len(line)(Bytes) - Fix:
[]rune(line)oderrunewidthverwenden - Status: [x] FIXED
H14. Bandwidth-Chart: Keine historischen Daten gerendert
- Source: Charts/Ports Review #6
- Rust:
chart_bandwidth.rs:92-109— zwei Line-Datasets (RX/TX) - Go:
app.go:1493-1508— nur Text-Labels, kein Sparkline - Fix: Sparklines für RX/TX History hinzufügen
- Status: [x] FIXED
H15. LogHeight Default: 40 statt 75
- Source: Popups Review #23
- Rust:
gui_state.rs:220— default75 - Go:
app.go:213— default40 - Fix: Default auf
75ändern - Status: [x] FIXED
MEDIUM (Verhaltensunterschiede)
M1. Binate Stats-Sammlung fehlt (keine Deduplizierung)
- Source: Docker Integration Review #2
- Rust:
docker_data/mod.rs:44-61— Binate-Enum, Spawn-Deduplizierung - Go:
app.go:1043-1081— keine Tracking, Duplikate möglich - Fix:
pendingStats map[string]boolfür In-Flight Tracking - Status: [x] FIXED
M2. Logs: Tail-500 statt inkrementell (since-Timestamp)
- Source: Docker Integration Review #9
- Rust:
docker_data/mod.rs:256-273—sinceParameter, akkumuliert - Go:
app.go:1091—Tail: "500", ersetzt jedes Mal - Status: [x] FIXED — uses
sincefor incremental fetching after initial load
M3. Per-Container Log-Speicher fehlt
- Source: Data Model Review #3
- Rust:
ContainerItem.logs— HashSet mit Dedup, per-Container Scroll - Go:
App.LogLines— einzelner globaler Slice - Status: [x] FIXED — Container.Logs/LogScroll/LogHScroll with save/restore on selection change
M4. Container-Selbstfilterung (oxker-Container verstecken) fehlt
- Source: Docker Integration Review #12, Data Model Review #9
- Rust:
docker_data/mod.rs:229-234— ENTRY_POINT Filter - Go: keine Selbstfilterung
- Status: [x] FIXED — respects Config.ShowSelf
M5. Docker Ping-Check bei Startup fehlt
- Source: Docker Integration Review #15
- Rust:
main.rs:68-88— Ping + Error mit Host-Pfad - Go:
app.go:207—docker.New()Error wird ignoriert - Status: [x] FIXED — Ping + Host in error message
M6. Filter-Mode: / beendet nicht den Modus (wird als Text eingegeben)
- Source: Input Review #14
- Rust:
input_handler:523-528—/beendet Filter-Mode - Go:
app.go:570-590—/wird als Zeichen eingefügt - Status: [x] FIXED (already implemented —
/in enter case)
M7. Search-Mode: # beendet nicht den Modus
- Source: Input Review #15
- Rust:
input_handler:409-414—#beendet Search-Mode - Go:
app.go:598-631—#wird als Zeichen eingefügt - Status: [x] FIXED (already implemented —
#in enter case)
M8. Direkte Action-Keys (s/x/r/d/p/u) existieren in Rust nicht
- Source: Input Review #17
- Rust: Actions nur über Commands-Panel mit Enter
- Go:
app.go:478-489— direkte Shortcuts - Note: Go-Erweiterung, könnte gewollt sein, aber kollidiert mit Rust-Keybindings
- Status: [x] WONTFIX — bewusste Erweiterung, Shortcuts sind nützlich
M9. Mouse-Scroll-Amount: 3 statt 1 (mit 10x Modifier)
- Source: Input Review #19
- Rust:
input_handler:828-829— Scroll by 1 oder 10 mit Ctrl - Go:
app.go:639-644— hardcoded 3 - Status: [x] FIXED (already 1)
M10. Mouse-Scroll in Inspect-Mode nicht unterstützt
- Source: Input Review #20
- Rust:
input_handler:810-818— Mouse-Scroll im Inspect - Go:
handleMousehat keinen Inspect-Check - Status: [x] FIXED (via C9)
M11. Error-Mode: andere Keys nicht blockiert
- Source: Input Review #24
- Rust:
handle_error— nur clear/quit Keys - Go: Sort-Keys, Scroll-Keys etc. funktionieren während Error
- Status: [x] FIXED (via C8)
M12. Unknown-State: falsche Commands
- Source: Main UI Review #7
- Rust:
container_state.rs:452—Unknown => [Delete]nur - Go:
app.go:1753-1754—Unknown => [start, restart, delete] - Status: [x] FIXED (via C6)
M13. Commands-Panel Scroll fehlt
- Source: Input Review #5
- Rust:
docker_controls_scrollbewegt Command-Selection - Go: Scroll im Commands-Panel ändert Container-Selection
- Status: [x] FIXED (via C7)
M14. Commands-Panel Breite: fest 14 statt 10%
- Source: Main UI Review #4
- Rust:
ui/mod.rs:419—Percentage(10) - Go:
app.go:1278—cmdW := 14 - Status: [x] FIXED — 10% mit min 12
M15. DockerConnect Error: kein Countdown, kein Auto-Exit
- Source: Popups Review #6/#17
- Rust: 5-Sekunden Countdown, Auto-Exit, Host-Anzeige
- Go: Standard-Error-Popup
- Status: [x] FIXED — 5s countdown + auto-exit + host in error message
M16. Delete-Dialog: Name nicht bold/highlighted
- Source: Popups Review #1
- Rust:
delete_confirm.rs:44-53— Name bold + highlighted - Go:
app.go:1542— einfacher String - Status: [x] FIXED
M17. Help-View: stark reduzierter Inhalt
- Source: Popups Review #12
- Rust: ~570 Zeilen, Logo, Version, Config-Pfad, Timezone, alle Keys
- Go: ~20 Zeilen, nur Basis-Keys
- Status: [x] FIXED — erweitert mit Config-Pfad, Panel-Info, vollständiger Keybinding-Liste
M18. Container-Name: führender / wird nicht entfernt
- Source: Charts/Ports Review #30
- Rust:
inspect.rs:35-38— Strip/Prefix - Go: Name direkt verwendet
- Status: [x] FIXED (already done via TrimPrefix)
M19. Inspect: Wrapping statt Truncation
- Source: Charts/Ports Review #29
- Rust:
inspect.rs:133—Wrap { trim: false } - Go:
app.go:1603— Truncation - Status: [x] FIXED
M20. Spaltenbreiten fest statt dynamisch
- Source: Main UI Review #1, Data Model Review #17
- Rust:
mod.rs:845-879— max Width pro Spalte aus Daten - Go:
app.go:1264-1273— feste Prozent-Widths - Status: [x] FIXED — dynamic widths based on container data
M21. State-Icons: andere Unicode-Zeichen
- Source: Main UI Review #24
- Rust:
✓,✖,॥,↻,!,? - Go:
✔,✖,‖,↻,!,? - Status: [x] FIXED — ✓ statt ✔
M22. Search-Navigation: Ctrl+N/P statt Down/Up
- Source: Input Review #16
- Rust: Down/Up Arrow für nächsten/vorherigen Match
- Go: Ctrl+N/Ctrl+P
- Status: [x] FIXED (already supports both Down/Up and Ctrl+N/P)
M23. Log-Search Case-Sensitivity nicht konfigurierbar
- Source: Data Model Review #19
- Rust:
config.log_search_case_sensitive - Go: immer case-insensitive
- Status: [x] FIXED — respects Config.LogSearchCaseSensitive
M24. Filter wraps around (Go), Rust stoppt an Grenzen
- Source: Data Model Review #16
- Rust:
FilterBy::next()/prev()gibt None an Grenzen - Go: Modulo-Wrapping
- Status: [x] FIXED — stoppt an Grenzen
M25. Overlay-Popups: base Parameter wird ignoriert
- Source: Popups Review #16
- Go:
overlayError(base),overlayInfo(base)— base wird nie verwendet - Status: [x] FIXED — overlay placement with transparent bg
LOW (Kosmetische/Konfigurationsunterschiede)
L1. Alle Farben hardcoded statt aus Config
- Betrifft: alle Panels, Popups, Charts, Headers
- Config
AppColorsexistiert, wird aber nie gelesen - Status: [x] FIXED — colorOr() resolver, borders/commands/state colors from config
L2. Custom Keymaps nicht implementiert
- Config
Keymapexistiert, wird aber nie verwendet - Alle Keys sind hardcoded Strings
- Status: [x] FIXED — keyMatch() checks config keymap with hardcoded fallbacks
L3. Mouse-Capture Toggle (m Key) fehlt
- Source: Input Review #1
- Status: [x] FIXED
L4. Force-Redraw Key (f) fehlt
- Source: Input Review #2
- Status: [x] FIXED — tea.ClearScreen
L5. Container-Name/Image Truncation bei 30 Zeichen
- Source: Data Model Review #18
- Status: [x] FIXED (handled by dynamic column widths M20)
L6. CpuStats Epsilon: 0.001 statt 0.01
- Source: Data Model Review #24
- Status: [x] FIXED (already 0.001)
L7. fmtRate fehlt GB/s Tier
- Source: Data Model Review #23
- Status: [x] FIXED
L8. InspectData: Name/ID nicht beim Inspizieren gespeichert
- Source: Data Model Review #21
- Status: [x] FIXED (already shown in viewInspect title)
L9. Scroll-Speed Modifier: Shift statt Ctrl
- Source: Input Review #3
- Status: [x] FIXED (already uses J/K = Shift+j/k)
L10. Horizontal-Scroll in Search-Mode fehlt
- Source: Input Review #8
- Status: [x] FIXED — left/right in search mode
L11. Header: "show help" → "exit help" Toggle fehlt
- Source: Main UI Review #19
- Status: [x] FIXED
L12. Header: ↓ rx / ↑ tx Pfeile existieren nicht in Rust
- Source: Main UI Review #20
- Status: [x] FIXED — removed arrows
L13. Charts: State-abhängige Farben fehlen
- Source: Charts/Ports Review #4/#8
- Status: [x] FIXED — dim color for non-running states
L14. Charts: Y-Achse Max-Wert fehlt
- Source: Charts/Ports Review #2
- Status: [x] FIXED — max label shown
L15. Filter-Bar: kein dediziertes UI (nur inline Text)
- Source: Charts/Ports Review #17/#18
- Status: [x] FIXED — dedicated styled filter bar
L16. Search-Bar: kein dediziertes UI (nur inline Text)
- Source: Charts/Ports Review #20/#21
- Status: [x] FIXED — dedicated styled search bar
L17. Ports: Title nicht zentriert, nicht als Border-Title
- Source: Charts/Ports Review #31
- Status: [x] FIXED — centered title
L18. Inspect: Scroll-Clamping fehlt
- Source: Charts/Ports Review #27
- Status: [x] FIXED — clampInspectScroll()
L19. "No containers" Message fehlt
- Source: Main UI Review #29
- Status: [x] FIXED
L20. Minimum Terminal-Size Handling fehlt
- Source: Main UI Review #30
- Status: [x] FIXED — 60x10 minimum with message
L21. Logs: "parsing logs" Init-State fehlt
- Source: Main UI Review #14
- Status: [x] FIXED
L22. Logs: scroll_padding fehlt
- Source: Main UI Review #15
- Status: [x] FIXED — auto-follow when at bottom
L23. Logs: color_logs Toggle fehlt
- Source: Main UI Review #16
- Status: [x] FIXED — stripAnsi when ColorLogs=false
L24. appendMax Slice-Leak (kein Ring-Buffer)
- Source: Data Model Review #22
- Status: [x] FIXED — in-place copy instead of reslice
L25. Delete-Dialog: Container-Not-Found Guard fehlt
- Source: Popups Review #2
- Status: [x] FIXED — guard + default name
L26. Network: alle Interfaces statt nur eth0
- Source: Docker Integration Review #3
- Note: Go-Verhalten ist besser, bewusste Abweichung
- Status: [x] WONTFIX — bewusste Verbesserung