Skip to content

Commit

Permalink
Merge branch 'release/v1.4.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
andydotxyz committed Dec 9, 2020
2 parents 57a9489 + 7489e4a commit f0fc94e
Show file tree
Hide file tree
Showing 82 changed files with 5,197 additions and 159 deletions.
1 change: 1 addition & 0 deletions .github/workflows/static_analysis.yml
Expand Up @@ -13,6 +13,7 @@ jobs:

- name: Get dependencies
run: |
sudo apt-get update
sudo apt-get install golang gcc libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libx11-dev xorg-dev
GO111MODULE=off go get golang.org/x/tools/cmd/goimports
GO111MODULE=off go get github.com/fzipp/gocyclo/cmd/gocyclo
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,29 @@
This file lists the main changes with each version of the Fyne toolkit.
More detailed release notes can be found on the [releases page](https://github.com/fyne-io/fyne/releases).

## 1.4.2 - 9 December 2020

### Added

* [fyne-cli] Add support for passing custom build tags (#1538)

### Changed

* Run validation on content change instead of on each Refresh in widget.Entry

### Fixed

* [fyne-cli] Android: allow to specify an inline password for the keystore
* Fixed Card widget MinSize (#1581)
* Fix missing release tag to enable BuildRelease in Settings.BuildType()
* Dialog shadow does not resize after Refresh (#1370)
* Android Duplicate Number Entry (#1256)
* Support older macOS by default - back to 10.11 (#886)
* Complete certification of macOS App Store releases (#1443)
* Fix compilation errors for early stage Wayland testing
* Fix entry.SetValidationError() not working correctly


## 1.4.1 - 20 November 2020

### Changed
Expand Down
5 changes: 2 additions & 3 deletions README.md
@@ -1,12 +1,11 @@
<p align="center">
<a href="https://pkg.go.dev/fyne.io/fyne?tab=doc" title="Go API Reference" rel="nofollow"><img src="https://img.shields.io/badge/go-documentation-blue.svg?style=flat" alt="Go API Reference"></a>
<a href="https://github.com/fyne-io/fyne/releases/tag/v1.4.1" title="1.4.1 Release" rel="nofollow"><img src="https://img.shields.io/badge/version-1.4.1-blue.svg?style=flat" alt="1.4.1 release"></a>
<a href="https://github.com/fyne-io/fyne/releases/tag/v1.4.2" title="1.4.2 Release" rel="nofollow"><img src="https://img.shields.io/badge/version-1.4.2-blue.svg?style=flat" alt="1.4.2 release"></a>
<a href='http://gophers.slack.com/messages/fyne'><img src='https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=blue' alt='Join us on Slack' /></a>
<br />
<a href="https://goreportcard.com/report/fyne.io/fyne"><img src="https://goreportcard.com/badge/fyne.io/fyne" alt="Code Status" /></a>
<a href="https://travis-ci.org/fyne-io/fyne"><img src="https://travis-ci.org/fyne-io/fyne.svg" alt="Build Status" /></a>
<a href="https://github.com/fyne-io/fyne/actions"><img src="https://github.com/fyne-io/fyne/workflows/Platform%20Tests/badge.svg" alt="Build Status" /></a>
<a href='https://coveralls.io/github/fyne-io/fyne?branch=develop'><img src='https://coveralls.io/repos/github/fyne-io/fyne/badge.svg?branch=develop' alt='Coverage Status' /></a>
<!--a href='https://sourcegraph.com/github.com/fyne-io/fyne?badge'><img src='https://sourcegraph.com/github.com/fyne-io/fyne/-/badge.svg' alt='Used By' /></a-->
</p>

# About
Expand Down
2 changes: 2 additions & 0 deletions canvas.go
Expand Up @@ -56,5 +56,7 @@ type Canvas interface {

// InteractiveArea returns the position and size of the central interactive area.
// Operating system elements may overlap the portions outside this area and widgets should avoid being outside.
//
// Since: 1.4
InteractiveArea() (Position, Size)
}
12 changes: 8 additions & 4 deletions canvas/raster.go
Expand Up @@ -15,10 +15,14 @@ var _ fyne.CanvasObject = (*Raster)(nil)
type Raster struct {
baseObject

Generator func(w, h int) image.Image // Render the raster image from code

Translucency float64 // Set a translucency value > 0.0 to fade the raster
ScaleMode ImageScale // Specify the type of scaling interpolation applied to the raster if it is not full-size
// Render the raster image from code
Generator func(w, h int) image.Image

// Set a translucency value > 0.0 to fade the raster
Translucency float64
// Specify the type of scaling interpolation applied to the raster if it is not full-size
// Since: 1.4.1
ScaleMode ImageScale
}

// Alpha is a convenience function that returns the alpha value for a raster
Expand Down
33 changes: 24 additions & 9 deletions cmd/fyne/commands/build.go
Expand Up @@ -5,11 +5,13 @@ import (
"os"
"os/exec"
"runtime"
"strings"
)

type builder struct {
os, srcdir string
release bool
tags []string
}

func (b *builder) build() error {
Expand All @@ -18,24 +20,37 @@ func (b *builder) build() error {
goos = targetOS()
}

var cmd *exec.Cmd
args := []string{"build"}
env := os.Environ()
env = append(env, "CGO_ENABLED=1") // in case someone is trying to cross-compile...

if goos == "windows" {
if b.release {
cmd = exec.Command("go", "build", "-ldflags", "-s -w -H=windowsgui", ".")
args = append(args, "-ldflags", "-s -w -H=windowsgui")
} else {
cmd = exec.Command("go", "build", "-ldflags", "-H=windowsgui", ".")
args = append(args, "-ldflags", "-H=windowsgui")
}
} else {
if goos == "darwin" {
env = append(env, "CGO_CFLAGS=-mmacosx-version-min=10.11")
env = append(env, "CGO_LDFLAGS=-mmacosx-version-min=10.11")
}
if b.release {
cmd = exec.Command("go", "build", "-ldflags", "-s -w", ".")
} else {
cmd = exec.Command("go", "build", ".")
args = append(args, "-ldflags", "-s -w")
}
}
cmd.Dir = b.srcdir
env := os.Environ()
env = append(env, "CGO_ENABLED=1") // in case someone is trying to cross-compile...

// handle build tags
tags := b.tags
if b.release {
tags = append(tags, "release")
}
if len(tags) > 0 {
args = append(args, "-tags", strings.Join(tags, ","))
}

cmd := exec.Command("go", args...)
cmd.Dir = b.srcdir
if goos != "ios" && goos != "android" {
env = append(env, "GOOS="+goos)
}
Expand Down
5 changes: 4 additions & 1 deletion cmd/fyne/commands/package-darwin.go
Expand Up @@ -4,6 +4,7 @@ import (
"image"
"os"
"path/filepath"
"strings"

"fyne.io/fyne/cmd/fyne/internal/templates"
"fyne.io/fyne/cmd/fyne/internal/util"
Expand All @@ -17,6 +18,7 @@ type darwinData struct {
AppID string
Version string
Build int
Category string
}

func (p *packager) packageDarwin() error {
Expand All @@ -27,7 +29,8 @@ func (p *packager) packageDarwin() error {
info := filepath.Join(contentsDir, "Info.plist")
infoFile, _ := os.Create(info)

tplData := darwinData{Name: p.name, ExeName: exeName, AppID: p.appID, Version: p.appVersion, Build: p.appBuild}
tplData := darwinData{Name: p.name, ExeName: exeName, AppID: p.appID, Version: p.appVersion, Build: p.appBuild,
Category: strings.ToLower(p.category)}
err := templates.InfoPlistDarwin.Execute(infoFile, tplData)
if err != nil {
return errors.Wrap(err, "Failed to write plist template")
Expand Down
4 changes: 4 additions & 0 deletions cmd/fyne/commands/package.go
Expand Up @@ -31,6 +31,7 @@ type packager struct {
appBuild int
install, release bool
certificate, profile string // optional flags for releasing
tags, category string
}

// NewPackager returns a packager command that can wrap executables into full GUI app packages.
Expand All @@ -48,6 +49,7 @@ func (p *packager) AddFlags() {
flag.StringVar(&p.appVersion, "appVersion", "", "Version number in the form x, x.y or x.y.z semantic version")
flag.IntVar(&p.appBuild, "appBuild", 0, "Build number, should be greater than 0 and incremented for each build")
flag.BoolVar(&p.release, "release", false, "Should this package be prepared for release? (disable debug etc)")
flag.StringVar(&p.tags, "tags", "", "A comma-separated list of build tags")
}

func (*packager) PrintHelp(indent string) {
Expand All @@ -71,10 +73,12 @@ func (p *packager) Run(_ []string) {
}

func (p *packager) buildPackage() error {
tags := strings.Split(p.tags, ",")
b := &builder{
os: p.os,
srcdir: p.srcDir,
release: p.release,
tags: tags,
}

return b.build()
Expand Down
99 changes: 94 additions & 5 deletions cmd/fyne/commands/release.go
Expand Up @@ -15,15 +15,28 @@ import (
"fyne.io/fyne/cmd/fyne/internal/util"
)

var (
macAppStoreCategories = []string{
"business", "developer-tools", "education", "entertainment", "finance", "games", "action-games",
"adventure-games", "arcade-games", "board-games", "card-games", "casino-games", "dice-games",
"educational-games", "family-games", "kids-games", "music-games", "puzzle-games", "racing-games",
"role-playing-games", "simulation-games", "sports-games", "strategy-games", "trivia-games", "word-games",
"graphics-design", "healthcare-fitness", "lifestyle", "medical", "music", "news", "photography",
"productivity", "reference", "social-networking", "sports", "travel", "utilities", "video", "weather",
}
)

// Declare conformity to Command interface
var _ Command = (*releaser)(nil)

type releaser struct {
packager

keyStore string
developer string
password string
keyStore string
keyStorePass string
keyPass string
developer string
password string
}

// NewReleaser returns a command that can adapt app packages for distribution
Expand All @@ -39,10 +52,14 @@ func (r *releaser) AddFlags() {
flag.StringVar(&r.appVersion, "appVersion", "", "Version number in the form x, x.y or x.y.z semantic version")
flag.IntVar(&r.appBuild, "appBuild", 0, "Build number, should be greater than 0 and incremented for each build")
flag.StringVar(&r.keyStore, "keyStore", "", "Android: location of .keystore file containing signing information")
flag.StringVar(&r.keyStorePass, "keyStorePass", "", "Android: password for the .keystore file, default take the password from stdin")
flag.StringVar(&r.keyPass, "keyPass", "", "Android: password for the signer's private key, which is needed if the private key is password-protected. Default take the password from stdin")
flag.StringVar(&r.certificate, "certificate", "", "iOS/macOS/Windows: name of the certificate to sign the build")
flag.StringVar(&r.profile, "profile", "", "iOS/macOS: name of the provisioning profile for this release build")
flag.StringVar(&r.developer, "developer", "", "Windows: the developer identity for your Microsoft store account")
flag.StringVar(&r.password, "password", "", "Windows: password for the certificate used to sign the build")
flag.StringVar(&r.tags, "tags", "", "A comma-separated list of build tags")
flag.StringVar(&r.category, "category", "", "macOS: category of the app for store listing")
}

func (r *releaser) PrintHelp(indent string) {
Expand Down Expand Up @@ -75,6 +92,9 @@ func (r *releaser) afterPackage() error {
}
return r.signAndroid(apk)
}
if r.os == "darwin" {
return r.packageMacOSRelease()
}
if r.os == "ios" {
return r.packageIOSRelease()
}
Expand Down Expand Up @@ -135,7 +155,7 @@ func (r *releaser) packageIOSRelease() error {
TeamID: team,
AppID: r.appID,
}
err = templates.EntitlementsDarwin.Execute(entitlements, entitlementData)
err = templates.EntitlementsDarwinMobile.Execute(entitlements, entitlementData)
entitlements.Close()
if err != nil {
return errors.New("failed to write entitlements plist template")
Expand All @@ -151,6 +171,44 @@ func (r *releaser) packageIOSRelease() error {
return exec.Command("zip", "-r", appName[:len(appName)-4]+".ipa", "Payload/").Run()
}

func (r *releaser) packageMacOSRelease() error {
appCert := r.certificate // try to derive two certificates from one name (they will be consistent)
if strings.Contains(appCert, "Installer") {
appCert = strings.Replace(appCert, "Installer", "Application", 1)
}
installCert := strings.Replace(appCert, "Application", "Installer", 1)
unsignedPath := r.name + "-unsigned.pkg"

defer os.RemoveAll(r.name + ".app") // this was the output of package and it can get in the way of future builds
entitlementPath := filepath.Join(r.dir, "entitlements.plist")
entitlements, _ := os.Create(entitlementPath)
err := templates.EntitlementsDarwin.Execute(entitlements, nil)
entitlements.Close()
if err != nil {
return errors.New("failed to write entitlements plist template")
}
defer os.Remove(entitlementPath)

cmd := exec.Command("codesign", "-vfs", appCert, "--entitlement", "entitlements.plist", r.name+".app")
err = cmd.Run()
if err != nil {
fyne.LogError("Codesign failed", err)
return errors.New("unable to codesign application bundle")
}

cmd = exec.Command("productbuild", "--component", r.name+".app", "/Applications/",
"--product", r.name+".app/Contents/Info.plist", unsignedPath)
err = cmd.Run()
if err != nil {
fyne.LogError("Product build failed", err)
return errors.New("unable to build macOS app package")
}
defer os.Remove(unsignedPath)

cmd = exec.Command("productsign", "--sign", installCert, unsignedPath, r.name+".pkg")
return cmd.Run()
}

func (r *releaser) packageWindowsRelease(outFile string) error {
payload := filepath.Join(r.dir, "Payload")
os.Mkdir(payload, 0750)
Expand Down Expand Up @@ -192,7 +250,17 @@ func (r *releaser) packageWindowsRelease(outFile string) error {

func (r *releaser) signAndroid(path string) error {
signer := filepath.Join(util.AndroidBuildToolsPath(), "/apksigner")
cmd := exec.Command(signer, "sign", "--ks", r.keyStore, path)

args := []string{"sign", "--ks", r.keyStore}
if r.keyStorePass != "" {
args = append(args, "--ks-pass", "pass:"+r.keyStorePass)
}
if r.keyPass != "" {
args = append(args, "--key-pass", "pass:"+r.keyPass)
}
args = append(args, path)

cmd := exec.Command(signer, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
Expand Down Expand Up @@ -241,6 +309,16 @@ func (r *releaser) validate() error {
if r.keyStore == "" {
return errors.New("missing required -keyStore parameter for android release")
}
} else if r.os == "darwin" {
if r.certificate == "" {
r.certificate = "3rd Party Mac Developer Application"
}
if r.category == "" {
return errors.New("missing required -category parameter for macOS release")
} else if !isValidMacOSCategory(r.category) {
return errors.New("category does not match one of the supported list: " +
strings.Join(macAppStoreCategories, ", "))
}
} else if r.os == "ios" {
if r.certificate == "" {
r.certificate = "Apple Distribution"
Expand Down Expand Up @@ -281,3 +359,14 @@ func findWindowsSDKBin() (string, error) {

return filepath.Dir(matches[0]), nil
}

func isValidMacOSCategory(in string) bool {
found := false
for _, cat := range macAppStoreCategories {
if cat == strings.ToLower(in) {
found = true
break
}
}
return found
}
10 changes: 10 additions & 0 deletions cmd/fyne/commands/release_test.go
Expand Up @@ -16,3 +16,13 @@ func TestReleaser_nameFromCertInfo(t *testing.T) {
badCase := "Cn=Company, O=Company, L=City, S=State, C=Country"
assert.Equal(t, "Company", rel.nameFromCertInfo(badCase))
}

func TestIsValidMacOSCategory(t *testing.T) {
assert.True(t, isValidMacOSCategory("games"))
assert.True(t, isValidMacOSCategory("utilities"))
assert.True(t, isValidMacOSCategory("Games"))

assert.False(t, isValidMacOSCategory("sporps"))
assert.False(t, isValidMacOSCategory("android-games"))
assert.False(t, isValidMacOSCategory(""))
}

0 comments on commit f0fc94e

Please sign in to comment.