Basic GUI client, login dialog, various comments fixes after copypaste.
Some checks failed
Linting and tests / Linting (push) Failing after 6s
Some checks failed
Linting and tests / Linting (push) Failing after 6s
This commit is contained in:
parent
91bc3acb08
commit
0c37f46b53
@ -8,6 +8,8 @@ import (
|
||||
"bunker/client/internal/services/core/mainwindow"
|
||||
"bunker/client/internal/services/core/options"
|
||||
"bunker/client/internal/services/core/translations"
|
||||
"bunker/client/internal/services/features/accounts"
|
||||
"bunker/client/internal/services/features/tasks"
|
||||
"bunker/commons"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
@ -33,6 +35,9 @@ func main() {
|
||||
checkError(options.Initialize(app))
|
||||
checkError(mainwindow.Initialize(app))
|
||||
|
||||
checkError(accounts.Initialize(app))
|
||||
checkError(tasks.Initialize(app))
|
||||
|
||||
checkError(app.Start())
|
||||
}
|
||||
|
||||
|
13
client/internal/helpers/platform.go
Normal file
13
client/internal/helpers/platform.go
Normal file
@ -0,0 +1,13 @@
|
||||
package helpers
|
||||
|
||||
import "runtime"
|
||||
|
||||
// IsMobile returns true if current platform related to mobile devices (phones, tablets).
|
||||
func IsMobile() bool {
|
||||
switch runtime.GOOS {
|
||||
case "android", "ios":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
@ -3,8 +3,9 @@ package core
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"bunker/client/internal/services/core/mainwindow/dto"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
)
|
||||
|
||||
// ServiceNameMainWindow is a name for main window service.
|
||||
@ -20,11 +21,18 @@ var (
|
||||
// MainWindow is an interface for main window service.
|
||||
type MainWindow interface {
|
||||
// AddTab adds tab in main window.
|
||||
AddTab(tab *container.TabItem)
|
||||
AddTab(tab *dto.Tab)
|
||||
// MainWindow returns main window instance (e.g. for using as parent with dialogs).
|
||||
MainWindow() fyne.Window
|
||||
// RegisterAboutWindowSysInfoHandler registers handler for System Info tab in About dialog.
|
||||
RegisterAboutWindowSysInfoHandler(name string, hndl SysInfoHandler) error
|
||||
// SetStatusProgressBarCurrentValue sets current value for progressbar in status bar.
|
||||
SetStatusProgressBarCurrentValue(current float64)
|
||||
// SetStatusProgressBarMaxValue sets maximum value for progressbar in status bar.
|
||||
SetStatusProgressBarMaxValue(current float64)
|
||||
// SetStatus sets text in status bar. If non-empty text is passed - then progress bar is also shown, and hidden
|
||||
// if passed text is empty.
|
||||
SetStatus(status string)
|
||||
}
|
||||
|
||||
// SysInfoHandler is a function signature for registering with additional system information handler for About dialog.
|
||||
|
20
client/internal/services/core/mainwindow/dto/tab.go
Normal file
20
client/internal/services/core/mainwindow/dto/tab.go
Normal file
@ -0,0 +1,20 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
)
|
||||
|
||||
// Tab is a DTO of main window's tab that is responsible for showing content.
|
||||
type Tab struct {
|
||||
// Name is a name for tab. Won't render by default on desktop, only on mouse hover, but will be rendered on mobiles.
|
||||
Name string
|
||||
// Sidebar is a sidebar widget. On desktop in will be shown on left side of window, on mobiles as separate window.
|
||||
Sidebar fyne.CanvasObject
|
||||
// Widget is a widget shown in window.
|
||||
Widget fyne.CanvasObject
|
||||
// Icon is an icon to show on tab.
|
||||
Icon canvas.Image
|
||||
// BadgeCount is a number to show on tab, like unread messages, incompleted tasks, etc.
|
||||
BadgeCount uint16
|
||||
}
|
@ -6,12 +6,12 @@ import (
|
||||
"os"
|
||||
|
||||
"bunker/client/internal/application"
|
||||
"bunker/client/internal/helpers"
|
||||
"bunker/client/internal/services/core"
|
||||
"bunker/client/internal/services/core/mainwindow/models"
|
||||
"bunker/commons"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/lang"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
@ -19,15 +19,18 @@ import (
|
||||
var _ = core.MainWindow(&mainWindow{})
|
||||
|
||||
type mainWindow struct {
|
||||
app *application.Application
|
||||
logger *slog.Logger
|
||||
window fyne.Window
|
||||
options core.Options
|
||||
tabs *container.AppTabs
|
||||
sysInfoHandlers map[string]*models.SysInfoHandler
|
||||
app *application.Application
|
||||
logger *slog.Logger
|
||||
window fyne.Window
|
||||
options core.Options
|
||||
tabsWidget *fyne.Container
|
||||
statusBarProgress *widget.ProgressBar
|
||||
statusBarStatus *widget.Label
|
||||
sysInfoHandlers map[string]*models.SysInfoHandler
|
||||
tabs []*models.Tab
|
||||
}
|
||||
|
||||
// Initialize инициализирует сервис.
|
||||
// Initialize initializes service.
|
||||
func Initialize(app *application.Application) error {
|
||||
mainW := &mainWindow{
|
||||
app: app,
|
||||
@ -70,20 +73,20 @@ func (m *mainWindow) Initialize() error {
|
||||
m.window = m.app.Fyne().NewWindow(lang.L("window.title"))
|
||||
// ToDo: сохранение и восстановление размеров окна.
|
||||
//nolint:mnd
|
||||
m.window.Resize(fyne.NewSize(800, 650))
|
||||
m.window.Resize(fyne.NewSize(1100, 800))
|
||||
|
||||
m.initializeMenu()
|
||||
var mainWindowCanvas fyne.CanvasObject
|
||||
|
||||
if helpers.IsMobile() {
|
||||
mainWindowCanvas = m.initializeMainWindowMobile()
|
||||
} else {
|
||||
mainWindowCanvas = m.initializeMainWindowDesktop()
|
||||
}
|
||||
|
||||
m.window.SetContent(mainWindowCanvas)
|
||||
|
||||
m.window.SetCloseIntercept(m.stopApp)
|
||||
|
||||
welcomeLabel := widget.NewLabel(lang.L("window.lorem_ipsum.text"))
|
||||
welcomeLabel.Wrapping = fyne.TextWrapWord
|
||||
|
||||
m.tabs = container.NewAppTabs(
|
||||
container.NewTabItem(lang.L("window.lorem_ipsum.tab_name"), welcomeLabel),
|
||||
)
|
||||
m.window.SetContent(m.tabs)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
package mainwindow
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func (m *mainWindow) initializeMainWindowDesktop() fyne.CanvasObject {
|
||||
switcherButton := m.initializeSwitcherDesktop()
|
||||
appNameLabel := widget.NewLabel("Bunker " + m.app.Fyne().Metadata().Custom["Version"])
|
||||
sidebarHeader := container.NewVBox(container.NewHBox(switcherButton, appNameLabel), widget.NewSeparator())
|
||||
sideBar := container.NewBorder(sidebarHeader, nil, nil, nil)
|
||||
|
||||
splitter := container.NewHSplit(sideBar, container.NewVBox(widget.NewLabel("widget data"), widget.NewSeparator()))
|
||||
splitter.SetOffset(0.2)
|
||||
|
||||
statusBar := m.initializeDesktopStatusBar()
|
||||
|
||||
mainWidget := container.NewBorder(nil, statusBar, nil, nil, splitter)
|
||||
|
||||
return mainWidget
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package mainwindow
|
||||
|
||||
import (
|
||||
"bunker/client/internal/widgets"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func (m *mainWindow) initializeDesktopStatusBar() fyne.CanvasObject {
|
||||
m.statusBarStatus = widget.NewLabel("Ready.")
|
||||
m.statusBarProgress = widget.NewProgressBar()
|
||||
m.statusBarProgress.Hide()
|
||||
|
||||
statusBarForToolbar := widgets.NewToolbarProgressBarWithBar(m.statusBarProgress)
|
||||
|
||||
statusBar := widget.NewToolbar()
|
||||
statusBar.Append(widgets.NewToolbarLabelWithLabel(m.statusBarStatus))
|
||||
statusBar.Append(statusBarForToolbar)
|
||||
statusBar.Append(widget.NewToolbarSpacer())
|
||||
|
||||
return statusBar
|
||||
}
|
||||
|
||||
func (m *mainWindow) SetStatusProgressBarCurrentValue(current float64) {
|
||||
m.statusBarProgress.SetValue(current)
|
||||
}
|
||||
|
||||
func (m *mainWindow) SetStatusProgressBarMaxValue(maxValue float64) {
|
||||
m.statusBarProgress.Max = maxValue
|
||||
}
|
||||
|
||||
func (m *mainWindow) SetStatus(status string) {
|
||||
m.statusBarStatus.SetText(status)
|
||||
|
||||
if status == "" {
|
||||
m.statusBarStatus.SetText("Ready.")
|
||||
m.statusBarProgress.Hide()
|
||||
} else {
|
||||
m.statusBarProgress.Show()
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package mainwindow
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func (m *mainWindow) initializeMainWindowMobile() fyne.CanvasObject {
|
||||
return widget.NewLabel("Mobile interface not yet implemented.")
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package mainwindow
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func (m *mainWindow) initializeSwitcherDesktop() fyne.CanvasObject {
|
||||
m.logger.Debug("Initializing desktop switcher...")
|
||||
|
||||
btn := widget.NewButtonWithIcon(
|
||||
"",
|
||||
m.app.Fyne().Settings().Theme().Icon(theme.IconNameMenu),
|
||||
m.desktopSwitcherButtonTapped,
|
||||
)
|
||||
|
||||
return btn
|
||||
}
|
||||
|
||||
func (m *mainWindow) desktopSwitcherButtonTapped() {
|
||||
m.logger.Debug("Showing desktop switcher...")
|
||||
|
||||
popup := widget.NewPopUp(widget.NewLabel("All hail switcher!"), m.window.Canvas())
|
||||
popup.ShowAtRelativePosition(fyne.NewPos(0, 0), m.window.Content())
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package mainwindow
|
||||
|
||||
func (m *mainWindow) initializeSwitcherMobile() {
|
||||
m.logger.Debug("Initializing mobile switcher...")
|
||||
}
|
18
client/internal/services/core/mainwindow/models/tab.go
Normal file
18
client/internal/services/core/mainwindow/models/tab.go
Normal file
@ -0,0 +1,18 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
)
|
||||
|
||||
// Tab is an internal representation of main window's tab that is responsible for showing content.
|
||||
type Tab struct {
|
||||
// Name is a name for tab. Won't render by default on desktop, only on mouse hover, but will be rendered on mobiles.
|
||||
Name string
|
||||
// Widget is a widget shown in window.
|
||||
Widget fyne.CanvasObject
|
||||
// Icon is an icon to show on tab.
|
||||
Icon canvas.Image
|
||||
// BadgeCount is a number to show on tab, like unread messages, incompleted tasks, etc.
|
||||
BadgeCount uint16
|
||||
}
|
@ -1,14 +1,8 @@
|
||||
package mainwindow
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/lang"
|
||||
"bunker/client/internal/services/core/mainwindow/dto"
|
||||
)
|
||||
|
||||
func (m *mainWindow) AddTab(tab *container.TabItem) {
|
||||
if len(m.tabs.Items) == 1 && m.tabs.Items[0].Text == lang.L("window.lorem_ipsum.tab_name") {
|
||||
m.tabs.Remove(m.tabs.Items[0])
|
||||
}
|
||||
|
||||
m.tabs.Append(tab)
|
||||
func (m *mainWindow) AddTab(tab *dto.Tab) {
|
||||
}
|
||||
|
@ -6,20 +6,16 @@ import (
|
||||
"bunker/client/internal/services/core/options/dto"
|
||||
)
|
||||
|
||||
// ServiceNameOptions это название для сервиса работы с настройками.
|
||||
// ServiceNameOptions is a name for options service which controls options dialog and options storage.
|
||||
const ServiceNameOptions = "core/options"
|
||||
|
||||
var (
|
||||
// ErrOptions говорит о возникновении ошибки в сервисе работы с настройками.
|
||||
ErrOptions = errors.New("options core service")
|
||||
// ErrOptionsIsInvalid говорит о неверной имплементации сервиса работы с настройками.
|
||||
ErrOptionsIsInvalid = errors.New("options service implementation is invalid")
|
||||
)
|
||||
// ErrOptionsIsInvalid appears when options service implementation is invalid.
|
||||
var ErrOptionsIsInvalid = errors.New("options service implementation is invalid")
|
||||
|
||||
// Options это интерфейс для сервиса работы с настройками.
|
||||
// Options is an interface for options service.
|
||||
type Options interface {
|
||||
// RegisterOptionsWidget регистрирует виджет настроек, а также необходимые дополнительные параметры.
|
||||
// RegisterOptionsWidget registers options widget for options dialog.
|
||||
RegisterOptionsWidget(widgetData *dto.OptionPane) error
|
||||
// ShowOptionsDialog показывает диалог с настройками. Используется только главным окном!
|
||||
// ShowOptionsDialog shows options dialog.
|
||||
ShowOptionsDialog()
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
@ -9,7 +10,11 @@ import (
|
||||
"bunker/client/internal/services/core/options/models"
|
||||
)
|
||||
|
||||
var _ = core.Options(&options{})
|
||||
var (
|
||||
_ = core.Options(&options{})
|
||||
|
||||
errOptions = errors.New("options core service")
|
||||
)
|
||||
|
||||
type options struct {
|
||||
app *application.Application
|
||||
@ -18,17 +23,17 @@ type options struct {
|
||||
mainWindow core.MainWindow
|
||||
|
||||
widgets map[string]*models.OptionPane
|
||||
widgetsItems []string // для рисования списка Fyne.
|
||||
widgetsItems []string // for Fyne's list widget.
|
||||
}
|
||||
|
||||
// Initialize инициализирует сервис.
|
||||
// Initialize initializes service.
|
||||
func Initialize(app *application.Application) error {
|
||||
opts := &options{
|
||||
app: app,
|
||||
}
|
||||
|
||||
if err := app.RegisterService(opts); err != nil {
|
||||
return fmt.Errorf("%w: %w", core.ErrOptions, err)
|
||||
return fmt.Errorf("%w: %w", &errOptions, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"bunker/client/internal/services/core"
|
||||
"bunker/client/internal/services/core/options/dto"
|
||||
"bunker/client/internal/services/core/options/models"
|
||||
)
|
||||
@ -15,7 +14,7 @@ func (o *options) RegisterOptionsWidget(widgetData *dto.OptionPane) error {
|
||||
if _, found := o.widgets[widgetData.Name]; found {
|
||||
return fmt.Errorf(
|
||||
"%w: RegisterOptionsWidget: '%s': %w",
|
||||
core.ErrOptions,
|
||||
errOptions,
|
||||
widgetData.Name,
|
||||
errWidgetPaneAlreadyRegistered,
|
||||
)
|
||||
|
@ -4,15 +4,11 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// ServiceNameTranslations это название для сервиса работы с переводами.
|
||||
// ServiceNameTranslations is a name for translations service.
|
||||
const ServiceNameTranslations = "core/translations"
|
||||
|
||||
var (
|
||||
// ErrTranslations говорит о возникновении ошибки в сервисе работы с настройками.
|
||||
ErrTranslations = errors.New("translations core service")
|
||||
// ErrTranslationsIsInvalid говорит о неверной имплементации сервиса работы с переводами.
|
||||
ErrTranslationsIsInvalid = errors.New("translations service implementation is invalid")
|
||||
)
|
||||
// ErrTranslationsIsInvalid appears when translations service implementation is invalid
|
||||
var ErrTranslationsIsInvalid = errors.New("translations service implementation is invalid")
|
||||
|
||||
// Translations это интерфейс для сервиса работы с переводами.
|
||||
// Translations is an interface for translations service.
|
||||
type Translations interface{}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package translations
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
@ -12,7 +13,11 @@ import (
|
||||
"fyne.io/fyne/v2/lang"
|
||||
)
|
||||
|
||||
var _ = core.Translations(&translations{})
|
||||
var (
|
||||
_ = core.Translations(&translations{})
|
||||
|
||||
errTranslations = errors.New("translations core service")
|
||||
)
|
||||
|
||||
type translations struct {
|
||||
app *application.Application
|
||||
@ -20,14 +25,14 @@ type translations struct {
|
||||
mainWindow core.MainWindow
|
||||
}
|
||||
|
||||
// Initialize инициализирует сервис.
|
||||
// Initialize initializes service.
|
||||
func Initialize(app *application.Application) error {
|
||||
transl := &translations{
|
||||
app: app,
|
||||
}
|
||||
|
||||
if err := app.RegisterService(transl); err != nil {
|
||||
return fmt.Errorf("%w: %w", core.ErrOptions, err)
|
||||
return fmt.Errorf("%w: %w", errTranslations, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -67,7 +72,7 @@ func (t *translations) Initialize() error {
|
||||
t.logger.Info("Current system locale.", "locale", lang.SystemLocale().String(), "LANG", langFromEnv)
|
||||
|
||||
if err := lang.AddTranslationsFS(langfiles.LangFiles, "files"); err != nil {
|
||||
return fmt.Errorf("%w: load translations: %w", core.ErrTranslations, err)
|
||||
return fmt.Errorf("%w: load translations: %w", errTranslations, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
4
client/internal/services/features/accounts.go
Normal file
4
client/internal/services/features/accounts.go
Normal file
@ -0,0 +1,4 @@
|
||||
package features
|
||||
|
||||
// ServiceNameAccounts is a name for accounts service.
|
||||
const ServiceNameAccounts = "features/accounts"
|
93
client/internal/services/features/accounts/accounts.go
Normal file
93
client/internal/services/features/accounts/accounts.go
Normal file
@ -0,0 +1,93 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"bunker/client/internal/application"
|
||||
"bunker/client/internal/services/core"
|
||||
"bunker/client/internal/services/features"
|
||||
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
var errAccounts = errors.New("accounts feature service")
|
||||
|
||||
type accounts struct {
|
||||
app *application.Application
|
||||
logger *slog.Logger
|
||||
db core.Database
|
||||
mainWindow core.MainWindow
|
||||
|
||||
loginDialogInstanceAddressEntry *widget.Entry
|
||||
loginDialogUsernameEntry *widget.Entry
|
||||
loginDialogPasswordEntry *widget.Entry
|
||||
}
|
||||
|
||||
// Initialize initializes service.
|
||||
func Initialize(app *application.Application) error {
|
||||
accts := &accounts{
|
||||
app: app,
|
||||
}
|
||||
|
||||
if err := app.RegisterService(accts); err != nil {
|
||||
return fmt.Errorf("%w: %w", errAccounts, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *accounts) Configure() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *accounts) ConnectDependencies() error {
|
||||
databaseRaw := a.app.Service(core.ServiceNameDatabase)
|
||||
if databaseRaw == nil {
|
||||
return fmt.Errorf("connect dependencies: get database service: %w", application.ErrServiceNotFound)
|
||||
}
|
||||
|
||||
database, valid := databaseRaw.(core.Database)
|
||||
if !valid {
|
||||
return fmt.Errorf("connect dependencies: type assert database service: %w", core.ErrDatabaseIsInvalid)
|
||||
}
|
||||
|
||||
a.db = database
|
||||
|
||||
mainWindowRaw := a.app.Service(core.ServiceNameMainWindow)
|
||||
if mainWindowRaw == nil {
|
||||
return fmt.Errorf("connect dependencies: get main window: %w", application.ErrServiceNotFound)
|
||||
}
|
||||
|
||||
mainWindow, valid := mainWindowRaw.(core.MainWindow)
|
||||
if !valid {
|
||||
return fmt.Errorf("connect dependencies: type assert main window: %w", core.ErrMainWindowIsInvalid)
|
||||
}
|
||||
|
||||
a.mainWindow = mainWindow
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *accounts) Initialize() error {
|
||||
a.logger = a.app.NewLogger("service", features.ServiceNameTasks)
|
||||
|
||||
a.logger.Info("Initializing...")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *accounts) Name() string {
|
||||
return features.ServiceNameTasks
|
||||
}
|
||||
|
||||
func (a *accounts) LaunchStartupTasks() error {
|
||||
a.loginDialogShow()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *accounts) Shutdown() error {
|
||||
return nil
|
||||
}
|
53
client/internal/services/features/accounts/login_dialog.go
Normal file
53
client/internal/services/features/accounts/login_dialog.go
Normal file
@ -0,0 +1,53 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
func (a *accounts) loginDialogLogin() {
|
||||
a.logger.Info(
|
||||
"Trying to log in...",
|
||||
"instance", a.loginDialogInstanceAddressEntry.Text,
|
||||
"username", a.loginDialogUsernameEntry.Text,
|
||||
"password", a.loginDialogPasswordEntry.Text,
|
||||
)
|
||||
}
|
||||
|
||||
func (a *accounts) loginDialogShow() {
|
||||
if a.loginDialogInstanceAddressEntry == nil {
|
||||
a.loginDialogInstanceAddressEntry = widget.NewEntry()
|
||||
a.loginDialogInstanceAddressEntry.SetText("http://localhost:53400")
|
||||
}
|
||||
|
||||
if a.loginDialogUsernameEntry == nil {
|
||||
a.loginDialogUsernameEntry = widget.NewEntry()
|
||||
a.loginDialogUsernameEntry.SetPlaceHolder("username")
|
||||
}
|
||||
|
||||
if a.loginDialogPasswordEntry == nil {
|
||||
a.loginDialogPasswordEntry = widget.NewEntry()
|
||||
} else {
|
||||
a.loginDialogPasswordEntry.SetText("")
|
||||
}
|
||||
|
||||
loginForm := widget.NewForm(
|
||||
widget.NewFormItem("Instance address:", a.loginDialogInstanceAddressEntry),
|
||||
widget.NewFormItem("Login:", a.loginDialogUsernameEntry),
|
||||
widget.NewFormItem("Password:", a.loginDialogPasswordEntry),
|
||||
)
|
||||
|
||||
loginButton := widget.NewButton("Log in", a.loginDialogLogin)
|
||||
|
||||
loginDialogContent := container.NewBorder(nil, loginButton, nil, nil, loginForm)
|
||||
|
||||
dialog := dialog.NewCustomWithoutButtons(
|
||||
"Login to Bunker instance",
|
||||
loginDialogContent,
|
||||
a.mainWindow.MainWindow(),
|
||||
)
|
||||
dialog.Resize(dialog.MinSize().AddWidthHeight(200, 0))
|
||||
|
||||
dialog.Show()
|
||||
}
|
4
client/internal/services/features/tasks.go
Normal file
4
client/internal/services/features/tasks.go
Normal file
@ -0,0 +1,4 @@
|
||||
package features
|
||||
|
||||
// ServiceNameTasks is a name for tasks service.
|
||||
const ServiceNameTasks = "features/tasks"
|
85
client/internal/services/features/tasks/tasks.go
Normal file
85
client/internal/services/features/tasks/tasks.go
Normal file
@ -0,0 +1,85 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"bunker/client/internal/application"
|
||||
"bunker/client/internal/services/core"
|
||||
"bunker/client/internal/services/features"
|
||||
)
|
||||
|
||||
var errTasks = errors.New("tasks feature service")
|
||||
|
||||
type tasks struct {
|
||||
app *application.Application
|
||||
logger *slog.Logger
|
||||
db core.Database
|
||||
mainWindow core.MainWindow
|
||||
}
|
||||
|
||||
// Initialize initializes service.
|
||||
func Initialize(app *application.Application) error {
|
||||
tsks := &tasks{
|
||||
app: app,
|
||||
}
|
||||
|
||||
if err := app.RegisterService(tsks); err != nil {
|
||||
return fmt.Errorf("%w: %w", errTasks, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tasks) Configure() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tasks) ConnectDependencies() error {
|
||||
databaseRaw := t.app.Service(core.ServiceNameDatabase)
|
||||
if databaseRaw == nil {
|
||||
return fmt.Errorf("connect dependencies: get database service: %w", application.ErrServiceNotFound)
|
||||
}
|
||||
|
||||
database, valid := databaseRaw.(core.Database)
|
||||
if !valid {
|
||||
return fmt.Errorf("connect dependencies: type assert database service: %w", core.ErrDatabaseIsInvalid)
|
||||
}
|
||||
|
||||
t.db = database
|
||||
|
||||
mainWindowRaw := t.app.Service(core.ServiceNameMainWindow)
|
||||
if mainWindowRaw == nil {
|
||||
return fmt.Errorf("connect dependencies: get main window: %w", application.ErrServiceNotFound)
|
||||
}
|
||||
|
||||
mainWindow, valid := mainWindowRaw.(core.MainWindow)
|
||||
if !valid {
|
||||
return fmt.Errorf("connect dependencies: type assert main window: %w", core.ErrMainWindowIsInvalid)
|
||||
}
|
||||
|
||||
t.mainWindow = mainWindow
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tasks) Initialize() error {
|
||||
t.logger = t.app.NewLogger("service", features.ServiceNameTasks)
|
||||
|
||||
t.logger.Info("Initializing...")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tasks) Name() string {
|
||||
return features.ServiceNameAccounts
|
||||
}
|
||||
|
||||
func (t *tasks) LaunchStartupTasks() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tasks) Shutdown() error {
|
||||
return nil
|
||||
}
|
21
client/internal/widgets/toolbar_label.go
Normal file
21
client/internal/widgets/toolbar_label.go
Normal file
@ -0,0 +1,21 @@
|
||||
package widgets
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
// ToolbarLabel is a label widget for toolbar.
|
||||
type ToolbarLabel struct {
|
||||
*widget.Label
|
||||
}
|
||||
|
||||
// NewToolbarLabelWithLabel creates new toolbar label with passed label as base widget.
|
||||
func NewToolbarLabelWithLabel(label *widget.Label) widget.ToolbarItem {
|
||||
return &ToolbarLabel{label}
|
||||
}
|
||||
|
||||
// ToolbarObject returns toolbar item.
|
||||
func (tl *ToolbarLabel) ToolbarObject() fyne.CanvasObject {
|
||||
return tl.Label
|
||||
}
|
23
client/internal/widgets/toolbar_progressbar.go
Normal file
23
client/internal/widgets/toolbar_progressbar.go
Normal file
@ -0,0 +1,23 @@
|
||||
package widgets
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
// ToolbarProgressBar is a progressbar widget for toolbar.
|
||||
type ToolbarProgressBar struct {
|
||||
*widget.ProgressBar
|
||||
}
|
||||
|
||||
// NewToolbarProgressBarWithBar creates new progressbar for toolbar with provided progressbar.
|
||||
func NewToolbarProgressBarWithBar(bar *widget.ProgressBar) *ToolbarProgressBar {
|
||||
return &ToolbarProgressBar{
|
||||
bar,
|
||||
}
|
||||
}
|
||||
|
||||
// ToolbarObject returns toolbar item.
|
||||
func (tl *ToolbarProgressBar) ToolbarObject() fyne.CanvasObject {
|
||||
return tl
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user