From ae8a780af9b11a27522c182fc1d2d735f1998899 Mon Sep 17 00:00:00 2001 From: inkeliz Date: Sun, 14 Dec 2025 12:50:14 +0000 Subject: [PATCH] gogio: add deeplink support Add a new flag "-schemes" which links the URL schemes to the app. Signed-off-by: inkeliz --- gogio/androidbuild.go | 11 +++++++ gogio/build_info.go | 11 +++++++ gogio/help.go | 5 ++++ gogio/iosbuild.go | 68 ++++++++++++++++++++++++++++++++++++------- gogio/macosbuild.go | 48 ++++++++++++++++++++---------- gogio/main.go | 1 + gogio/windowsbuild.go | 10 ++++++- 7 files changed, 127 insertions(+), 27 deletions(-) diff --git a/gogio/androidbuild.go b/gogio/androidbuild.go index f6dc924..03951a0 100644 --- a/gogio/androidbuild.go +++ b/gogio/androidbuild.go @@ -48,6 +48,7 @@ type manifestData struct { Features []string IconSnip string AppName string + Schemes []string } const ( @@ -442,6 +443,7 @@ func exeAndroid(tmpDir string, tools *androidTools, bi *buildInfo, extraJars, pe Features: features, IconSnip: iconSnip, AppName: appName, + Schemes: bi.schemes, } tmpl, err := template.New("test").Parse( ` @@ -458,11 +460,20 @@ func exeAndroid(tmpDir string, tools *androidTools, bi *buildInfo, extraJars, pe android:theme="@style/Theme.GioApp" android:configChanges="screenSize|screenLayout|smallestScreenSize|orientation|keyboardHidden" android:windowSoftInputMode="adjustResize" + android:launchMode="singleInstance" android:exported="true"> + {{range .Schemes}} + + + + + + + {{end}} `) diff --git a/gogio/build_info.go b/gogio/build_info.go index f168330..5c17f41 100644 --- a/gogio/build_info.go +++ b/gogio/build_info.go @@ -31,6 +31,7 @@ type buildInfo struct { notaryAppleID string notaryPassword string notaryTeamID string + schemes []string } type Semver struct { @@ -78,6 +79,7 @@ func newBuildInfo(pkgPath string) (*buildInfo, error) { notaryAppleID: *notaryID, notaryPassword: *notaryPass, notaryTeamID: *notaryTeamID, + schemes: getCommaList(*schemes), } return bi, nil } @@ -147,6 +149,15 @@ func getLdFlags(appID string) string { return strings.Join(ldflags, " ") } +func getCommaList(s string) (list []string) { + for _, v := range strings.Split(s, ",") { + if v := strings.TrimSpace(v); v != "" { + list = append(list, v) + } + } + return list +} + type packageMetadata struct { PkgPath string Dir string diff --git a/gogio/help.go b/gogio/help.go index d6f6554..0338344 100644 --- a/gogio/help.go +++ b/gogio/help.go @@ -82,4 +82,9 @@ for details. If not provided, the password will be prompted. The -notaryteamid flag specifies the team ID to use for notarization of MacOS app, ignored if -notaryid is not provided. + +The -schemes flag specifies a list of comma separated URI schemes that the program can +handle. For example, use -schemes yourAppName to receive a app.URLEvent for URIs +starting with yourAppName://. It is only supported on Android, iOS, macOS and Windows. +On Windows, it will restrict the program to a single instance. ` diff --git a/gogio/iosbuild.go b/gogio/iosbuild.go index 00594f0..5d1db69 100644 --- a/gogio/iosbuild.go +++ b/gogio/iosbuild.go @@ -4,6 +4,7 @@ package main import ( "archive/zip" + "bytes" "crypto/sha1" "encoding/hex" "errors" @@ -15,6 +16,7 @@ import ( "slices" "strconv" "strings" + "text/template" "time" "golang.org/x/sync/errgroup" @@ -302,36 +304,57 @@ func buildInfoPlist(bi *buildInfo) string { case "tvos": supportPlatform = "AppleTVOS" } - return fmt.Sprintf(` + + manifestSrc := struct { + AppName string + AppID string + Version string + VersionCode uint32 + Platform string + MinVersion int + SupportPlatform string + Schemes []string + }{ + AppName: appName, + AppID: bi.appID, + Version: bi.version.String(), + VersionCode: bi.version.VersionCode, + Platform: platform, + MinVersion: minIOSVersion, + SupportPlatform: supportPlatform, + Schemes: bi.schemes, + } + + tmpl, err := template.New("manifest").Parse(` CFBundleDevelopmentRegion en CFBundleExecutable - %s + {{.AppName}} CFBundleIdentifier - %s + {{.AppID}} CFBundleInfoDictionaryVersion 6.0 CFBundleName - %s + {{.AppName}} CFBundlePackageType APPL CFBundleShortVersionString - %s + {{.Version}} CFBundleVersion - %d + {{.VersionCode}} UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities arm64 DTPlatformName - %s + {{.Platform}} DTPlatformVersion 12.4 MinimumOSVersion - %d + {{.MinVersion}} UIDeviceFamily 1 @@ -339,7 +362,7 @@ func buildInfoPlist(bi *buildInfo) string { CFBundleSupportedPlatforms - %s + {{.SupportPlatform}} UISupportedInterfaceOrientations @@ -354,13 +377,36 @@ func buildInfoPlist(bi *buildInfo) string { DTSDKBuild 16G73 DTSDKName - %s12.4 + {{.Platform}}12.4 DTXcode 1030 DTXcodeBuild 10G8 + {{if .Schemes}} + CFBundleURLTypes + + {{range .Schemes}} + + CFBundleURLSchemes + + {{.}} + + + {{end}} + + {{end}} -`, appName, bi.appID, appName, bi.version, bi.version.VersionCode, platform, minIOSVersion, supportPlatform, platform) +`) + if err != nil { + panic(err) + } + + var manifestBuffer bytes.Buffer + if err := tmpl.Execute(&manifestBuffer, manifestSrc); err != nil { + panic(err) + } + + return manifestBuffer.String() } func iosPlatformFor(target string) string { diff --git a/gogio/macosbuild.go b/gogio/macosbuild.go index c77f350..b9b79dd 100644 --- a/gogio/macosbuild.go +++ b/gogio/macosbuild.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "errors" "fmt" "os" @@ -34,9 +35,7 @@ func buildMac(tmpDir string, bi *buildInfo) error { return err } - if err := builder.setInfo(bi, name); err != nil { - return fmt.Errorf("can't build the resources: %v", err) - } + builder.setInfo(bi, name) for _, arch := range bi.archs { tmpDest := filepath.Join(builder.TempDir, filepath.Base(builder.DestDir)) @@ -122,7 +121,20 @@ func (b *macBuilder) setIcon(path string) (err error) { return err } -func (b *macBuilder) setInfo(buildInfo *buildInfo, name string) error { +func (b *macBuilder) setInfo(buildInfo *buildInfo, name string) { + + manifestSrc := struct { + Name string + Bundle string + Version Semver + Schemes []string + }{ + Name: name, + Bundle: buildInfo.appID, + Version: buildInfo.version, + Schemes: buildInfo.schemes, + } + t, err := template.New("manifest").Parse(` @@ -137,20 +149,28 @@ func (b *macBuilder) setInfo(buildInfo *buildInfo, name string) error { CFBundlePackageType APPL + {{if .Schemes}} + CFBundleURLTypes + + {{range .Schemes}} + + CFBundleURLSchemes + + {{.}} + + + {{end}} + + {{end}} `) if err != nil { - return err + panic(err) } - var manifest bufferCoff - if err := t.Execute(&manifest, struct { - Name, Bundle string - }{ - Name: name, - Bundle: buildInfo.appID, - }); err != nil { - return err + var manifest bytes.Buffer + if err := t.Execute(&manifest, manifestSrc); err != nil { + panic(err) } b.Manifest = manifest.Bytes() @@ -164,8 +184,6 @@ func (b *macBuilder) setInfo(buildInfo *buildInfo, name string) error { `) - - return nil } func (b *macBuilder) buildProgram(buildInfo *buildInfo, binDest string, name string, arch string) error { diff --git a/gogio/main.go b/gogio/main.go index 5945250..fb730f2 100644 --- a/gogio/main.go +++ b/gogio/main.go @@ -41,6 +41,7 @@ var ( notaryID = flag.String("notaryid", "", "specify the apple id to use for notarization.") notaryPass = flag.String("notarypass", "", "specify app-specific password of the Apple ID to be used for notarization.") notaryTeamID = flag.String("notaryteamid", "", "specify the team id to use for notarization.") + schemes = flag.String("schemes", "", "specify a list of comma separated URL schemes that the program accepts") ) func main() { diff --git a/gogio/windowsbuild.go b/gogio/windowsbuild.go index af93bb2..40dd7aa 100644 --- a/gogio/windowsbuild.go +++ b/gogio/windowsbuild.go @@ -202,10 +202,18 @@ func (b *windowsBuilder) buildProgram(buildInfo *buildInfo, name string, arch st dest = filepath.Join(filepath.Dir(b.DestDir), name+"_"+arch+".exe") } + ldflags := buildInfo.ldflags + if buildInfo.schemes != nil { + ldflags += ` -X "gioui.org/app.schemesURI=` + strings.Join(buildInfo.schemes, ",") + `" ` + } + if buildInfo.appID != "" { + ldflags += ` -X "gioui.org/app.ID=` + buildInfo.appID + `" ` + } + cmd := exec.Command( "go", "build", - "-ldflags=-H=windowsgui "+buildInfo.ldflags, + "-ldflags=-H=windowsgui "+ldflags, "-tags="+buildInfo.tags, "-o", dest, buildInfo.pkgPath,