diff --git a/go.mod b/go.mod index c7bf53a..c18e09b 100644 --- a/go.mod +++ b/go.mod @@ -8,5 +8,5 @@ require ( github.com/mattn/go-runewidth v0.0.9 github.com/natefinch/atomic v0.0.0-20200526193002-18c0533a5b09 github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 - golang.org/x/text v0.3.3 // indirect + golang.org/x/text v0.3.3 ) diff --git a/go.sum b/go.sum index 61aac6c..46f0f8b 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,4 @@ github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/a-h/gemini v0.0.14 h1:p3ZJOv4Fqu34P7P2B080B+nnBJSbEtnOwhkZQNZOpoY= -github.com/a-h/gemini v0.0.14/go.mod h1:p9wvIRDc2s3Lnbkw7CgNzDNgJHPuXDwh3dOF7w0NT8s= github.com/a-h/gemini v0.0.44 h1:mK+WFhHVoGxRtR9Z3/1Lc5wqLgkkR966Xcm41V54Rb0= github.com/a-h/gemini v0.0.44/go.mod h1:PatDaeVQiNS3FNRktd3EwcL/0Vr6D/FgSBnq/8oIJt8= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= diff --git a/main.go b/main.go index 39d736f..d31a6db 100644 --- a/main.go +++ b/main.go @@ -523,21 +523,26 @@ func handleSuccessResponse(state *State) { return } if !(mediaType == "text/gemini" || mediaType == "text/plain") { - opts := []string{"Open", "Save", "Cancel"} - if !strings.HasPrefix(mediaType, "text/") { - opts = []string{"Save", "Cancel"} - } fileName := getFileNameFromURL(state.U, mediaType) - switch NewOptions(state.Screen, fmt.Sprintf("Server returned a %q file (%v)\n\n%s", meta, fileName, state.U.String()), opts...).Focus() { - case "Save": - err := atomic.WriteFile(fileName, state.Response.Body) + tmp := path.Join(os.TempDir(), fileName) + err := atomic.WriteFile(tmp, state.Response.Body) + if err != nil { + NewOptions(state.Screen, fmt.Sprintf("Failed to save file: %v", err), "OK").Focus() + return + } + switch NewOptions(state.Screen, fmt.Sprintf("Server returned a %q file (%v)\n\n%s", meta, fileName, state.U.String()), "Open", "Keep", "Discard").Focus() { + case "Open": + browser.OpenFile(tmp) + case "Keep": + _, err = copy(tmp, fileName) if err != nil { NewOptions(state.Screen, fmt.Sprintf("Failed to save file: %v", err), "OK").Focus() + return } - return - case "Cancel": - return + case "Discard": + os.Remove(tmp) } + return } // Use the charset to load the content. var cs string @@ -562,6 +567,28 @@ func handleSuccessResponse(state *State) { return } +func copy(src, dst string) (int64, error) { + sourceFileStat, err := os.Stat(src) + if err != nil { + return 0, err + } + if !sourceFileStat.Mode().IsRegular() { + return 0, fmt.Errorf("%s is not a regular file", src) + } + source, err := os.Open(src) + if err != nil { + return 0, err + } + defer source.Close() + destination, err := os.Create(dst) + if err != nil { + return 0, err + } + defer destination.Close() + nBytes, err := io.Copy(destination, source) + return nBytes, err +} + func getFileNameFromURL(u *url.URL, mimeType string) string { fileName := path.Base(u.String()) if fileName == "." {