package ui import ( "encoding/json" "os" "sync" "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/widget" "gitea.unprism.ru/KRBL/FemaInstaller/pkg/config" ) var mu = sync.Mutex{} // MainWindow represents the main application window type MainWindow struct { Window fyne.Window IPEntry *widget.Entry PortEntry *widget.Entry LoginEntry *widget.Entry PasswordEntry *widget.Entry SerialEntry *widget.Entry TailNumberEntry *widget.Entry DefaultHostEntry *widget.Entry ArchivePathEntry *widget.Entry StatusLabel *widget.Label InstallButton *widget.Button } func loadConfig() *config.SSHConfig { fileName := "config.json" if _, err := os.Stat(fileName); os.IsNotExist(err) { return nil } data, err := os.ReadFile(fileName) if err != nil { return nil } var cfg config.SSHConfig err = json.Unmarshal(data, &cfg) if err != nil { return nil } return &cfg } // NewMainWindow creates a new main window for the application func NewMainWindow(app fyne.App, installHandler func(*config.SSHConfig) error) *MainWindow { window := app.NewWindow("Fema Installer") // Create form fields mainWindow := &MainWindow{ Window: window, IPEntry: widget.NewEntry(), PortEntry: widget.NewEntry(), LoginEntry: widget.NewEntry(), PasswordEntry: widget.NewPasswordEntry(), SerialEntry: widget.NewEntry(), TailNumberEntry: widget.NewEntry(), DefaultHostEntry: widget.NewEntry(), ArchivePathEntry: widget.NewEntry(), StatusLabel: widget.NewLabel(""), } cfg := loadConfig() if cfg != nil { mainWindow.IPEntry.SetText(cfg.IP) mainWindow.PortEntry.SetText(cfg.Port) mainWindow.LoginEntry.SetText(cfg.Login) mainWindow.PasswordEntry.SetText(cfg.Password) mainWindow.SerialEntry.SetText(cfg.Serial) mainWindow.TailNumberEntry.SetText(cfg.TailNumber) mainWindow.DefaultHostEntry.SetText(cfg.DefaultHost) mainWindow.ArchivePathEntry.SetText(cfg.ArchivePath) } // Disable archive path entry (will be set by file selector) mainWindow.ArchivePathEntry.Disable() // Create archive selection button selectArchiveBtn := widget.NewButton("Select Archive", func() { CustomFileSelector(window, func(path string) { mainWindow.ArchivePathEntry.SetText(path) }) }) // Create install button mainWindow.InstallButton = widget.NewButton("Install", func() { config := &config.SSHConfig{ IP: mainWindow.IPEntry.Text, Port: mainWindow.PortEntry.Text, Login: mainWindow.LoginEntry.Text, Password: mainWindow.PasswordEntry.Text, Serial: mainWindow.SerialEntry.Text, TailNumber: mainWindow.TailNumberEntry.Text, DefaultHost: mainWindow.DefaultHostEntry.Text, ArchivePath: mainWindow.ArchivePathEntry.Text, } mainWindow.StatusLabel.SetText("Starting installation...") go func() { // Validate serial number if len([]rune(config.Serial)) != 16 { mainWindow.StatusLabel.SetText("Serial number must be 16 characters") dialog.ShowInformation("Error", "Serial number must be 16 characters", window) return } mu.Lock() jsonData, _ := json.MarshalIndent(config, "", " ") // Записываем JSON в файл fileName := "config.json" os.WriteFile(fileName, jsonData, 0644) mu.Unlock() // Perform installation err := installHandler(config) if err != nil { dialog.ShowError(err, window) mainWindow.StatusLabel.SetText("Installation failed") } else { mainWindow.StatusLabel.SetText("Installation completed successfully!") dialog.ShowInformation("Success", "Installation completed successfully!", window) } }() }) // Create form layout form := container.NewVBox( widget.NewForm( widget.NewFormItem("IP", mainWindow.IPEntry), widget.NewFormItem("Port", mainWindow.PortEntry), widget.NewFormItem("Login", mainWindow.LoginEntry), widget.NewFormItem("Password", mainWindow.PasswordEntry), widget.NewFormItem("Serial Number", mainWindow.SerialEntry), widget.NewFormItem("Tail Number", mainWindow.TailNumberEntry), widget.NewFormItem("Default Server", mainWindow.DefaultHostEntry), widget.NewFormItem("Archive", container.NewHBox(mainWindow.ArchivePathEntry, selectArchiveBtn)), ), mainWindow.InstallButton, mainWindow.StatusLabel, ) // Set window content and size window.SetContent(form) window.Resize(fyne.NewSize(400, 300)) return mainWindow } // Show displays the main window func (w *MainWindow) Show() { w.Window.Show() } // ShowAndRun displays the main window and starts the application func (w *MainWindow) ShowAndRun() { w.Window.ShowAndRun() }