104 lines
3.5 KiB
Go
104 lines
3.5 KiB
Go
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 := platform.DeviceType()
|
|
|
|
// 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()
|
|
// Heal a stale display identity (older builds baked the subject UUID and no avatar into
|
|
// the on-disk session) from the authoritative /api/me, and re-persist, BEFORE injecting it
|
|
// — so the name + picture are correct on every launch instead of depending on a fragile
|
|
// per-launch WebView /api/me (the source of the intermittent UUID regression). Bounded +
|
|
// best-effort: offline keeps the persisted identity.
|
|
session = platform.HealIdentity(session, app.apiBase)
|
|
|
|
// 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: "Commilitia Drop",
|
|
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
|
|
}
|