Add cmd/passgo-gui files updated for Android implementation.
This commit is contained in:
parent
8611bfb5e0
commit
ea9b4b3861
|
@ -64,6 +64,15 @@ public class PgpConnect extends Fragment {
|
||||||
installComplete(this);
|
installComplete(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//For debugging:
|
||||||
|
/*private void printExtras(Intent data) {
|
||||||
|
Bundle bundle = data.getExtras();
|
||||||
|
if (bundle != null) {
|
||||||
|
for (String k : bundle.keySet()) {
|
||||||
|
Log.d("gio", "extra:" + k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
Log.d("gio", "onActivityResult(" + requestCode + "): " + resultCode);
|
Log.d("gio", "onActivityResult(" + requestCode + "): " + resultCode);
|
||||||
|
@ -74,12 +83,6 @@ public class PgpConnect extends Fragment {
|
||||||
stringResult(requestCode, null);
|
stringResult(requestCode, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Bundle bundle = data.getExtras();
|
|
||||||
if (bundle != null) {
|
|
||||||
for (String k : bundle.keySet()) {
|
|
||||||
Log.d("gio", "data extra:" + k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (data.getAction()) {
|
switch (data.getAction()) {
|
||||||
case OpenPgpApi.ACTION_DECRYPT_VERIFY: {
|
case OpenPgpApi.ACTION_DECRYPT_VERIFY: {
|
||||||
Log.d("gio", "action decrypt");
|
Log.d("gio", "action decrypt");
|
||||||
|
@ -247,7 +250,7 @@ public class PgpConnect extends Fragment {
|
||||||
case OpenPgpApi.RESULT_CODE_SUCCESS: {
|
case OpenPgpApi.RESULT_CODE_SUCCESS: {
|
||||||
try {
|
try {
|
||||||
String ret = os.toString("UTF-8");
|
String ret = os.toString("UTF-8");
|
||||||
Log.d(OpenPgpApi.TAG, "output: " + ret);
|
//Log.d(OpenPgpApi.TAG, "output: " + ret);
|
||||||
stringResult(chint, ret);
|
stringResult(chint, ret);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
Log.e("gio", "UnsupportedEncodingException", e);
|
Log.e("gio", "UnsupportedEncodingException", e);
|
||||||
|
@ -264,7 +267,7 @@ public class PgpConnect extends Fragment {
|
||||||
PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
|
PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
|
||||||
try {
|
try {
|
||||||
IntentSender sender = pi.getIntentSender();
|
IntentSender sender = pi.getIntentSender();
|
||||||
Log.d("PgpConnect", "IntentSender:" + sender.toString());
|
//Log.d("PgpConnect", "IntentSender:" + sender.toString());
|
||||||
startIntentSenderForResult(sender, chint, null, 0, 0, 0, null);
|
startIntentSenderForResult(sender, chint, null, 0, 0, 0, null);
|
||||||
} catch (IntentSender.SendIntentException e) {
|
} catch (IntentSender.SendIntentException e) {
|
||||||
Log.e("gio", "SendIntentException", e);
|
Log.e("gio", "SendIntentException", e);
|
||||||
|
|
|
@ -5,27 +5,37 @@ package main
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"golang.org/x/image/font/gofont/goregular"
|
"git.wow.st/gmp/passgo"
|
||||||
"golang.org/x/image/font/sfnt"
|
"gioui.org/app"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log(Info, "Android start")
|
log(Info, "Android start")
|
||||||
var err error
|
// Use a larger font on Android
|
||||||
regular, err = sfnt.Parse(goregular.TTF)
|
fontSize = 24
|
||||||
|
}
|
||||||
|
|
||||||
|
func initPgp(w *app.Window) {
|
||||||
|
passgo.InitPgp(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConfDir() (string, error) {
|
||||||
|
ret, err := app.DataDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log(Fatal, "Cannot parse default font: ", err)
|
log(Error, "Cannot get data directory:", err)
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
confDir = app.DataDir()
|
if _, err := os.Stat(ret); os.IsNotExist(err) {
|
||||||
if _, err := os.Stat(confDir); os.IsNotExist(err) {
|
err = os.MkdirAll(ret, 0700)
|
||||||
err = os.MkdirAll(confDir, 0700)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log(Info, "Cannot create configuration directory ", confDir)
|
log(Error, "Cannot create configuration directory ", ret)
|
||||||
log(Fatal, err)
|
return "", err
|
||||||
} else {
|
} else {
|
||||||
log(Info, "Configuration directory created")
|
log(Info, "Configuration directory created")
|
||||||
|
return ret, nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log(Info, "Configuration directory found")
|
log(Info, "Configuration directory found")
|
||||||
|
return ret, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,10 @@ import (
|
||||||
"os/user"
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"golang.org/x/image/font/gofont/goregular"
|
"gioui.org/app"
|
||||||
"golang.org/x/image/font/sfnt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func setFont() error {
|
/*func setFont() error {
|
||||||
f, err := os.Open("/System/Library/Fonts/AppleSDGothicNeo.ttc")
|
f, err := os.Open("/System/Library/Fonts/AppleSDGothicNeo.ttc")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log(Info, "Cannot open system font.")
|
log(Info, "Cannot open system font.")
|
||||||
|
@ -29,28 +28,38 @@ func setFont() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}*/
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
err := setFont()
|
fontSize = 16
|
||||||
if err != nil {
|
//err := setFont()
|
||||||
regular, err = sfnt.Parse(goregular.TTF)
|
//if err != nil {
|
||||||
if err != nil {
|
// regular, err = sfnt.Parse(goregular.TTF)
|
||||||
log(Fatal, "Cannot parse default font: ", err)
|
// if err != nil {
|
||||||
}
|
// log(Fatal, "Cannot parse default font: ", err)
|
||||||
}
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initPgp(w *app.Window) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConfDir() (string, error) {
|
||||||
usr, err := user.Current()
|
usr, err := user.Current()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log(Fatal, "Cannot get current user: ", err)
|
log(Error, "Cannot get current user: ", err)
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
confDir = path.Join(usr.HomeDir, ".config/passgo")
|
ret := path.Join(usr.HomeDir, ".config/passgo")
|
||||||
if _, err := os.Stat(confDir); os.IsNotExist(err) {
|
if _, err := os.Stat(ret); os.IsNotExist(err) {
|
||||||
err = os.MkdirAll(confDir, 0700)
|
err = os.MkdirAll(ret, 0700)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log(Info, "Cannot create configuration directory ", confDir)
|
log(Info, "Cannot create configuration directory ", confDir)
|
||||||
log(Fatal, err)
|
return "", err
|
||||||
} else {
|
} else {
|
||||||
log(Info, "Configuration directory created")
|
log(Info, "Configuration directory created")
|
||||||
|
return ret, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,22 +3,27 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"runtime"
|
||||||
|
"runtime/pprof"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gioui.org/ui"
|
"gioui.org/app"
|
||||||
"gioui.org/ui/app"
|
"gioui.org/io/key"
|
||||||
"gioui.org/ui/key"
|
"gioui.org/io/system"
|
||||||
"gioui.org/ui/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/ui/measure"
|
"gioui.org/text"
|
||||||
"gioui.org/ui/text"
|
"gioui.org/unit"
|
||||||
|
"gioui.org/widget"
|
||||||
|
"gioui.org/widget/material"
|
||||||
|
|
||||||
"golang.org/x/image/font/sfnt"
|
"gioui.org/font/gofont"
|
||||||
|
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
@ -33,7 +38,31 @@ type conf struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
if false { go func() {
|
||||||
|
f, err := os.Create("cpuprofile")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Can't create CPU profile\n")
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
fmt.Printf("Starting CPU profile\n")
|
||||||
|
if err := pprof.StartCPUProfile(f); err != nil {
|
||||||
|
fmt.Printf("Can't start CPU profile\n")
|
||||||
|
f.Close()
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 10)
|
||||||
|
fmt.Printf("Stopping CPU profile\n")
|
||||||
|
pprof.StopCPUProfile()
|
||||||
|
f.Close()
|
||||||
|
fmt.Printf("CPU profile written\n")
|
||||||
|
}() }
|
||||||
var fd *os.File
|
var fd *os.File
|
||||||
|
var err error
|
||||||
|
confDir, err = getConfDir()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Can't get config directory")
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
confFile := path.Join(confDir, "config.yml")
|
confFile := path.Join(confDir, "config.yml")
|
||||||
if _, err := os.Stat(confFile); os.IsNotExist(err) {
|
if _, err := os.Stat(confFile); os.IsNotExist(err) {
|
||||||
fd, err = os.Create(confFile)
|
fd, err = os.Create(confFile)
|
||||||
|
@ -71,7 +100,10 @@ func main() {
|
||||||
chdir = make(chan struct{})
|
chdir = make(chan struct{})
|
||||||
passch = make(chan []byte)
|
passch = make(chan []byte)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
log(Info,"passgo.Identities()")
|
||||||
passgo.Identities()
|
passgo.Identities()
|
||||||
|
}()
|
||||||
go Updater()
|
go Updater()
|
||||||
log(Info, "Staring event loop")
|
log(Info, "Staring event loop")
|
||||||
go eventLoop()
|
go eventLoop()
|
||||||
|
@ -80,8 +112,8 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
fontSize float32
|
||||||
confDir string
|
confDir string
|
||||||
regular *sfnt.Font
|
|
||||||
Config conf
|
Config conf
|
||||||
l []passgo.Pass
|
l []passgo.Pass
|
||||||
mux sync.Mutex
|
mux sync.Mutex
|
||||||
|
@ -90,10 +122,13 @@ var (
|
||||||
updated chan struct{}
|
updated chan struct{}
|
||||||
chdir chan struct{}
|
chdir chan struct{}
|
||||||
passch chan []byte
|
passch chan []byte
|
||||||
|
th *material.Theme
|
||||||
)
|
)
|
||||||
|
|
||||||
func Updater() {
|
func Updater() {
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
update := func() {
|
update := func() {
|
||||||
|
fmt.Printf("update()\n")
|
||||||
ltmp, err := store.List()
|
ltmp, err := store.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log(Info, err)
|
log(Info, err)
|
||||||
|
@ -138,7 +173,8 @@ func saveConf(fds ...*os.File) {
|
||||||
} else {
|
} else {
|
||||||
fd, err = os.Create(path.Join(confDir, "config.yml"))
|
fd, err = os.Create(path.Join(confDir, "config.yml"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log(Fatal, "Cannot open config file: ", err)
|
log(Error, "Config file = ", path.Join(confDir, "config.yml"))
|
||||||
|
log(Fatal, "Cannot open config file: ", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer fd.Close()
|
defer fd.Close()
|
||||||
|
@ -154,25 +190,25 @@ func saveConf(fds ...*os.File) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func eventLoop() {
|
func eventLoop() {
|
||||||
|
gofont.Register()
|
||||||
|
th = material.NewTheme()
|
||||||
|
th.TextSize = unit.Sp(fontSize)
|
||||||
w := app.NewWindow(
|
w := app.NewWindow(
|
||||||
app.WithWidth(ui.Dp(250)),
|
app.Size(unit.Dp(250), unit.Dp(500)),
|
||||||
app.WithTitle("passgo"))
|
app.Title("passgo"))
|
||||||
q := w.Queue()
|
gtx := &layout.Context{Queue: w.Queue()}
|
||||||
var c ui.Config
|
time.Sleep(time.Second/5)
|
||||||
ops := new(ui.Ops)
|
|
||||||
var dims layout.Dimensions
|
|
||||||
var cs layout.Constraints
|
|
||||||
var margincs layout.Constraints
|
var margincs layout.Constraints
|
||||||
var faces measure.Faces
|
|
||||||
var c1 layout.FlexChild // flex child for title bar
|
var c1 layout.FlexChild // flex child for title bar
|
||||||
face := faces.For(regular, ui.Sp(16))
|
|
||||||
|
|
||||||
sysinset := &layout.Inset{}
|
sysinset := &layout.Inset{}
|
||||||
margin := layout.UniformInset(ui.Dp(10))
|
margin := layout.UniformInset(unit.Dp(10))
|
||||||
|
|
||||||
title := &text.Label{Face: face, Text: "passgo"}
|
title := th.Body1("passgo")
|
||||||
dotsBtn := &Button{
|
dotsBtn := &Button{
|
||||||
Face: face,
|
Size: unit.Sp(fontSize),
|
||||||
Label: "\xe2\x8b\xae",
|
Label: "\xe2\x8b\xae",
|
||||||
Alignment: text.Middle,
|
Alignment: text.Middle,
|
||||||
Color: black,
|
Color: black,
|
||||||
|
@ -185,12 +221,12 @@ func eventLoop() {
|
||||||
lst := &layout.List{Axis: layout.Vertical}
|
lst := &layout.List{Axis: layout.Vertical}
|
||||||
passBtns := make([]*Button, 0)
|
passBtns := make([]*Button, 0)
|
||||||
pathnames := make([]string, 0)
|
pathnames := make([]string, 0)
|
||||||
copied := &Overlay{Face: face, Text: "copied to clipboard",
|
copied := &Overlay{Size: unit.Sp(fontSize), Text: "copied to clipboard",
|
||||||
Color: black,
|
Color: black,
|
||||||
Background: darkgray,
|
Background: darkgray,
|
||||||
Alignment: text.Middle,
|
Alignment: text.Middle,
|
||||||
}
|
}
|
||||||
cleared := &Overlay{Face: face, Text: "clipboard cleared",
|
cleared := &Overlay{Size: unit.Sp(fontSize), Text: "clipboard cleared",
|
||||||
Color: black,
|
Color: black,
|
||||||
Background: darkgray,
|
Background: darkgray,
|
||||||
Alignment: text.Middle,
|
Alignment: text.Middle,
|
||||||
|
@ -210,7 +246,7 @@ func eventLoop() {
|
||||||
z = "/"
|
z = "/"
|
||||||
}
|
}
|
||||||
passBtns = append(passBtns, &Button{
|
passBtns = append(passBtns, &Button{
|
||||||
Face: face,
|
Size: unit.Sp(fontSize),
|
||||||
Label: strings.Join([]string{s, n, z}, ""),
|
Label: strings.Join([]string{s, n, z}, ""),
|
||||||
Background: gray,
|
Background: gray,
|
||||||
})
|
})
|
||||||
|
@ -223,6 +259,8 @@ func eventLoop() {
|
||||||
idBtns := make([]*Button, 0)
|
idBtns := make([]*Button, 0)
|
||||||
|
|
||||||
updateIdBtns := func() {
|
updateIdBtns := func() {
|
||||||
|
//return
|
||||||
|
log(Info,"passgo.Identities()")
|
||||||
ids, err := passgo.Identities()
|
ids, err := passgo.Identities()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log(Info, err)
|
log(Info, err)
|
||||||
|
@ -231,7 +269,7 @@ func eventLoop() {
|
||||||
for i, n := range ids {
|
for i, n := range ids {
|
||||||
if i >= len(idBtns) {
|
if i >= len(idBtns) {
|
||||||
idBtns = append(idBtns, &Button{
|
idBtns = append(idBtns, &Button{
|
||||||
Face: face,
|
Size: unit.Sp(fontSize),
|
||||||
Label: n,
|
Label: n,
|
||||||
Alignment: text.End,
|
Alignment: text.End,
|
||||||
Color: black,
|
Color: black,
|
||||||
|
@ -245,70 +283,70 @@ func eventLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
confBtn := &Button{
|
confBtn := &Button{
|
||||||
Face: face,
|
Size: unit.Sp(fontSize),
|
||||||
Label: "configure",
|
Label: "configure",
|
||||||
Alignment: text.Middle,
|
Alignment: text.Middle,
|
||||||
Color: black,
|
Color: black,
|
||||||
Background: gray,
|
Background: gray,
|
||||||
}
|
}
|
||||||
|
|
||||||
storeDirLabel := &text.Label{Face: face, Text: "Store directory"}
|
storeDirLabel := th.Label(unit.Sp(fontSize), "Store directory")
|
||||||
storeDirEd := &text.Editor{Face: face, SingleLine: true}
|
storeDirEd := &widget.Editor{ SingleLine: true}
|
||||||
storeDirEd.SetText(store.Dir)
|
storeDirEd.SetText(store.Dir)
|
||||||
saveBtn := &Button{
|
saveBtn := &Button{
|
||||||
Face: face,
|
Size: unit.Sp(fontSize),
|
||||||
Label: "save",
|
Label: "save",
|
||||||
Alignment: text.End,
|
Alignment: text.End,
|
||||||
Color: black,
|
Color: black,
|
||||||
Background: gray,
|
Background: gray,
|
||||||
}
|
}
|
||||||
backBtn := &Button{
|
backBtn := &Button{
|
||||||
Face: face,
|
Size: unit.Sp(fontSize),
|
||||||
Label: "back",
|
Label: "back",
|
||||||
Alignment: text.End,
|
Alignment: text.End,
|
||||||
Color: black,
|
Color: black,
|
||||||
Background: gray,
|
Background: gray,
|
||||||
}
|
}
|
||||||
confirmLabel := &text.Label{Face: face, Text: "Password exists. Overwrite?"}
|
confirmLabel := th.Label(unit.Sp(fontSize), "Password exists. Overwrite?")
|
||||||
yesBtn := &Button{
|
yesBtn := &Button{
|
||||||
Face: face,
|
Size: unit.Sp(fontSize),
|
||||||
Label: "yes",
|
Label: "yes",
|
||||||
Alignment: text.End,
|
Alignment: text.End,
|
||||||
Color: black,
|
Color: black,
|
||||||
Background: gray,
|
Background: gray,
|
||||||
}
|
}
|
||||||
|
|
||||||
promptLabel := &text.Label{Face: face, Text: "passphrase"}
|
promptLabel := th.Label(unit.Sp(fontSize), "passphrase")
|
||||||
promptEd := &text.Editor{Face: face, SingleLine: true, Submit: true}
|
promptEd := &widget.Editor{ SingleLine: true, Submit: true }
|
||||||
okBtn := &Button{
|
okBtn := &Button{
|
||||||
Face: face,
|
Size: unit.Sp(fontSize),
|
||||||
Label: "ok",
|
Label: "ok",
|
||||||
Alignment: text.End,
|
Alignment: text.End,
|
||||||
Color: black,
|
Color: black,
|
||||||
Background: gray,
|
Background: gray,
|
||||||
}
|
}
|
||||||
plusBtn := &Button{
|
plusBtn := &Button{
|
||||||
Face: face,
|
Size: unit.Sp(fontSize),
|
||||||
Label: "+",
|
Label: "+",
|
||||||
Alignment: text.Middle,
|
Alignment: text.Middle,
|
||||||
Color: black,
|
Color: black,
|
||||||
Background: gray,
|
Background: gray,
|
||||||
}
|
}
|
||||||
|
|
||||||
insertLabel := &text.Label{Face: face, Text: "Insert"}
|
insertLabel := th.Label(unit.Sp(fontSize), "Insert")
|
||||||
passnameLabel := &text.Label{Face: face, Text: "password name:"}
|
passnameLabel := th.Label(unit.Sp(fontSize), "password name:")
|
||||||
passnameEd := &text.Editor{Face: face, SingleLine: true, Submit: true}
|
passnameEd := &widget.Editor{ SingleLine: true }
|
||||||
passvalLabel := &text.Label{Face: face, Text: "password value:"}
|
passvalLabel := th.Label(unit.Sp(fontSize), "password value:")
|
||||||
passvalEd := &text.Editor{Face: face, SingleLine: true, Submit: true}
|
passvalEd := &widget.Editor{ SingleLine: true, Submit: true }
|
||||||
|
|
||||||
noidLabel := &text.Label{Face: face, Text: "No GPG ids available. Please create a private key"}
|
noidLabel := th.Label(unit.Sp(fontSize), "No GPG ids available. Please create a private key")
|
||||||
idLabel := &text.Label{Face: face, Text: "Select ID"}
|
idLabel := th.Label(unit.Sp(fontSize), "Select ID")
|
||||||
|
|
||||||
anim := &time.Ticker{}
|
anim := &time.Ticker{}
|
||||||
animating := false
|
animating := false
|
||||||
animOn := func() {
|
animOn := func() {
|
||||||
log(Info, "animOn()")
|
log(Info, "animOn()")
|
||||||
anim = time.NewTicker(time.Second / 120)
|
anim = time.NewTicker(time.Second / 30)
|
||||||
animating = true
|
animating = true
|
||||||
w.Invalidate()
|
w.Invalidate()
|
||||||
}
|
}
|
||||||
|
@ -319,6 +357,7 @@ func eventLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var listPage, idPage, insertPage, confirmPage, confPage, promptPage, page func()
|
var listPage, idPage, insertPage, confirmPage, confPage, promptPage, page func()
|
||||||
|
_ = idPage
|
||||||
|
|
||||||
prompt := func() []byte {
|
prompt := func() []byte {
|
||||||
page = promptPage
|
page = promptPage
|
||||||
|
@ -333,30 +372,29 @@ func eventLoop() {
|
||||||
start2 := float64(Config.ClearDelay)
|
start2 := float64(Config.ClearDelay)
|
||||||
fade2a, end := start2+1.5, start2+2.0
|
fade2a, end := start2+1.5, start2+2.0
|
||||||
|
|
||||||
cs = flex.Flexible(1.0)
|
c2 := flex.Flex(gtx, 1.0, func() {
|
||||||
mux.Lock()
|
mux.Lock()
|
||||||
if lst.Dragging() {
|
if lst.Dragging() {
|
||||||
key.HideInputOp{}.Add(ops)
|
key.HideInputOp{}.Add(gtx.Ops)
|
||||||
}
|
}
|
||||||
var c2 layout.FlexChild
|
|
||||||
switch {
|
switch {
|
||||||
case store.Empty:
|
case store.Empty:
|
||||||
c2 = flex.End(confBtn.Layout(c, q, ops, cs))
|
confBtn.Layout(gtx)
|
||||||
if confBtn.Clicked() {
|
if confBtn.Clicked() {
|
||||||
log(Info, "Configure")
|
log(Info, "Configure")
|
||||||
w.Invalidate()
|
w.Invalidate()
|
||||||
page = confPage
|
page = confPage
|
||||||
}
|
}
|
||||||
case store.Id == "":
|
//case store.Id == "":
|
||||||
c2 = flex.End(idLabel.Layout(ops, cs))
|
// idLabel.Layout(gtx)
|
||||||
w.Invalidate()
|
// w.Invalidate()
|
||||||
page = idPage
|
// //page = idPage
|
||||||
default:
|
default:
|
||||||
for lst.Init(c, q, ops, cs, len(passBtns)); lst.More(); lst.Next() {
|
gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
|
||||||
i := lst.Index()
|
lst.Layout(gtx, len(passBtns), func(i int) {
|
||||||
btn := passBtns[i]
|
btn := passBtns[i]
|
||||||
dims = btn.Layout(c, q, ops, lst.Constraints())
|
gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
|
||||||
lst.End(dims)
|
btn.Layout(gtx)
|
||||||
if btn.Clicked() {
|
if btn.Clicked() {
|
||||||
log(Info, "Clicked ", btn.Label)
|
log(Info, "Clicked ", btn.Label)
|
||||||
// don't block UI thread on decryption attempt
|
// don't block UI thread on decryption attempt
|
||||||
|
@ -385,11 +423,11 @@ func eventLoop() {
|
||||||
}
|
}
|
||||||
}(pathnames[i])
|
}(pathnames[i])
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
c2 = flex.End(lst.Layout())
|
|
||||||
}
|
}
|
||||||
mux.Unlock()
|
mux.Unlock()
|
||||||
flex.Layout(c1, c2)
|
})
|
||||||
|
flex.Layout(gtx, c1, c2)
|
||||||
x := time.Since(overlayStart).Seconds()
|
x := time.Since(overlayStart).Seconds()
|
||||||
if x >= fade1b && x < start2 && animating {
|
if x >= fade1b && x < start2 && animating {
|
||||||
animOff()
|
animOff()
|
||||||
|
@ -426,11 +464,12 @@ func eventLoop() {
|
||||||
overlay.Color = black
|
overlay.Color = black
|
||||||
overlay.Background = darkgray
|
overlay.Background = darkgray
|
||||||
}
|
}
|
||||||
cs = margincs
|
gtx.Constraints = margincs
|
||||||
al := layout.Align{Alignment: layout.SE}
|
al := layout.Align(layout.SE)
|
||||||
cs = al.Begin(ops, cs)
|
al.Layout(gtx, func() {
|
||||||
cs.Width.Min = cs.Width.Max
|
gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
|
||||||
dims = al.End(overlay.Layout(c, ops, cs))
|
overlay.Layout(gtx)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if x > start2 && x < fade2a {
|
if x > start2 && x < fade2a {
|
||||||
// animOff()
|
// animOff()
|
||||||
|
@ -441,23 +480,25 @@ func eventLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
idPage = func() {
|
idPage = func() {
|
||||||
|
log(Info,"idPage()")
|
||||||
if !animating {
|
if !animating {
|
||||||
animOn()
|
animOn()
|
||||||
}
|
}
|
||||||
cs = flex.Rigid()
|
c2 := flex.Rigid(gtx, func() {
|
||||||
c2 := flex.End(idLabel.Layout(ops, cs))
|
idLabel.Layout(gtx)
|
||||||
var c3 layout.FlexChild
|
})
|
||||||
//if len(idBtns) == 0 {
|
//if len(idBtns) == 0 {
|
||||||
updateIdBtns()
|
updateIdBtns()
|
||||||
//}
|
//}
|
||||||
cs = flex.Rigid()
|
c3 := flex.Rigid(gtx, func() {
|
||||||
if len(idBtns) == 0 { // still zero after update
|
if len(idBtns) == 0 { // still zero after update
|
||||||
c3 = flex.End(noidLabel.Layout(ops, cs))
|
noidLabel.Layout(gtx)
|
||||||
} else {
|
} else {
|
||||||
for lst.Init(c, q, ops, cs, len(idBtns)); lst.More(); lst.Next() {
|
for i := 0; i < len(idBtns); i++ {
|
||||||
lst.End(idBtns[lst.Index()].Layout(c, q, ops, lst.Constraints()))
|
lst.Layout(gtx, len(idBtns), func(i int) {
|
||||||
|
idBtns[i].Layout(gtx)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
c3 = flex.End(lst.Layout())
|
|
||||||
for _, btn := range idBtns {
|
for _, btn := range idBtns {
|
||||||
if btn.Clicked() {
|
if btn.Clicked() {
|
||||||
log(Info, "ID selected: ", btn.Label)
|
log(Info, "ID selected: ", btn.Label)
|
||||||
|
@ -468,20 +509,23 @@ func eventLoop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flex.Layout(c1, c2, c3)
|
})
|
||||||
|
flex.Layout(gtx, c1, c2, c3)
|
||||||
}
|
}
|
||||||
|
|
||||||
var insName, insValue string
|
var insName, insValue string
|
||||||
genBtn := &SelButton{SelColor: darkgray}
|
genBtn := &SelButton{SelColor: gray}
|
||||||
genBtn.Button = Button{Face: face, Label: "generate", Background: gray}
|
genBtn.Button = Button{Size: unit.Sp(fontSize), Label: "generate"}
|
||||||
symBtn := &SelButton{SelColor: gray, Selected: true}
|
symBtn := &SelButton{SelColor: gray}
|
||||||
numBtn := &SelButton{SelColor: gray, Selected: true}
|
numBtn := &SelButton{SelColor: gray}
|
||||||
symBtn.Button = Button{Face: face, Label: "@", Background: darkgray}
|
symBtn.Button = Button{Size: unit.Sp(fontSize), Label: "@"}
|
||||||
numBtn.Button = Button{Face: face, Label: "#", Background: darkgray}
|
numBtn.Button = Button{Size: unit.Sp(fontSize), Label: "#"}
|
||||||
lenEd := &text.Editor{Face: face, SingleLine: true, Alignment: text.End}
|
symBtn.Select()
|
||||||
|
numBtn.Select()
|
||||||
|
lenEd := &widget.Editor{ SingleLine: true, Alignment: text.End }
|
||||||
lenEd.SetText("15")
|
lenEd.SetText("15")
|
||||||
lBtn := &Button{Face: face, Label: "<", Background: gray}
|
lBtn := &Button{Size: unit.Sp(fontSize), Label: "<", Background: gray}
|
||||||
rBtn := &Button{Face: face, Label: ">", Background: gray}
|
rBtn := &Button{Size: unit.Sp(fontSize), Label: ">", Background: gray}
|
||||||
|
|
||||||
updatePw := func() {
|
updatePw := func() {
|
||||||
if !genBtn.Selected {
|
if !genBtn.Selected {
|
||||||
|
@ -499,46 +543,49 @@ func eventLoop() {
|
||||||
default:
|
default:
|
||||||
gen = rand.Letter
|
gen = rand.Letter
|
||||||
}
|
}
|
||||||
l,_ := strconv.Atoi(lenEd.Text())
|
l, _ := strconv.Atoi(lenEd.Text())
|
||||||
pw,_ := rand.Slice(gen,l)
|
pw, _ := rand.Slice(gen, l)
|
||||||
passvalEd.SetText(string(pw))
|
passvalEd.SetText(string(pw))
|
||||||
}
|
}
|
||||||
|
|
||||||
resetInsertPage := func() {
|
|
||||||
passnameEd.SetText("")
|
|
||||||
passvalEd.SetText("")
|
|
||||||
genBtn.Deselect()
|
|
||||||
}
|
|
||||||
|
|
||||||
insertPage = func() {
|
insertPage = func() {
|
||||||
c2 := flex.End(insertLabel.Layout(ops, flex.Rigid()))
|
c2 := flex.Rigid(gtx, func() { insertLabel.Layout(gtx) })
|
||||||
|
c3 := flex.Rigid(gtx, func() { passnameLabel.Layout(gtx) })
|
||||||
|
c4 := flex.Rigid(gtx, func() { th.Editor("name").Layout(gtx, passnameEd) })
|
||||||
|
c5 := flex.Rigid(gtx, func() { passvalLabel.Layout(gtx) })
|
||||||
|
c6 := flex.Rigid(gtx, func() { th.Editor("password").Layout(gtx, passvalEd) })
|
||||||
|
|
||||||
c3 := flex.End(passnameLabel.Layout(ops, flex.Rigid()))
|
|
||||||
c4 := flex.End(passnameEd.Layout(c, q, ops, flex.Rigid()))
|
|
||||||
c5 := flex.End(passvalLabel.Layout(ops, flex.Rigid()))
|
|
||||||
c6 := flex.End(passvalEd.Layout(c, q, ops, flex.Rigid()))
|
|
||||||
|
|
||||||
al := &layout.Align{Alignment: layout.E}
|
|
||||||
btnflx := &layout.Flex{Axis: layout.Horizontal}
|
btnflx := &layout.Flex{Axis: layout.Horizontal}
|
||||||
btnflx.Init(ops, al.Begin(ops, flex.Rigid()))
|
al := layout.Align(layout.E)
|
||||||
bc1 := btnflx.End(lBtn.Layout(c, q, ops, btnflx.Rigid()))
|
c7 := flex.Rigid(gtx, func() {
|
||||||
cs := btnflx.Rigid()
|
bc1 := btnflx.Rigid(gtx, func() { lBtn.Layout(gtx) })
|
||||||
cs.Width.Min = 60
|
bc2 := btnflx.Rigid(gtx, func() {
|
||||||
bc2 := btnflx.End(lenEd.Layout(c, q, ops, cs))
|
gtx.Constraints.Width.Min = 60
|
||||||
bc3 := btnflx.End(rBtn.Layout(c, q, ops, btnflx.Rigid()))
|
th.Editor("len").Layout(gtx, lenEd)
|
||||||
bc4 := btnflx.End(symBtn.Layout(c, q, ops, btnflx.Rigid()))
|
})
|
||||||
bc5 := btnflx.End(numBtn.Layout(c, q, ops, btnflx.Rigid()))
|
|
||||||
bc6 := btnflx.End(genBtn.Layout(c, q, ops, btnflx.Rigid()))
|
|
||||||
c7 := flex.End(al.End(btnflx.Layout(bc1, bc2, bc3, bc4, bc5, bc6)))
|
|
||||||
|
|
||||||
btnflx.Init(ops, al.Begin(ops, flex.Rigid()))
|
bc3 := btnflx.Rigid(gtx, func() { rBtn.Layout(gtx) })
|
||||||
bc1 = btnflx.End(backBtn.Layout(c, q, ops, btnflx.Rigid()))
|
bc4 := btnflx.Rigid(gtx, func() { symBtn.Layout(gtx) })
|
||||||
bc2 = btnflx.End(saveBtn.Layout(c, q, ops, btnflx.Rigid()))
|
bc5 := btnflx.Rigid(gtx, func() { numBtn.Layout(gtx) })
|
||||||
c8 := flex.End(al.End(btnflx.Layout(bc1, bc2)))
|
bc6 := btnflx.Rigid(gtx, func() { genBtn.Layout(gtx) })
|
||||||
flex.Layout(c1, c2, c3, c4, c5, c6, c7, c8)
|
|
||||||
|
al.Layout(gtx, func() {
|
||||||
|
btnflx.Layout(gtx, bc1, bc2, bc3, bc4, bc5, bc6)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
c8 := flex.Rigid(gtx, func() {
|
||||||
|
bc1 := btnflx.Rigid(gtx, func() { backBtn.Layout(gtx) })
|
||||||
|
bc2 := btnflx.Rigid(gtx, func() { saveBtn.Layout(gtx) })
|
||||||
|
al.Layout(gtx, func() {
|
||||||
|
btnflx.Layout(gtx, bc1, bc2)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
flex.Layout(gtx, c1, c2, c3, c4, c5, c6, c7, c8)
|
||||||
|
|
||||||
if lBtn.Clicked() {
|
if lBtn.Clicked() {
|
||||||
l,_ := strconv.Atoi(lenEd.Text())
|
l, _ := strconv.Atoi(lenEd.Text())
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
l -= 1
|
l -= 1
|
||||||
}
|
}
|
||||||
|
@ -547,8 +594,8 @@ func eventLoop() {
|
||||||
w.Invalidate()
|
w.Invalidate()
|
||||||
}
|
}
|
||||||
if rBtn.Clicked() {
|
if rBtn.Clicked() {
|
||||||
l,_ := strconv.Atoi(lenEd.Text())
|
l, _ := strconv.Atoi(lenEd.Text())
|
||||||
lenEd.SetText(strconv.Itoa(l+1))
|
lenEd.SetText(strconv.Itoa(l + 1))
|
||||||
updatePw()
|
updatePw()
|
||||||
w.Invalidate()
|
w.Invalidate()
|
||||||
}
|
}
|
||||||
|
@ -566,7 +613,6 @@ func eventLoop() {
|
||||||
}
|
}
|
||||||
if backBtn.Clicked() {
|
if backBtn.Clicked() {
|
||||||
w.Invalidate()
|
w.Invalidate()
|
||||||
resetInsertPage()
|
|
||||||
page = listPage
|
page = listPage
|
||||||
}
|
}
|
||||||
if saveBtn.Clicked() {
|
if saveBtn.Clicked() {
|
||||||
|
@ -582,20 +628,26 @@ func eventLoop() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
store.Insert(passnameEd.Text(), passvalEd.Text())
|
//Do not block the UI thread.
|
||||||
|
go store.Insert(passnameEd.Text(), passvalEd.Text())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmPage = func() {
|
confirmPage = func() {
|
||||||
cs = flex.Rigid()
|
c2 := flex.Rigid(gtx, func() {
|
||||||
c2 := flex.End(confirmLabel.Layout(ops, cs))
|
confirmLabel.Layout(gtx)
|
||||||
al := &layout.Align{Alignment: layout.E}
|
})
|
||||||
|
al := layout.Align(layout.E)
|
||||||
btnflx := &layout.Flex{Axis: layout.Horizontal}
|
btnflx := &layout.Flex{Axis: layout.Horizontal}
|
||||||
btnflx.Init(ops, al.Begin(ops, flex.Rigid()))
|
c3 := flex.Rigid(gtx, func() {
|
||||||
bc1 := btnflx.End(backBtn.Layout(c, q, ops, btnflx.Rigid()))
|
bc1 := btnflx.Rigid(gtx, func() { backBtn.Layout(gtx) })
|
||||||
bc2 := btnflx.End(yesBtn.Layout(c, q, ops, btnflx.Rigid()))
|
bc2 := btnflx.Rigid(gtx, func() { yesBtn.Layout(gtx) })
|
||||||
c3 := flex.End(al.End(btnflx.Layout(bc1, bc2)))
|
|
||||||
flex.Layout(c1, c2, c3)
|
al.Layout(gtx, func() {
|
||||||
|
btnflx.Layout(gtx, bc1, bc2)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
flex.Layout(gtx, c1, c2, c3)
|
||||||
|
|
||||||
if backBtn.Clicked() {
|
if backBtn.Clicked() {
|
||||||
w.Invalidate()
|
w.Invalidate()
|
||||||
|
@ -604,28 +656,29 @@ func eventLoop() {
|
||||||
if yesBtn.Clicked() {
|
if yesBtn.Clicked() {
|
||||||
w.Invalidate()
|
w.Invalidate()
|
||||||
page = listPage
|
page = listPage
|
||||||
resetInsertPage()
|
go store.Insert(insName, insValue)
|
||||||
store.Insert(insName, insValue)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
confPage = func() {
|
confPage = func() {
|
||||||
cs = flex.Rigid()
|
c2 := flex.Rigid(gtx, func() { storeDirLabel.Layout(gtx) })
|
||||||
c2 := flex.End(storeDirLabel.Layout(ops, cs))
|
c3 := flex.Rigid(gtx, func() { th.Editor("directory").Layout(gtx, storeDirEd) })
|
||||||
cs = flex.Rigid()
|
|
||||||
c3 := flex.End(storeDirEd.Layout(c, q, ops, cs))
|
al := layout.Align(layout.E)
|
||||||
cs = flex.Rigid()
|
c4 := flex.Rigid(gtx, func() {
|
||||||
al := &layout.Align{Alignment: layout.E}
|
|
||||||
cs = al.Begin(ops, cs)
|
|
||||||
btnflx := &layout.Flex{Axis: layout.Horizontal}
|
btnflx := &layout.Flex{Axis: layout.Horizontal}
|
||||||
btnflx.Init(ops, cs)
|
bc1 := btnflx.Rigid(gtx, func() {
|
||||||
cs = btnflx.Rigid()
|
backBtn.Layout(gtx)
|
||||||
bc1 := btnflx.End(backBtn.Layout(c, q, ops, cs))
|
})
|
||||||
cs = btnflx.Rigid()
|
bc2 := btnflx.Rigid(gtx, func() {
|
||||||
bc2 := btnflx.End(saveBtn.Layout(c, q, ops, cs))
|
saveBtn.Layout(gtx)
|
||||||
dims = btnflx.Layout(bc1, bc2)
|
})
|
||||||
c4 := flex.End(al.End(dims))
|
al.Layout(gtx, func() {
|
||||||
flex.Layout(c1, c2, c3, c4)
|
btnflx.Layout(gtx, bc1, bc2)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
flex.Layout(gtx, c1, c2, c3, c4)
|
||||||
|
|
||||||
if backBtn.Clicked() {
|
if backBtn.Clicked() {
|
||||||
log(Info, "Back")
|
log(Info, "Back")
|
||||||
storeDirEd.SetText(store.Dir)
|
storeDirEd.SetText(store.Dir)
|
||||||
|
@ -650,29 +703,30 @@ func eventLoop() {
|
||||||
|
|
||||||
promptPage = func() {
|
promptPage = func() {
|
||||||
submit := false
|
submit := false
|
||||||
for e, ok := promptEd.Next(c, q); ok; e, ok = promptEd.Next(c, q) {
|
for _, e := range promptEd.Events(gtx) {
|
||||||
switch e.(type) {
|
switch e.(type) {
|
||||||
case text.SubmitEvent:
|
case widget.SubmitEvent:
|
||||||
log(Info, "Submit")
|
log(Info, "Submit")
|
||||||
submit = true
|
submit = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cs = flex.Rigid()
|
c2 := flex.Rigid(gtx, func() { promptLabel.Layout(gtx) })
|
||||||
c2 := flex.End(promptLabel.Layout(ops, cs))
|
c3 := flex.Rigid(gtx, func() { th.Editor("password").Layout(gtx, promptEd) })
|
||||||
cs = flex.Rigid()
|
c4 := flex.Rigid(gtx, func() {
|
||||||
c3 := flex.End(promptEd.Layout(c, q, ops, cs))
|
al := layout.Align(layout.E)
|
||||||
cs = flex.Rigid()
|
|
||||||
al := &layout.Align{Alignment: layout.E}
|
|
||||||
cs = al.Begin(ops, cs)
|
|
||||||
btnflx := &layout.Flex{Axis: layout.Horizontal}
|
btnflx := &layout.Flex{Axis: layout.Horizontal}
|
||||||
btnflx.Init(ops, cs)
|
bc1 := btnflx.Rigid(gtx, func() {
|
||||||
cs = btnflx.Rigid()
|
backBtn.Layout(gtx)
|
||||||
bc1 := btnflx.End(backBtn.Layout(c, q, ops, cs))
|
})
|
||||||
cs = btnflx.Rigid()
|
bc2 := btnflx.Rigid(gtx, func() {
|
||||||
bc2 := btnflx.End(okBtn.Layout(c, q, ops, cs))
|
okBtn.Layout(gtx)
|
||||||
dims = btnflx.Layout(bc1, bc2)
|
})
|
||||||
c4 := flex.End(al.End(dims))
|
al.Layout(gtx, func() {
|
||||||
flex.Layout(c1, c2, c3, c4)
|
btnflx.Layout(gtx, bc1, bc2)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
flex.Layout(gtx, c1, c2, c3, c4)
|
||||||
|
|
||||||
if submit || okBtn.Clicked() {
|
if submit || okBtn.Clicked() {
|
||||||
log(Info, "Ok")
|
log(Info, "Ok")
|
||||||
go func() { // do not block UI thread
|
go func() { // do not block UI thread
|
||||||
|
@ -693,6 +747,9 @@ func eventLoop() {
|
||||||
|
|
||||||
page = listPage
|
page = listPage
|
||||||
|
|
||||||
|
ms := &runtime.MemStats{}
|
||||||
|
x := 0
|
||||||
|
var mallocs uint64
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-updated:
|
case <-updated:
|
||||||
|
@ -702,36 +759,46 @@ func eventLoop() {
|
||||||
case <-anim.C:
|
case <-anim.C:
|
||||||
w.Invalidate()
|
w.Invalidate()
|
||||||
case e := <-w.Events():
|
case e := <-w.Events():
|
||||||
|
x++
|
||||||
|
if x == 100 {
|
||||||
|
runtime.ReadMemStats(ms)
|
||||||
|
mallocs = ms.Mallocs
|
||||||
|
}
|
||||||
switch e := e.(type) {
|
switch e := e.(type) {
|
||||||
case app.DestroyEvent:
|
case system.DestroyEvent:
|
||||||
return
|
return
|
||||||
case app.UpdateEvent:
|
case system.StageEvent:
|
||||||
c = &e.Config
|
if e.Stage == system.StageRunning {
|
||||||
ops.Reset()
|
initPgp(w)
|
||||||
faces.Reset(c)
|
}
|
||||||
cs = layout.RigidConstraints(e.Size)
|
case system.FrameEvent:
|
||||||
|
gtx.Reset(e.Config, e.Size)
|
||||||
|
|
||||||
sysinset.Top = e.Insets.Top
|
sysinset.Top = e.Insets.Top
|
||||||
sysinset.Bottom = e.Insets.Bottom
|
sysinset.Bottom = e.Insets.Bottom
|
||||||
sysinset.Left = e.Insets.Left
|
sysinset.Left = e.Insets.Left
|
||||||
sysinset.Right = e.Insets.Right
|
sysinset.Right = e.Insets.Right
|
||||||
cs = sysinset.Begin(c, ops, cs)
|
|
||||||
cs = margin.Begin(c, ops, cs)
|
sysinset.Layout(gtx, func() {
|
||||||
margincs = cs
|
margin.Layout(gtx, func() {
|
||||||
flex.Init(ops, cs)
|
margincs = gtx.Constraints
|
||||||
cs = flex.Rigid()
|
c1 = flex.Rigid(gtx, func() {
|
||||||
titleflex.Init(ops, cs)
|
ct2 := titleflex.Rigid(gtx, func() {
|
||||||
cs = titleflex.Rigid()
|
plusBtn.Layout(gtx)
|
||||||
ct2 := titleflex.End(plusBtn.Layout(c, q, ops, cs))
|
})
|
||||||
cs = titleflex.Rigid()
|
ct3 := titleflex.Rigid(gtx, func() {
|
||||||
ct3 := titleflex.End(dotsBtn.Layout(c, q, ops, cs))
|
dotsBtn.Layout(gtx)
|
||||||
cs = titleflex.Flexible(1.0)
|
})
|
||||||
cs.Width.Min = cs.Width.Max
|
ct1 := titleflex.Flex(gtx, 1.0, func() {
|
||||||
ct1 := titleflex.End(title.Layout(ops, cs))
|
gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
|
||||||
c1 = flex.End(titleflex.Layout(ct1, ct2, ct3))
|
title.Layout(gtx)
|
||||||
|
})
|
||||||
|
titleflex.Layout(gtx, ct1, ct2, ct3)
|
||||||
|
})
|
||||||
|
|
||||||
page()
|
page()
|
||||||
|
})
|
||||||
sysinset.End(margin.End(dims))
|
})
|
||||||
|
|
||||||
if dotsBtn.Clicked() {
|
if dotsBtn.Clicked() {
|
||||||
log(Info, "Configure")
|
log(Info, "Configure")
|
||||||
|
@ -744,7 +811,12 @@ func eventLoop() {
|
||||||
insName, insValue = "", ""
|
insName, insValue = "", ""
|
||||||
page = insertPage
|
page = insertPage
|
||||||
}
|
}
|
||||||
w.Update(ops)
|
e.Frame(gtx.Ops)
|
||||||
|
}
|
||||||
|
if x == 100 {
|
||||||
|
x = 0
|
||||||
|
runtime.ReadMemStats(ms)
|
||||||
|
fmt.Printf("mallocs: %d\n", ms.Mallocs-mallocs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,14 @@ import (
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
|
||||||
"gioui.org/ui"
|
"gioui.org/f32"
|
||||||
"gioui.org/ui/f32"
|
"gioui.org/gesture"
|
||||||
"gioui.org/ui/gesture"
|
"gioui.org/io/pointer"
|
||||||
"gioui.org/ui/input"
|
"gioui.org/layout"
|
||||||
"gioui.org/ui/layout"
|
"gioui.org/op/clip"
|
||||||
"gioui.org/ui/paint"
|
"gioui.org/op/paint"
|
||||||
"gioui.org/ui/pointer"
|
"gioui.org/text"
|
||||||
"gioui.org/ui/text"
|
"gioui.org/unit"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -22,7 +22,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Overlay struct {
|
type Overlay struct {
|
||||||
Face text.Face
|
Size unit.Value
|
||||||
Text string
|
Text string
|
||||||
Click gesture.Click
|
Click gesture.Click
|
||||||
Color color.RGBA
|
Color color.RGBA
|
||||||
|
@ -30,30 +30,24 @@ type Overlay struct {
|
||||||
Alignment text.Alignment
|
Alignment text.Alignment
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Overlay) Layout(c ui.Config, ops *ui.Ops, cs layout.Constraints) layout.Dimensions {
|
func (b *Overlay) Layout(gtx *layout.Context) {
|
||||||
ins := layout.UniformInset(ui.Dp(1))
|
ins := layout.UniformInset(unit.Dp(1))
|
||||||
cs = ins.Begin(c, ops, cs)
|
ins.Layout(gtx, func() {
|
||||||
var dims layout.Dimensions
|
|
||||||
st := layout.Stack{}
|
st := layout.Stack{}
|
||||||
st.Init(ops, cs)
|
c2 := st.Rigid(gtx, func() {
|
||||||
{
|
l := th.Label(b.Size, b.Text)
|
||||||
cs = st.Rigid()
|
ins := layout.UniformInset(unit.Dp(4))
|
||||||
l := text.Label{
|
l.Color = b.Color
|
||||||
Face: b.Face,
|
ins.Layout(gtx, func() {
|
||||||
Text: b.Text,
|
l.Layout(gtx)
|
||||||
Alignment: b.Alignment,
|
})
|
||||||
}
|
pointer.RectAreaOp{image.Rect(0, 0, gtx.Dimensions.Size.X, gtx.Dimensions.Size.Y)}.Add(gtx.Ops)
|
||||||
ins := layout.UniformInset(ui.Dp(4))
|
})
|
||||||
l.Material.Record(ops)
|
c1 := st.Expand(gtx, func() {
|
||||||
paint.ColorOp{Color: b.Color}.Add(ops)
|
layoutRRect(b.Background, gtx)
|
||||||
l.Material.Stop()
|
})
|
||||||
dims = ins.End(l.Layout(ops, ins.Begin(c, ops, cs)))
|
st.Layout(gtx, c1, c2)
|
||||||
pointer.RectAreaOp{image.Rect(0, 0, dims.Size.X, dims.Size.Y)}.Add(ops)
|
})
|
||||||
}
|
|
||||||
c2 := st.End(dims)
|
|
||||||
c1 := st.End(layoutRRect(b.Background, c, ops, st.Expand()))
|
|
||||||
dims = st.Layout(c1, c2)
|
|
||||||
return ins.End(dims)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SelButton struct {
|
type SelButton struct {
|
||||||
|
@ -63,7 +57,7 @@ type SelButton struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Button struct {
|
type Button struct {
|
||||||
Face text.Face
|
Size unit.Value
|
||||||
Label string
|
Label string
|
||||||
Click gesture.Click
|
Click gesture.Click
|
||||||
Color color.RGBA
|
Color color.RGBA
|
||||||
|
@ -72,89 +66,65 @@ type Button struct {
|
||||||
clicked bool
|
clicked bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func layoutRRect(col color.RGBA, c ui.Config, ops *ui.Ops, cs layout.Constraints) layout.Dimensions {
|
func layoutRRect(col color.RGBA, gtx *layout.Context) {
|
||||||
r := float32(c.Px(ui.Dp(4)))
|
r := float32(gtx.Config.Px(unit.Dp(4)))
|
||||||
sz := image.Point{X: cs.Width.Min, Y: cs.Height.Min}
|
sz := image.Point{X: gtx.Constraints.Width.Min, Y: gtx.Constraints.Height.Min}
|
||||||
w, h := float32(sz.X), float32(sz.Y)
|
w, h := float32(sz.X), float32(sz.Y)
|
||||||
rrect(ops, w, h, r, r, r, r)
|
rect := f32.Rectangle{
|
||||||
paint.ColorOp{Color: col}.Add(ops)
|
f32.Point{0, 0},
|
||||||
paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: w, Y: h}}}.Add(ops)
|
f32.Point{w, h},
|
||||||
return layout.Dimensions{Size: sz}
|
}
|
||||||
|
clip.RoundRect(gtx.Ops, rect, r, r, r, r)
|
||||||
|
paint.ColorOp{Color: col}.Add(gtx.Ops)
|
||||||
|
paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: w, Y: h}}}.Add(gtx.Ops)
|
||||||
|
gtx.Dimensions = layout.Dimensions{Size: sz}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://pomax.github.io/bezierinfo/#circles_cubic.
|
func (b *Button) Layout(gtx *layout.Context) {
|
||||||
func rrect(ops *ui.Ops, width, height, se, sw, nw, ne float32) {
|
|
||||||
w, h := float32(width), float32(height)
|
|
||||||
const c = 0.55228475 // 4*(sqrt(2)-1)/3
|
|
||||||
var b paint.PathBuilder
|
|
||||||
b.Init(ops)
|
|
||||||
b.Move(f32.Point{X: w, Y: h - se})
|
|
||||||
b.Cube(f32.Point{X: 0, Y: se * c}, f32.Point{X: -se + se*c, Y: se}, f32.Point{X: -se, Y: se}) // SE
|
|
||||||
b.Line(f32.Point{X: sw - w + se, Y: 0})
|
|
||||||
b.Cube(f32.Point{X: -sw * c, Y: 0}, f32.Point{X: -sw, Y: -sw + sw*c}, f32.Point{X: -sw, Y: -sw}) // SW
|
|
||||||
b.Line(f32.Point{X: 0, Y: nw - h + sw})
|
|
||||||
b.Cube(f32.Point{X: 0, Y: -nw * c}, f32.Point{X: nw - nw*c, Y: -nw}, f32.Point{X: nw, Y: -nw}) // NW
|
|
||||||
b.Line(f32.Point{X: w - ne - nw, Y: 0})
|
|
||||||
b.Cube(f32.Point{X: ne * c, Y: 0}, f32.Point{X: ne, Y: ne - ne*c}, f32.Point{X: ne, Y: ne}) // NE
|
|
||||||
b.End()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Button) Layout(c ui.Config, q input.Queue, ops *ui.Ops, cs layout.Constraints) layout.Dimensions {
|
|
||||||
b.clicked = false
|
b.clicked = false
|
||||||
for ev, ok := b.Click.Next(q); ok; ev, ok = b.Click.Next(q) {
|
for _, ev := range b.Click.Events(gtx) {
|
||||||
if ev.Type == gesture.TypeClick {
|
if ev.Type == gesture.TypeClick {
|
||||||
b.clicked = true
|
b.clicked = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ins := layout.UniformInset(ui.Dp(1))
|
ins := layout.UniformInset(unit.Dp(1))
|
||||||
cs = ins.Begin(c, ops, cs)
|
ins.Layout(gtx, func() {
|
||||||
var dims layout.Dimensions
|
|
||||||
st := layout.Stack{}
|
st := layout.Stack{}
|
||||||
st.Init(ops, cs)
|
c2 := st.Rigid(gtx, func() {
|
||||||
{
|
l := th.Label(b.Size, b.Label)
|
||||||
cs = st.Rigid()
|
ins := layout.UniformInset(unit.Dp(4))
|
||||||
l := text.Label{
|
|
||||||
Face: b.Face,
|
|
||||||
Text: b.Label,
|
|
||||||
Alignment: b.Alignment,
|
|
||||||
}
|
|
||||||
ins := layout.UniformInset(ui.Dp(4))
|
|
||||||
//paint.ColorOp{Color: b.Color}.Add(ops)
|
//paint.ColorOp{Color: b.Color}.Add(ops)
|
||||||
dims = ins.End(l.Layout(ops, ins.Begin(c, ops, cs)))
|
ins.Layout(gtx, func() {
|
||||||
pointer.RectAreaOp{image.Rect(0, 0, dims.Size.X, dims.Size.Y)}.Add(ops)
|
l.Layout(gtx)
|
||||||
b.Click.Add(ops)
|
})
|
||||||
}
|
pointer.RectAreaOp{image.Rect(0, 0, gtx.Dimensions.Size.X, gtx.Dimensions.Size.Y)}.Add(gtx.Ops)
|
||||||
c2 := st.End(dims)
|
b.Click.Add(gtx.Ops)
|
||||||
c1 := st.End(layoutRRect(b.Background, c, ops, st.Expand()))
|
})
|
||||||
dims = st.Layout(c1, c2)
|
c1 := st.Expand(gtx, func() {
|
||||||
return ins.End(dims)
|
layoutRRect(b.Background, gtx)
|
||||||
|
})
|
||||||
|
st.Layout(gtx, c1, c2)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Button) Clicked() bool {
|
func (b *Button) Clicked() bool {
|
||||||
return b.clicked
|
return b.clicked
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *SelButton) Select() {
|
func (b *SelButton) Toggle() {
|
||||||
if b.Selected {
|
b.Selected = !b.Selected
|
||||||
return
|
|
||||||
}
|
|
||||||
b.Selected = true
|
|
||||||
b.SelColor, b.Background = b.Background, b.SelColor
|
b.SelColor, b.Background = b.Background, b.SelColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *SelButton) Select() {
|
||||||
|
if !b.Selected {
|
||||||
|
b.Toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (b *SelButton) Deselect() {
|
func (b *SelButton) Deselect() {
|
||||||
if !b.Selected {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b.Selected = false
|
|
||||||
b.SelColor, b.Background = b.Background, b.SelColor
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *SelButton) Toggle() {
|
|
||||||
if b.Selected {
|
if b.Selected {
|
||||||
b.Deselect()
|
b.Toggle()
|
||||||
} else {
|
|
||||||
b.Select()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,4 +136,3 @@ func (b *SelButton) Clicked() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
main.go
13
main.go
|
@ -54,10 +54,23 @@ func GetStore(store *Store) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Can't read .gpg-id: %s", err)
|
return fmt.Errorf("Can't read .gpg-id: %s", err)
|
||||||
}
|
}
|
||||||
|
// extract only the email address portion of the ID (required
|
||||||
|
// for Android)
|
||||||
if id[len(id)-1] == '\n' {
|
if id[len(id)-1] == '\n' {
|
||||||
id = id[:len(id)-1]
|
id = id[:len(id)-1]
|
||||||
}
|
}
|
||||||
|
for i := len(id) - 1; i > 0; i-- {
|
||||||
|
if id[i] == '>' {
|
||||||
|
for j := i-1; j > 0; j-- {
|
||||||
|
if id[j] == '<' {
|
||||||
|
id = id[j+1:i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
store.Id = string(id)
|
store.Id = string(id)
|
||||||
|
log.Printf("ID = %s", store.Id)
|
||||||
return getKeyring()
|
return getKeyring()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user