dict @ b7ca1117b18e228b84dd62a677a0a2ca52b3c549

feat: Add async request
 1diff --git a/cmd/ui/ui.go b/cmd/ui/ui.go
 2index b5f2f2fca941082410826eb92820fcb5b44172f8..50b854328935a0a51ff79a78d5e66c0c66b60b82 100644
 3--- a/cmd/ui/ui.go
 4+++ b/cmd/ui/ui.go
 5@@ -4,6 +4,7 @@ import (
 6 	"context"
 7 	"fmt"
 8 	"log/slog"
 9+	"sync"
10 
11 	"github.com/gdamore/tcell/v2"
12 	"github.com/rivo/tview"
13@@ -47,30 +48,52 @@ 	textView := tview.NewTextView().
14 		SetDynamicColors(true).
15 		SetRegions(true)
16 
17+	app := tview.NewApplication()
18+
19+	search := ""
20+	tx := sync.Mutex{}
21+
22 	input := tview.NewInputField().
23 		SetChangedFunc(func(v string) {
24-			textView.Clear()
25+
26+			tx.Lock()
27+			defer tx.Unlock()
28+			search = v
29 
30-			words, err := db.SelectDict(ctx, v, 100)
31-			if err != nil {
32-				return
33-			}
34+			go func(v string) {
35+				words, err := db.SelectDict(ctx, v, 100)
36+				if err != nil {
37+					return
38+				}
39+
40+				tx.Lock()
41+				if search != v {
42+					tx.Unlock()
43+					return
44+				}
45+				tx.Unlock()
46+
47+				textView.Clear()
48+				lastWord := ""
49+				for _, w := range words {
50+					w.Word = tview.Escape(w.Word)
51+					w.Line = tview.Escape(w.Line)
52 
53-			lastWord := ""
54-			for _, w := range words {
55+					if lastWord == w.Word {
56+						fmt.Fprintf(textView, "%s\n", w.Line)
57+					} else if lastWord == "" {
58+						fmt.Fprintf(textView, "[::bu]%s[-:-:-]\n", w.Word)
59+						fmt.Fprintf(textView, "%s\n", w.Line)
60+					} else {
61+						fmt.Fprintf(textView, "\n[::bu]%s[-:-:-]\n", w.Word)
62+						fmt.Fprintf(textView, "%s\n", w.Line)
63+					}
64 
65-				if lastWord == w.Word {
66-					fmt.Fprintf(textView, "%s\n", w.Line)
67-				} else if lastWord == "" {
68-					fmt.Fprintf(textView, "[bold]%s[normal]\n", w.Word)
69-					fmt.Fprintf(textView, "%s\n", w.Line)
70-				} else {
71-					fmt.Fprintf(textView, "\n[bold]%s[normal]\n", w.Word)
72-					fmt.Fprintf(textView, "%s\n", w.Line)
73+					lastWord = w.Word
74 				}
75 
76-				lastWord = w.Word
77-			}
78+				app.Draw()
79+			}(v)
80 		}).
81 		SetAutocompleteFunc(func(v string) []string {
82 			if len(v) == 0 {
83@@ -98,10 +121,8 @@ 		SetRows(1, 0, 3).
84 		AddItem(input, 0, 0, 1, 3, 0, 0, false).
85 		AddItem(textView, 1, 0, 1, 3, 0, 0, false)
86 
87-	err = tview.NewApplication().
88+	return app.
89 		SetRoot(grid, true).
90 		SetFocus(input).
91 		Run()
92-
93-	return err
94 }