reset rebuilt the model without the JEV runner, so a new or opened sheet silently lost JEV. It now carries over with the rest of the session state, and the import path no longer needs its own workaround. An import that finishes while the terminal is in the background now sends a desktop notification, like JEV answers do.
- commit
- c6482c732ba970752723623f5b2da33557144a7a
- parent
- 3ddbafc5639159388cf074e13d4d6773b40deef8
- author
- Dami <dami.etoile@gmail.com>
| M | internal/ | 10 | ++++++++++ |
| M | internal/ | 5 | ++++- |
| M | internal/ | 5 | ++--- |
| M | internal/ | 19 | +++++++++++++++++++ |
@@ -111,3 +111,13 @@ func TestJEVWithoutKeyExplains(t *testing.T) {
111111 t.Error("Ask JEV again is available without a key")112112 }113113 }114+115+// Starting a new sheet or opening a file keeps JEV on.116+func TestJEVSurvivesNewSheet(t *testing.T) {117+ m, fake := jevModel(t)118+ run(m, m.runCommand("file.new"))119+ press(t, m, `=JEV.TEST("x", "Is this on?")`, "<enter>")120+ if got := m.sheet.Value(addr("A1")); got.Kind != sheet.Bool || fake.calls != 1 {121+ t.Errorf("after File > New: A1 %+v, %d requests", got, fake.calls)122+ }123+}@@ -234,8 +234,11 @@ func (m *Model) fail(msg string) {
234234 m.errMsg = msg235235 }236236 237+// reset starts over on s, as File > New and Open do. What belongs to the238+// session rather than the sheet carries over: the window, theme, terminal239+// state and the JEV connection.237240 func (m *Model) reset(s *sheet.Sheet, filename string) {238- *m = Model{sheet: s, filename: filename, width: m.width, height: m.height, th: m.th, term: m.term, lastChart: -1}241+ *m = Model{sheet: s, filename: filename, width: m.width, height: m.height, th: m.th, term: m.term, jev: m.jev, lastChart: -1}239242 }240243 241244 func isDigits(s string) bool {@@ -312,9 +312,7 @@ func (m *Model) handleImported(msg importedMsg) tea.Cmd {
312312 m.fail(fmt.Sprintf("Couldn't import %s: %v", filepath.Base(msg.name), msg.err))313313 return nil314314 }315- jev := m.jev316315 m.reset(msg.res.Sheet, "")317- m.jev = jev318316 m.xfer.source, m.xfer.kind = msg.name, msg.res.Kind319317 what := filepath.Base(msg.name)320318 switch {@@ -327,7 +325,8 @@ func (m *Model) handleImported(msg importedMsg) tea.Cmd {
327325 if len(msg.res.Notes) > 0 {328326 m.note += "; " + strings.Join(msg.res.Notes, "; ")329327 }330- return nil328+ // A long import may finish while the terminal is in the background.329+ return m.notifyDone("Imported " + what)331330 }332331 333332 // openTablePicker asks which table of a SQLite database to import, or@@ -3,6 +3,7 @@ package ui
33 import (44 "context"55 "database/sql"6+ "fmt"67 "os"78 "path/filepath"89 "strings"@@ -292,3 +293,21 @@ func TestImportOnStart(t *testing.T) {
292293 t.Errorf("A1 %q name %q err %q", input(m, "A1"), m.displayName(), m.errMsg)293294 }294295 }296+297+// An import that finishes while the terminal is in the background says so298+// with a desktop notification.299+func TestImportNotifiesWhenBlurred(t *testing.T) {300+ m := newModel()301+ send(m, tea.BlurMsg{})302+ m.xfer.job = &importJob{id: 5, name: "big.csv", prog: fileio.NewProgress(), cancel: func() {}}303+ _, cmd := m.Update(importedMsg{id: 5, name: "big.csv", res: &fileio.Result{Sheet: sheet.New(), Rows: 3}})304+ var notified bool305+ for _, msg := range flatten(cmd) {306+ if raw, ok := msg.(tea.RawMsg); ok && strings.Contains(fmt.Sprint(raw.Msg), "012: Imported big.csv") {307+ notified = true308+ }309+ }310+ if !notified {311+ t.Error("no notification for a background import")312+ }313+}