Refactor configuration and cryptographic services to use a unified API structure
This commit is contained in:
parent
2bfa3b7250
commit
4a2cc5b8ab
16 changed files with 537 additions and 130 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
|||
wails3
|
||||
build/
|
||||
vendor/
|
||||
.idea
|
||||
126
README.md
126
README.md
|
|
@ -1,8 +1,126 @@
|
|||
# Core
|
||||
# Core by Snider
|
||||
|
||||
A Helper for GoLang projects, who also use, but not exclusive to Wails.io v3+
|
||||
Core is an opinionated framework for building Go applications written for assured information exchange between the front-end and back-end of a Web3 environment.
|
||||
|
||||
You need a file called apptray.png in your assets folder
|
||||
There is no assumption of what front-end framework you are using, and no assumption of what back-end framework you are using.
|
||||
|
||||
However, Core provides a set of services that are useful for building applications that are built for the Web3 environment.
|
||||
|
||||
With working defaults, Core is designed to be as simple as possible to use, yet powerful enough to be used in a wide variety of applications.
|
||||
|
||||
## Libraries used in Core
|
||||
- [Wails.io](https://github.com/wailsapp/wails) - A framework for building desktop applications using Go and web technologies.
|
||||
- [ProtonMail OpenPGP](https://github.com/ProtonMail/go-crypto)
|
||||
## Features
|
||||
- [Core](#core) - Manages application configuration
|
||||
- [Core.Config](#coreconfig) - Manages application configuration
|
||||
- [Core.Crypto](#corecrypto) - Manages cryptographic operations
|
||||
- [Core.Database](#coredatabase) - Manages database operations
|
||||
- [Core.IPC](#coreipc) - Manages inter-process communication
|
||||
- [Core.Log](#corelog) - Manages logging
|
||||
- [Core.Network](#corenetwork) - Manages network operations
|
||||
- [Core.Storage](#corestorage) - Manages storage operations
|
||||
- [Core.UI](#coreui) - Manages user interface operations
|
||||
- [Core.Utils](#coreutils) - Manages utility operations
|
||||
- [Core.Display](#coredisplay) - Manages Windows, system tray and their states
|
||||
|
||||
|
||||
## Core
|
||||
|
||||
Core allows you to easily instantiate complex services within a locked-down environment enforcing logical enclaves.
|
||||
|
||||
### Basic Usage
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"cmd/demo"
|
||||
|
||||
"https://github.com/Snider/Core"
|
||||
)
|
||||
|
||||
func main() {
|
||||
demoService := core.New(
|
||||
core.WithService(demo.Register),
|
||||
core.WithServiceLock(), // This can go anywhere in the chain to be the Final Service (provides security clarity)
|
||||
)
|
||||
demoService.Run() // handled by wails, not implemented yet
|
||||
demoService.Wait() // handled by wails, not implemented yet
|
||||
demoService.Close() // handled by wails, not implemented yet
|
||||
}
|
||||
```
|
||||
|
||||
### Multiple Services
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"cmd/demo"
|
||||
|
||||
"https://github.com/Snider/Core"
|
||||
)
|
||||
|
||||
func main() {
|
||||
coreService := core.New(
|
||||
core.WithService(demo.Register),
|
||||
core.WithService(demo.RegisterDemo2),
|
||||
core.WithServiceLock(),
|
||||
)
|
||||
|
||||
rickService := core.New(
|
||||
core.WithService(demo.Register),
|
||||
core.WithService(demo.RegisterDemo2),
|
||||
core.WithServiceLock(),
|
||||
)
|
||||
mortyService := core.New(
|
||||
core.WithService(demo.Register),
|
||||
core.WithService(demo.RegisterDemo2),
|
||||
core.WithServiceLock(),
|
||||
)
|
||||
|
||||
core.Mod[API](coreService,"demo").name = "demo"
|
||||
core.Mod[API](rickService).name = "demo2"
|
||||
core.Mod[API](mortyService).name = "demo2"
|
||||
|
||||
}
|
||||
```
|
||||
### Registering Services
|
||||
Core aunties that your application is not able to access any of the services that are not explicitly registered.
|
||||
|
||||
That said,
|
||||
|
||||
## Core.Display
|
||||
|
||||
Display is a Wails.io service that provides the ability to open windows.
|
||||
Core.Display remembers the locations of your users windows and will reopen them when the application is restarted.
|
||||
Also allows you to adjust your windowing programmatically via JavaScript bindings, and for it to be persistent.
|
||||
|
||||
### Open A Window On Startup
|
||||
|
||||
```go
|
||||
func (d *API) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
|
||||
d.OpenWindow(
|
||||
OptName("main"),
|
||||
OptHeight(900),
|
||||
OptWidth(1280),
|
||||
OptURL("/"),
|
||||
OptTitle("Core"),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
```go
|
||||
window := d.OpenWindow(
|
||||
OptName("main"),
|
||||
OptHeight(900),
|
||||
OptWidth(1280),
|
||||
OptURL("/"),
|
||||
OptTitle("Core"),
|
||||
)
|
||||
```
|
||||
|
||||
### Full Wails Example
|
||||
```go
|
||||
package main
|
||||
|
||||
|
|
@ -38,4 +156,4 @@ func main() {
|
|||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/Snider/Core"
|
||||
"github.com/Snider/Core/config"
|
||||
"github.com/Snider/Core/crypt"
|
||||
"github.com/Snider/Core/display"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
|
@ -23,8 +24,9 @@ func main() {
|
|||
app.RegisterService(application.NewService(core.Service(
|
||||
core.WithWails(app), // Provides the Wails application instance to core services
|
||||
core.WithAssets(assets), // Provides the embed.FS to core services
|
||||
core.WithService(display.Register), // Provides the ability to open windows
|
||||
core.WithService(config.Register), // Provides the ability to persist UI state (windows reopen where they closed)
|
||||
core.WithService(display.Register), // Provides the ability to open windows
|
||||
core.WithService(crypt.Register), // Provides cryptographic functions
|
||||
core.WithServiceLock(), // locks core from accepting new services blocking access to IPC
|
||||
)))
|
||||
|
||||
|
|
|
|||
61
cmd/demo/demo.go
Normal file
61
cmd/demo/demo.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package demo
|
||||
|
||||
import "github.com/Snider/Core"
|
||||
|
||||
// this instance is the singleton instance of the demo module.
|
||||
var instance *API
|
||||
|
||||
type API struct {
|
||||
name string
|
||||
core *core.Core
|
||||
}
|
||||
|
||||
func main() {
|
||||
coreService := core.New(
|
||||
core.WithService(demo.Register),
|
||||
core.WithService(demo.RegisterDemo2),
|
||||
core.WithServiceLock(),
|
||||
)
|
||||
|
||||
rickService := core.New(
|
||||
core.WithService(demo.Register),
|
||||
core.WithService(demo.RegisterDemo2),
|
||||
core.WithServiceLock(),
|
||||
)
|
||||
mortyService := core.New(
|
||||
core.WithService(demo.Register),
|
||||
core.WithService(demo.RegisterDemo2),
|
||||
core.WithServiceLock(),
|
||||
)
|
||||
|
||||
core.Mod[API](coreService, "demo").name = "demo"
|
||||
core.Mod[API](rickService).name = "demo2"
|
||||
core.Mod[API](mortyService).name = "demo2"
|
||||
|
||||
}
|
||||
|
||||
func RegisterDemo(c *core.Core) error {
|
||||
instance = &API{
|
||||
core: c,
|
||||
}
|
||||
if err := c.RegisterModule("demo", instance); err != nil {
|
||||
return err
|
||||
}
|
||||
c.RegisterAction(handleActionCall)
|
||||
return nil
|
||||
}
|
||||
|
||||
func RegisterDemo2(c *core.Core) error {
|
||||
instance = &API{
|
||||
core: c,
|
||||
}
|
||||
if err := c.RegisterModule("demo", instance); err != nil {
|
||||
return err
|
||||
}
|
||||
c.RegisterAction(handleActionCall)
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleActionCall(c *core.Core, msg core.Message) error {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ const configFileName = "config.json"
|
|||
var ErrSetupRequired = errors.New("setup required: config.json not found")
|
||||
|
||||
// Service provides access to the application's configuration.
|
||||
var service *Config
|
||||
var instance *API
|
||||
|
||||
// NewService creates and initializes a new configuration service.
|
||||
// It loads an existing configuration or creates a default one if not found.
|
||||
|
|
@ -32,7 +32,7 @@ func Register(c *core.Core) error {
|
|||
configDir := filepath.Join(userHomeDir, "config")
|
||||
//configPath := filepath.Join(configDir, configFileName)
|
||||
|
||||
service = &Config{
|
||||
instance = &API{
|
||||
core: c,
|
||||
UserHomeDir: userHomeDir,
|
||||
ConfigDir: configDir,
|
||||
|
|
@ -43,11 +43,31 @@ func Register(c *core.Core) error {
|
|||
Language: "en",
|
||||
}
|
||||
|
||||
return c.RegisterModule("config", service)
|
||||
err = c.RegisterModule("config", instance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.RegisterAction(handleActionCall)
|
||||
return nil
|
||||
}
|
||||
func handleActionCall(c *core.Core, msg core.Message) error {
|
||||
switch m := msg.(type) {
|
||||
|
||||
case core.ActionServiceStartup:
|
||||
//err := instance.ServiceStartup(context.Background(), application.ServiceOptions{})
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
c.App.Logger.Info("Config service started")
|
||||
return nil
|
||||
default:
|
||||
c.App.Logger.Error("Unknown message type", "type", fmt.Sprintf("%T", m))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// newDefaultConfig creates a default configuration with resolved paths and ensures directories exist.
|
||||
func newDefaultConfig() (*Config, error) {
|
||||
func newDefaultConfig() (*API, error) {
|
||||
if strings.Contains(appName, "..") || strings.Contains(appName, string(filepath.Separator)) {
|
||||
return nil, fmt.Errorf("invalid app name '%s': contains path traversal characters", appName)
|
||||
}
|
||||
|
|
@ -68,7 +88,7 @@ func newDefaultConfig() (*Config, error) {
|
|||
return nil, fmt.Errorf("could not resolve cache directory: %w", err)
|
||||
}
|
||||
|
||||
cfg := &Config{
|
||||
instance := &API{
|
||||
UserHomeDir: userHomeDir,
|
||||
RootDir: rootDir,
|
||||
CacheDir: cacheDir,
|
||||
|
|
@ -80,18 +100,18 @@ func newDefaultConfig() (*Config, error) {
|
|||
Language: "en", // Hardcoded default, will be overridden if loaded or detected
|
||||
}
|
||||
|
||||
dirs := []string{cfg.RootDir, cfg.ConfigDir, cfg.DataDir, cfg.CacheDir, cfg.WorkspacesDir, cfg.UserHomeDir}
|
||||
dirs := []string{instance.RootDir, instance.ConfigDir, instance.DataDir, instance.CacheDir, instance.WorkspacesDir, instance.UserHomeDir}
|
||||
for _, dir := range dirs {
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return nil, fmt.Errorf("could not create directory %s: %w", dir, err)
|
||||
}
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
return instance, nil
|
||||
}
|
||||
|
||||
// Save writes the current configuration to config.json.
|
||||
func (c *Config) Save() error {
|
||||
func (c *API) Save() error {
|
||||
configPath := filepath.Join(c.ConfigDir, configFileName)
|
||||
|
||||
data, err := json.MarshalIndent(*c, "", " ")
|
||||
|
|
@ -106,7 +126,7 @@ func (c *Config) Save() error {
|
|||
}
|
||||
|
||||
// IsFeatureEnabled checks if a given feature is enabled in the configuration.
|
||||
func (c *Config) IsFeatureEnabled(feature string) bool {
|
||||
func (c *API) IsFeatureEnabled(feature string) bool {
|
||||
for _, f := range c.Features {
|
||||
if f == feature {
|
||||
return true
|
||||
|
|
@ -116,7 +136,7 @@ func (c *Config) IsFeatureEnabled(feature string) bool {
|
|||
}
|
||||
|
||||
// EnableFeature adds a feature to the list of enabled features and saves the config.
|
||||
func (c *Config) EnableFeature(feature string) error {
|
||||
func (c *API) EnableFeature(feature string) error {
|
||||
if c.IsFeatureEnabled(feature) {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
// Config holds the resolved paths and user-configurable settings for the application.
|
||||
type Config struct {
|
||||
type API struct {
|
||||
// --- Dynamic Paths (not stored in config.json) ---
|
||||
core *core.Core
|
||||
DataDir string `json:"-"`
|
||||
|
|
@ -27,7 +27,7 @@ type Config struct {
|
|||
}
|
||||
|
||||
// Key retrieves a configuration value by its key. It checks JSON tags and field names (case-insensitive).
|
||||
func (c *Config) Key(key string) (interface{}, error) {
|
||||
func (c *API) Key(key string) (interface{}, error) {
|
||||
// Use reflection to inspect the struct fields.
|
||||
val := reflect.ValueOf(c).Elem()
|
||||
typ := val.Type()
|
||||
|
|
|
|||
|
|
@ -1,23 +1,63 @@
|
|||
package crypt
|
||||
|
||||
import (
|
||||
"github.com/Snider/Core/config"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
core "github.com/Snider/Core"
|
||||
"github.com/Snider/Core/crypt/lib/openpgp"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
// HashType defines the supported hashing algorithms.
|
||||
type HashType string
|
||||
// createServerKeyPair is a package-level variable that can be swapped for testing.
|
||||
var createServerKeyPair = openpgp.CreateServerKeyPair
|
||||
|
||||
const (
|
||||
LTHN HashType = "lthn"
|
||||
SHA512 HashType = "sha512"
|
||||
SHA256 HashType = "sha256"
|
||||
SHA1 HashType = "sha1"
|
||||
MD5 HashType = "md5"
|
||||
)
|
||||
|
||||
// Service provides cryptographic functions.
|
||||
// It is the main entry point for all cryptographic operations
|
||||
// and is bound to the frontend.
|
||||
type Service struct {
|
||||
config *config.Config
|
||||
// ServiceStartup Startup is called when the app starts. It handles one-time cryptographic setup.
|
||||
func (s *API) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
|
||||
// Define the directory for server keys based on the central config.
|
||||
//serverKeysDir := filepath.Join(s.config.DataDir, "server_keys")
|
||||
//if err := filesystem.EnsureDir(filesystem.Local, serverKeysDir); err != nil {
|
||||
// return fmt.Errorf("failed to create server keys directory: %w", err)
|
||||
//}
|
||||
//
|
||||
//// Check for server key pair using the configured path.
|
||||
//serverKeyPath := filepath.Join(serverKeysDir, "server.lthn.pub")
|
||||
//if !filesystem.IsFile(filesystem.Local, serverKeyPath) {
|
||||
// log.Println("Creating server key pair...")
|
||||
// if err := createServerKeyPair(serverKeysDir); err != nil {
|
||||
// return fmt.Errorf("failed to create server key pair: %w", err)
|
||||
// }
|
||||
// log.Println("Server key pair created.")
|
||||
//}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Register creates a new crypt service and registers it with the core.
|
||||
var instance *API
|
||||
|
||||
func Register(c *core.Core) error {
|
||||
instance = &API{
|
||||
core: c,
|
||||
}
|
||||
if err := c.RegisterModule("crypt", instance); err != nil {
|
||||
return err
|
||||
}
|
||||
c.RegisterAction(handleActionCall)
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleActionCall(c *core.Core, msg core.Message) error {
|
||||
switch m := msg.(type) {
|
||||
|
||||
case core.ActionServiceStartup:
|
||||
err := instance.ServiceStartup(context.Background(), application.ServiceOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.App.Logger.Info("Crypt service started")
|
||||
return nil
|
||||
default:
|
||||
c.App.Logger.Error("Unknown message type", "type", fmt.Sprintf("%T", m))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
// Hash computes a hash of the payload using the specified algorithm.
|
||||
func (s *Service) Hash(lib HashType, payload string) string {
|
||||
func (s *API) Hash(lib HashType, payload string) string {
|
||||
switch lib {
|
||||
case LTHN:
|
||||
return lthn.Hash(payload)
|
||||
|
|
|
|||
24
crypt/header.go
Normal file
24
crypt/header.go
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package crypt
|
||||
|
||||
import (
|
||||
core "github.com/Snider/Core"
|
||||
)
|
||||
|
||||
// HashType defines the supported hashing algorithms.
|
||||
type HashType string
|
||||
|
||||
const (
|
||||
LTHN HashType = "lthn"
|
||||
SHA512 HashType = "sha512"
|
||||
SHA256 HashType = "sha256"
|
||||
SHA1 HashType = "sha1"
|
||||
MD5 HashType = "md5"
|
||||
)
|
||||
|
||||
// Service provides cryptographic functions.
|
||||
// It is the main entry point for all cryptographic operations
|
||||
// and is bound to the frontend.
|
||||
|
||||
type API struct {
|
||||
core *core.Core
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
package crypt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/Snider/Core/config"
|
||||
"github.com/Snider/Core/crypt/lib/openpgp"
|
||||
"github.com/Snider/Core/filesystem"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
// createServerKeyPair is a package-level variable that can be swapped for testing.
|
||||
var createServerKeyPair = openpgp.CreateServerKeyPair
|
||||
|
||||
// NewService creates a new crypt.Service, accepting a config service instance.
|
||||
func NewService(cfg *config.Config) *Service {
|
||||
return &Service{
|
||||
config: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceStartup Startup is called when the app starts. It handles one-time cryptographic setup.
|
||||
func (s *Service) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
|
||||
// Define the directory for server keys based on the central config.
|
||||
serverKeysDir := filepath.Join(s.config.DataDir, "server_keys")
|
||||
if err := filesystem.EnsureDir(filesystem.Local, serverKeysDir); err != nil {
|
||||
return fmt.Errorf("failed to create server keys directory: %w", err)
|
||||
}
|
||||
|
||||
// Check for server key pair using the configured path.
|
||||
serverKeyPath := filepath.Join(serverKeysDir, "server.lthn.pub")
|
||||
if !filesystem.IsFile(filesystem.Local, serverKeyPath) {
|
||||
log.Println("Creating server key pair...")
|
||||
if err := createServerKeyPair(serverKeysDir); err != nil {
|
||||
return fmt.Errorf("failed to create server key pair: %w", err)
|
||||
}
|
||||
log.Println("Server key pair created.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
// Luhn validates a number using the Luhn algorithm.
|
||||
func (s *Service) Luhn(payload string) bool {
|
||||
func (s *API) Luhn(payload string) bool {
|
||||
payload = strings.ReplaceAll(payload, " ", "")
|
||||
sum := 0
|
||||
isSecond := false
|
||||
|
|
@ -31,7 +31,7 @@ func (s *Service) Luhn(payload string) bool {
|
|||
}
|
||||
|
||||
// Fletcher16 computes the Fletcher-16 checksum.
|
||||
func (s *Service) Fletcher16(payload string) uint16 {
|
||||
func (s *API) Fletcher16(payload string) uint16 {
|
||||
data := []byte(payload)
|
||||
var sum1, sum2 uint16
|
||||
for _, b := range data {
|
||||
|
|
@ -42,7 +42,7 @@ func (s *Service) Fletcher16(payload string) uint16 {
|
|||
}
|
||||
|
||||
// Fletcher32 computes the Fletcher-32 checksum.
|
||||
func (s *Service) Fletcher32(payload string) uint32 {
|
||||
func (s *API) Fletcher32(payload string) uint32 {
|
||||
data := []byte(payload)
|
||||
// Pad with 0 to make it even length for uint16 conversion
|
||||
if len(data)%2 != 0 {
|
||||
|
|
@ -59,7 +59,7 @@ func (s *Service) Fletcher32(payload string) uint32 {
|
|||
}
|
||||
|
||||
// Fletcher64 computes the Fletcher-64 checksum.
|
||||
func (s *Service) Fletcher64(payload string) uint64 {
|
||||
func (s *API) Fletcher64(payload string) uint64 {
|
||||
data := []byte(payload)
|
||||
// Pad to multiple of 4
|
||||
if len(data)%4 != 0 {
|
||||
|
|
|
|||
|
|
@ -12,13 +12,15 @@ import (
|
|||
type ActionOpenWindow struct {
|
||||
Target string
|
||||
}
|
||||
type API struct {
|
||||
core *core.Core
|
||||
}
|
||||
|
||||
var instance *API
|
||||
|
||||
func Register(c *core.Core) error {
|
||||
instance = &API{
|
||||
core: c,
|
||||
windowHandles: make(map[string]*application.WebviewWindow),
|
||||
core: c,
|
||||
}
|
||||
if err := c.RegisterModule("display", instance); err != nil {
|
||||
return err
|
||||
|
|
@ -30,7 +32,8 @@ func Register(c *core.Core) error {
|
|||
func handleActionCall(c *core.Core, msg core.Message) error {
|
||||
switch m := msg.(type) {
|
||||
case *ActionOpenWindow:
|
||||
instance.OpenWindow(m.Target, application.WebviewWindowOptions{
|
||||
instance.NewWithStruct(&Window{
|
||||
Name: "main",
|
||||
Title: "Core",
|
||||
Height: 900,
|
||||
Width: 1280,
|
||||
|
|
@ -42,6 +45,7 @@ func handleActionCall(c *core.Core, msg core.Message) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.App.Logger.Info("Display service started")
|
||||
return nil
|
||||
default:
|
||||
c.App.Logger.Error("Unknown message type", "type", fmt.Sprintf("%T", m))
|
||||
|
|
@ -139,16 +143,16 @@ Platform Information:`,
|
|||
}
|
||||
|
||||
func (d *API) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
|
||||
d.core.App.Logger.Info("Display service starting up")
|
||||
d.analyzeScreens()
|
||||
d.monitorScreenChanges()
|
||||
d.buildMenu()
|
||||
d.systemTray()
|
||||
d.core.App.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Title: "Core",
|
||||
Height: 900,
|
||||
Width: 1280,
|
||||
URL: "/",
|
||||
})
|
||||
d.OpenWindow(
|
||||
OptName("main"),
|
||||
OptHeight(900),
|
||||
OptWidth(1280),
|
||||
OptURL("/"),
|
||||
OptTitle("Core"),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
package display
|
||||
|
||||
import (
|
||||
"github.com/Snider/Core"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
// Brand defines the type for different application brands.
|
||||
type Brand string
|
||||
|
||||
const (
|
||||
AdminHub Brand = "admin-hub"
|
||||
ServerHub Brand = "server-hub"
|
||||
GatewayHub Brand = "gateway-hub"
|
||||
DeveloperHub Brand = "developer-hub"
|
||||
ClientHub Brand = "client-hub"
|
||||
)
|
||||
|
||||
// Service manages all OS-level UI interactions (menus, windows, tray).
|
||||
// It is the main entry point for all display-related operations.
|
||||
type API struct {
|
||||
// --- Injected Dependencies ---
|
||||
core *core.Core
|
||||
|
||||
windowHandles map[string]*application.WebviewWindow
|
||||
}
|
||||
|
|
@ -22,7 +22,8 @@ func (d *API) systemTray() {
|
|||
// systray.SetIcon(appTrayIcon)
|
||||
//}
|
||||
// Create a hidden window for the system tray menu to interact with
|
||||
trayWindow := d.core.App.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
trayWindow := d.NewWithStruct(&Window{
|
||||
Name: "system-tray",
|
||||
Title: "System Tray Status",
|
||||
URL: "/#/system-tray",
|
||||
Width: 400,
|
||||
|
|
|
|||
|
|
@ -1,19 +1,73 @@
|
|||
package display
|
||||
|
||||
import "github.com/wailsapp/wails/v3/pkg/application"
|
||||
import (
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
// OpenWindow creates and shows a new webview window.
|
||||
// This function is callable from the frontend.
|
||||
func (d *API) OpenWindow(name string, options application.WebviewWindowOptions) {
|
||||
// Check if a window with that name already exists
|
||||
if window, exists := d.core.App.Window.GetByName(name); exists {
|
||||
window.Focus()
|
||||
return
|
||||
type Option func(*Window) error
|
||||
|
||||
type Window = application.WebviewWindowOptions
|
||||
|
||||
func OptName(s string) Option {
|
||||
return func(o *Window) error {
|
||||
o.Name = s
|
||||
return nil
|
||||
}
|
||||
}
|
||||
func OptTitle(s string) Option {
|
||||
return func(o *Window) error {
|
||||
o.Title = s
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
window := d.core.App.Window.NewWithOptions(options)
|
||||
d.windowHandles[name] = window
|
||||
window.Show()
|
||||
func OptURL(s string) Option {
|
||||
return func(o *Window) error {
|
||||
o.URL = s
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func OptWidth(i int) Option {
|
||||
return func(o *Window) error {
|
||||
o.Width = i
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func OptHeight(i int) Option {
|
||||
return func(o *Window) error {
|
||||
o.Height = i
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func applyOptions(opts ...Option) *Window {
|
||||
w := &Window{}
|
||||
if opts == nil {
|
||||
return w
|
||||
}
|
||||
for _, o := range opts {
|
||||
if err := o(w); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
// NewWithOptions creates a new window using the provided options and returns its handle.
|
||||
// The caller is responsible for showing the window.
|
||||
func (d *API) NewWithStruct(options *Window) *application.WebviewWindow {
|
||||
return d.core.App.Window.NewWithOptions(*options)
|
||||
}
|
||||
func (d *API) NewWithOptions(opts ...Option) *application.WebviewWindow {
|
||||
return d.NewWithStruct(applyOptions(opts...))
|
||||
}
|
||||
|
||||
// OpenWindow is a legacy or direct method to open a window using Wails-native options.
|
||||
// It returns the handle of the created window. The caller is responsible for showing the window.
|
||||
func (d *API) OpenWindow(opts ...Option) *application.WebviewWindow {
|
||||
return d.NewWithOptions(opts...)
|
||||
}
|
||||
|
||||
// SelectDirectory opens a directory selection dialog and returns the selected path.
|
||||
|
|
@ -21,7 +75,6 @@ func (d *API) SelectDirectory() (string, error) {
|
|||
dialog := application.OpenFileDialog()
|
||||
dialog.SetTitle("Select Project Directory")
|
||||
if path, err := dialog.PromptForSingleSelection(); err == nil {
|
||||
// Use selected directory path
|
||||
return path, nil
|
||||
}
|
||||
return "", nil
|
||||
|
|
|
|||
152
go.sum
Normal file
152
go.sum
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
|
||||
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||
github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
|
||||
github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
|
||||
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
|
||||
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
||||
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
|
||||
github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM=
|
||||
github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
|
||||
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0=
|
||||
github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
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/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A=
|
||||
github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
|
||||
github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M=
|
||||
github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
|
||||
github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y=
|
||||
github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
|
||||
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
|
||||
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.10 h1:+5FbKNTe5Z9aspU88DPIKJ9z2KZoaGCu6Sr6kKR/5mU=
|
||||
github.com/pkg/sftp v1.13.10/go.mod h1:bJ1a7uDhrX/4OII+agvy28lzRvQrmIQuaHrcI1HbeGA=
|
||||
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/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
|
||||
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg=
|
||||
github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/wailsapp/go-webview2 v1.0.22 h1:YT61F5lj+GGaat5OB96Aa3b4QA+mybD0Ggq6NZijQ58=
|
||||
github.com/wailsapp/go-webview2 v1.0.22/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
|
||||
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
|
||||
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
|
||||
github.com/wailsapp/wails/v3 v3.0.0-alpha.36 h1:GQ8vSrFgafITwMd/p4k+WBjG9K/anma9Pk2eJ/5CLsI=
|
||||
github.com/wailsapp/wails/v3 v3.0.0-alpha.36/go.mod h1:7i8tSuA74q97zZ5qEJlcVZdnO+IR7LT2KU8UpzYMPsw=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs=
|
||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo=
|
||||
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
|
||||
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
|
||||
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
Loading…
Add table
Reference in a new issue