From adf9bc9c278a066f56c40548a90a463527672d46 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Tue, 23 Jan 2024 21:33:01 +0600 Subject: [PATCH 1/6] Code refactoring. Added files with functions for various OS (//go:build windows, //go:build !windows). --- src/convertor/view.go | 3 +++ src/handler/convertor.go | 8 +------- src/handler/convertor_anyos.go | 10 ++++++++++ src/handler/convertor_windows.go | 8 ++++++++ src/helper/helper.go | 13 +++++++------ src/helper/path_separator.go | 8 ++++++++ src/helper/path_separator_window.go | 8 ++++++++ src/setting/view.go | 2 ++ 8 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 src/handler/convertor_anyos.go create mode 100644 src/handler/convertor_windows.go create mode 100644 src/helper/path_separator.go create mode 100644 src/helper/path_separator_window.go diff --git a/src/convertor/view.go b/src/convertor/view.go index db26786..6df9a50 100644 --- a/src/convertor/view.go +++ b/src/convertor/view.go @@ -2,6 +2,7 @@ package convertor import ( "errors" + "ffmpegGui/helper" "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" @@ -131,6 +132,7 @@ func (v View) getButtonFileVideoForConversion(form *widget.Form, progress *widge progress.Refresh() conversionMessage.Text = "" }, v.w) + helper.FileDialogResize(fileDialog, v.w) fileDialog.Show() }) @@ -162,6 +164,7 @@ func (v View) getButtonForSelectingDirectoryForSaving() (button *widget.Button, buttonMessage.Text = r.Path() setStringSuccessStyle(buttonMessage) }, v.w) + helper.FileDialogResize(fileDialog, v.w) fileDialog.Show() }) diff --git a/src/handler/convertor.go b/src/handler/convertor.go index 8d3d5f5..e1de919 100644 --- a/src/handler/convertor.go +++ b/src/handler/convertor.go @@ -9,7 +9,6 @@ import ( "fyne.io/fyne/v2/widget" "io" "regexp" - "runtime" "strconv" "strings" ) @@ -69,12 +68,7 @@ func (h ConvertorHandler) checkingFFPathUtilities() bool { return true } - var pathsToFF []convertor.FFPathUtilities - if runtime.GOOS == "windows" { - pathsToFF = []convertor.FFPathUtilities{{"ffmpeg\\bin\\ffmpeg.exe", "ffmpeg\\bin\\ffprobe.exe"}} - } else { - pathsToFF = []convertor.FFPathUtilities{{"ffmpeg/bin/ffmpeg", "ffmpeg/bin/ffprobe"}, {"ffmpeg", "ffprobe"}} - } + pathsToFF := getPathsToFF() for _, item := range pathsToFF { ffmpegChecking, _ := h.convertorService.ChangeFFmpegPath(item.FFmpeg) if ffmpegChecking == false { diff --git a/src/handler/convertor_anyos.go b/src/handler/convertor_anyos.go new file mode 100644 index 0000000..66d5fb6 --- /dev/null +++ b/src/handler/convertor_anyos.go @@ -0,0 +1,10 @@ +//go:build !windows +// +build !windows + +package handler + +import "ffmpegGui/convertor" + +func getPathsToFF() []convertor.FFPathUtilities { + return []convertor.FFPathUtilities{{"ffmpeg/bin/ffmpeg", "ffmpeg/bin/ffprobe"}, {"ffmpeg", "ffprobe"}} +} diff --git a/src/handler/convertor_windows.go b/src/handler/convertor_windows.go new file mode 100644 index 0000000..2def3f1 --- /dev/null +++ b/src/handler/convertor_windows.go @@ -0,0 +1,8 @@ +//go:build windows +// +build windows + +package handler + +func getPathsToFF() []convertor.FFPathUtilities { + return []convertor.FFPathUtilities{{"ffmpeg\\bin\\ffmpeg.exe", "ffmpeg\\bin\\ffprobe.exe"}} +} diff --git a/src/helper/helper.go b/src/helper/helper.go index b98d666..682704c 100644 --- a/src/helper/helper.go +++ b/src/helper/helper.go @@ -1,10 +1,11 @@ package helper -import "runtime" +import ( + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/dialog" +) -func PathSeparator() string { - if runtime.GOOS == "windows" { - return "\\" - } - return "/" +func FileDialogResize(fileDialog *dialog.FileDialog, w fyne.Window) { + contentSize := w.Content().Size() + fileDialog.Resize(fyne.Size{Width: contentSize.Width - 50, Height: contentSize.Height - 50}) } diff --git a/src/helper/path_separator.go b/src/helper/path_separator.go new file mode 100644 index 0000000..905b935 --- /dev/null +++ b/src/helper/path_separator.go @@ -0,0 +1,8 @@ +//go:build !windows +// +build !windows + +package helper + +func PathSeparator() string { + return "/" +} diff --git a/src/helper/path_separator_window.go b/src/helper/path_separator_window.go new file mode 100644 index 0000000..433e550 --- /dev/null +++ b/src/helper/path_separator_window.go @@ -0,0 +1,8 @@ +//go:build windows +// +build windows + +package helper + +func PathSeparator() string { + return "\\" +} diff --git a/src/setting/view.go b/src/setting/view.go index 7a85e0d..7e67dcf 100644 --- a/src/setting/view.go +++ b/src/setting/view.go @@ -1,6 +1,7 @@ package setting import ( + "ffmpegGui/helper" "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" @@ -81,6 +82,7 @@ func (v View) getButtonSelectFile() (filePath *string, button *widget.Button, bu buttonMessage.Text = r.URI().Path() setStringSuccessStyle(buttonMessage) }, v.w) + helper.FileDialogResize(fileDialog, v.w) fileDialog.Show() }) From 846986279c1cdb75a793dd672fd8aa50deeca209 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Tue, 23 Jan 2024 21:33:30 +0600 Subject: [PATCH 2/6] Added icon. --- src/icon.png | Bin 0 -> 15564 bytes src/main.go | 4 ++++ 2 files changed, 4 insertions(+) create mode 100644 src/icon.png diff --git a/src/icon.png b/src/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..067ee50097ee04538ee79d50bd3427c750e16e3c GIT binary patch literal 15564 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 literal 0 HcmV?d00001 diff --git a/src/main.go b/src/main.go index 46aec63..cb619dd 100644 --- a/src/main.go +++ b/src/main.go @@ -19,6 +19,10 @@ import ( func main() { a := app.New() + iconResource, err := fyne.LoadResourceFromPath("icon.png") + if err == nil { + a.SetIcon(iconResource) + } w := a.NewWindow("GUI FFMpeg!") w.Resize(fyne.Size{Width: 800, Height: 600}) w.CenterOnScreen() From d68382e418f0d5588b912be2bdc9e164609e7f60 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Sat, 27 Jan 2024 21:08:27 +0600 Subject: [PATCH 3/6] Fixed a bug when the video was fully converted, but the progress bar showed not 100, but, for example, 99. --- src/handler/convertor.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/handler/convertor.go b/src/handler/convertor.go index e1de919..919b2f4 100644 --- a/src/handler/convertor.go +++ b/src/handler/convertor.go @@ -163,9 +163,6 @@ func (p progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error { scannerOut := bufio.NewScanner(stdOut) for scannerOut.Scan() { - if isProcessCompleted != true { - isProcessCompleted = true - } data := scannerOut.Text() re := regexp.MustCompile(`frame=(\d+)`) a := re.FindAllStringSubmatch(data, -1) @@ -181,6 +178,7 @@ func (p progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error { p.progressbar.Value = p.totalDuration p.progressbar.Refresh() isProcessCompleted = true + break } if p.progressbar.Value != progress { p.progressbar.Value = progress From 6df775955fd2fcd023ad7ccb91a937f0a0381400 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Sat, 27 Jan 2024 21:17:04 +0600 Subject: [PATCH 4/6] Minor optimization. Raised "progress=end" after data:= Scanner Out.Text(). --- src/handler/convertor.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/handler/convertor.go b/src/handler/convertor.go index 919b2f4..e09accb 100644 --- a/src/handler/convertor.go +++ b/src/handler/convertor.go @@ -164,6 +164,14 @@ func (p progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error { scannerOut := bufio.NewScanner(stdOut) for scannerOut.Scan() { data := scannerOut.Text() + + if strings.Contains(data, "progress=end") { + p.progressbar.Value = p.totalDuration + p.progressbar.Refresh() + isProcessCompleted = true + break + } + re := regexp.MustCompile(`frame=(\d+)`) a := re.FindAllStringSubmatch(data, -1) @@ -174,12 +182,6 @@ func (p progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error { } progress = float64(c) } - if strings.Contains(data, "progress=end") { - p.progressbar.Value = p.totalDuration - p.progressbar.Refresh() - isProcessCompleted = true - break - } if p.progressbar.Value != progress { p.progressbar.Value = progress p.progressbar.Refresh() From 3c563d1966d14f330e399bd42905cdda8b930afd Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Sun, 28 Jan 2024 22:01:16 +0600 Subject: [PATCH 5/6] Added the ability to select a language. --- src/convertor/view.go | 64 ++++++++++++---- src/error/view.go | 52 +++++++++++-- src/go.mod | 4 +- src/go.sum | 6 ++ src/handler/convertor.go | 54 ++++++++++---- src/languages/active.en.toml | 75 +++++++++++++++++++ src/languages/active.kk.toml | 75 +++++++++++++++++++ src/languages/active.ru.toml | 19 +++++ src/languages/translate.en.toml | 0 src/languages/translate.kk.toml | 0 src/localizer/service.go | 128 ++++++++++++++++++++++++++++++++ src/localizer/view.go | 76 +++++++++++++++++++ src/main.go | 34 +++++++-- src/setting/view.go | 60 ++++++++++++--- 14 files changed, 591 insertions(+), 56 deletions(-) create mode 100644 src/languages/active.en.toml create mode 100644 src/languages/active.kk.toml create mode 100644 src/languages/active.ru.toml create mode 100644 src/languages/translate.en.toml create mode 100644 src/languages/translate.kk.toml create mode 100644 src/localizer/service.go create mode 100644 src/localizer/view.go diff --git a/src/convertor/view.go b/src/convertor/view.go index 6df9a50..3fb68ee 100644 --- a/src/convertor/view.go +++ b/src/convertor/view.go @@ -3,11 +3,13 @@ package convertor import ( "errors" "ffmpegGui/helper" + "ffmpegGui/localizer" "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/widget" + "github.com/nicksnyder/go-i18n/v2/i18n" "image/color" ) @@ -18,7 +20,8 @@ type ViewContract interface { } type View struct { - w fyne.Window + w fyne.Window + localizerService localizer.ServiceContract } type HandleConvertSetting struct { @@ -33,8 +36,11 @@ type enableFormConversionStruct struct { form *widget.Form } -func NewView(w fyne.Window) *View { - return &View{w} +func NewView(w fyne.Window, localizerService localizer.ServiceContract) *View { + return &View{ + w: w, + localizerService: localizerService, + } } func (v View) Main( @@ -52,18 +58,35 @@ func (v View) Main( buttonForSelectedDir, buttonForSelectedDirMessage, pathToSaveDirectory := v.getButtonForSelectingDirectoryForSaving() isOverwriteOutputFiles := false - checkboxOverwriteOutputFiles := widget.NewCheck("Разрешить перезаписать файл", func(b bool) { + checkboxOverwriteOutputFilesTitle := v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "checkboxOverwriteOutputFilesTitle", + }) + checkboxOverwriteOutputFiles := widget.NewCheck(checkboxOverwriteOutputFilesTitle, func(b bool) { isOverwriteOutputFiles = b }) form.Items = []*widget.FormItem{ - {Text: "Файл для ковертации:", Widget: fileVideoForConversion}, - {Widget: fileVideoForConversionMessage}, - {Text: "Папка куда будет сохраняться:", Widget: buttonForSelectedDir}, - {Widget: buttonForSelectedDirMessage}, - {Widget: checkboxOverwriteOutputFiles}, + { + Text: v.localizerService.GetMessage(&i18n.LocalizeConfig{MessageID: "fileVideoForConversionTitle"}), + Widget: fileVideoForConversion, + }, + { + Widget: fileVideoForConversionMessage, + }, + { + Text: v.localizerService.GetMessage(&i18n.LocalizeConfig{MessageID: "buttonForSelectedDirTitle"}), + Widget: buttonForSelectedDir, + }, + { + Widget: buttonForSelectedDirMessage, + }, + { + Widget: checkboxOverwriteOutputFiles, + }, } - form.SubmitText = "Конвертировать" + form.SubmitText = v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "converterVideoFilesSubmitTitle", + }) enableFormConversionStruct := enableFormConversionStruct{ fileVideoForConversion: fileVideoForConversion, @@ -73,7 +96,9 @@ func (v View) Main( form.OnSubmit = func() { if len(*pathToSaveDirectory) == 0 { - showConversionMessage(conversionMessage, errors.New("Не выбрали папку для сохранения!")) + showConversionMessage(conversionMessage, errors.New(v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "errorSelectedFolderSave", + }))) enableFormConversion(enableFormConversionStruct) return } @@ -97,7 +122,10 @@ func (v View) Main( enableFormConversion(enableFormConversionStruct) } - v.w.SetContent(widget.NewCard("Конвертор видео файлов в mp4", "", container.NewVBox(form, conversionMessage, progress))) + converterVideoFilesTitle := v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "converterVideoFilesTitle", + }) + v.w.SetContent(widget.NewCard(converterVideoFilesTitle, "", container.NewVBox(form, conversionMessage, progress))) form.Disable() } @@ -108,7 +136,11 @@ func (v View) getButtonFileVideoForConversion(form *widget.Form, progress *widge fileVideoForConversionMessage.TextSize = 16 fileVideoForConversionMessage.TextStyle = fyne.TextStyle{Bold: true} - button := widget.NewButton("выбрать", func() { + buttonTitle := v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "choose", + }) + + button := widget.NewButton(buttonTitle, func() { fileDialog := dialog.NewFileOpen( func(r fyne.URIReadCloser, err error) { if err != nil { @@ -147,7 +179,11 @@ func (v View) getButtonForSelectingDirectoryForSaving() (button *widget.Button, path := "" dirPath = &path - button = widget.NewButton("выбрать", func() { + buttonTitle := v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "choose", + }) + + button = widget.NewButton(buttonTitle, func() { fileDialog := dialog.NewFolderOpen( func(r fyne.ListableURI, err error) { if err != nil { diff --git a/src/error/view.go b/src/error/view.go index df3fc7d..101f0af 100644 --- a/src/error/view.go +++ b/src/error/view.go @@ -1,9 +1,11 @@ package error import ( + "ffmpegGui/localizer" "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/widget" + "github.com/nicksnyder/go-i18n/v2/i18n" ) type ViewContract interface { @@ -11,16 +13,54 @@ type ViewContract interface { } type View struct { - w fyne.Window + w fyne.Window + localizerService localizer.ServiceContract } -func NewView(w fyne.Window) *View { - return &View{w} +func NewView(w fyne.Window, localizerService localizer.ServiceContract) *View { + return &View{ + w: w, + localizerService: localizerService, + } } func (v View) PanicError(err error) { - v.w.SetContent(container.NewVBox( - widget.NewLabel("Произошла ошибка!"), - widget.NewLabel("Ошибка: "+err.Error()), + messageHead := v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "error", + }) + + v.w.SetContent(container.NewBorder( + container.NewVBox( + widget.NewLabel(messageHead), + widget.NewLabel(err.Error()), + ), + nil, + nil, + nil, + localizer.LanguageSelectionForm(v.localizerService, func(lang localizer.Lang) { + v.PanicError(err) + }), + )) +} + +func (v View) PanicErrorWriteDirectoryData() { + message := v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "errorDatabase", + }) + messageHead := v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "error", + }) + + v.w.SetContent(container.NewBorder( + container.NewVBox( + widget.NewLabel(messageHead), + widget.NewLabel(message), + ), + nil, + nil, + nil, + localizer.LanguageSelectionForm(v.localizerService, func(lang localizer.Lang) { + v.PanicErrorWriteDirectoryData() + }), )) } diff --git a/src/go.mod b/src/go.mod index 2831b7f..0d1f420 100644 --- a/src/go.mod +++ b/src/go.mod @@ -5,6 +5,7 @@ go 1.21 require ( fyne.io/fyne/v2 v2.4.3 // indirect fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e // indirect + github.com/BurntSushi/toml v1.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fredbi/uri v1.0.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect @@ -21,6 +22,7 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e // indirect github.com/mattn/go-sqlite3 v1.14.19 // indirect + github.com/nicksnyder/go-i18n/v2 v2.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect @@ -31,7 +33,7 @@ require ( golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/text v0.14.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/driver/sqlite v1.5.4 // indirect gorm.io/gorm v1.25.5 // indirect diff --git a/src/go.sum b/src/go.sum index 0fdad10..695098f 100644 --- a/src/go.sum +++ b/src/go.sum @@ -42,6 +42,8 @@ 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= @@ -226,6 +228,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN 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/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= @@ -477,6 +481,8 @@ 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.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.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= diff --git a/src/handler/convertor.go b/src/handler/convertor.go index e09accb..053ece0 100644 --- a/src/handler/convertor.go +++ b/src/handler/convertor.go @@ -5,8 +5,10 @@ import ( "errors" "ffmpegGui/convertor" "ffmpegGui/helper" + "ffmpegGui/localizer" "ffmpegGui/setting" "fyne.io/fyne/v2/widget" + "github.com/nicksnyder/go-i18n/v2/i18n" "io" "regexp" "strconv" @@ -17,23 +19,35 @@ type ConvertorHandler struct { convertorService convertor.ServiceContract convertorView convertor.ViewContract settingView setting.ViewContract + localizerView localizer.ViewContract settingRepository setting.RepositoryContract + localizerService localizer.ServiceContract } func NewConvertorHandler( convertorService convertor.ServiceContract, convertorView convertor.ViewContract, settingView setting.ViewContract, + localizerView localizer.ViewContract, settingRepository setting.RepositoryContract, + localizerService localizer.ServiceContract, ) *ConvertorHandler { return &ConvertorHandler{ - convertorService, - convertorView, - settingView, - settingRepository, + convertorService: convertorService, + convertorView: convertorView, + settingView: settingView, + localizerView: localizerView, + settingRepository: settingRepository, + localizerService: localizerService, } } +func (h ConvertorHandler) LanguageSelection() { + h.localizerView.LanguageSelection(func(lang localizer.Lang) { + h.GetConvertor() + }) +} + func (h ConvertorHandler) GetConvertor() { if h.checkingFFPathUtilities() == true { h.convertorView.Main(h.runConvert) @@ -47,7 +61,7 @@ func (h ConvertorHandler) runConvert(setting convertor.HandleConvertSetting, pro if err != nil { return err } - progress := NewProgress(totalDuration, progressbar) + progress := NewProgress(totalDuration, progressbar, h.localizerService) return h.convertorService.RunConvert( convertor.ConvertSetting{ @@ -91,12 +105,18 @@ func (h ConvertorHandler) checkingFFPathUtilities() bool { func (h ConvertorHandler) saveSettingFFPath(ffmpegPath string, ffprobePath string) error { ffmpegChecking, _ := h.convertorService.ChangeFFmpegPath(ffmpegPath) if ffmpegChecking == false { - return errors.New("это не FFmpeg") + errorText := h.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "errorFFmpeg", + }) + return errors.New(errorText) } ffprobeChecking, _ := h.convertorService.ChangeFFprobePath(ffprobePath) if ffprobeChecking == false { - return errors.New("это не FFprobe") + errorText := h.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "errorFFprobe", + }) + return errors.New(errorText) } ffmpegEntity := setting.Setting{Code: "ffmpeg", Value: ffmpegPath} @@ -124,16 +144,18 @@ func (h ConvertorHandler) checkingFFPath() bool { } type progress struct { - totalDuration float64 - progressbar *widget.ProgressBar - protocol string + totalDuration float64 + progressbar *widget.ProgressBar + protocol string + localizerService localizer.ServiceContract } -func NewProgress(totalDuration float64, progressbar *widget.ProgressBar) progress { +func NewProgress(totalDuration float64, progressbar *widget.ProgressBar, localizerService localizer.ServiceContract) progress { return progress{ - totalDuration: totalDuration, - progressbar: progressbar, - protocol: "pipe:", + totalDuration: totalDuration, + progressbar: progressbar, + protocol: "pipe:", + localizerService: localizerService, } } @@ -190,7 +212,9 @@ func (p progress) Run(stdOut io.ReadCloser, stdErr io.ReadCloser) error { if isProcessCompleted == false { if len(errorText) == 0 { - errorText = "не смогли отконвертировать видео" + errorText = p.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "errorConverter", + }) } return errors.New(errorText) } diff --git a/src/languages/active.en.toml b/src/languages/active.en.toml new file mode 100644 index 0000000..5fa57a1 --- /dev/null +++ b/src/languages/active.en.toml @@ -0,0 +1,75 @@ +[buttonForSelectedDirTitle] +hash = "sha1-52b13f1b13e82d22e8c4102332db5d4ec551247b" +other = "Folder where it will be saved:" + +[checkboxOverwriteOutputFilesTitle] +hash = "sha1-5860124bb781e7ef680f573fa93977e96328d4e7" +other = "Allow file to be overwritten" + +[choose] +hash = "sha1-f60bb5f761024d973834b5e9d25ceebce2c85f94" +other = "choose" + +[converterVideoFilesSubmitTitle] +hash = "sha1-7ac460f3c24c9952082f2db6e4d62f752598709c" +other = "Convert" + +[converterVideoFilesTitle] +hash = "sha1-4d972809e4c7f9c9ff2c110a126bbc183c9429ce" +other = "Converter video files to mp4" + +[error] +hash = "sha1-a7df8f8b5d754f226ac4cb320577fe692b33e483" +other = "An error has occurred!" + +[errorConverter] +hash = "sha1-55ebddceddb8b044e33cc3893ec2eba7bbd9fcf9" +other = "Couldn't convert video" + +[errorDatabase] +hash = "sha1-531abc3f0d12727e542df6e5a22de91098380fc1" +other = "could not create file 'database' in folder 'data'" + +[errorFFmpeg] +hash = "sha1-ccf0b95c0d1b392dc215258d917eb4e5d0b88ed0" +other = "this is not FFmpeg" + +[errorFFprobe] +hash = "sha1-86d1b0b4c4ccd6a4f71e758fc67ce11aff4ba9b8" +other = "this is not FFprobe" + +[errorSelectedFolderSave] +hash = "sha1-83da899677cdc90e4344e3b94ee03c46b51bee4c" +other = "You haven't selected a folder to save!" + +[fileVideoForConversionTitle] +hash = "sha1-5e727d4a2ff3f21080e51e81641595b2e668f3be" +other = "File for conversion:" + +[languageSelectionFormHead] +hash = "sha1-0ff5fa82cf684112660128cba1711297acf11003" +other = "Switch language" + +[languageSelectionHead] +hash = "sha1-daf1108fc10d3b1a908288d611f749b3cc651e4b" +other = "Choose language" + +[pathToFfmpeg] +hash = "sha1-2eba439f365640ff77e0ed6a7486fcb662573850" +other = "Path to ffmpeg:" + +[pathToFfprobe] +hash = "sha1-02ad53337801906f8ebfee4616100dd9f43eabd7" +other = "Path to ffprobe:" + +[save] +hash = "sha1-4864057d626a868fa60f999bed3191d61d045ddc" +other = "Save" + +[selectFFPathTitle] +hash = "sha1-95581446a28d968ff1a027c623159a7eb08654cf" +other = "Specify the path to FFmpeg and FFprobe" + +[titleDownloadLink] +hash = "sha1-92df86371f6c3a06ca1e4754f113142776a32d49" +other = "You can download it from here" diff --git a/src/languages/active.kk.toml b/src/languages/active.kk.toml new file mode 100644 index 0000000..f1f713e --- /dev/null +++ b/src/languages/active.kk.toml @@ -0,0 +1,75 @@ +[buttonForSelectedDirTitle] +hash = "sha1-52b13f1b13e82d22e8c4102332db5d4ec551247b" +other = "Файлды сақтауға арналған каталог:" + +[checkboxOverwriteOutputFilesTitle] +hash = "sha1-5860124bb781e7ef680f573fa93977e96328d4e7" +other = "Файлды қайта жазуға рұқсат беріңіз" + +[choose] +hash = "sha1-f60bb5f761024d973834b5e9d25ceebce2c85f94" +other = "таңдау" + +[converterVideoFilesSubmitTitle] +hash = "sha1-7ac460f3c24c9952082f2db6e4d62f752598709c" +other = "Файлды түрлендіру" + +[converterVideoFilesTitle] +hash = "sha1-4d972809e4c7f9c9ff2c110a126bbc183c9429ce" +other = "Бейне файлдарын mp4 форматына түрлендіру" + +[error] +hash = "sha1-a7df8f8b5d754f226ac4cb320577fe692b33e483" +other = "Қате орын алды!" + +[errorConverter] +hash = "sha1-55ebddceddb8b044e33cc3893ec2eba7bbd9fcf9" +other = "Бейнені түрлендіру мүмкін болмады" + +[errorDatabase] +hash = "sha1-531abc3f0d12727e542df6e5a22de91098380fc1" +other = "'data' қалтасында 'database' файлын жасау мүмкін болмады" + +[errorFFmpeg] +hash = "sha1-ccf0b95c0d1b392dc215258d917eb4e5d0b88ed0" +other = "бұл FFmpeg емес" + +[errorFFprobe] +hash = "sha1-86d1b0b4c4ccd6a4f71e758fc67ce11aff4ba9b8" +other = "бұл FFprobe емес" + +[errorSelectedFolderSave] +hash = "sha1-83da899677cdc90e4344e3b94ee03c46b51bee4c" +other = "Сіз сақталатын қалтаны таңдамадыңыз!" + +[fileVideoForConversionTitle] +hash = "sha1-5e727d4a2ff3f21080e51e81641595b2e668f3be" +other = "Түрлендіруге арналған файл:" + +[languageSelectionFormHead] +hash = "sha1-0ff5fa82cf684112660128cba1711297acf11003" +other = "Тілді ауыстыру" + +[languageSelectionHead] +hash = "sha1-daf1108fc10d3b1a908288d611f749b3cc651e4b" +other = "Тілді таңдаңыз" + +[pathToFfmpeg] +hash = "sha1-2eba439f365640ff77e0ed6a7486fcb662573850" +other = "ffmpeg жол:" + +[pathToFfprobe] +hash = "sha1-02ad53337801906f8ebfee4616100dd9f43eabd7" +other = "ffprobe жол:" + +[save] +hash = "sha1-4864057d626a868fa60f999bed3191d61d045ddc" +other = "Сақтау" + +[selectFFPathTitle] +hash = "sha1-95581446a28d968ff1a027c623159a7eb08654cf" +other = "FFmpeg және FFprobe жолын көрсетіңіз" + +[titleDownloadLink] +hash = "sha1-92df86371f6c3a06ca1e4754f113142776a32d49" +other = "Сіз оны осы жерден жүктей аласыз" diff --git a/src/languages/active.ru.toml b/src/languages/active.ru.toml new file mode 100644 index 0000000..b4185d9 --- /dev/null +++ b/src/languages/active.ru.toml @@ -0,0 +1,19 @@ +buttonForSelectedDirTitle = "Папка куда будет сохраняться:" +checkboxOverwriteOutputFilesTitle = "Разрешить перезаписать файл" +choose = "выбрать" +converterVideoFilesSubmitTitle = "Конвертировать" +converterVideoFilesTitle = "Конвертор видео файлов в mp4" +error = "Произошла ошибка!" +errorConverter = "не смогли отконвертировать видео" +errorDatabase = "не смогли создать файл 'database' в папке 'data'" +errorFFmpeg = "это не FFmpeg" +errorFFprobe = "это не FFprobe" +errorSelectedFolderSave = "Не выбрали папку для сохранения!" +fileVideoForConversionTitle = "Файл для ковертации:" +languageSelectionFormHead = "Переключить язык" +languageSelectionHead = "Выберите язык" +pathToFfmpeg = "Путь к ffmpeg:" +pathToFfprobe = "Путь к ffprobe:" +save = "Сохранить" +selectFFPathTitle = "Укажите путь к FFmpeg и к FFprobe" +titleDownloadLink = "Скачать можно от сюда" diff --git a/src/languages/translate.en.toml b/src/languages/translate.en.toml new file mode 100644 index 0000000..e69de29 diff --git a/src/languages/translate.kk.toml b/src/languages/translate.kk.toml new file mode 100644 index 0000000..e69de29 diff --git a/src/localizer/service.go b/src/localizer/service.go new file mode 100644 index 0000000..129c31b --- /dev/null +++ b/src/localizer/service.go @@ -0,0 +1,128 @@ +package localizer + +import ( + "github.com/BurntSushi/toml" + "github.com/nicksnyder/go-i18n/v2/i18n" + "golang.org/x/text/cases" + "golang.org/x/text/language" + "golang.org/x/text/language/display" + "path/filepath" + "sort" +) + +type ServiceContract interface { + GetLanguages() []Lang + GetMessage(localizeConfig *i18n.LocalizeConfig) string + SetCurrentLanguage(lang Lang) error + GetCurrentLanguage() *CurrentLanguage +} + +type Lang struct { + Code string + Title string +} + +type CurrentLanguage struct { + Lang Lang + localizer *i18n.Localizer + localizerDefault *i18n.Localizer +} + +type Service struct { + bundle *i18n.Bundle + languages []Lang + currentLanguage *CurrentLanguage +} + +func NewService(directory string, languageDefault language.Tag) (*Service, error) { + bundle := i18n.NewBundle(languageDefault) + bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) + + languages, err := initLanguages(directory, bundle) + if err != nil { + return nil, err + } + + localizerDefault := i18n.NewLocalizer(bundle, languageDefault.String()) + + return &Service{ + bundle: bundle, + languages: languages, + currentLanguage: &CurrentLanguage{ + Lang: Lang{ + Code: languageDefault.String(), + Title: cases.Title(languageDefault).String(display.Self.Name(languageDefault)), + }, + localizer: localizerDefault, + localizerDefault: localizerDefault, + }, + }, nil +} + +func initLanguages(directory string, bundle *i18n.Bundle) ([]Lang, error) { + var languages []Lang + + files, err := filepath.Glob(directory + "/active.*.toml") + if err != nil { + return nil, err + } + for _, file := range files { + language, err := bundle.LoadMessageFile(file) + if err != nil { + return nil, err + } + title := cases.Title(language.Tag).String(display.Self.Name(language.Tag)) + languages = append(languages, Lang{Code: language.Tag.String(), Title: title}) + } + + sort.Sort(languagesSort(languages)) + + return languages, nil +} + +func (s Service) GetLanguages() []Lang { + return s.languages +} + +func (s Service) GetMessage(localizeConfig *i18n.LocalizeConfig) string { + message, err := s.GetCurrentLanguage().localizer.Localize(localizeConfig) + if err != nil { + message, err = s.GetCurrentLanguage().localizerDefault.Localize(localizeConfig) + if err != nil { + return err.Error() + } + } + return message +} + +func (s Service) SetCurrentLanguage(lang Lang) error { + s.currentLanguage.Lang = lang + s.currentLanguage.localizer = i18n.NewLocalizer(s.bundle, lang.Code) + return nil +} + +func (s Service) GetCurrentLanguage() *CurrentLanguage { + return s.currentLanguage +} + +type languagesSort []Lang + +func (l languagesSort) Len() int { return len(l) } +func (l languagesSort) Swap(i, j int) { l[i], l[j] = l[j], l[i] } +func (l languagesSort) Less(i, j int) bool { + return languagePriority(l[i]) < languagePriority(l[j]) +} +func languagePriority(l Lang) int { + priority := 0 + + switch l.Code { + case "ru": + priority = -3 + case "kk": + priority = -2 + case "en": + priority = -1 + } + + return priority +} diff --git a/src/localizer/view.go b/src/localizer/view.go new file mode 100644 index 0000000..351d9c9 --- /dev/null +++ b/src/localizer/view.go @@ -0,0 +1,76 @@ +package localizer + +import ( + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/widget" + "github.com/nicksnyder/go-i18n/v2/i18n" +) + +type ViewContract interface { + LanguageSelection(funcSelected func(lang Lang)) +} + +type View struct { + w fyne.Window + localizerService ServiceContract +} + +func NewView(w fyne.Window, localizerService ServiceContract) *View { + return &View{ + w: w, + localizerService: localizerService, + } +} + +func (v View) LanguageSelection(funcSelected func(lang Lang)) { + languages := v.localizerService.GetLanguages() + listView := widget.NewList( + func() int { + return len(languages) + }, + func() fyne.CanvasObject { + return widget.NewLabel("template") + }, + func(i widget.ListItemID, o fyne.CanvasObject) { + block := o.(*widget.Label) + block.SetText(languages[i].Title) + }) + listView.OnSelected = func(id widget.ListItemID) { + _ = v.localizerService.SetCurrentLanguage(languages[id]) + funcSelected(languages[id]) + } + + messageHead := v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "languageSelectionHead", + }) + + v.w.SetContent(widget.NewCard(messageHead, "", listView)) +} + +func LanguageSelectionForm(localizerService ServiceContract, funcSelected func(lang Lang)) fyne.CanvasObject { + languages := localizerService.GetLanguages() + currentLanguage := localizerService.GetCurrentLanguage() + listView := widget.NewList( + func() int { + return len(languages) + }, + func() fyne.CanvasObject { + return widget.NewLabel("template") + }, + func(i widget.ListItemID, o fyne.CanvasObject) { + block := o.(*widget.Label) + block.SetText(languages[i].Title) + if languages[i].Code == currentLanguage.Lang.Code { + block.TextStyle = fyne.TextStyle{Bold: true} + } + }) + listView.OnSelected = func(id widget.ListItemID) { + _ = localizerService.SetCurrentLanguage(languages[id]) + funcSelected(languages[id]) + } + + messageHead := localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "languageSelectionFormHead", + }) + return widget.NewCard(messageHead, "", listView) +} diff --git a/src/main.go b/src/main.go index cb619dd..47cf9ed 100644 --- a/src/main.go +++ b/src/main.go @@ -3,19 +3,23 @@ package main import ( "errors" "ffmpegGui/convertor" - myError "ffmpegGui/error" + error2 "ffmpegGui/error" "ffmpegGui/handler" + "ffmpegGui/localizer" "ffmpegGui/migration" "ffmpegGui/setting" "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/widget" _ "github.com/mattn/go-sqlite3" + "golang.org/x/text/language" "gorm.io/driver/sqlite" "gorm.io/gorm" "os" ) -//const appVersion string = "0.1.1" +//const appVersion string = "0.2.0" func main() { a := app.New() @@ -27,10 +31,16 @@ func main() { w.Resize(fyne.Size{Width: 800, Height: 600}) w.CenterOnScreen() - errorView := myError.NewView(w) + localizerService, err := localizer.NewService("languages", language.Russian) + if err != nil { + panicErrorLang(w, err) + w.ShowAndRun() + return + } + errorView := error2.NewView(w, localizerService) if canCreateFile("data/database") != true { - errorView.PanicError(errors.New("не смогли создать файл 'database' в папке 'data'")) + errorView.PanicErrorWriteDirectoryData() w.ShowAndRun() return } @@ -67,13 +77,14 @@ func main() { ffPathUtilities := convertor.FFPathUtilities{FFmpeg: pathFFmpeg, FFprobe: pathFFprobe} - convertorView := convertor.NewView(w) - settingView := setting.NewView(w) + localizerView := localizer.NewView(w, localizerService) + convertorView := convertor.NewView(w, localizerService) + settingView := setting.NewView(w, localizerService) convertorService := convertor.NewService(ffPathUtilities) defer appCloseWithConvert(convertorService) - mainHandler := handler.NewConvertorHandler(convertorService, convertorView, settingView, settingRepository) + mainHandler := handler.NewConvertorHandler(convertorService, convertorView, settingView, localizerView, settingRepository, localizerService) - mainHandler.GetConvertor() + mainHandler.LanguageSelection() w.ShowAndRun() } @@ -99,3 +110,10 @@ func canCreateFile(path string) bool { _ = file.Close() return true } + +func panicErrorLang(w fyne.Window, err error) { + w.SetContent(container.NewVBox( + widget.NewLabel("Произошла ошибка!"), + widget.NewLabel("произошла ошибка при получении языковых переводах. \n\r"+err.Error()), + )) +} diff --git a/src/setting/view.go b/src/setting/view.go index 7e67dcf..397972f 100644 --- a/src/setting/view.go +++ b/src/setting/view.go @@ -2,11 +2,13 @@ package setting import ( "ffmpegGui/helper" + "ffmpegGui/localizer" "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/widget" + "github.com/nicksnyder/go-i18n/v2/i18n" "image/color" "net/url" ) @@ -16,11 +18,15 @@ type ViewContract interface { } type View struct { - w fyne.Window + w fyne.Window + localizerService localizer.ServiceContract } -func NewView(w fyne.Window) *View { - return &View{w} +func NewView(w fyne.Window, localizerService localizer.ServiceContract) *View { + return &View{ + w: w, + localizerService: localizerService, + } } func (v View) SelectFFPath(save func(ffmpegPath string, ffprobePath string) error) { @@ -39,14 +45,37 @@ func (v View) SelectFFPath(save func(ffmpegPath string, ffprobePath string) erro form := &widget.Form{ Items: []*widget.FormItem{ - {Text: "Скачать можно от сюда", Widget: link}, - {Text: "Путь к ffmpeg:", Widget: buttonFFmpeg}, - {Widget: buttonFFmpegMessage}, - {Text: "Путь к ffprobe:", Widget: buttonFFprobe}, - {Widget: buttonFFprobeMessage}, - {Widget: errorMessage}, + { + Text: v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "titleDownloadLink", + }), + Widget: link, + }, + { + Text: v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "pathToFfmpeg", + }), + Widget: buttonFFmpeg, + }, + { + Widget: buttonFFmpegMessage, + }, + { + Text: v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "pathToFfprobe", + }), + Widget: buttonFFprobe, + }, + { + Widget: buttonFFprobeMessage, + }, + { + Widget: errorMessage, + }, }, - SubmitText: "Сохранить", + SubmitText: v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "save", + }), OnSubmit: func() { err := save(string(*ffmpegPath), string(*ffprobePath)) if err != nil { @@ -54,7 +83,10 @@ func (v View) SelectFFPath(save func(ffmpegPath string, ffprobePath string) erro } }, } - v.w.SetContent(widget.NewCard("Укажите путь к FFmpeg и к FFprobe", "", container.NewVBox(form))) + selectFFPathTitle := v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "selectFFPathTitle", + }) + v.w.SetContent(widget.NewCard(selectFFPathTitle, "", container.NewVBox(form))) } func (v View) getButtonSelectFile() (filePath *string, button *widget.Button, buttonMessage *canvas.Text) { @@ -65,7 +97,11 @@ func (v View) getButtonSelectFile() (filePath *string, button *widget.Button, bu buttonMessage.TextSize = 16 buttonMessage.TextStyle = fyne.TextStyle{Bold: true} - button = widget.NewButton("выбрать", func() { + buttonTitle := v.localizerService.GetMessage(&i18n.LocalizeConfig{ + MessageID: "choose", + }) + + button = widget.NewButton(buttonTitle, func() { fileDialog := dialog.NewFileOpen( func(r fyne.URIReadCloser, err error) { if err != nil { From 6f0bbf7e29f5bbb0e2b503e30b80a6fc7c74c519 Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Sun, 28 Jan 2024 22:08:40 +0600 Subject: [PATCH 6/6] Windows OS fix. Added import "ffmpeg Gui/convertor" to convertor_windows.go --- src/handler/convertor_windows.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/handler/convertor_windows.go b/src/handler/convertor_windows.go index 2def3f1..aee0790 100644 --- a/src/handler/convertor_windows.go +++ b/src/handler/convertor_windows.go @@ -3,6 +3,8 @@ package handler +import "ffmpegGui/convertor" + func getPathsToFF() []convertor.FFPathUtilities { return []convertor.FFPathUtilities{{"ffmpeg\\bin\\ffmpeg.exe", "ffmpeg\\bin\\ffprobe.exe"}} }