package main import ( "embed" "os" "runtime" "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/assetserver" "cdrop-desktop/platform" ) //go:embed all:frontend/dist var assets embed.FS func main() { // Create an instance of the app structure app := NewApp() // Reverse-proxy /api/* to the backend so the embedded web UI can keep its // same-origin relative URLs (see platform.NewAPIProxy). SSE streams through. apiProxy, err := platform.NewAPIProxy(app.apiBase) if err != nil { println("Error:", err.Error()) return } // Windows: Wails' custom-scheme AssetServer buffers a handler's response until // it returns, so the long-lived SSE never reaches the WebView (device list // never loads, status stuck on "connecting"). Serve /api from a loopback HTTP // origin instead — WebView2's normal network stack streams it — and point the // page there via the injected api_base. macOS streams the custom scheme fine, // so it keeps api_base="" (same-origin relative /api through apiProxy). webAPIBase := "" if runtime.GOOS == "windows" { if base, lerr := platform.StartLocalAPIServer(app.apiBase); lerr == nil { webAPIBase = base } else { println("local api server:", lerr.Error()) } } // Tell the backend this is a native desktop client, not a browser, so the // device list shows the right kind. The page forwards it as X-Device-Type. deviceType := "" switch runtime.GOOS { case "darwin": deviceType = "macos" case "windows": deviceType = "windows" case "linux": deviceType = "linux" } // Restore the persisted login + device name by injecting them into index.html // at load — the wails:// scheme has no persistent WebView storage (see // session.go). session, _ := platform.LoadSession() // When the OS starts us at login, the autostart entry appends a --hidden flag // (see SetLaunchAtLogin). Come up straight to the menu bar / tray with no // window — the user didn't open the app, so don't steal focus. The frontend // still loads, so clipboard sync runs in the background. A manual launch has // no flag and shows the window as usual. hidden := launchedHidden() app.startHidden = hidden // Create application with options err = wails.Run(&options.App{ Title: "cdrop", Width: 1024, Height: 768, StartHidden: hidden, AssetServer: &assetserver.Options{ Assets: assets, Handler: apiProxy, Middleware: platform.SessionInjectMiddleware(session, platform.ResolveDeviceName(), webAPIBase, deviceType), }, BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, Menu: app.buildMenu(), OnStartup: app.startup, OnBeforeClose: app.beforeClose, Bind: []interface{}{ app, }, }) if err != nil { println("Error:", err.Error()) } } // launchedHidden reports whether this process was started by the login autostart // entry, which appends a --hidden flag to the launch command (see // SetLaunchAtLogin on each platform). Manual launches never carry it. func launchedHidden() bool { for _, arg := range os.Args[1:] { if arg == "--hidden" { return true } } return false }