Remove bbolt database dependency

Replaced bbolt-based database handling with Fyne built-in preferences for storing application settings. Deleted migration logic, database initialization, and error handling related to bbolt, simplifying the codebase and reducing external dependencies.
This commit is contained in:
Leonid Nikitin 2025-05-30 00:34:33 +05:00
parent 7340f43d6e
commit d69767f5e9
Signed by: kor-elf
GPG Key ID: DAB5355A11C22541
24 changed files with 67 additions and 259 deletions

View File

@ -3,7 +3,4 @@
Name = "GUI for FFmpeg"
ID = "net.kor-elf.projects.gui-for-ffmpeg"
Version = "0.9.0"
Build = 4
[Migrations]
fyneDo = true
Build = 11

View File

@ -26,7 +26,6 @@
7. Создаться папка **fyne-cross/bin** и там будет созданна папка с тем названием под которую Вы компилировали приложения (linux-amd64 или windows-amd64).
8. В папку **fyne-cross/bin/linux-amd64** или **fyne-cross/bin/windows-amd64** копируете:
* icon.png
* data
* languages
* LICENSE
* LICENSE-3RD-PARTY.txt

View File

@ -5,12 +5,12 @@ import (
)
type RepositoryContract interface {
GetPathFfmpeg() (string, error)
SavePathFfmpeg(code string) (setting.Setting, error)
GetPathFfprobe() (string, error)
SavePathFfprobe(code string) (setting.Setting, error)
GetPathFfplay() (string, error)
SavePathFfplay(code string) (setting.Setting, error)
GetPathFfmpeg() string
SavePathFfmpeg(code string) setting.Setting
GetPathFfprobe() string
SavePathFfprobe(code string) setting.Setting
GetPathFfplay() string
SavePathFfplay(code string) setting.Setting
}
type Repository struct {
@ -21,26 +21,26 @@ func NewRepository(settingRepository setting.RepositoryContract) *Repository {
return &Repository{settingRepository: settingRepository}
}
func (r Repository) GetPathFfmpeg() (string, error) {
func (r Repository) GetPathFfmpeg() string {
return r.settingRepository.GetValue("ffmpeg")
}
func (r Repository) SavePathFfmpeg(path string) (setting.Setting, error) {
func (r Repository) SavePathFfmpeg(path string) setting.Setting {
return r.settingRepository.CreateOrUpdate("ffmpeg", path)
}
func (r Repository) GetPathFfprobe() (string, error) {
func (r Repository) GetPathFfprobe() string {
return r.settingRepository.GetValue("ffprobe")
}
func (r Repository) SavePathFfprobe(path string) (setting.Setting, error) {
func (r Repository) SavePathFfprobe(path string) setting.Setting {
return r.settingRepository.CreateOrUpdate("ffprobe", path)
}
func (r Repository) GetPathFfplay() (string, error) {
func (r Repository) GetPathFfplay() string {
return r.settingRepository.GetValue("ffplay")
}
func (r Repository) SavePathFfplay(path string) (setting.Setting, error) {
func (r Repository) SavePathFfplay(path string) setting.Setting {
return r.settingRepository.CreateOrUpdate("ffplay", path)
}

View File

@ -353,7 +353,7 @@ func newDirectoryForSaving(app kernel.AppContract, settingDirectoryForSaving set
locationURI, err = storage.ListerForURI(r)
if err == nil {
_, _ = settingDirectoryForSaving.SaveDirectoryForSaving(locationURI.Path())
_ = settingDirectoryForSaving.SaveDirectoryForSaving(locationURI.Path())
}
}, locationURI)
@ -363,10 +363,7 @@ func newDirectoryForSaving(app kernel.AppContract, settingDirectoryForSaving set
}
func getDirectoryForSaving(settingDirectoryForSaving setting.DirectoryForSavingContract) (fyne.ListableURI, error) {
path, err := settingDirectoryForSaving.GetDirectoryForSaving()
if err != nil {
return nil, err
}
path := settingDirectoryForSaving.GetDirectoryForSaving()
if len(path) > 0 {
path = "file://" + path

2
data/.gitignore vendored
View File

@ -1,2 +0,0 @@
*
!.gitignore

View File

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

View File

@ -1,14 +1,12 @@
package error
import (
"errors"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/lang"
"fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/localizer"
"github.com/nicksnyder/go-i18n/v2/i18n"
"go.etcd.io/bbolt"
)
type ViewContract interface {
@ -37,17 +35,10 @@ func (v View) PanicError(err error) {
MessageID: "error",
})
messagetText := err.Error()
if errors.Is(err, bbolt.ErrTimeout) {
messagetText = v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorDatabaseTimeout",
})
}
v.app.GetWindow().SetContent(container.NewBorder(
container.NewVBox(
widget.NewLabel(messageHead),
widget.NewLabel(messagetText),
widget.NewLabel(err.Error()),
),
nil,
nil,
@ -57,30 +48,3 @@ func (v View) PanicError(err error) {
}),
))
}
func (v View) PanicErrorWriteDirectoryData() {
if v.isSetLanguage {
v.isSetLanguage = false
_ = v.app.GetLocalizerService().SetCurrentLanguageByCode(lang.SystemLocale().LanguageString())
}
message := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorDatabase",
})
messageHead := v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "error",
})
v.app.GetWindow().SetContent(container.NewBorder(
container.NewVBox(
widget.NewLabel(messageHead),
widget.NewLabel(message),
),
nil,
nil,
nil,
localizer.LanguageSelectionForm(v.app.GetLocalizerService(), func(lang kernel.Lang) {
v.PanicErrorWriteDirectoryData()
}),
))
}

1
go.mod
View File

@ -9,7 +9,6 @@ require (
github.com/BurntSushi/toml v1.5.0
github.com/nicksnyder/go-i18n/v2 v2.6.0
github.com/ulikunitz/xz v0.5.12
go.etcd.io/bbolt v1.4.0
golang.org/x/image v0.27.0
golang.org/x/text v0.25.0
)

4
go.sum
View File

@ -67,14 +67,10 @@ github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo=
github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=

View File

@ -61,9 +61,9 @@ func (h ConvertorHandler) MainConvertor() {
}
func (h ConvertorHandler) FfPathSelection() {
ffmpeg, _ := h.convertorRepository.GetPathFfmpeg()
ffprobe, _ := h.convertorRepository.GetPathFfprobe()
ffplay, _ := h.convertorRepository.GetPathFfplay()
ffmpeg := h.convertorRepository.GetPathFfmpeg()
ffprobe := h.convertorRepository.GetPathFfprobe()
ffplay := h.convertorRepository.GetPathFfplay()
h.convertorView.SelectFFPath(ffmpeg, ffprobe, ffplay, h.saveSettingFFPath, h.MainConvertor, h.downloadFFmpeg)
}
@ -122,9 +122,9 @@ func (h ConvertorHandler) checkingFFPathUtilities() bool {
if ffplayChecking == false {
continue
}
_, _ = h.convertorRepository.SavePathFfmpeg(item.FFmpeg)
_, _ = h.convertorRepository.SavePathFfprobe(item.FFprobe)
_, _ = h.convertorRepository.SavePathFfplay(item.FFplay)
_ = h.convertorRepository.SavePathFfmpeg(item.FFmpeg)
_ = h.convertorRepository.SavePathFfprobe(item.FFprobe)
_ = h.convertorRepository.SavePathFfplay(item.FFplay)
return true
}
@ -156,9 +156,9 @@ func (h ConvertorHandler) saveSettingFFPath(ffmpegPath string, ffprobePath strin
return errors.New(errorText)
}
_, _ = h.convertorRepository.SavePathFfmpeg(ffmpegPath)
_, _ = h.convertorRepository.SavePathFfprobe(ffprobePath)
_, _ = h.convertorRepository.SavePathFfplay(ffplayPath)
_ = h.convertorRepository.SavePathFfmpeg(ffmpegPath)
_ = h.convertorRepository.SavePathFfprobe(ffprobePath)
_ = h.convertorRepository.SavePathFfplay(ffplayPath)
h.MainConvertor()

View File

@ -28,9 +28,9 @@ func NewMainHandler(
}
func (h MainHandler) Start() {
language, err := h.localizerRepository.GetCode()
if err != nil {
err = h.app.GetLocalizerService().SetCurrentLanguageByCode(lang.SystemLocale().LanguageString())
language := h.localizerRepository.GetCode()
if len(language) == 0 {
err := h.app.GetLocalizerService().SetCurrentLanguageByCode(lang.SystemLocale().LanguageString())
if err != nil {
h.menuHandler.LanguageSelection()
return

View File

@ -143,7 +143,7 @@ func (h MenuHandler) openAbout() {
func (h MenuHandler) LanguageSelection() {
h.localizerView.LanguageSelection(func(lang kernel.Lang) {
_, _ = h.localizerRepository.Save(lang.Code)
_ = h.localizerRepository.Save(lang.Code)
h.convertorHandler.MainConvertor()
})
}
@ -154,10 +154,7 @@ func (h MenuHandler) settingsSelection() {
if err != nil {
return err
}
_, err = h.localizerRepository.Save(setting.Language.Code)
if err != nil {
return err
}
_ = h.localizerRepository.Save(setting.Language.Code)
err = h.themeService.SetCurrentTheme(setting.ThemeInfo)
if err != nil {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -230,14 +230,6 @@ other = "An error has occurred!"
hash = "sha1-55ebddceddb8b044e33cc3893ec2eba7bbd9fcf9"
other = "Couldn't convert video"
[errorDatabase]
hash = "sha1-531abc3f0d12727e542df6e5a22de91098380fc1"
other = "could not create file 'database' in folder 'data'"
[errorDatabaseTimeout]
hash = "sha1-f8153516ac2442d19be4b6daccce839d204ff09f"
other = "Could not open configuration file.\nMake sure another copy of the program is not running!"
[errorDragAndDropFile]
hash = "sha1-863cf1ad9c820d5b0c2006ceeaa29e25f81c1714"
other = "Not all files were added"

View File

@ -230,14 +230,6 @@ other = "Қате орын алды!"
hash = "sha1-55ebddceddb8b044e33cc3893ec2eba7bbd9fcf9"
other = "Бейнені түрлендіру мүмкін болмады"
[errorDatabase]
hash = "sha1-531abc3f0d12727e542df6e5a22de91098380fc1"
other = "'data' қалтасында 'database' файлын жасау мүмкін болмады"
[errorDatabaseTimeout]
hash = "sha1-f8153516ac2442d19be4b6daccce839d204ff09f"
other = "Конфигурация файлын аша алмады.\nБағдарламаның басқа көшірмесі іске қосылмағанына көз жеткізіңіз!"
[errorDragAndDropFile]
hash = "sha1-863cf1ad9c820d5b0c2006ceeaa29e25f81c1714"
other = "Барлық файлдар қосылмаған"

View File

@ -56,8 +56,6 @@ encoder_wmv2 = "Windows Media Video 8"
encoder_xbm = "XBM (X BitMap) image"
error = "Произошла ошибка!"
errorConverter = "не смогли отконвертировать видео"
errorDatabase = "не смогли создать файл 'database' в папке 'data'"
errorDatabaseTimeout = "Не смогли открыть файл конфигурации.\nУбедитесь, что другая копия программы не запущена!"
errorDragAndDropFile = "Не все файлы добавились"
errorFFmpeg = "это не FFmpeg"
errorFFmpegVersion = "Не смогли определить версию FFmpeg"

View File

@ -5,8 +5,8 @@ import (
)
type RepositoryContract interface {
GetCode() (string, error)
Save(code string) (setting.Setting, error)
GetCode() string
Save(code string) setting.Setting
}
type Repository struct {
@ -17,10 +17,10 @@ func NewRepository(settingRepository setting.RepositoryContract) *Repository {
return &Repository{settingRepository: settingRepository}
}
func (r Repository) GetCode() (string, error) {
func (r Repository) GetCode() string {
return r.settingRepository.GetValue("language")
}
func (r Repository) Save(code string) (setting.Setting, error) {
func (r Repository) Save(code string) setting.Setting {
return r.settingRepository.CreateOrUpdate("language", code)
}

64
main.go
View File

@ -1,22 +1,16 @@
package main
import (
"errors"
"fyne.io/fyne/v2"
"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"
"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/localizer"
"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/setting"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/theme"
"go.etcd.io/bbolt"
"golang.org/x/text/language"
"os"
"time"
)
var application kernel.AppContract
@ -53,55 +47,14 @@ func init() {
func main() {
errorView := error2.NewView(application)
if canCreateFile("data/database.db") != true {
errorView.PanicErrorWriteDirectoryData()
application.GetWindow().ShowAndRun()
return
}
db, err := bbolt.Open("data/database.db", 0600, &bbolt.Options{Timeout: 3 * time.Second})
if err != nil {
errorView.PanicError(err)
application.GetWindow().ShowAndRun()
return
}
defer db.Close()
err = migration.Run(db)
if err != nil {
errorView.PanicError(err)
application.GetWindow().ShowAndRun()
return
}
settingRepository := setting.NewRepository(db)
settingRepository := setting.NewRepository(application.GetAppFyne())
settingDirectoryForSaving := setting.NewSettingDirectoryForSaving(settingRepository)
convertorRepository := convertor.NewRepository(settingRepository)
pathFFmpeg, err := convertorRepository.GetPathFfmpeg()
if err != nil && errors.Is(err, dberror.ErrRecordNotFound) == false {
errorView.PanicError(err)
application.GetWindow().ShowAndRun()
return
}
ffPathUtilities.FFmpeg = pathFFmpeg
pathFFprobe, err := convertorRepository.GetPathFfprobe()
if err != nil && errors.Is(err, dberror.ErrRecordNotFound) == false {
errorView.PanicError(err)
application.GetWindow().ShowAndRun()
return
}
ffPathUtilities.FFprobe = pathFFprobe
pathFFplay, err := convertorRepository.GetPathFfplay()
if err != nil && errors.Is(err, dberror.ErrRecordNotFound) == false {
errorView.PanicError(err)
application.GetWindow().ShowAndRun()
return
}
ffPathUtilities.FFplay = pathFFplay
ffPathUtilities.FFmpeg = convertorRepository.GetPathFfmpeg()
ffPathUtilities.FFprobe = convertorRepository.GetPathFfprobe()
ffPathUtilities.FFplay = convertorRepository.GetPathFfplay()
application.RunConvertor()
defer application.AfterClosing()
@ -129,12 +82,3 @@ func main() {
application.GetWindow().SetMainMenu(mainMenu.GetMainMenu())
application.GetWindow().ShowAndRun()
}
func canCreateFile(path string) bool {
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
return false
}
_ = file.Close()
return true
}

View File

@ -1,12 +0,0 @@
package migration
import (
"go.etcd.io/bbolt"
)
func Run(db *bbolt.DB) error {
return db.Update(func(tx *bbolt.Tx) error {
_, err := tx.CreateBucketIfNotExists([]byte("settings"))
return err
})
}

View File

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

View File

@ -1,6 +1,6 @@
package setting
type Setting struct {
Code string `json:"code"`
Value string `json:"value"`
Code string
Value string
}

View File

@ -1,82 +1,39 @@
package setting
import (
"encoding/json"
"errors"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/db"
"go.etcd.io/bbolt"
"fyne.io/fyne/v2"
)
type RepositoryContract interface {
Create(setting Setting) (Setting, error)
CreateOrUpdate(code string, value string) (Setting, error)
GetValue(code string) (value string, err error)
Create(setting Setting) Setting
CreateOrUpdate(code string, value string) Setting
GetValue(code string) string
}
type Repository struct {
db *bbolt.DB
app fyne.App
}
func NewRepository(db *bbolt.DB) *Repository {
return &Repository{db}
func NewRepository(app fyne.App) *Repository {
return &Repository{
app: app,
}
}
func (r Repository) GetValue(code string) (value string, err error) {
var setting Setting
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 {
return "", err
}
return setting.Value, nil
func (r Repository) GetValue(code string) string {
return r.app.Preferences().String(code)
}
func (r Repository) Create(setting Setting) (Setting, error) {
err := r.db.Update(func(tx *bbolt.Tx) error {
b := tx.Bucket([]byte("settings"))
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
func (r Repository) Create(setting Setting) Setting {
r.app.Preferences().SetString(setting.Code, setting.Value)
return setting
}
func (r Repository) CreateOrUpdate(code string, value string) (Setting, error) {
func (r Repository) CreateOrUpdate(code string, value string) Setting {
var setting Setting
setting.Code = code
setting.Value = value
err := r.db.Update(func(tx *bbolt.Tx) error {
b := tx.Bucket([]byte("settings"))
if b == nil {
return errors.New("bucket 'settings' not found")
}
data, err := json.Marshal(setting)
if err != nil {
return err
}
return b.Put([]byte(code), data)
})
return setting, err
r.app.Preferences().SetString(code, value)
return setting
}

View File

@ -4,7 +4,7 @@ import "git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
type RepositoryContract interface {
GetCode() string
Save(code string) (setting.Setting, error)
Save(code string) setting.Setting
}
type Repository struct {
@ -16,13 +16,13 @@ func NewRepository(settingRepository setting.RepositoryContract) *Repository {
}
func (r Repository) GetCode() string {
name, err := r.settingRepository.GetValue("theme")
if err != nil {
name := r.settingRepository.GetValue("theme")
if len(name) == 0 {
return "default"
}
return name
}
func (r Repository) Save(code string) (setting.Setting, error) {
func (r Repository) Save(code string) setting.Setting {
return r.settingRepository.CreateOrUpdate("theme", code)
}

View File

@ -55,10 +55,7 @@ func (t theme) List() map[string]ThemeInfoContract {
}
func (t theme) SetCurrentTheme(themeInfo ThemeInfoContract) error {
_, err := t.repository.Save(themeInfo.GetName())
if err != nil {
return err
}
_ = t.repository.Save(themeInfo.GetName())
if themeInfo.GetName() == "default" {
t.app.GetAppFyne().Settings().SetTheme(fyneTheme.DefaultTheme())