main 5041353

doctor.go RawHistoryFolder

1package cmd
2
3import (
4	"fmt"
5
6	"github.com/spf13/cobra"
7
8	"github.com/bnema/dumber/internal/application/usecase"
9	"github.com/bnema/dumber/internal/cli/styles"
10	"github.com/bnema/dumber/internal/infrastructure/deps"
11	"github.com/bnema/dumber/internal/infrastructure/media"
12)
13
14var (
15	doctorOnlyRuntime bool
16	doctorOnlyMedia   bool
17)
18
19var doctorCmd = &cobra.Command{
20	Use:   "doctor",
21	Short: "Check runtime requirements and diagnose issues",
22	Long: `Doctor checks system prerequisites for running the GUI browser.
23
24By default it runs both:
25- Runtime checks for GTK and WebKit fallback libraries
26- Media checks (GStreamer/VA-API)
27
28Use flags to run only one category.
29
30Examples:
31  dumber doctor
32  dumber doctor --runtime
33  dumber doctor --media`,
34	RunE: runDoctor,
35}
36
37func init() {
38	rootCmd.AddCommand(doctorCmd)
39	doctorCmd.Flags().BoolVar(&doctorOnlyRuntime, "runtime", false, "Only run runtime checks for GTK and WebKit fallback libraries")
40	doctorCmd.Flags().BoolVar(&doctorOnlyMedia, "media", false, "Only run media checks (GStreamer/VA-API)")
41}
42func runDoctor(_ *cobra.Command, _ []string) error {
43	app := GetApp()
44	if app == nil {
45		return fmt.Errorf("app not initialized")
46	}
47
48	if doctorOnlyRuntime && doctorOnlyMedia {
49		return fmt.Errorf("--runtime and --media are mutually exclusive")
50	}
51
52	runRuntime := !doctorOnlyMedia
53	runMedia := !doctorOnlyRuntime
54
55	report := styles.DoctorReport{OverallOK: true}
56
57	runtimeOK := true
58	if runRuntime {
59		probe := deps.NewPkgConfigProbe()
60		runtimeUC := usecase.NewCheckRuntimeDependenciesUseCase(probe)
61		runtimeOut, err := runtimeUC.Execute(app.Ctx(), usecase.CheckRuntimeDependenciesInput{
62			Prefix: app.Config.Engine.WebKit.Prefix,
63		})
64		if err != nil {
65			return err
66		}
67
68		runtimeOK = runtimeOut.OK
69		report.Runtime = styles.DoctorRuntimeReport{
70			Prefix: runtimeOut.Prefix,
71			OK:     runtimeOut.OK,
72			Checks: make([]styles.DoctorRuntimeCheck, 0, len(runtimeOut.Checks)),
73		}
74
75		for _, c := range runtimeOut.Checks {
76			report.Runtime.Checks = append(report.Runtime.Checks, styles.DoctorRuntimeCheck{
77				Name:            c.DisplayName,
78				PkgConfigName:   c.PkgConfigName,
79				Installed:       c.Installed,
80				Version:         c.Version,
81				RequiredVersion: c.RequiredVersion,
82				OK:              c.MeetsRequirement,
83				Error:           c.Error,
84			})
85		}
86	}
87
88	mediaOK := true
89	if runMedia {
90		adapter := media.New()
91		mediaOut := usecase.NewCheckMediaUseCase(adapter).Diagnose(app.Ctx())
92
93		mediaOK = mediaOut.GStreamerAvailable
94		report.Media = &styles.DoctorMediaReport{
95			GStreamerAvailable: mediaOut.GStreamerAvailable,
96			HWAccelAvailable:   mediaOut.HWAccelAvailable,
97			AV1HWAvailable:     mediaOut.AV1HWAvailable,
98			HasVAPlugin:        mediaOut.HasVAPlugin,
99			HasVAAPIPlugin:     mediaOut.HasVAAPIPlugin,
100			HasNVCodecPlugin:   mediaOut.HasNVCodecPlugin,
101			AV1Decoders:        mediaOut.AV1Decoders,
102			H264Decoders:       mediaOut.H264Decoders,
103			H265Decoders:       mediaOut.H265Decoders,
104			VP9Decoders:        mediaOut.VP9Decoders,
105			VAAPIAvailable:     mediaOut.VAAPIAvailable,
106			VAAPIDriver:        mediaOut.VAAPIDriver,
107			VAAPIVersion:       mediaOut.VAAPIVersion,
108			Warnings:           mediaOut.Warnings,
109		}
110	}
111
112	report.OverallOK = runtimeOK && mediaOK
113
114	renderer := styles.NewDoctorRenderer(app.Theme)
115	fmt.Println(renderer.Render(report))
116
117	if runRuntime && !runtimeOK {
118		return fmt.Errorf("runtime requirements not met")
119	}
120	if runMedia && !mediaOK {
121		return fmt.Errorf("media requirements not met")
122	}
123
124	return nil
125}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close