feat: refactor screenshot capture implementation and update UI reload labels
This commit is contained in:
@@ -8,32 +8,18 @@ import (
|
|||||||
"image/png"
|
"image/png"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/kbinani/screenshot"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
user32 = syscall.NewLazyDLL("user32.dll")
|
user32 = syscall.NewLazyDLL("user32.dll")
|
||||||
gdi32 = syscall.NewLazyDLL("gdi32.dll")
|
|
||||||
dwmapi = syscall.NewLazyDLL("dwmapi.dll")
|
dwmapi = syscall.NewLazyDLL("dwmapi.dll")
|
||||||
|
|
||||||
// user32 functions
|
// user32 functions
|
||||||
getForegroundWindow = user32.NewProc("GetForegroundWindow")
|
getForegroundWindow = user32.NewProc("GetForegroundWindow")
|
||||||
getWindowRect = user32.NewProc("GetWindowRect")
|
getWindowRect = user32.NewProc("GetWindowRect")
|
||||||
getClientRect = user32.NewProc("GetClientRect")
|
|
||||||
getDC = user32.NewProc("GetDC")
|
|
||||||
releaseDC = user32.NewProc("ReleaseDC")
|
|
||||||
findWindowW = user32.NewProc("FindWindowW")
|
findWindowW = user32.NewProc("FindWindowW")
|
||||||
getWindowDC = user32.NewProc("GetWindowDC")
|
|
||||||
printWindow = user32.NewProc("PrintWindow")
|
|
||||||
clientToScreen = user32.NewProc("ClientToScreen")
|
|
||||||
|
|
||||||
// gdi32 functions
|
|
||||||
createCompatibleDC = gdi32.NewProc("CreateCompatibleDC")
|
|
||||||
createCompatibleBitmap = gdi32.NewProc("CreateCompatibleBitmap")
|
|
||||||
selectObject = gdi32.NewProc("SelectObject")
|
|
||||||
bitBlt = gdi32.NewProc("BitBlt")
|
|
||||||
deleteDC = gdi32.NewProc("DeleteDC")
|
|
||||||
deleteObject = gdi32.NewProc("DeleteObject")
|
|
||||||
getDIBits = gdi32.NewProc("GetDIBits")
|
|
||||||
|
|
||||||
// dwmapi functions
|
// dwmapi functions
|
||||||
dwmGetWindowAttribute = dwmapi.NewProc("DwmGetWindowAttribute")
|
dwmGetWindowAttribute = dwmapi.NewProc("DwmGetWindowAttribute")
|
||||||
@@ -47,39 +33,7 @@ type RECT struct {
|
|||||||
Bottom int32
|
Bottom int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// POINT structure for Windows API
|
|
||||||
type POINT struct {
|
|
||||||
X int32
|
|
||||||
Y int32
|
|
||||||
}
|
|
||||||
|
|
||||||
// BITMAPINFOHEADER structure
|
|
||||||
type BITMAPINFOHEADER struct {
|
|
||||||
BiSize uint32
|
|
||||||
BiWidth int32
|
|
||||||
BiHeight int32
|
|
||||||
BiPlanes uint16
|
|
||||||
BiBitCount uint16
|
|
||||||
BiCompression uint32
|
|
||||||
BiSizeImage uint32
|
|
||||||
BiXPelsPerMeter int32
|
|
||||||
BiYPelsPerMeter int32
|
|
||||||
BiClrUsed uint32
|
|
||||||
BiClrImportant uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// BITMAPINFO structure
|
|
||||||
type BITMAPINFO struct {
|
|
||||||
BmiHeader BITMAPINFOHEADER
|
|
||||||
BmiColors [1]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SRCCOPY = 0x00CC0020
|
|
||||||
DIB_RGB_COLORS = 0
|
|
||||||
BI_RGB = 0
|
|
||||||
PW_CLIENTONLY = 1
|
|
||||||
PW_RENDERFULLCONTENT = 2
|
|
||||||
DWMWA_EXTENDED_FRAME_BOUNDS = 9
|
DWMWA_EXTENDED_FRAME_BOUNDS = 9
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -113,82 +67,10 @@ func CaptureWindowByHandle(hwnd uintptr) (*image.RGBA, error) {
|
|||||||
return nil, fmt.Errorf("invalid window dimensions: %dx%d", width, height)
|
return nil, fmt.Errorf("invalid window dimensions: %dx%d", width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get window DC
|
// Using kbinani/screenshot to capture the rectangle on screen
|
||||||
hdcWindow, _, err := getWindowDC.Call(hwnd)
|
img, err := screenshot.CaptureRect(image.Rect(int(rect.Left), int(rect.Top), int(rect.Right), int(rect.Bottom)))
|
||||||
if hdcWindow == 0 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("GetWindowDC failed: %v", err)
|
return nil, fmt.Errorf("screenshot.CaptureRect failed: %v", err)
|
||||||
}
|
|
||||||
defer releaseDC.Call(hwnd, hdcWindow)
|
|
||||||
|
|
||||||
// Create compatible DC
|
|
||||||
hdcMem, _, err := createCompatibleDC.Call(hdcWindow)
|
|
||||||
if hdcMem == 0 {
|
|
||||||
return nil, fmt.Errorf("CreateCompatibleDC failed: %v", err)
|
|
||||||
}
|
|
||||||
defer deleteDC.Call(hdcMem)
|
|
||||||
|
|
||||||
// Create compatible bitmap
|
|
||||||
hBitmap, _, err := createCompatibleBitmap.Call(hdcWindow, uintptr(width), uintptr(height))
|
|
||||||
if hBitmap == 0 {
|
|
||||||
return nil, fmt.Errorf("CreateCompatibleBitmap failed: %v", err)
|
|
||||||
}
|
|
||||||
defer deleteObject.Call(hBitmap)
|
|
||||||
|
|
||||||
// Select bitmap into DC
|
|
||||||
oldBitmap, _, _ := selectObject.Call(hdcMem, hBitmap)
|
|
||||||
defer selectObject.Call(hdcMem, oldBitmap)
|
|
||||||
|
|
||||||
// Try PrintWindow first (works better with layered/composited windows)
|
|
||||||
ret, _, _ = printWindow.Call(hwnd, hdcMem, PW_RENDERFULLCONTENT)
|
|
||||||
if ret == 0 {
|
|
||||||
// Fallback to BitBlt
|
|
||||||
ret, _, err = bitBlt.Call(
|
|
||||||
hdcMem, 0, 0, uintptr(width), uintptr(height),
|
|
||||||
hdcWindow, 0, 0,
|
|
||||||
SRCCOPY,
|
|
||||||
)
|
|
||||||
if ret == 0 {
|
|
||||||
return nil, fmt.Errorf("BitBlt failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare BITMAPINFO
|
|
||||||
bmi := BITMAPINFO{
|
|
||||||
BmiHeader: BITMAPINFOHEADER{
|
|
||||||
BiSize: uint32(unsafe.Sizeof(BITMAPINFOHEADER{})),
|
|
||||||
BiWidth: int32(width),
|
|
||||||
BiHeight: -int32(height), // Negative for top-down DIB
|
|
||||||
BiPlanes: 1,
|
|
||||||
BiBitCount: 32,
|
|
||||||
BiCompression: BI_RGB,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate buffer for pixel data
|
|
||||||
pixelDataSize := width * height * 4
|
|
||||||
pixelData := make([]byte, pixelDataSize)
|
|
||||||
|
|
||||||
// Get the bitmap bits
|
|
||||||
ret, _, err = getDIBits.Call(
|
|
||||||
hdcMem,
|
|
||||||
hBitmap,
|
|
||||||
0,
|
|
||||||
uintptr(height),
|
|
||||||
uintptr(unsafe.Pointer(&pixelData[0])),
|
|
||||||
uintptr(unsafe.Pointer(&bmi)),
|
|
||||||
DIB_RGB_COLORS,
|
|
||||||
)
|
|
||||||
if ret == 0 {
|
|
||||||
return nil, fmt.Errorf("GetDIBits failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert BGRA to RGBA
|
|
||||||
img := image.NewRGBA(image.Rect(0, 0, width, height))
|
|
||||||
for i := 0; i < len(pixelData); i += 4 {
|
|
||||||
img.Pix[i+0] = pixelData[i+2] // R <- B
|
|
||||||
img.Pix[i+1] = pixelData[i+1] // G <- G
|
|
||||||
img.Pix[i+2] = pixelData[i+0] // B <- R
|
|
||||||
img.Pix[i+3] = pixelData[i+3] // A <- A
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return img, nil
|
return img, nil
|
||||||
|
|||||||
@@ -43,7 +43,8 @@
|
|||||||
"settings_danger_reset_button": "Reset data",
|
"settings_danger_reset_button": "Reset data",
|
||||||
"settings_danger_reload_ui_label": "Reload UI",
|
"settings_danger_reload_ui_label": "Reload UI",
|
||||||
"settings_danger_reload_app_label": "Reload App",
|
"settings_danger_reload_app_label": "Reload App",
|
||||||
"settings_danger_reload_hint": "Reloads the application interface. Useful if the UI becomes unresponsive.",
|
"settings_danger_reload_all_label": "Reload UI/App",
|
||||||
|
"settings_danger_reload_hint": "Reloads the application interface. Useful if it becomes unresponsive.",
|
||||||
"settings_danger_reload_button_ui": "Reload UI",
|
"settings_danger_reload_button_ui": "Reload UI",
|
||||||
"settings_danger_reload_button_app": "Reload app",
|
"settings_danger_reload_button_app": "Reload app",
|
||||||
"settings_danger_reset_dialog_title": "Are you absolutely sure?",
|
"settings_danger_reset_dialog_title": "Are you absolutely sure?",
|
||||||
|
|||||||
@@ -42,8 +42,9 @@
|
|||||||
"settings_danger_reset_hint": "Questo cancellerà tutte le tue impostazioni e riporterà l'app allo stato predefinito.",
|
"settings_danger_reset_hint": "Questo cancellerà tutte le tue impostazioni e riporterà l'app allo stato predefinito.",
|
||||||
"settings_danger_reset_button": "Reimposta dati",
|
"settings_danger_reset_button": "Reimposta dati",
|
||||||
"settings_danger_reload_ui_label": "Ricarica UI",
|
"settings_danger_reload_ui_label": "Ricarica UI",
|
||||||
"settings_danger_reload__app_label": "Ricarica App",
|
"settings_danger_reload_app_label": "Ricarica App",
|
||||||
"settings_danger_reload_hint": "Ricarica l'interfaccia dell'applicazione. Utile se l'UI non risponde.",
|
"settings_danger_reload_all_label": "Ricarica UI/App",
|
||||||
|
"settings_danger_reload_hint": "Ricarica l'interfaccia dell'applicazione. Utile se non risponde.",
|
||||||
"settings_danger_reload_button_ui": "Ricarica UI",
|
"settings_danger_reload_button_ui": "Ricarica UI",
|
||||||
"settings_danger_reload_button_app": "Ricarica app",
|
"settings_danger_reload_button_app": "Ricarica app",
|
||||||
"settings_danger_reset_dialog_title": "Sei assolutamente sicuro?",
|
"settings_danger_reset_dialog_title": "Sei assolutamente sicuro?",
|
||||||
|
|||||||
@@ -195,10 +195,14 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Sync update checker setting to backend config.ini
|
// Sync update checker setting to backend config.ini
|
||||||
let previousUpdateCheckerEnabled = form.enableUpdateChecker;
|
let previousUpdateCheckerEnabled = $state<boolean | undefined>(undefined);
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
if (!browser) return;
|
if (!browser) return;
|
||||||
|
if (previousUpdateCheckerEnabled === undefined) {
|
||||||
|
previousUpdateCheckerEnabled = form.enableUpdateChecker;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (form.enableUpdateChecker !== previousUpdateCheckerEnabled) {
|
if (form.enableUpdateChecker !== previousUpdateCheckerEnabled) {
|
||||||
try {
|
try {
|
||||||
await SetUpdateCheckerEnabled(form.enableUpdateChecker ?? true);
|
await SetUpdateCheckerEnabled(form.enableUpdateChecker ?? true);
|
||||||
@@ -354,7 +358,7 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="min-h-[calc(100vh-1rem)] bg-gradient-to-b from-background to-muted/30">
|
<div class="min-h-[calc(100vh-1rem)] bg-linear-to-b from-background to-muted/30">
|
||||||
<div
|
<div
|
||||||
class="mx-auto flex max-w-3xl flex-col gap-4 px-4 py-6 sm:px-6 sm:py-10 opacity-80"
|
class="mx-auto flex max-w-3xl flex-col gap-4 px-4 py-6 sm:px-6 sm:py-10 opacity-80"
|
||||||
>
|
>
|
||||||
@@ -868,12 +872,13 @@
|
|||||||
class="flex items-center justify-between gap-4 rounded-lg border border-destructive/30 bg-card p-4"
|
class="flex items-center justify-between gap-4 rounded-lg border border-destructive/30 bg-card p-4"
|
||||||
>
|
>
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
<Label class="text-sm">{m.settings_danger_reload_ui_label()}</Label>
|
<Label class="text-sm">{m.settings_danger_reload_all_label()}</Label>
|
||||||
<div class="text-sm text-muted-foreground">
|
<div class="text-sm text-muted-foreground">
|
||||||
{m.settings_danger_reload_hint()}
|
{m.settings_danger_reload_hint()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
<a
|
<a
|
||||||
data-sveltekit-reload
|
data-sveltekit-reload
|
||||||
href="/"
|
href="/"
|
||||||
@@ -882,18 +887,6 @@
|
|||||||
>
|
>
|
||||||
{m.settings_danger_reload_button_ui()}
|
{m.settings_danger_reload_button_ui()}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="flex items-center justify-between gap-4 rounded-lg border border-destructive/30 bg-card p-4"
|
|
||||||
>
|
|
||||||
<div class="space-y-1">
|
|
||||||
<Label class="text-sm">{m.settings_danger_reload_app_label()}</Label>
|
|
||||||
<div class="text-sm text-muted-foreground">
|
|
||||||
{m.settings_danger_reload_hint()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
class={`${buttonVariants({ variant: "destructive" })} cursor-pointer hover:cursor-pointer`}
|
class={`${buttonVariants({ variant: "destructive" })} cursor-pointer hover:cursor-pointer`}
|
||||||
onclick={restartEntireApp}
|
onclick={restartEntireApp}
|
||||||
@@ -902,6 +895,7 @@
|
|||||||
{m.settings_danger_reload_button_app()}
|
{m.settings_danger_reload_button_app()}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
|
|||||||
4
go.mod
4
go.mod
@@ -4,6 +4,7 @@ go 1.24.4
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/jaypipes/ghw v0.21.2
|
github.com/jaypipes/ghw v0.21.2
|
||||||
|
github.com/kbinani/screenshot v0.0.0-20250624051815-089614a94018
|
||||||
github.com/teamwork/tnef v0.0.0-20200108124832-7deabccfdb32
|
github.com/teamwork/tnef v0.0.0-20200108124832-7deabccfdb32
|
||||||
github.com/wailsapp/wails/v2 v2.11.0
|
github.com/wailsapp/wails/v2 v2.11.0
|
||||||
golang.org/x/sys v0.40.0
|
golang.org/x/sys v0.40.0
|
||||||
@@ -13,18 +14,21 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bep/debounce v1.2.1 // indirect
|
github.com/bep/debounce v1.2.1 // indirect
|
||||||
|
github.com/gen2brain/shm v0.1.0 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/gorilla/websocket v1.5.3 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
github.com/jaypipes/pcidb v1.1.1 // indirect
|
github.com/jaypipes/pcidb v1.1.1 // indirect
|
||||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
|
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
|
||||||
|
github.com/jezek/xgb v1.1.1 // indirect
|
||||||
github.com/labstack/echo/v4 v4.13.3 // indirect
|
github.com/labstack/echo/v4 v4.13.3 // indirect
|
||||||
github.com/labstack/gommon v0.4.2 // indirect
|
github.com/labstack/gommon v0.4.2 // indirect
|
||||||
github.com/leaanthony/go-ansi-parser v1.6.1 // indirect
|
github.com/leaanthony/go-ansi-parser v1.6.1 // indirect
|
||||||
github.com/leaanthony/gosod v1.0.4 // indirect
|
github.com/leaanthony/gosod v1.0.4 // indirect
|
||||||
github.com/leaanthony/slicer v1.6.0 // indirect
|
github.com/leaanthony/slicer v1.6.0 // indirect
|
||||||
github.com/leaanthony/u v1.1.1 // indirect
|
github.com/leaanthony/u v1.1.1 // indirect
|
||||||
|
github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||||
|
|||||||
9
go.sum
9
go.sum
@@ -4,6 +4,8 @@ github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3IS
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/gen2brain/shm v0.1.0 h1:MwPeg+zJQXN0RM9o+HqaSFypNoNEcNpeoGp0BTSx2YY=
|
||||||
|
github.com/gen2brain/shm v0.1.0/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
@@ -20,6 +22,10 @@ github.com/jaypipes/pcidb v1.1.1/go.mod h1:x27LT2krrUgjf875KxQXKB0Ha/YXLdZRVmw6h
|
|||||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
|
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
|
||||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
|
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
|
github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4=
|
||||||
|
github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
|
||||||
|
github.com/kbinani/screenshot v0.0.0-20250624051815-089614a94018 h1:NQYgMY188uWrS+E/7xMVpydsI48PMHcc7SfR4OxkDF4=
|
||||||
|
github.com/kbinani/screenshot v0.0.0-20250624051815-089614a94018/go.mod h1:Pmpz2BLf55auQZ67u3rvyI2vAQvNetkK/4zYUmpauZQ=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
|
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
|
||||||
@@ -36,6 +42,8 @@ github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/
|
|||||||
github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
|
github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
|
||||||
github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M=
|
github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M=
|
||||||
github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
|
github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
|
||||||
|
github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc=
|
||||||
|
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||||
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
|
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
|
||||||
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||||
@@ -95,6 +103,7 @@ golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
|||||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|||||||
Reference in New Issue
Block a user