Compare commits

...

16 Commits

Author SHA1 Message Date
a053ffbed6 Merge pull request 'Версия 0.8.0' (#9) from develop into main
Reviewed-on: #9
2025-05-11 19:45:39 +05:00
3149ca25e1
Add version and build information to FyneApp.toml
Updated the FyneApp.toml file to include the application version (0.8.0) and build number (4). These additions help in tracking application releases and builds efficiently.
2025-05-11 19:01:36 +05:00
992762ef0a
Add gratitude view and menu item
Introduce a new "Gratitude" view with localized messages and display functionality.
2025-05-11 18:35:21 +05:00
411e6c554a
Update menu view and third-party licenses
Added new dependencies and license details to both `menu/view.go` and `LICENSE-3RD-PARTY.txt`. Updated copyright notices, hyperlinks, and license text to reflect the latest projects and comply with their licensing terms.
2025-05-11 16:25:03 +05:00
bf3340e526
Add drag-and-drop support for single file selection
Implemented functionality to handle single file drag-and-drop in the UI, including error handling for multiple files and directories. Updated localization files to support new messages related to drag-and-drop usage and errors.
2025-05-11 15:07:37 +05:00
6be10dbd75
Add FyneApp.toml configuration file
Introduce a new FyneApp.toml file to configure application metadata. This includes details like the app's icon, name, and ID, as well as migration settings. These changes prepare the app for Fyne framework integration.
2025-05-11 01:44:17 +05:00
16b32e0167
Add persistent storage for directory saving setting
Introduced `DirectoryForSaving` for managing directory paths persistently. Integrated the new setting into relevant modules, ensuring the selected directory is saved and loaded across sessions.
2025-05-11 01:29:07 +05:00
2a7d860cbf
Add missing fyne import in convertor_windows.go
The fyne package import was added to fix missing dependencies in the file.
2025-05-11 00:50:23 +05:00
cf2a0933b4
Update program link URL in menu/view.go
Updated the host and path for the program link to reflect the correct URL structure. This ensures users are directed to the proper project page.
2025-05-10 18:36:17 +05:00
fa6c929ec8
Update app version to 0.8.0
Bumped the application version from 0.7.0 to 0.8.0 in `main.go`. This prepares the app for the new release and reflects recent changes or improvements.
2025-05-10 18:35:26 +05:00
cce45ee791
Update dependencies in go.sum to latest versions
This commit removes outdated dependencies and adds updated versions of required modules in the `go.sum` file. The changes ensure the project uses the latest compatible releases, improving stability and maintaining compatibility with current updates.
2025-05-10 18:09:38 +05:00
da7d9c8035
Fix .mts duration parsing by extracting leading digits
This update addresses a parsing issue for .mts files by introducing a fallback to extract and parse only the leading digits when converting frame data to a float. A new helper function `getFirstDigits` is added to isolate and handle numeric values correctly.
2025-05-10 00:55:16 +05:00
17c570bf1d
Fixed error handling for setting default duration on failure
Previously, failures in getting the total duration resulted in queue status updates and interruptions due to errors. Now, if we could not determine the duration, we return zero. This will at least allow us to simply convert without a progress bar.
2025-05-10 00:54:15 +05:00
86886fb5d9
Replace GORM with bbolt for database operations
Migrated from GORM to bbolt for lightweight key-value storage, better aligning with project requirements. Updated repository methods to utilize bbolt's native APIs and removed dependencies associated with GORM.
2025-05-09 23:58:48 +05:00
f262d5f931
Add Linux support for downloading and setting up FFmpeg.
This commit introduces platform-specific functionality for downloading, extracting, and configuring FFmpeg on Linux systems.
2025-05-06 23:10:29 +05:00
12dc5c8ef9
Add progress tracking to unzip operation on Windows
Introduced a progress bar to display the extraction progress when unzipping files using the `unZip` function. This enhancement provides visual feedback by updating the progress as file data is unpacked, improving user experience.
2025-05-06 23:08:29 +05:00
30 changed files with 1667 additions and 1728 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
fyne-cross/* fyne-cross/*
ffmpeg/*

9
FyneApp.toml Normal file
View File

@ -0,0 +1,9 @@
[Details]
Icon = "icon.png"
Name = "GUI for FFmpeg"
ID = "net.kor-elf.projects.gui-for-ffmpeg"
Version = "0.8.0"
Build = 4
[Migrations]
fyneDo = true

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
package convertor package convertor
import ( import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
@ -24,12 +25,21 @@ type ViewContract interface {
} }
type View struct { type View struct {
app kernel.AppContract app kernel.AppContract
downloadFFmpeg *downloadFFmpeg
}
type downloadFFmpeg struct {
isDownloadFFmpeg bool
blockDownloadFFmpegContainer *fyne.Container
} }
func NewView(app kernel.AppContract) *View { func NewView(app kernel.AppContract) *View {
return &View{ return &View{
app: app, app: app,
downloadFFmpeg: &downloadFFmpeg{
blockDownloadFFmpegContainer: nil,
},
} }
} }

View File

@ -11,8 +11,10 @@ import (
encoder2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder" encoder2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/encoder"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel/encoder" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel/encoder"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
"github.com/nicksnyder/go-i18n/v2/i18n" "github.com/nicksnyder/go-i18n/v2/i18n"
"image/color" "image/color"
"os"
"path/filepath" "path/filepath"
) )
@ -40,13 +42,13 @@ type HandleConvertSetting struct {
Encoder encoder2.EncoderContract Encoder encoder2.EncoderContract
} }
func NewConversion(app kernel.AppContract, formats encoder.ConvertorFormatsContract, runConvert func(setting HandleConvertSetting)) *Conversion { func NewConversion(app kernel.AppContract, formats encoder.ConvertorFormatsContract, runConvert func(setting HandleConvertSetting), settingDirectoryForSaving setting.DirectoryForSavingContract) *Conversion {
conversionMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255}) conversionMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
conversionMessage.TextSize = 16 conversionMessage.TextSize = 16
conversionMessage.TextStyle = fyne.TextStyle{Bold: true} conversionMessage.TextStyle = fyne.TextStyle{Bold: true}
fileForConversion := newFileForConversion(app) fileForConversion := newFileForConversion(app)
directoryForSaving := newDirectoryForSaving(app) directoryForSaving := newDirectoryForSaving(app, settingDirectoryForSaving)
overwriteOutputFiles := newOverwriteOutputFiles(app) overwriteOutputFiles := newOverwriteOutputFiles(app)
selectEncoder := newSelectEncoder(app, formats) selectEncoder := newSelectEncoder(app, formats)
@ -194,6 +196,10 @@ func newFileForConversion(app kernel.AppContract) *fileForConversion {
buttonTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ buttonTitle := app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "choose", MessageID: "choose",
}) + "\n\r\n\r" + app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "or",
}) + "\n\r\n\r" + app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "dragAndDrop1File",
}) })
fileForConversion.message = canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255}) fileForConversion.message = canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
@ -224,10 +230,54 @@ func newFileForConversion(app kernel.AppContract) *fileForConversion {
fileForConversion.eventSelectFile(nil) fileForConversion.eventSelectFile(nil)
listableURI := storage.NewFileURI(filepath.Dir(r.URI().Path())) listableURI := storage.NewFileURI(filepath.Dir(r.URI().Path()))
locationURI, err = storage.ListerForURI(listableURI) locationURI, _ = storage.ListerForURI(listableURI)
}, locationURI) }, locationURI)
}) })
app.GetWindow().SetOnDropped(func(position fyne.Position, uris []fyne.URI) {
if len(uris) == 0 {
return
}
if len(uris) > 1 {
fileForConversion.message.Text = app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorDragAndDrop1File",
})
setStringErrorStyle(fileForConversion.message)
fileForConversion.eventSelectFile(errors.New(fileForConversion.message.Text))
return
}
uri := uris[0]
info, err := os.Stat(uri.Path())
if err != nil {
fileForConversion.message.Text = err.Error()
setStringErrorStyle(fileForConversion.message)
fileForConversion.eventSelectFile(err)
return
}
if info.IsDir() {
fileForConversion.message.Text = app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorIsFolder",
})
setStringErrorStyle(fileForConversion.message)
fileForConversion.eventSelectFile(errors.New(fileForConversion.message.Text))
return
}
fileForConversion.file.Path = uri.Path()
fileForConversion.file.Name = uri.Name()
fileForConversion.file.Ext = uri.Extension()
fileForConversion.message.Text = uri.Path()
setStringSuccessStyle(fileForConversion.message)
fileForConversion.eventSelectFile(nil)
listableURI := storage.NewFileURI(filepath.Dir(uri.Path()))
locationURI, _ = storage.ListerForURI(listableURI)
})
return fileForConversion return fileForConversion
} }
@ -247,7 +297,7 @@ type directoryForSaving struct {
path string path string
} }
func newDirectoryForSaving(app kernel.AppContract) *directoryForSaving { func newDirectoryForSaving(app kernel.AppContract, settingDirectoryForSaving setting.DirectoryForSavingContract) *directoryForSaving {
directoryForSaving := &directoryForSaving{ directoryForSaving := &directoryForSaving{
path: "", path: "",
} }
@ -262,6 +312,13 @@ func newDirectoryForSaving(app kernel.AppContract) *directoryForSaving {
var locationURI fyne.ListableURI var locationURI fyne.ListableURI
location, err := getDirectoryForSaving(settingDirectoryForSaving)
if err == nil {
directoryForSaving.path = location.Path()
directoryForSaving.message.Text = location.Path()
setStringSuccessStyle(directoryForSaving.message)
}
directoryForSaving.button = widget.NewButton(buttonTitle, func() { directoryForSaving.button = widget.NewButton(buttonTitle, func() {
app.GetWindow().NewFolderOpen(func(r fyne.ListableURI, err error) { app.GetWindow().NewFolderOpen(func(r fyne.ListableURI, err error) {
if err != nil { if err != nil {
@ -277,7 +334,11 @@ func newDirectoryForSaving(app kernel.AppContract) *directoryForSaving {
directoryForSaving.message.Text = r.Path() directoryForSaving.message.Text = r.Path()
setStringSuccessStyle(directoryForSaving.message) setStringSuccessStyle(directoryForSaving.message)
locationURI, _ = storage.ListerForURI(r) locationURI, err = storage.ListerForURI(r)
if err == nil {
_, _ = settingDirectoryForSaving.SaveDirectoryForSaving(locationURI.Path())
}
}, locationURI) }, locationURI)
}) })
@ -285,6 +346,24 @@ func newDirectoryForSaving(app kernel.AppContract) *directoryForSaving {
return directoryForSaving return directoryForSaving
} }
func getDirectoryForSaving(settingDirectoryForSaving setting.DirectoryForSavingContract) (fyne.ListableURI, error) {
path, err := settingDirectoryForSaving.GetDirectoryForSaving()
if err != nil {
return nil, err
}
if len(path) > 0 {
path = "file://" + path
}
uri, err := storage.ParseURI(path)
if err != nil {
return nil, err
}
return storage.ListerForURI(uri)
}
type overwriteOutputFiles struct { type overwriteOutputFiles struct {
checkbox *widget.Check checkbox *widget.Check
isChecked bool isChecked bool

View File

@ -82,9 +82,13 @@ func (v View) SelectFFPath(
MessageID: "selectFFPathTitle", MessageID: "selectFFPathTitle",
}) })
if v.downloadFFmpeg.blockDownloadFFmpegContainer == nil {
v.downloadFFmpeg.blockDownloadFFmpegContainer = v.blockDownloadFFmpeg(donwloadFFmpeg)
}
v.app.GetWindow().SetContent(widget.NewCard(selectFFPathTitle, "", container.NewVBox( v.app.GetWindow().SetContent(widget.NewCard(selectFFPathTitle, "", container.NewVBox(
form, form,
v.blockDownloadFFmpeg(donwloadFFmpeg), v.downloadFFmpeg.blockDownloadFFmpegContainer,
))) )))
} }

View File

@ -1,5 +1,5 @@
//go:build !windows //go:build !windows && !linux
// +build !windows // +build !windows,!linux
package convertor package convertor

View File

@ -0,0 +1,68 @@
//go:build linux
// +build linux
package convertor
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/image/colornames"
"image/color"
)
func (v View) blockDownloadFFmpeg(
donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error,
) *fyne.Container {
errorDownloadFFmpegMessage := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
errorDownloadFFmpegMessage.TextSize = 16
errorDownloadFFmpegMessage.TextStyle = fyne.TextStyle{Bold: true}
progressDownloadFFmpegMessage := canvas.NewText("", color.RGBA{R: 49, G: 127, B: 114, A: 255})
progressDownloadFFmpegMessage.TextSize = 16
progressDownloadFFmpegMessage.TextStyle = fyne.TextStyle{Bold: true}
progressBar := widget.NewProgressBar()
var buttonDownloadFFmpeg *widget.Button
buttonDownloadFFmpeg = widget.NewButton(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "download",
}), func() {
fyne.Do(func() {
buttonDownloadFFmpeg.Disable()
})
go func() {
err := donwloadFFmpeg(progressBar, progressDownloadFFmpegMessage)
if err != nil {
errorDownloadFFmpegMessage.Text = err.Error()
}
fyne.Do(func() {
buttonDownloadFFmpeg.Enable()
})
}()
})
downloadFFmpegFromSiteMessage := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "downloadFFmpegFromSite",
})
return container.NewVBox(
canvas.NewLine(colornames.Darkgreen),
widget.NewCard(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "buttonDownloadFFmpeg",
}), "", container.NewVBox(
widget.NewRichTextFromMarkdown(
downloadFFmpegFromSiteMessage+" [https://github.com/BtbN/FFmpeg-Builds/releases](https://github.com/BtbN/FFmpeg-Builds/releases)",
),
buttonDownloadFFmpeg,
errorDownloadFFmpegMessage,
progressDownloadFFmpegMessage,
progressBar,
)),
)
}

View File

@ -32,14 +32,19 @@ func (v View) blockDownloadFFmpeg(
buttonDownloadFFmpeg = widget.NewButton(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ buttonDownloadFFmpeg = widget.NewButton(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "download", MessageID: "download",
}), func() { }), func() {
buttonDownloadFFmpeg.Disable()
err := donwloadFFmpeg(progressBar, progressDownloadFFmpegMessage) go func() {
if err != nil { fyne.Do(func() {
errorDownloadFFmpegMessage.Text = err.Error() buttonDownloadFFmpeg.Disable()
} })
err := donwloadFFmpeg(progressBar, progressDownloadFFmpegMessage)
buttonDownloadFFmpeg.Enable() if err != nil {
errorDownloadFFmpegMessage.Text = err.Error()
}
fyne.Do(func() {
buttonDownloadFFmpeg.Enable()
})
}()
}) })
downloadFFmpegFromSiteMessage := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ downloadFFmpegFromSiteMessage := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{

7
db/db.go Normal file
View File

@ -0,0 +1,7 @@
package db
import "errors"
var (
ErrRecordNotFound = errors.New("record not found")
)

58
go.mod
View File

@ -1,44 +1,46 @@
module git.kor-elf.net/kor-elf/gui-for-ffmpeg module git.kor-elf.net/kor-elf/gui-for-ffmpeg
go 1.21 go 1.23.0
toolchain go1.23.9
require ( require (
fyne.io/fyne/v2 v2.4.3 fyne.io/fyne/v2 v2.6.1
github.com/BurntSushi/toml v1.3.2 github.com/BurntSushi/toml v1.5.0
github.com/mattn/go-sqlite3 v1.14.21 github.com/nicksnyder/go-i18n/v2 v2.6.0
github.com/nicksnyder/go-i18n/v2 v2.4.0 github.com/ulikunitz/xz v0.5.12
golang.org/x/text v0.14.0 go.etcd.io/bbolt v1.4.0
gorm.io/driver/sqlite v1.5.4 golang.org/x/image v0.27.0
gorm.io/gorm v1.25.6 golang.org/x/text v0.25.0
) )
require ( require (
fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e // indirect fyne.io/systray v1.11.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fredbi/uri v1.1.0 // indirect github.com/fredbi/uri v1.1.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe // indirect github.com/fyne-io/gl-js v0.1.0 // indirect
github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 // indirect github.com/fyne-io/glfw-js v0.2.0 // indirect
github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 // indirect github.com/fyne-io/image v0.1.1 // indirect
github.com/fyne-io/oksvg v0.1.0 // indirect
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240118000515-a250818d05e3 // indirect github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 // indirect
github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8 // indirect github.com/go-text/render v0.2.0 // indirect
github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a // indirect github.com/go-text/typesetting v0.3.0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect github.com/hack-pad/go-indexeddb v0.3.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/hack-pad/safejs v0.1.1 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jeandeaual/go-locale v0.0.0-20250421151639-a9d6ed1b3d45 // indirect
github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rymdport/portal v0.4.1 // indirect
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect
github.com/stretchr/testify v1.8.4 // indirect github.com/stretchr/testify v1.10.0 // indirect
github.com/tevino/abool v1.2.0 // indirect github.com/yuin/goldmark v1.7.11 // indirect
github.com/yuin/goldmark v1.5.5 // indirect golang.org/x/net v0.40.0 // indirect
golang.org/x/image v0.11.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sys v0.16.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect
) )

749
go.sum
View File

@ -1,697 +1,86 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= fyne.io/fyne/v2 v2.6.1 h1:kjPJD4/rBS9m2nHJp+npPSuaK79yj6ObMTuzR6VQ1Is=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= fyne.io/fyne/v2 v2.6.1/go.mod h1:YZt7SksjvrSNJCwbWFV32WON3mE1Sr7L41D29qMZ/lU=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
fyne.io/fyne/v2 v2.4.3 h1:v2wncjEAcwXZ8UNmTCWTGL9+sGyPc5RuzBvM96GcC78=
fyne.io/fyne/v2 v2.4.3/go.mod h1:1h3BKxmQYRJlr2g+RGVxedzr6vLVQ/AJmFWcF9CJnoQ=
fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e h1:Hvs+kW2VwCzNToF3FmnIAzmivNgrclwPgoUdVSrjkP8=
fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e/go.mod h1:oM2AQqGJ1AMo4nNqZFYU8xYygSBZkW2hmdJ7n4yjedE=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fredbi/uri v1.0.0 h1:s4QwUAZ8fz+mbTsukND+4V5f+mJ/wjaTokwstGUAemg=
github.com/fredbi/uri v1.0.0/go.mod h1:1xC40RnIOGCaQzswaOvrzvG/3M3F0hyDVb3aO/1iGy0=
github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8= github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8=
github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4= github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fyne-io/gl-js v0.1.0 h1:8luJzNs0ntEAJo+8x8kfUOXujUlP8gB3QMOxO2mUdpM=
github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe h1:A/wiwvQ0CAjPkuJytaD+SsXkPU0asQ+guQEIg1BJGX4= github.com/fyne-io/gl-js v0.1.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI=
github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe/go.mod h1:d4clgH0/GrRwWjRzJJQXxT/h1TyuNSfF/X64zb/3Ggg= github.com/fyne-io/glfw-js v0.2.0 h1:8GUZtN2aCoTPNqgRDxK5+kn9OURINhBEBc7M4O1KrmM=
github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 h1:+31CdF/okdokeFNoy9L/2PccG3JFidQT3ev64/r4pYU= github.com/fyne-io/glfw-js v0.2.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk=
github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504/go.mod h1:gLRWYfYnMA9TONeppRSikMdXlHQ97xVsPojddUv3b/E= github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA=
github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 h1:hnLq+55b7Zh7/2IRzWCpiTcAvjv/P8ERF+N7+xXbZhk= github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM=
github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2/go.mod h1:eO7W361vmlPOrykIg+Rsh1SZ3tQBaOsfzZhsIOb/Lm0= github.com/fyne-io/oksvg v0.1.0 h1:7EUKk3HV3Y2E+qypp3nWqMXD7mum0hCw2KEGhI1fnBw=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/fyne-io/oksvg v0.1.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI=
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 h1:zDw5v7qm4yH7N8C8uWd+8Ii9rROdgWxQuGoJ9WDXxfk=
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA= github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA=
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 h1:RkGhqHxEVAvPM0/R+8g7XRwQnHatO0KAuVcwHo8q9W8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728/go.mod h1:SyRD8YfuKk+ZXlDqYiqe1qMSqjNgtHzBTG810KUagMc=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b h1:GgabKamyOYguHqHjSkDACcgoPIz3w0Dis/zJ1wyHHHU= github.com/go-text/typesetting v0.3.0 h1:OWCgYpp8njoxSRpwrdd1bQOxdjOXDj9Rqart9ML4iF4=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-text/typesetting v0.3.0/go.mod h1:qjZLkhRgOEYMhU9eHBr3AR4sfnGJvOXNLt8yRAySFuY=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240118000515-a250818d05e3 h1:nanQfMsOs3gnuKRm0E5jXWomedE/9YIFXdmHJNZYeqc= github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC+94v2xrb1PoS4NIDe7DGYtLnU2wWiQe9a1B1c0=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240118000515-a250818d05e3/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8 h1:VkKnvzbvHqgEfm351rfr8Uclu5fnwq8HP2ximUzJsBM=
github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8/go.mod h1:h29xCucjNsDcYb7+0rJokxVwYAq+9kQ19WiFuBKkYtc=
github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a h1:VjN8ttdfklC0dnAdKbZqGNESdERUxtE3l8a/4Grgarc=
github.com/go-text/typesetting v0.0.0-20230616162802-9c17dd34aa4a/go.mod h1:evDBbvNR/KaVFZ2ZlDSOWWXIUKq0wCOEtzLxRM8SG3k=
github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22 h1:LBQTFxP2MfsyEDqSKmUBZaDuDHN1vpqDyOZjcqS7MYI=
github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/hack-pad/safejs v0.1.1 h1:d5qPO0iQ7h2oVtpzGnLExE+Wn9AtytxIfltcS2b9KD8=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/hack-pad/safejs v0.1.1/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/jeandeaual/go-locale v0.0.0-20250421151639-a9d6ed1b3d45 h1:vFdvrlsVU+p/KFBWTq0lTG4fvWvG88sawGlCzM+RUEU=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/jeandeaual/go-locale v0.0.0-20250421151639-a9d6ed1b3d45/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/nicksnyder/go-i18n/v2 v2.6.0 h1:C/m2NNWNiTB6SK4Ao8df5EWm3JETSTIGNXBpMJTxzxQ=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/nicksnyder/go-i18n/v2 v2.6.0/go.mod h1:88sRqr0C6OPyJn0/KRNaEz1uWorjxIKP7rUUcvycecE=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20211219123610-ec9572f70e60/go.mod h1:cz9oNYuRUWGdHmLF2IodMLkAhcPtXeULvcBNagUrxTI=
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
github.com/goxjs/gl v0.0.0-20210104184919-e3fafc6f8f2a/go.mod h1:dy/f2gjY09hwVfIyATps4G2ai7/hLwLkc5TrPqONuXY=
github.com/goxjs/glfw v0.0.0-20191126052801-d2efb5f20838/go.mod h1:oS8P8gVOT4ywTcjV6wZlOU4GuVFQ8F5328KY3MJ79CY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e h1:LvL4XsI70QxOGHed6yhQtAU34Kx3Qq2wwBzGFKY8zKk=
github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.21 h1:IXocQLOykluc3xPE0Lvy8FtggMz1G+U3mEjg+0zGizc=
github.com/mattn/go-sqlite3 v1.14.21/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nicksnyder/go-i18n/v2 v2.3.0 h1:2NPsCsNFCVd7i+Su0xYsBrIhS3bE2XMv5gNTft2O+PQ=
github.com/nicksnyder/go-i18n/v2 v2.3.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/rymdport/portal v0.4.1 h1:2dnZhjf5uEaeDjeF/yBIeeRo6pNI2QAKm7kq1w/kbnA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rymdport/portal v0.4.1/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE=
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
github.com/tevino/abool v1.2.0 h1:heAkClL8H6w+mK5md9dzsuohKeXHUpY7Vw0ZCKW+huA= golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
github.com/tevino/abool v1.2.0/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.5.5 h1:IJznPe8wOzfIKETmMkd06F8nXkmlhaHqFRM9l1hAGsU=
github.com/yuin/goldmark v1.5.5/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda h1:O+EUvnBNPwI4eLthn8W5K+cS8zQZfgTABPLNm6Bna34=
golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.5.4 h1:IqXwXi8M/ZlPzH/947tn5uik3aYQslP9BVveoax0nV0=
gorm.io/driver/sqlite v1.5.4/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4=
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.6 h1:V92+vVda1wEISSOMtodHVRcUIOPYa2tgQtyF+DfFx+A=
gorm.io/gorm v1.25.6/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 h1:oomkgU6VaQDsV6qZby2uz1Lap0eXmku8+2em3A/l700=
honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2/go.mod h1:sUMDUKNB2ZcVjt92UnLy3cdGs+wDAcrPdV3JP6sVgA4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@ -7,6 +7,7 @@ import (
error2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/error" error2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/error"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/helper" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/helper"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
"github.com/nicksnyder/go-i18n/v2/i18n" "github.com/nicksnyder/go-i18n/v2/i18n"
) )
@ -18,10 +19,11 @@ type ConvertorHandlerContract interface {
} }
type ConvertorHandler struct { type ConvertorHandler struct {
app kernel.AppContract app kernel.AppContract
convertorView convertor.ViewContract convertorView convertor.ViewContract
errorView error2.ViewContract errorView error2.ViewContract
convertorRepository convertor.RepositoryContract convertorRepository convertor.RepositoryContract
settingDirectoryForSaving setting.DirectoryForSavingContract
} }
func NewConvertorHandler( func NewConvertorHandler(
@ -29,12 +31,14 @@ func NewConvertorHandler(
convertorView convertor.ViewContract, convertorView convertor.ViewContract,
errorView error2.ViewContract, errorView error2.ViewContract,
convertorRepository convertor.RepositoryContract, convertorRepository convertor.RepositoryContract,
settingDirectoryForSaving setting.DirectoryForSavingContract,
) *ConvertorHandler { ) *ConvertorHandler {
return &ConvertorHandler{ return &ConvertorHandler{
app: app, app: app,
convertorView: convertorView, convertorView: convertorView,
errorView: errorView, errorView: errorView,
convertorRepository: convertorRepository, convertorRepository: convertorRepository,
settingDirectoryForSaving: settingDirectoryForSaving,
} }
} }
@ -45,7 +49,7 @@ func (h ConvertorHandler) MainConvertor() {
h.errorView.PanicError(err) h.errorView.PanicError(err)
return return
} }
conversion := view.NewConversion(h.app, formats, h.runConvert) conversion := view.NewConversion(h.app, formats, h.runConvert, h.settingDirectoryForSaving)
h.convertorView.Main(conversion) h.convertorView.Main(conversion)
return return
} }

View File

@ -1,5 +1,5 @@
//go:build !windows //go:build !windows && !linux
// +build !windows // +build !windows,!linux
package handler package handler

230
handler/convertor_linux.go Normal file
View File

@ -0,0 +1,230 @@
//go:build linux
// +build linux
package handler
import (
"archive/tar"
"errors"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"github.com/nicksnyder/go-i18n/v2/i18n"
"github.com/ulikunitz/xz"
"io"
"net/http"
"os"
"path/filepath"
)
func getPathsToFF() []kernel.FFPathUtilities {
return []kernel.FFPathUtilities{{"ffmpeg/bin/ffmpeg", "ffmpeg/bin/ffprobe"}, {"ffmpeg", "ffprobe"}}
}
func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) {
isDirectoryFFmpeg := isDirectory("ffmpeg")
if isDirectoryFFmpeg == false {
err = os.Mkdir("ffmpeg", 0777)
if err != nil {
return err
}
}
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "downloadRun",
})
fyne.Do(func() {
progressMessage.Refresh()
})
err = downloadFile("ffmpeg/ffmpeg.tar.xz", "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz", progressBar)
if err != nil {
return err
}
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "unzipRun",
})
fyne.Do(func() {
progressMessage.Refresh()
})
err = unTarXz("ffmpeg/ffmpeg.tar.xz", "ffmpeg", progressBar)
if err != nil {
return err
}
_ = os.Remove("ffmpeg/ffmpeg.tar.xz")
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "testFF",
})
fyne.Do(func() {
progressMessage.Refresh()
})
err = h.saveSettingFFPath("ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffmpeg", "ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffprobe")
if err != nil {
return err
}
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "completedQueue",
})
fyne.Do(func() {
progressMessage.Refresh()
})
return nil
}
func downloadFile(filepath string, url string, progressBar *widget.ProgressBar) (err error) {
progressBar.Value = 0
progressBar.Max = 100
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
f, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer f.Close()
buf := make([]byte, 32*1024)
var downloaded int64
for {
n, err := resp.Body.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return err
}
if n > 0 {
f.Write(buf[:n])
downloaded += int64(n)
progressBar.Value = float64(downloaded) / float64(resp.ContentLength) * 100
fyne.Do(func() {
progressBar.Refresh()
})
}
}
return nil
}
func unTarXz(fileTar string, directory string, progressBar *widget.ProgressBar) error {
progressBar.Value = 0
progressBar.Max = 100
fyne.Do(func() {
progressBar.Refresh()
})
f, err := os.Open(fileTar)
if err != nil {
return err
}
defer f.Close()
xzReader, err := xz.NewReader(f)
if err != nil {
return err
}
tarReader := tar.NewReader(xzReader)
totalFiles := 0
for {
_, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
totalFiles++
}
// Rewind back to the beginning of the file to re-process
_, err = f.Seek(0, 0)
if err != nil {
return err
}
xzReader, err = xz.NewReader(f)
if err != nil {
return err
}
tarReader = tar.NewReader(xzReader)
// We count the number of files already unpacked
unpackedFiles := 0
for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
targetPath := filepath.Join(directory, header.Name)
switch header.Typeflag {
case tar.TypeDir:
err := os.MkdirAll(targetPath, 0755)
if err != nil {
return err
}
case tar.TypeReg:
outFile, err := os.Create(targetPath)
if err != nil {
return err
}
defer outFile.Close()
_, err = io.Copy(outFile, tarReader)
if err != nil {
return err
}
default:
return errors.New("unsupported file type")
}
unpackedFiles++
progressBar.Value = float64(unpackedFiles) / float64(totalFiles) * 100
fyne.Do(func() {
progressBar.Refresh()
})
}
ffmpegPath := filepath.Join(directory, "ffmpeg-master-latest-linux64-gpl", "bin", "ffmpeg")
err = os.Chmod(ffmpegPath, 0755)
if err != nil {
return err
}
ffprobePath := filepath.Join(directory, "ffmpeg-master-latest-linux64-gpl", "bin", "ffprobe")
err = os.Chmod(ffprobePath, 0755)
if err != nil {
return err
}
return nil
}
func isDirectory(path string) bool {
fileInfo, err := os.Stat(path)
if err != nil {
return false
}
return fileInfo.IsDir()
}

View File

@ -6,6 +6,7 @@ package handler
import ( import (
"archive/zip" "archive/zip"
"errors" "errors"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
@ -32,7 +33,9 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "downloadRun", MessageID: "downloadRun",
}) })
progressMessage.Refresh() fyne.Do(func() {
progressMessage.Refresh()
})
err = downloadFile("ffmpeg/ffmpeg.zip", "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip", progressBar) err = downloadFile("ffmpeg/ffmpeg.zip", "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip", progressBar)
if err != nil { if err != nil {
return err return err
@ -41,8 +44,10 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "unzipRun", MessageID: "unzipRun",
}) })
progressMessage.Refresh() fyne.Do(func() {
err = unZip("ffmpeg/ffmpeg.zip", "ffmpeg") progressMessage.Refresh()
})
err = unZip("ffmpeg/ffmpeg.zip", "ffmpeg", progressBar)
if err != nil { if err != nil {
return err return err
} }
@ -51,12 +56,21 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "testFF", MessageID: "testFF",
}) })
progressMessage.Refresh() fyne.Do(func() {
progressMessage.Refresh()
})
err = h.saveSettingFFPath("ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffmpeg.exe", "ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffprobe.exe") err = h.saveSettingFFPath("ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffmpeg.exe", "ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffprobe.exe")
if err != nil { if err != nil {
return err return err
} }
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "completedQueue",
})
fyne.Do(func() {
progressMessage.Refresh()
})
return nil return nil
} }
@ -94,19 +108,35 @@ func downloadFile(filepath string, url string, progressBar *widget.ProgressBar)
f.Write(buf[:n]) f.Write(buf[:n])
downloaded += int64(n) downloaded += int64(n)
progressBar.Value = float64(downloaded) / float64(resp.ContentLength) * 100 progressBar.Value = float64(downloaded) / float64(resp.ContentLength) * 100
progressBar.Refresh() fyne.Do(func() {
progressBar.Refresh()
})
} }
} }
return nil return nil
} }
func unZip(fileZip string, directory string) error { func unZip(fileZip string, directory string, progressBar *widget.ProgressBar) error {
progressBar.Value = 0
progressBar.Max = 100
fyne.Do(func() {
progressBar.Refresh()
})
archive, err := zip.OpenReader(fileZip) archive, err := zip.OpenReader(fileZip)
if err != nil { if err != nil {
return err return err
} }
defer archive.Close() defer archive.Close()
totalBytes := int64(0)
for _, f := range archive.File {
totalBytes += int64(f.UncompressedSize64)
}
unpackedBytes := int64(0)
for _, f := range archive.File { for _, f := range archive.File {
filePath := filepath.Join(directory, f.Name) filePath := filepath.Join(directory, f.Name)
@ -132,10 +162,17 @@ func unZip(fileZip string, directory string) error {
return err return err
} }
if _, err := io.Copy(dstFile, fileInArchive); err != nil { bytesRead, err := io.Copy(dstFile, fileInArchive)
if err != nil {
return err return err
} }
unpackedBytes += bytesRead
progressBar.Value = float64(unpackedBytes) / float64(totalBytes) * 100
fyne.Do(func() {
progressBar.Refresh()
})
dstFile.Close() dstFile.Close()
fileInArchive.Close() fileInArchive.Close()
} }

View File

@ -86,9 +86,16 @@ func (h MenuHandler) getMenuHelp() *fyne.Menu {
about.Label = text about.Label = text
}) })
gratitude := fyne.NewMenuItem(h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "gratitude",
}), h.openGratitude)
h.app.GetLocalizerService().AddChangeCallback("gratitude", func(text string) {
gratitude.Label = text
})
help := fyne.NewMenu(h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ help := fyne.NewMenu(h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "help", MessageID: "help",
}), about) }), about, gratitude)
h.app.GetLocalizerService().AddChangeCallback("help", func(text string) { h.app.GetLocalizerService().AddChangeCallback("help", func(text string) {
help.Label = text help.Label = text
help.Refresh() help.Refresh()
@ -114,6 +121,10 @@ func (h MenuHandler) openAbout() {
h.menuView.About(ffmpeg, ffprobe) h.menuView.About(ffmpeg, ffprobe)
} }
func (h MenuHandler) openGratitude() {
h.menuView.Gratitude()
}
func (h MenuHandler) LanguageSelection() { func (h MenuHandler) LanguageSelection() {
h.localizerView.LanguageSelection(func(lang kernel.Lang) { h.localizerView.LanguageSelection(func(lang kernel.Lang) {
_, _ = h.localizerRepository.Save(lang.Code) _, _ = h.localizerRepository.Save(lang.Code)

View File

@ -84,10 +84,7 @@ func (a App) RunConvertor() {
totalDuration, err := a.convertorService.GetTotalDuration(&queue.Setting.VideoFileInput) totalDuration, err := a.convertorService.GetTotalDuration(&queue.Setting.VideoFileInput)
if err != nil { if err != nil {
queue.Status = StatusType(Error) totalDuration = 0
queue.Error = err
a.Window.GetLayout().ChangeQueueStatus(queueId, queue)
continue
} }
progress := a.Window.GetLayout().NewProgressbar(queueId, totalDuration) progress := a.Window.GetLayout().NewProgressbar(queueId, totalDuration)

View File

@ -11,6 +11,7 @@ import (
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"unicode"
) )
type File struct { type File struct {
@ -126,7 +127,13 @@ func (s Convertor) GetTotalDuration(file *File) (duration float64, err error) {
if len(frames) == 0 { if len(frames) == 0 {
return s.getAlternativeTotalDuration(file) return s.getAlternativeTotalDuration(file)
} }
return strconv.ParseFloat(frames, 64)
duration, err = strconv.ParseFloat(frames, 64)
if err != nil {
// fix .mts duration
return strconv.ParseFloat(getFirstDigits(frames), 64)
}
return duration, err
} }
func (s Convertor) getAlternativeTotalDuration(file *File) (duration float64, err error) { func (s Convertor) getAlternativeTotalDuration(file *File) (duration float64, err error) {
@ -241,3 +248,15 @@ func (s Convertor) GetSupportFormats() (encoder.ConvertorFormatsContract, error)
func (s Convertor) GetRunningProcesses() map[int]*exec.Cmd { func (s Convertor) GetRunningProcesses() map[int]*exec.Cmd {
return s.runningProcesses.items return s.runningProcesses.items
} }
func getFirstDigits(s string) string {
result := ""
for _, r := range s {
if unicode.IsDigit(r) {
result += string(r)
} else {
break
}
}
return result
}

View File

@ -118,15 +118,16 @@ func (o QueueLayoutObject) GetProgressbar(queueId int) *widget.ProgressBar {
func (o QueueLayoutObject) Add(id int, queue *Queue) { func (o QueueLayoutObject) Add(id int, queue *Queue) {
progressBar := widget.NewProgressBar() progressBar := widget.NewProgressBar()
statusMessage := canvas.NewText(o.getStatusTitle(queue.Status), theme.PrimaryColor())
messageError := canvas.NewText("", theme.ErrorColor()) statusMessage := canvas.NewText(o.getStatusTitle(queue.Status), theme.Color(theme.ColorNamePrimary))
messageError := canvas.NewText("", theme.Color(theme.ColorNameError))
content := container.NewVBox( content := container.NewVBox(
container.NewHScroll(widget.NewLabel(queue.Setting.VideoFileInput.Name)), container.NewHScroll(widget.NewLabel(queue.Setting.VideoFileInput.Name)),
progressBar, progressBar,
container.NewHScroll(statusMessage), container.NewHScroll(statusMessage),
container.NewHScroll(messageError), container.NewHScroll(messageError),
canvas.NewLine(theme.FocusColor()), canvas.NewLine(theme.Color(theme.ColorNameFocus)),
container.NewPadded(), container.NewPadded(),
) )
@ -158,11 +159,15 @@ func (o QueueLayoutObject) ChangeQueueStatus(queueId int, queue *Queue) {
statusColor := o.getStatusColor(queue.Status) statusColor := o.getStatusColor(queue.Status)
item.StatusMessage.Text = o.getStatusTitle(queue.Status) item.StatusMessage.Text = o.getStatusTitle(queue.Status)
item.StatusMessage.Color = statusColor item.StatusMessage.Color = statusColor
item.StatusMessage.Refresh() fyne.Do(func() {
item.StatusMessage.Refresh()
})
if queue.Error != nil { if queue.Error != nil {
item.MessageError.Text = queue.Error.Error() item.MessageError.Text = queue.Error.Error()
item.MessageError.Color = statusColor item.MessageError.Color = statusColor
item.MessageError.Refresh() fyne.Do(func() {
item.MessageError.Refresh()
})
} }
if o.queueStatisticsFormat.isChecked(queue.Status) == false && item.CanvasObject.Visible() == true { if o.queueStatisticsFormat.isChecked(queue.Status) == false && item.CanvasObject.Visible() == true {
item.CanvasObject.Hide() item.CanvasObject.Hide()
@ -175,14 +180,14 @@ func (o QueueLayoutObject) ChangeQueueStatus(queueId int, queue *Queue) {
func (o QueueLayoutObject) getStatusColor(status StatusContract) color.Color { func (o QueueLayoutObject) getStatusColor(status StatusContract) color.Color {
if status == StatusType(Error) { if status == StatusType(Error) {
return theme.ErrorColor() return theme.Color(theme.ColorNameError)
} }
if status == StatusType(Completed) { if status == StatusType(Completed) {
return color.RGBA{R: 49, G: 127, B: 114, A: 255} return color.RGBA{R: 49, G: 127, B: 114, A: 255}
} }
return theme.PrimaryColor() return theme.Color(theme.ColorNamePrimary)
} }
func (o QueueLayoutObject) getStatusTitle(status StatusContract) string { func (o QueueLayoutObject) getStatusTitle(status StatusContract) string {
@ -215,8 +220,9 @@ func (p Progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error {
p.progressbar.Value = 0 p.progressbar.Value = 0
p.progressbar.Max = p.totalDuration p.progressbar.Max = p.totalDuration
p.progressbar.Refresh() fyne.Do(func() {
p.progressbar.Refresh()
})
progress := 0.0 progress := 0.0
go func() { go func() {
@ -246,7 +252,9 @@ func (p Progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error {
data := strings.TrimSpace(string(line)) data := strings.TrimSpace(string(line))
if strings.Contains(data, "progress=end") { if strings.Contains(data, "progress=end") {
p.progressbar.Value = p.totalDuration p.progressbar.Value = p.totalDuration
p.progressbar.Refresh() fyne.Do(func() {
p.progressbar.Refresh()
})
isProcessCompleted = true isProcessCompleted = true
break break
} }
@ -263,7 +271,9 @@ func (p Progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error {
} }
if p.progressbar.Value != progress { if p.progressbar.Value != progress {
p.progressbar.Value = progress p.progressbar.Value = progress
p.progressbar.Refresh() fyne.Do(func() {
p.progressbar.Refresh()
})
} }
} }
@ -529,6 +539,8 @@ func (s queueStatistics) remove() {
func (s queueStatistics) formatText(refresh bool) { func (s queueStatistics) formatText(refresh bool) {
s.widget.Text = s.title + ": " + strconv.FormatInt(*s.count, 10) s.widget.Text = s.title + ": " + strconv.FormatInt(*s.count, 10)
if refresh == true { if refresh == true {
s.widget.Refresh() fyne.Do(func() {
s.widget.Refresh()
})
} }
} }

View File

@ -12,6 +12,7 @@ type WindowContract interface {
SetMainMenu(menu *fyne.MainMenu) SetMainMenu(menu *fyne.MainMenu)
NewFileOpen(callback func(fyne.URIReadCloser, error), location fyne.ListableURI) *dialog.FileDialog NewFileOpen(callback func(fyne.URIReadCloser, error), location fyne.ListableURI) *dialog.FileDialog
NewFolderOpen(callback func(fyne.ListableURI, error), location fyne.ListableURI) *dialog.FileDialog NewFolderOpen(callback func(fyne.ListableURI, error), location fyne.ListableURI) *dialog.FileDialog
SetOnDropped(callback func(position fyne.Position, uris []fyne.URI))
ShowAndRun() ShowAndRun()
GetLayout() LayoutContract GetLayout() LayoutContract
} }
@ -26,7 +27,7 @@ func newWindow(w fyne.Window, layout LayoutContract) Window {
w.Resize(windowSize) w.Resize(windowSize)
w.CenterOnScreen() w.CenterOnScreen()
go func() { fyne.Do(func() {
/** /**
* Bug fixed. * Bug fixed.
* When starting the program, sometimes the window was displayed incorrectly. * When starting the program, sometimes the window was displayed incorrectly.
@ -35,7 +36,7 @@ func newWindow(w fyne.Window, layout LayoutContract) Window {
windowSize.Height += 1 windowSize.Height += 1
time.Sleep(time.Millisecond * 500) time.Sleep(time.Millisecond * 500)
w.Resize(windowSize) w.Resize(windowSize)
}() })
return Window{ return Window{
windowFyne: w, windowFyne: w,
@ -44,7 +45,9 @@ func newWindow(w fyne.Window, layout LayoutContract) Window {
} }
func (w Window) SetContent(content fyne.CanvasObject) { func (w Window) SetContent(content fyne.CanvasObject) {
w.windowFyne.SetContent(w.layout.SetContent(content)) fyne.Do(func() {
w.windowFyne.SetContent(w.layout.SetContent(content))
})
} }
func (w Window) NewFileOpen(callback func(fyne.URIReadCloser, error), location fyne.ListableURI) *dialog.FileDialog { func (w Window) NewFileOpen(callback func(fyne.URIReadCloser, error), location fyne.ListableURI) *dialog.FileDialog {
@ -78,3 +81,7 @@ func (w Window) ShowAndRun() {
func (w Window) GetLayout() LayoutContract { func (w Window) GetLayout() LayoutContract {
return w.layout return w.layout
} }
func (w Window) SetOnDropped(callback func(position fyne.Position, uris []fyne.URI)) {
w.windowFyne.SetOnDropped(callback)
}

View File

@ -62,6 +62,10 @@ other = "Will be downloaded from the site:"
hash = "sha1-55f87f114628fa2d5d8e67d1e1cda22c0e4f9271" hash = "sha1-55f87f114628fa2d5d8e67d1e1cda22c0e4f9271"
other = "Downloading..." other = "Downloading..."
[dragAndDrop1File]
hash = "sha1-7259670822df1cc92ef5f06ed3c0e9407746975a"
other = "drag and drop 1 file"
[encoderGroupAudio] [encoderGroupAudio]
hash = "sha1-24321cb5400df96be8f3e2131918bebdb3a01bba" hash = "sha1-24321cb5400df96be8f3e2131918bebdb3a01bba"
other = "Audio" other = "Audio"
@ -218,6 +222,10 @@ other = "Couldn't convert video"
hash = "sha1-531abc3f0d12727e542df6e5a22de91098380fc1" hash = "sha1-531abc3f0d12727e542df6e5a22de91098380fc1"
other = "could not create file 'database' in folder 'data'" other = "could not create file 'database' in folder 'data'"
[errorDragAndDrop1File]
hash = "sha1-a8edb5cbd622f3ce4ec07a2377e22ec5fad4491b"
other = "You can only drag and drop 1 file."
[errorFFmpeg] [errorFFmpeg]
hash = "sha1-ccf0b95c0d1b392dc215258d917eb4e5d0b88ed0" hash = "sha1-ccf0b95c0d1b392dc215258d917eb4e5d0b88ed0"
other = "this is not FFmpeg" other = "this is not FFmpeg"
@ -234,6 +242,10 @@ other = "this is not FFprobe"
hash = "sha1-da7b37d7df3fafbd153665b13888413d52b24c17" hash = "sha1-da7b37d7df3fafbd153665b13888413d52b24c17"
other = "Failed to determine FFprobe version" other = "Failed to determine FFprobe version"
[errorIsFolder]
hash = "sha1-f937d090b6e320957514d850657cdf2f911dc6aa"
other = "You can only drag and drop a file"
[errorQueue] [errorQueue]
hash = "sha1-72aecd9ad85642d84d62dbbf3cf70953c5f696c7" hash = "sha1-72aecd9ad85642d84d62dbbf3cf70953c5f696c7"
other = "Error" other = "Error"
@ -270,6 +282,14 @@ other = "File:"
hash = "sha1-7759891ba1ef9f7adc70defc7ac18fbf149c1a68" hash = "sha1-7759891ba1ef9f7adc70defc7ac18fbf149c1a68"
other = "Preset" other = "Preset"
[gratitude]
hash = "sha1-51968fc38e53a9a11c861126c62404674fd6096f"
other = "Gratitude"
[gratitudeText]
hash = "sha1-cb343e4d39ca31e6da6f72b9394cc915cb7d1258"
other = "I sincerely thank you for your invaluable\n\r and timely assistance:"
[help] [help]
hash = "sha1-6a45cef900c668effcb2ab10da05855c1fd10f6f" hash = "sha1-6a45cef900c668effcb2ab10da05855c1fd10f6f"
other = "Help" other = "Help"
@ -294,6 +314,10 @@ other = "License information"
hash = "sha1-359fff328717c05104e51a2d29f05bf1875d26b7" hash = "sha1-359fff328717c05104e51a2d29f05bf1875d26b7"
other = "Licenses from other products used in the program" other = "Licenses from other products used in the program"
[or]
hash = "sha1-30bb0333ca1583110e4ced513b5d2455b86f529b"
other = "or"
[parameterCheckbox] [parameterCheckbox]
hash = "sha1-9e35221d454870996fd51d576249cf47d1784a3c" hash = "sha1-9e35221d454870996fd51d576249cf47d1784a3c"
other = "Enable option" other = "Enable option"

View File

@ -62,6 +62,10 @@ other = "Сайттан жүктеледі:"
hash = "sha1-55f87f114628fa2d5d8e67d1e1cda22c0e4f9271" hash = "sha1-55f87f114628fa2d5d8e67d1e1cda22c0e4f9271"
other = "Жүктеп алынуда..." other = "Жүктеп алынуда..."
[dragAndDrop1File]
hash = "sha1-7259670822df1cc92ef5f06ed3c0e9407746975a"
other = "1 файлды сүйреңіз"
[encoderGroupAudio] [encoderGroupAudio]
hash = "sha1-24321cb5400df96be8f3e2131918bebdb3a01bba" hash = "sha1-24321cb5400df96be8f3e2131918bebdb3a01bba"
other = "Аудио" other = "Аудио"
@ -218,6 +222,10 @@ other = "Бейнені түрлендіру мүмкін болмады"
hash = "sha1-531abc3f0d12727e542df6e5a22de91098380fc1" hash = "sha1-531abc3f0d12727e542df6e5a22de91098380fc1"
other = "'data' қалтасында 'database' файлын жасау мүмкін болмады" other = "'data' қалтасында 'database' файлын жасау мүмкін болмады"
[errorDragAndDrop1File]
hash = "sha1-a8edb5cbd622f3ce4ec07a2377e22ec5fad4491b"
other = "Тек 1 файлды сүйреп апаруға болады"
[errorFFmpeg] [errorFFmpeg]
hash = "sha1-ccf0b95c0d1b392dc215258d917eb4e5d0b88ed0" hash = "sha1-ccf0b95c0d1b392dc215258d917eb4e5d0b88ed0"
other = "бұл FFmpeg емес" other = "бұл FFmpeg емес"
@ -234,6 +242,10 @@ other = "бұл FFprobe емес"
hash = "sha1-da7b37d7df3fafbd153665b13888413d52b24c17" hash = "sha1-da7b37d7df3fafbd153665b13888413d52b24c17"
other = "FFprobe нұсқасын анықтау мүмкін болмады" other = "FFprobe нұсқасын анықтау мүмкін болмады"
[errorIsFolder]
hash = "sha1-f937d090b6e320957514d850657cdf2f911dc6aa"
other = "Тек файлды сүйреп апаруға болады"
[errorQueue] [errorQueue]
hash = "sha1-72aecd9ad85642d84d62dbbf3cf70953c5f696c7" hash = "sha1-72aecd9ad85642d84d62dbbf3cf70953c5f696c7"
other = "Қате" other = "Қате"
@ -270,6 +282,14 @@ other = "Файл:"
hash = "sha1-7759891ba1ef9f7adc70defc7ac18fbf149c1a68" hash = "sha1-7759891ba1ef9f7adc70defc7ac18fbf149c1a68"
other = "Алдын ала орнатылған" other = "Алдын ала орнатылған"
[gratitude]
hash = "sha1-51968fc38e53a9a11c861126c62404674fd6096f"
other = "Алғыс"
[gratitudeText]
hash = "sha1-cb343e4d39ca31e6da6f72b9394cc915cb7d1258"
other = "Сізге баға жетпес және уақтылы көмектескеніңіз\n\r үшін шын жүректен алғыс айтамын:"
[help] [help]
hash = "sha1-6a45cef900c668effcb2ab10da05855c1fd10f6f" hash = "sha1-6a45cef900c668effcb2ab10da05855c1fd10f6f"
other = "Анықтама" other = "Анықтама"
@ -294,6 +314,10 @@ other = "Лицензия туралы ақпарат"
hash = "sha1-359fff328717c05104e51a2d29f05bf1875d26b7" hash = "sha1-359fff328717c05104e51a2d29f05bf1875d26b7"
other = "Бағдарламада пайдаланылатын басқа өнімдердің лицензиялары" other = "Бағдарламада пайдаланылатын басқа өнімдердің лицензиялары"
[or]
hash = "sha1-30bb0333ca1583110e4ced513b5d2455b86f529b"
other = "немесе"
[parameterCheckbox] [parameterCheckbox]
hash = "sha1-9e35221d454870996fd51d576249cf47d1784a3c" hash = "sha1-9e35221d454870996fd51d576249cf47d1784a3c"
other = "Опцияны қосу" other = "Опцияны қосу"

View File

@ -14,6 +14,7 @@ converterVideoFilesTitle = "Конвертер видео, аудио и кар
download = "Скачать" download = "Скачать"
downloadFFmpegFromSite = "Будет скачано с сайта:" downloadFFmpegFromSite = "Будет скачано с сайта:"
downloadRun = "Скачивается..." downloadRun = "Скачивается..."
dragAndDrop1File = "перетащить 1 файл"
encoderGroupAudio = "Аудио" encoderGroupAudio = "Аудио"
encoderGroupImage = "Картинки" encoderGroupImage = "Картинки"
encoderGroupVideo = "Видео" encoderGroupVideo = "Видео"
@ -53,10 +54,12 @@ encoder_xbm = "XBM (X BitMap) image"
error = "Произошла ошибка!" error = "Произошла ошибка!"
errorConverter = "не смогли отконвертировать видео" errorConverter = "не смогли отконвертировать видео"
errorDatabase = "не смогли создать файл 'database' в папке 'data'" errorDatabase = "не смогли создать файл 'database' в папке 'data'"
errorDragAndDrop1File = "Можно перетащить только 1 файл"
errorFFmpeg = "это не FFmpeg" errorFFmpeg = "это не FFmpeg"
errorFFmpegVersion = "Не смогли определить версию FFmpeg" errorFFmpegVersion = "Не смогли определить версию FFmpeg"
errorFFprobe = "это не FFprobe" errorFFprobe = "это не FFprobe"
errorFFprobeVersion = "Не смогли определить версию FFprobe" errorFFprobeVersion = "Не смогли определить версию FFprobe"
errorIsFolder = "Можно перетаскивать только файл"
errorQueue = "Ошибка" errorQueue = "Ошибка"
errorSelectedEncoder = "Конвертер не выбран" errorSelectedEncoder = "Конвертер не выбран"
errorSelectedFolderSave = "Папка для сохранения не выбрана!" errorSelectedFolderSave = "Папка для сохранения не выбрана!"
@ -66,12 +69,15 @@ ffmpegLGPL = "Это программное обеспечение исполь
ffmpegTrademark = "**FFmpeg** — торговая марка **[Fabrice Bellard](http://bellard.org/)** , создателя проекта **[FFmpeg](https://ffmpeg.org/about.html)**." ffmpegTrademark = "**FFmpeg** — торговая марка **[Fabrice Bellard](http://bellard.org/)** , создателя проекта **[FFmpeg](https://ffmpeg.org/about.html)**."
fileForConversionTitle = "Файл:" fileForConversionTitle = "Файл:"
formPreset = "Предустановка" formPreset = "Предустановка"
gratitude = "Благодарность"
gratitudeText = "Я искренне благодарю вас за неоценимую\n\rи своевременную помощь:"
help = "Справка" help = "Справка"
inProgressQueue = "Выполняется" inProgressQueue = "Выполняется"
languageSelectionFormHead = "Переключить язык" languageSelectionFormHead = "Переключить язык"
languageSelectionHead = "Выберите язык" languageSelectionHead = "Выберите язык"
licenseLink = "Сведения о лицензии" licenseLink = "Сведения о лицензии"
licenseLinkOther = "Лицензии от других продуктов, которые используются в программе" licenseLinkOther = "Лицензии от других продуктов, которые используются в программе"
or = "или"
parameterCheckbox = "Включить параметр" parameterCheckbox = "Включить параметр"
pathToFfmpeg = "Путь к FFmpeg:" pathToFfmpeg = "Путь к FFmpeg:"
pathToFfprobe = "Путь к FFprobe:" pathToFfprobe = "Путь к FFprobe:"

29
main.go
View File

@ -4,6 +4,7 @@ import (
"errors" "errors"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/convertor"
dberror "git.kor-elf.net/kor-elf/gui-for-ffmpeg/db"
error2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/error" error2 "git.kor-elf.net/kor-elf/gui-for-ffmpeg/error"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/handler" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/handler"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
@ -11,11 +12,10 @@ import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/menu" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/menu"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/migration" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/migration"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
_ "github.com/mattn/go-sqlite3" "go.etcd.io/bbolt"
"golang.org/x/text/language" "golang.org/x/text/language"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"os" "os"
"time"
) )
var application kernel.AppContract var application kernel.AppContract
@ -26,7 +26,7 @@ func init() {
appMetadata := &fyne.AppMetadata{ appMetadata := &fyne.AppMetadata{
ID: "net.kor-elf.projects.gui-for-ffmpeg", ID: "net.kor-elf.projects.gui-for-ffmpeg",
Name: "GUI for FFmpeg", Name: "GUI for FFmpeg",
Version: "0.7.0", Version: "0.8.0",
Icon: iconResource, Icon: iconResource,
} }
@ -50,20 +50,20 @@ func init() {
func main() { func main() {
errorView := error2.NewView(application) errorView := error2.NewView(application)
if canCreateFile("data/database") != true { if canCreateFile("data/database.db") != true {
errorView.PanicErrorWriteDirectoryData() errorView.PanicErrorWriteDirectoryData()
application.GetWindow().ShowAndRun() application.GetWindow().ShowAndRun()
return return
} }
db, err := gorm.Open(sqlite.Open("data/database"), &gorm.Config{}) db, err := bbolt.Open("data/database.db", 0600, &bbolt.Options{Timeout: 3 * time.Second})
if err != nil { if err != nil {
errorView.PanicError(err) errorView.PanicError(err)
application.GetWindow().ShowAndRun() application.GetWindow().ShowAndRun()
return return
} }
defer appCloseWithDb(db) defer db.Close()
err = migration.Run(db) err = migration.Run(db)
if err != nil { if err != nil {
@ -73,9 +73,11 @@ func main() {
} }
settingRepository := setting.NewRepository(db) settingRepository := setting.NewRepository(db)
settingDirectoryForSaving := setting.NewSettingDirectoryForSaving(settingRepository)
convertorRepository := convertor.NewRepository(settingRepository) convertorRepository := convertor.NewRepository(settingRepository)
pathFFmpeg, err := convertorRepository.GetPathFfmpeg() pathFFmpeg, err := convertorRepository.GetPathFfmpeg()
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) == false { if err != nil && errors.Is(err, dberror.ErrRecordNotFound) == false {
errorView.PanicError(err) errorView.PanicError(err)
application.GetWindow().ShowAndRun() application.GetWindow().ShowAndRun()
return return
@ -83,7 +85,7 @@ func main() {
ffPathUtilities.FFmpeg = pathFFmpeg ffPathUtilities.FFmpeg = pathFFmpeg
pathFFprobe, err := convertorRepository.GetPathFfprobe() pathFFprobe, err := convertorRepository.GetPathFfprobe()
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) == false { if err != nil && errors.Is(err, dberror.ErrRecordNotFound) == false {
errorView.PanicError(err) errorView.PanicError(err)
application.GetWindow().ShowAndRun() application.GetWindow().ShowAndRun()
return return
@ -95,7 +97,7 @@ func main() {
localizerView := localizer.NewView(application) localizerView := localizer.NewView(application)
convertorView := convertor.NewView(application) convertorView := convertor.NewView(application)
convertorHandler := handler.NewConvertorHandler(application, convertorView, errorView, convertorRepository) convertorHandler := handler.NewConvertorHandler(application, convertorView, errorView, convertorRepository, settingDirectoryForSaving)
localizerRepository := localizer.NewRepository(settingRepository) localizerRepository := localizer.NewRepository(settingRepository)
menuView := menu.NewView(application) menuView := menu.NewView(application)
@ -108,13 +110,6 @@ func main() {
application.GetWindow().ShowAndRun() application.GetWindow().ShowAndRun()
} }
func appCloseWithDb(db *gorm.DB) {
sqlDB, err := db.DB()
if err == nil {
_ = sqlDB.Close()
}
}
func canCreateFile(path string) bool { func canCreateFile(path string) bool {
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666) file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
if err != nil { if err != nil {

View File

@ -13,6 +13,7 @@ import (
type ViewContract interface { type ViewContract interface {
About(ffmpegVersion string, ffprobeVersion string) About(ffmpegVersion string, ffprobeVersion string)
Gratitude()
} }
type View struct { type View struct {
@ -25,6 +26,40 @@ func NewView(app kernel.AppContract) *View {
} }
} }
func (v View) Gratitude() {
view := v.app.GetAppFyne().NewWindow(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "gratitude",
}))
view.Resize(fyne.Size{Width: 500, Height: 400})
view.SetFixedSize(true)
image := canvas.NewImageFromFile("icon.png")
image.SetMinSize(fyne.Size{Width: 100, Height: 100})
image.FillMode = canvas.ImageFillContain
gratitude := canvas.NewText(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "gratitude",
}), colornames.Darkgreen)
gratitude.TextStyle = fyne.TextStyle{Bold: true}
gratitude.TextSize = 20
view.SetContent(
container.NewScroll(container.NewVBox(
container.NewBorder(nil, nil, container.NewVBox(image), nil, container.NewVBox(
gratitude,
widget.NewLabel(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "gratitudeText",
})),
widget.NewLabel("Екатерина"),
widget.NewLabel("Евгений"),
),
))),
)
view.CenterOnScreen()
view.Show()
}
func (v View) About(ffmpegVersion string, ffprobeVersion string) { func (v View) About(ffmpegVersion string, ffprobeVersion string) {
view := v.app.GetAppFyne().NewWindow(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ view := v.app.GetAppFyne().NewWindow(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "about", MessageID: "about",
@ -40,8 +75,8 @@ func (v View) About(ffmpegVersion string, ffprobeVersion string) {
MessageID: "programmLink", MessageID: "programmLink",
}), &url.URL{ }), &url.URL{
Scheme: "https", Scheme: "https",
Host: "git.kor-elf.net", Host: "gui-for-ffmpeg.projects.kor-elf.net",
Path: "kor-elf/gui-for-ffmpeg/releases", Path: "/",
}) })
licenseLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ licenseLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
@ -294,6 +329,19 @@ func (v View) getOther() *fyne.Container {
widget.NewLabel("Copyright (c) 2022, Fyne.io"), widget.NewLabel("Copyright (c) 2022, Fyne.io"),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/fyne-io/oksvg", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "fyne-io/oksvg",
})),
container.NewHBox(widget.NewHyperlink("BSD 3-Clause License", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "fyne-io/oksvg/blob/master/LICENSE",
})),
widget.NewLabel("Copyright (c) 2018, Steven R Wiley. All rights reserved."),
canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/go-gl/gl", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/go-gl/gl", &url.URL{
Scheme: "https", Scheme: "https",
Host: "github.com", Host: "github.com",
@ -356,33 +404,44 @@ func (v View) getOther() *fyne.Container {
Host: "github.com", Host: "github.com",
Path: "godbus/dbus/blob/master/LICENSE", Path: "godbus/dbus/blob/master/LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2013, Georg Reinke (<guelfey at gmail dot com>), Google"), widget.NewLabel("Copyright (c) 2013, Georg Reinke (<guelfey at gmail dot com>), Google. All rights reserved."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/gopherjs/gopherjs", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/hack-pad/go-indexeddb", &url.URL{
Scheme: "https", Scheme: "https",
Host: "github.com", Host: "github.com",
Path: "gopherjs/gopherjs", Path: "hack-pad/go-indexeddb",
})), })),
container.NewHBox(widget.NewHyperlink("BSD 2-Clause \"Simplified\" License", &url.URL{ container.NewHBox(widget.NewHyperlink("Apache License 2.0", &url.URL{
Scheme: "https", Scheme: "https",
Host: "github.com", Host: "github.com",
Path: "gopherjs/gopherjs/blob/master/LICENSE", Path: "hack-pad/go-indexeddb/blob/main/LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2013 Richard Musiol. All rights reserved."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/jinzhu/inflection", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/hack-pad/safejs", &url.URL{
Scheme: "https", Scheme: "https",
Host: "github.com", Host: "github.com",
Path: "jinzhu/inflection", Path: "hack-pad/safejs",
})), })),
container.NewHBox(widget.NewHyperlink("The MIT License (MIT)", &url.URL{ container.NewHBox(widget.NewHyperlink("Apache License 2.0", &url.URL{
Scheme: "https", Scheme: "https",
Host: "github.com", Host: "github.com",
Path: "jinzhu/inflection/blob/master/LICENSE", Path: "hack-pad/safejs/blob/main/LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2015 - Jinzhu"), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/jeandeaual/go-locale", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "jeandeaual/go-locale",
})),
container.NewHBox(widget.NewHyperlink("MIT License", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "jeandeaual/go-locale/blob/master/LICENSE",
})),
widget.NewLabel("Copyright (c) 2020 Alexis Jeandeau"),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/jsummers/gobmp", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/jsummers/gobmp", &url.URL{
@ -398,17 +457,17 @@ func (v View) getOther() *fyne.Container {
widget.NewLabel("Copyright (c) 2012-2015 Jason Summers"), widget.NewLabel("Copyright (c) 2012-2015 Jason Summers"),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/mattn/go-sqlite3", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/nfnt/resize", &url.URL{
Scheme: "https", Scheme: "https",
Host: "github.com", Host: "github.com",
Path: "mattn/go-sqlite3", Path: "nfnt/resize",
})), })),
container.NewHBox(widget.NewHyperlink("The MIT License (MIT)", &url.URL{ container.NewHBox(widget.NewHyperlink("ISC License", &url.URL{
Scheme: "https", Scheme: "https",
Host: "github.com", Host: "github.com",
Path: "mattn/go-sqlite3/blob/master/LICENSE", Path: "nfnt/resize/blob/master/LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2014 Yasuhiro Matsumoto"), widget.NewLabel("Copyright (c) 2012, Jan Schlicht <jan.schlicht@gmail.com>"),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/nicksnyder/go-i18n/v2", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/nicksnyder/go-i18n/v2", &url.URL{
@ -434,7 +493,19 @@ func (v View) getOther() *fyne.Container {
Host: "github.com", Host: "github.com",
Path: "pmezard/go-difflib/blob/master/LICENSE", Path: "pmezard/go-difflib/blob/master/LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2013, Patrick Mezard"), widget.NewLabel("Copyright (c) 2013, Patrick Mezard. All rights reserved."),
canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/rymdport/portal", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "rymdport/portal",
})),
container.NewHBox(widget.NewHyperlink("Apache License 2.0", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "rymdport/portal/blob/main/LICENSE",
})),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/srwiley/oksvg", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/srwiley/oksvg", &url.URL{
@ -447,7 +518,7 @@ func (v View) getOther() *fyne.Container {
Host: "github.com", Host: "github.com",
Path: "srwiley/oksvg/blob/master/LICENSE", Path: "srwiley/oksvg/blob/master/LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2018, Steven R Wiley"), widget.NewLabel("Copyright (c) 2018, Steven R Wiley. All rights reserved."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/srwiley/rasterx", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/srwiley/rasterx", &url.URL{
@ -460,7 +531,7 @@ func (v View) getOther() *fyne.Container {
Host: "github.com", Host: "github.com",
Path: "srwiley/rasterx/blob/master/LICENSE", Path: "srwiley/rasterx/blob/master/LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2018, Steven R Wiley"), widget.NewLabel("Copyright (c) 2018, Steven R Wiley. All rights reserved."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/stretchr/testify", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/stretchr/testify", &url.URL{
@ -476,17 +547,17 @@ func (v View) getOther() *fyne.Container {
widget.NewLabel("Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors."), widget.NewLabel("Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/tevino/abool", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/ulikunitz/xz", &url.URL{
Scheme: "https", Scheme: "https",
Host: "github.com", Host: "github.com",
Path: "tevino/abool", Path: "ulikunitz/xz",
})), })),
container.NewHBox(widget.NewHyperlink("The MIT License (MIT)", &url.URL{ container.NewHBox(widget.NewHyperlink("License", &url.URL{
Scheme: "https", Scheme: "https",
Host: "github.com", Host: "github.com",
Path: "tevino/abool/blob/master/LICENSE", Path: "ulikunitz/xz/blob/master/LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2016 Tevin Zhang"), widget.NewLabel("Copyright (c) 2014-2022 Ulrich Kunitz. All rights reserved."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/yuin/goldmark", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/yuin/goldmark", &url.URL{
@ -502,6 +573,19 @@ func (v View) getOther() *fyne.Container {
widget.NewLabel("Copyright (c) 2019 Yusuke Inuzuka"), widget.NewLabel("Copyright (c) 2019 Yusuke Inuzuka"),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("go.etcd.io/bbolt", &url.URL{
Scheme: "https",
Host: "pkg.go.dev",
Path: "go.etcd.io/bbolt",
})),
container.NewHBox(widget.NewHyperlink("MIT License", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "etcd-io/bbolt/blob/main/LICENSE",
})),
widget.NewLabel("Copyright (c) 2013 Ben Johnson"),
canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("golang.org/x/image", &url.URL{ container.NewHBox(widget.NewHyperlink("golang.org/x/image", &url.URL{
Scheme: "https", Scheme: "https",
Host: "pkg.go.dev", Host: "pkg.go.dev",
@ -512,20 +596,7 @@ func (v View) getOther() *fyne.Container {
Host: "cs.opensource.google", Host: "cs.opensource.google",
Path: "go/x/image/+/master:LICENSE", Path: "go/x/image/+/master:LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2009 The Go Authors. All rights reserved."), widget.NewLabel("Copyright 2009 The Go Authors."),
canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("golang.org/x/mobile", &url.URL{
Scheme: "https",
Host: "pkg.go.dev",
Path: "golang.org/x/mobile",
})),
container.NewHBox(widget.NewHyperlink("License", &url.URL{
Scheme: "https",
Host: "cs.opensource.google",
Path: "go/x/mobile/+/master:LICENSE",
})),
widget.NewLabel("Copyright (c) 2009 The Go Authors. All rights reserved."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("golang.org/x/net", &url.URL{ container.NewHBox(widget.NewHyperlink("golang.org/x/net", &url.URL{
@ -538,7 +609,7 @@ func (v View) getOther() *fyne.Container {
Host: "cs.opensource.google", Host: "cs.opensource.google",
Path: "go/x/net/+/master:LICENSE", Path: "go/x/net/+/master:LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2009 The Go Authors. All rights reserved."), widget.NewLabel("Copyright 2009 The Go Authors."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("golang.org/x/sys", &url.URL{ container.NewHBox(widget.NewHyperlink("golang.org/x/sys", &url.URL{
@ -551,7 +622,7 @@ func (v View) getOther() *fyne.Container {
Host: "cs.opensource.google", Host: "cs.opensource.google",
Path: "go/x/sys/+/master:LICENSE", Path: "go/x/sys/+/master:LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2009 The Go Authors. All rights reserved."), widget.NewLabel("Copyright 2009 The Go Authors."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("golang.org/x/text", &url.URL{ container.NewHBox(widget.NewHyperlink("golang.org/x/text", &url.URL{
@ -564,7 +635,7 @@ func (v View) getOther() *fyne.Container {
Host: "cs.opensource.google", Host: "cs.opensource.google",
Path: "go/x/text/+/master:LICENSE", Path: "go/x/text/+/master:LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2009 The Go Authors. All rights reserved."), widget.NewLabel("Copyright 2009 The Go Authors."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("gopkg.in/yaml.v3", &url.URL{ container.NewHBox(widget.NewHyperlink("gopkg.in/yaml.v3", &url.URL{
@ -572,38 +643,14 @@ func (v View) getOther() *fyne.Container {
Host: "github.com", Host: "github.com",
Path: "go-yaml/yaml/tree/v3.0.1", Path: "go-yaml/yaml/tree/v3.0.1",
})), })),
container.NewHBox(widget.NewHyperlink("Licensed under the Apache License, Version 2.0", &url.URL{ container.NewHBox(widget.NewHyperlink("MIT License and Apache License 2.0", &url.URL{
Scheme: "http", Scheme: "http",
Host: "www.apache.org",
Path: "licenses/LICENSE-2.0",
})),
widget.NewLabel("Copyright 2011-2016 Canonical Ltd."),
canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("gorm.io/gorm", &url.URL{
Scheme: "https",
Host: "github.com", Host: "github.com",
Path: "go-gorm/gorm", Path: "go-yaml/yaml/blob/v3.0.1/LICENSE",
})), })),
container.NewHBox(widget.NewHyperlink("The MIT License (MIT)", &url.URL{ widget.NewLabel("Copyright (c) 2006-2010 Kirill Simonov"),
Scheme: "https", widget.NewLabel("Copyright (c) 2006-2011 Kirill Simonov"),
Host: "github.com", widget.NewLabel("Copyright (c) 2011-2019 Canonical Ltd"),
Path: "go-gorm/gorm/blob/master/LICENSE",
})),
widget.NewLabel("Copyright (c) 2013-NOW Jinzhu <wosmvp@gmail.com>"),
canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("honnef.co/go/js/dom", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "dominikh/go-js-dom",
})),
container.NewHBox(widget.NewHyperlink("The MIT License (MIT)", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "dominikh/go-js-dom/blob/master/LICENSE",
})),
widget.NewLabel("Copyright (c) 2014 Dominik Honnef"),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/golang/go", &url.URL{ container.NewHBox(widget.NewHyperlink("github.com/golang/go", &url.URL{
@ -616,20 +663,7 @@ func (v View) getOther() *fyne.Container {
Host: "github.com", Host: "github.com",
Path: "golang/go/blob/master/LICENSE", Path: "golang/go/blob/master/LICENSE",
})), })),
widget.NewLabel("Copyright (c) 2009 The Go Authors. All rights reserved."), widget.NewLabel("Copyright 2009 The Go Authors."),
canvas.NewLine(colornames.Darkgreen),
container.NewHBox(widget.NewHyperlink("github.com/golang/go", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "golang/go",
})),
container.NewHBox(widget.NewHyperlink("BSD 3-Clause \"New\" or \"Revised\" License", &url.URL{
Scheme: "https",
Host: "github.com",
Path: "golang/go/blob/master/LICENSE",
})),
widget.NewLabel("Copyright (c) 2009 The Go Authors. All rights reserved."),
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),
) )
} }

View File

@ -1,15 +1,12 @@
package migration package migration
import ( import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting" "go.etcd.io/bbolt"
"gorm.io/gorm"
) )
func Run(db *gorm.DB) error { func Run(db *bbolt.DB) error {
err := db.AutoMigrate(&setting.Setting{}) return db.Update(func(tx *bbolt.Tx) error {
if err != nil { _, err := tx.CreateBucketIfNotExists([]byte("settings"))
return err return err
} })
return nil
} }

View File

@ -0,0 +1,22 @@
package setting
type DirectoryForSavingContract interface {
GetDirectoryForSaving() (string, error)
SaveDirectoryForSaving(path string) (Setting, error)
}
type DirectoryForSaving struct {
settingRepository RepositoryContract
}
func NewSettingDirectoryForSaving(settingRepository RepositoryContract) *DirectoryForSaving {
return &DirectoryForSaving{settingRepository: settingRepository}
}
func (setting DirectoryForSaving) GetDirectoryForSaving() (string, error) {
return setting.settingRepository.GetValue("directoryForSaving")
}
func (setting DirectoryForSaving) SaveDirectoryForSaving(path string) (Setting, error) {
return setting.settingRepository.CreateOrUpdate("directoryForSaving", path)
}

View File

@ -1,7 +1,6 @@
package setting package setting
type Setting struct { type Setting struct {
ID uint `gorm:"primary_key"` Code string `json:"code"`
Code string `gorm:"type:varchar(100);uniqueIndex;not null"` Value string `json:"value"`
Value string `gorm:"type:text"`
} }

View File

@ -1,8 +1,10 @@
package setting package setting
import ( import (
"encoding/json"
"errors" "errors"
"gorm.io/gorm" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/db"
"go.etcd.io/bbolt"
) )
type RepositoryContract interface { type RepositoryContract interface {
@ -12,44 +14,69 @@ type RepositoryContract interface {
} }
type Repository struct { type Repository struct {
db *gorm.DB db *bbolt.DB
} }
func NewRepository(db *gorm.DB) *Repository { func NewRepository(db *bbolt.DB) *Repository {
return &Repository{db} return &Repository{db}
} }
func (r Repository) GetValue(code string) (value string, err error) { func (r Repository) GetValue(code string) (value string, err error) {
var setting Setting var setting Setting
err = r.db.Where("code = ?", code).First(&setting).Error
err = r.db.View(func(tx *bbolt.Tx) error {
b := tx.Bucket([]byte("settings"))
if b == nil {
return errors.New("bucket 'settings' not found")
}
val := b.Get([]byte(code))
if val == nil {
return db.ErrRecordNotFound
}
return json.Unmarshal(val, &setting)
})
if err != nil { if err != nil {
return "", err return "", err
} }
return setting.Value, err
return setting.Value, nil
} }
func (r Repository) Create(setting Setting) (Setting, error) { func (r Repository) Create(setting Setting) (Setting, error) {
err := r.db.Create(&setting).Error err := r.db.Update(func(tx *bbolt.Tx) error {
if err != nil { b := tx.Bucket([]byte("settings"))
return setting, err if b == nil {
} return errors.New("bucket 'settings' not found")
}
data, err := json.Marshal(setting)
if err != nil {
return err
}
return b.Put([]byte(setting.Code), data)
})
return setting, err return setting, err
} }
func (r Repository) CreateOrUpdate(code string, value string) (Setting, error) { func (r Repository) CreateOrUpdate(code string, value string) (Setting, error) {
var setting Setting var setting Setting
err := r.db.Where("code = ?", code).First(&setting).Error setting.Code = code
if err != nil { setting.Value = value
if errors.Is(err, gorm.ErrRecordNotFound) == true {
setting = Setting{Code: code, Value: value} err := r.db.Update(func(tx *bbolt.Tx) error {
return r.Create(setting) b := tx.Bucket([]byte("settings"))
} else { if b == nil {
return setting, err return errors.New("bucket 'settings' not found")
} }
}
err = r.db.Model(&setting).UpdateColumn("value", value).Error data, err := json.Marshal(setting)
if err != nil { if err != nil {
return setting, err return err
} }
return b.Put([]byte(code), data)
})
return setting, err return setting, err
} }