detached 737371e

Align CEF folder upload handling with purego-cef 0.13

commit
737371e4480b6c1b05fa203156733007abf8a69c
author
brice · · 2026-05-07 23:43 UTC
parent
eb6293e
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
4 files · +16 -18
M go.mod +1 -3
@@ -6,7 +6,7 @@ require (
66 github.com/a-h/templ v0.3.1001
77 github.com/andybalholm/brotli v1.2.1
88 github.com/bnema/purego v0.11.0-bnema.2
9- github.com/bnema/purego-cef v0.12.0
9+ github.com/bnema/purego-cef v0.13.0
1010 github.com/bnema/purego-cef2gtk v0.1.0
1111 github.com/bnema/purego-pipewire v0.1.2
1212 github.com/bnema/purego-sqlite v0.1.2
@@ -80,5 +80,3 @@ require (
8080 )
8181
8282 tool github.com/a-h/templ/cmd/templ
83-
84-replace github.com/bnema/purego-cef => ../purego-cef
@@ -6,7 +6,7 @@ require (
6 github.com/a-h/templ v0.3.10016 github.com/a-h/templ v0.3.1001
7 github.com/andybalholm/brotli v1.2.17 github.com/andybalholm/brotli v1.2.1
8 github.com/bnema/purego v0.11.0-bnema.28 github.com/bnema/purego v0.11.0-bnema.2
9- github.com/bnema/purego-cef v0.12.09+ github.com/bnema/purego-cef v0.13.0
10 github.com/bnema/purego-cef2gtk v0.1.010 github.com/bnema/purego-cef2gtk v0.1.0
11 github.com/bnema/purego-pipewire v0.1.211 github.com/bnema/purego-pipewire v0.1.2
12 github.com/bnema/purego-sqlite v0.1.212 github.com/bnema/purego-sqlite v0.1.2
@@ -80,5 +80,3 @@ require (
80 )80 )
81 81
82 tool github.com/a-h/templ/cmd/templ82 tool github.com/a-h/templ/cmd/templ
83-
84-replace github.com/bnema/purego-cef => ../purego-cef
M go.sum +2 -2 generated file: collapsed
M internal/infrastructure/cef/file_dialog.go +9 -9
@@ -29,7 +29,7 @@ type cefFileDialogRequest struct {
2929
3030 type fileDialogPresenter func(*WebView, cefFileDialogRequest, purecef.FileDialogCallback)
3131
32-const maxFolderUploadExperimentFiles = 5000
32+const maxExpandedFolderUploadFiles = 5000
3333
3434 var (
3535 decodeCEFStringList = purecef.StringListToSlice
@@ -118,7 +118,7 @@ func presentGTKFileDialog(wv *WebView, req cefFileDialogRequest, callback purece
118118 Int("path_count", len(paths)).
119119 Strs("paths", paths).
120120 Msg("cef: file dialog selection captured")
121- paths = folderUploadExperimentPaths(wv, req.Mode, paths)
121+ paths = folderUploadPaths(wv, req.Mode, paths)
122122 dispatchFileDialogResult(wv, callback, paths)
123123 }
124124 dialog.ConnectResponse(&onResponse)
@@ -343,7 +343,7 @@ func selectedFileDialogPaths(dialog *gtk.FileChooserNative, mode purecef.FileDia
343343 return nil
344344 }
345345
346-func folderUploadExperimentPaths(wv *WebView, mode purecef.FileDialogMode, paths []string) []string {
346+func folderUploadPaths(wv *WebView, mode purecef.FileDialogMode, paths []string) []string {
347347 if mode != purecef.FileDialogModeFileDialogOpenFolder || len(paths) != 1 {
348348 return paths
349349 }
@@ -353,7 +353,7 @@ func folderUploadExperimentPaths(wv *WebView, mode purecef.FileDialogMode, paths
353353 }
354354 info, err := os.Stat(folder)
355355 if err != nil || !info.IsDir() {
356- logCEFFileDialog(wv).Warn().Err(err).Str("path", folder).Msg("cef: folder mode experiment skipped; selected path is not a directory")
356+ logCEFFileDialog(wv).Warn().Err(err).Str("path", folder).Msg("cef: folder upload path expansion skipped; selected path is not a directory")
357357 return paths
358358 }
359359
@@ -361,7 +361,7 @@ func folderUploadExperimentPaths(wv *WebView, mode purecef.FileDialogMode, paths
361361 truncated := false
362362 walkErr := filepath.WalkDir(folder, func(path string, entry fs.DirEntry, err error) error {
363363 if err != nil {
364- logCEFFileDialog(wv).Debug().Err(err).Str("path", path).Msg("cef: folder mode experiment skipped unreadable entry")
364+ logCEFFileDialog(wv).Debug().Err(err).Str("path", path).Msg("cef: folder upload path expansion skipped unreadable entry")
365365 return nil
366366 }
367367 if path == folder || entry.IsDir() || entry.Type()&os.ModeSymlink != 0 {
@@ -372,18 +372,18 @@ func folderUploadExperimentPaths(wv *WebView, mode purecef.FileDialogMode, paths
372372 return nil
373373 }
374374 files = append(files, path)
375- if len(files) >= maxFolderUploadExperimentFiles {
375+ if len(files) >= maxExpandedFolderUploadFiles {
376376 truncated = true
377377 return filepath.SkipAll
378378 }
379379 return nil
380380 })
381381 if walkErr != nil {
382- logCEFFileDialog(wv).Warn().Err(walkErr).Str("folder", folder).Msg("cef: folder mode experiment failed to enumerate selected folder")
382+ logCEFFileDialog(wv).Warn().Err(walkErr).Str("folder", folder).Msg("cef: folder upload descendant enumeration failed; using selected directory path")
383383 return paths
384384 }
385385 if len(files) == 0 {
386- logCEFFileDialog(wv).Warn().Str("folder", folder).Msg("cef: folder mode experiment found no descendant files; using selected directory path")
386+ logCEFFileDialog(wv).Warn().Str("folder", folder).Msg("cef: folder upload descendant enumeration found no regular files; using selected directory path")
387387 return paths
388388 }
389389
@@ -391,7 +391,7 @@ func folderUploadExperimentPaths(wv *WebView, mode purecef.FileDialogMode, paths
391391 Str("folder", folder).
392392 Int("file_count", len(files)).
393393 Bool("truncated", truncated).
394- Msg("cef: folder mode experiment passing descendant file paths instead of selected directory")
394+ Msg("cef: folder upload expanded selected directory to descendant file paths")
395395 return files
396396 }
397397
@@ -29,7 +29,7 @@ type cefFileDialogRequest struct {
29 29
30 type fileDialogPresenter func(*WebView, cefFileDialogRequest, purecef.FileDialogCallback)30 type fileDialogPresenter func(*WebView, cefFileDialogRequest, purecef.FileDialogCallback)
31 31
32-const maxFolderUploadExperimentFiles = 500032+const maxExpandedFolderUploadFiles = 5000
33 33
34 var (34 var (
35 decodeCEFStringList = purecef.StringListToSlice35 decodeCEFStringList = purecef.StringListToSlice
@@ -118,7 +118,7 @@ func presentGTKFileDialog(wv *WebView, req cefFileDialogRequest, callback purece
118 Int("path_count", len(paths)).118 Int("path_count", len(paths)).
119 Strs("paths", paths).119 Strs("paths", paths).
120 Msg("cef: file dialog selection captured")120 Msg("cef: file dialog selection captured")
121- paths = folderUploadExperimentPaths(wv, req.Mode, paths)121+ paths = folderUploadPaths(wv, req.Mode, paths)
122 dispatchFileDialogResult(wv, callback, paths)122 dispatchFileDialogResult(wv, callback, paths)
123 }123 }
124 dialog.ConnectResponse(&onResponse)124 dialog.ConnectResponse(&onResponse)
@@ -343,7 +343,7 @@ func selectedFileDialogPaths(dialog *gtk.FileChooserNative, mode purecef.FileDia
343 return nil343 return nil
344 }344 }
345 345
346-func folderUploadExperimentPaths(wv *WebView, mode purecef.FileDialogMode, paths []string) []string {346+func folderUploadPaths(wv *WebView, mode purecef.FileDialogMode, paths []string) []string {
347 if mode != purecef.FileDialogModeFileDialogOpenFolder || len(paths) != 1 {347 if mode != purecef.FileDialogModeFileDialogOpenFolder || len(paths) != 1 {
348 return paths348 return paths
349 }349 }
@@ -353,7 +353,7 @@ func folderUploadExperimentPaths(wv *WebView, mode purecef.FileDialogMode, paths
353 }353 }
354 info, err := os.Stat(folder)354 info, err := os.Stat(folder)
355 if err != nil || !info.IsDir() {355 if err != nil || !info.IsDir() {
356- logCEFFileDialog(wv).Warn().Err(err).Str("path", folder).Msg("cef: folder mode experiment skipped; selected path is not a directory")356+ logCEFFileDialog(wv).Warn().Err(err).Str("path", folder).Msg("cef: folder upload path expansion skipped; selected path is not a directory")
357 return paths357 return paths
358 }358 }
359 359
@@ -361,7 +361,7 @@ func folderUploadExperimentPaths(wv *WebView, mode purecef.FileDialogMode, paths
361 truncated := false361 truncated := false
362 walkErr := filepath.WalkDir(folder, func(path string, entry fs.DirEntry, err error) error {362 walkErr := filepath.WalkDir(folder, func(path string, entry fs.DirEntry, err error) error {
363 if err != nil {363 if err != nil {
364- logCEFFileDialog(wv).Debug().Err(err).Str("path", path).Msg("cef: folder mode experiment skipped unreadable entry")364+ logCEFFileDialog(wv).Debug().Err(err).Str("path", path).Msg("cef: folder upload path expansion skipped unreadable entry")
365 return nil365 return nil
366 }366 }
367 if path == folder || entry.IsDir() || entry.Type()&os.ModeSymlink != 0 {367 if path == folder || entry.IsDir() || entry.Type()&os.ModeSymlink != 0 {
@@ -372,18 +372,18 @@ func folderUploadExperimentPaths(wv *WebView, mode purecef.FileDialogMode, paths
372 return nil372 return nil
373 }373 }
374 files = append(files, path)374 files = append(files, path)
375- if len(files) >= maxFolderUploadExperimentFiles {375+ if len(files) >= maxExpandedFolderUploadFiles {
376 truncated = true376 truncated = true
377 return filepath.SkipAll377 return filepath.SkipAll
378 }378 }
379 return nil379 return nil
380 })380 })
381 if walkErr != nil {381 if walkErr != nil {
382- logCEFFileDialog(wv).Warn().Err(walkErr).Str("folder", folder).Msg("cef: folder mode experiment failed to enumerate selected folder")382+ logCEFFileDialog(wv).Warn().Err(walkErr).Str("folder", folder).Msg("cef: folder upload descendant enumeration failed; using selected directory path")
383 return paths383 return paths
384 }384 }
385 if len(files) == 0 {385 if len(files) == 0 {
386- logCEFFileDialog(wv).Warn().Str("folder", folder).Msg("cef: folder mode experiment found no descendant files; using selected directory path")386+ logCEFFileDialog(wv).Warn().Str("folder", folder).Msg("cef: folder upload descendant enumeration found no regular files; using selected directory path")
387 return paths387 return paths
388 }388 }
389 389
@@ -391,7 +391,7 @@ func folderUploadExperimentPaths(wv *WebView, mode purecef.FileDialogMode, paths
391 Str("folder", folder).391 Str("folder", folder).
392 Int("file_count", len(files)).392 Int("file_count", len(files)).
393 Bool("truncated", truncated).393 Bool("truncated", truncated).
394- Msg("cef: folder mode experiment passing descendant file paths instead of selected directory")394+ Msg("cef: folder upload expanded selected directory to descendant file paths")
395 return files395 return files
396 }396 }
397 397
M internal/infrastructure/cef/file_dialog_test.go +4 -4
@@ -81,7 +81,7 @@ func TestOnFileDialogDelegatesDecodedRequestToPresenter(t *testing.T) {
8181 require.Equal(t, []string{"Image Files", "Text Files"}, gotReq.AcceptDescriptions)
8282 }
8383
84-func TestFolderUploadExperimentPathsExpandsDirectoryFiles(t *testing.T) {
84+func TestFolderUploadPathsExpandsDirectoryFiles(t *testing.T) {
8585 dir := t.TempDir()
8686 first := filepath.Join(dir, "first.txt")
8787 second := filepath.Join(dir, "nested", "second.txt")
@@ -89,15 +89,15 @@ func TestFolderUploadExperimentPathsExpandsDirectoryFiles(t *testing.T) {
8989 require.NoError(t, os.WriteFile(first, []byte("first"), 0o644))
9090 require.NoError(t, os.WriteFile(second, []byte("second"), 0o644))
9191
92- got := folderUploadExperimentPaths(&WebView{ctx: context.Background()}, purecef.FileDialogModeFileDialogOpenFolder, []string{dir})
92+ got := folderUploadPaths(&WebView{ctx: context.Background()}, purecef.FileDialogModeFileDialogOpenFolder, []string{dir})
9393
9494 require.ElementsMatch(t, []string{first, second}, got)
9595 }
9696
97-func TestFolderUploadExperimentPathsKeepsEmptyDirectoryPath(t *testing.T) {
97+func TestFolderUploadPathsKeepsEmptyDirectoryPath(t *testing.T) {
9898 dir := t.TempDir()
9999
100- got := folderUploadExperimentPaths(&WebView{ctx: context.Background()}, purecef.FileDialogModeFileDialogOpenFolder, []string{dir})
100+ got := folderUploadPaths(&WebView{ctx: context.Background()}, purecef.FileDialogModeFileDialogOpenFolder, []string{dir})
101101
102102 require.Equal(t, []string{dir}, got)
103103 }
@@ -81,7 +81,7 @@ func TestOnFileDialogDelegatesDecodedRequestToPresenter(t *testing.T) {
81 require.Equal(t, []string{"Image Files", "Text Files"}, gotReq.AcceptDescriptions)81 require.Equal(t, []string{"Image Files", "Text Files"}, gotReq.AcceptDescriptions)
82 }82 }
83 83
84-func TestFolderUploadExperimentPathsExpandsDirectoryFiles(t *testing.T) {84+func TestFolderUploadPathsExpandsDirectoryFiles(t *testing.T) {
85 dir := t.TempDir()85 dir := t.TempDir()
86 first := filepath.Join(dir, "first.txt")86 first := filepath.Join(dir, "first.txt")
87 second := filepath.Join(dir, "nested", "second.txt")87 second := filepath.Join(dir, "nested", "second.txt")
@@ -89,15 +89,15 @@ func TestFolderUploadExperimentPathsExpandsDirectoryFiles(t *testing.T) {
89 require.NoError(t, os.WriteFile(first, []byte("first"), 0o644))89 require.NoError(t, os.WriteFile(first, []byte("first"), 0o644))
90 require.NoError(t, os.WriteFile(second, []byte("second"), 0o644))90 require.NoError(t, os.WriteFile(second, []byte("second"), 0o644))
91 91
92- got := folderUploadExperimentPaths(&WebView{ctx: context.Background()}, purecef.FileDialogModeFileDialogOpenFolder, []string{dir})92+ got := folderUploadPaths(&WebView{ctx: context.Background()}, purecef.FileDialogModeFileDialogOpenFolder, []string{dir})
93 93
94 require.ElementsMatch(t, []string{first, second}, got)94 require.ElementsMatch(t, []string{first, second}, got)
95 }95 }
96 96
97-func TestFolderUploadExperimentPathsKeepsEmptyDirectoryPath(t *testing.T) {97+func TestFolderUploadPathsKeepsEmptyDirectoryPath(t *testing.T) {
98 dir := t.TempDir()98 dir := t.TempDir()
99 99
100- got := folderUploadExperimentPaths(&WebView{ctx: context.Background()}, purecef.FileDialogModeFileDialogOpenFolder, []string{dir})100+ got := folderUploadPaths(&WebView{ctx: context.Background()}, purecef.FileDialogModeFileDialogOpenFolder, []string{dir})
101 101
102 require.Equal(t, []string{dir}, got)102 require.Equal(t, []string{dir}, got)
103 }103 }

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