package main
import (
"fmt"
"io"
"strings"
"gio.tools/icons"
"gioui.org/app"
"gioui.org/font"
"gioui.org/io/clipboard"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/unit"
"gioui.org/widget"
"gioui.org/widget/material"
)
func (a *Application) MainView(w *app.Window) error {
pws := gpwList{}
for _, p := range a.Passwords {
gp := newGPassword(p)
pws = append(pws, gp)
}
var (
ops op.Ops
searchBox widget.Editor
searchBtn widget.Clickable
addBtn widget.Clickable
pwlist widget.List
th = material.NewTheme()
)
pwlist.List.Axis = layout.Vertical
for {
switch e := w.Event().(type) {
case app.FrameEvent:
gtx := app.NewContext(&ops, e)
if searchBtn.Clicked(gtx) {
sl := a.Passwords.Search(searchBox.Text())
pws = nil
for _, p := range sl {
pws = append(pws, newGPassword(p))
}
pws.sort()
w.Invalidate()
}
if addBtn.Clicked(gtx) {
np, err := a.AddView(w)
if err != nil {
fmt.Println(err.Error())
}
if np.ID > 0 {
a.Passwords = append(a.Passwords, np)
a.Passwords.Sort()
gp := newGPassword(np)
pws = append(pws, gp)
pws.sort()
w.Invalidate()
}
}
for i := range pws {
p := pws[i]
if p.CopyBtn.Clicked(gtx) {
gtx.Execute(clipboard.WriteCmd{Type: "application/text", Data: io.NopCloser(strings.NewReader(p.Password))})
}
if p.ShowBtn.Clicked(gtx) {
p.toggleShow()
}
if p.EditBtn.Clicked(gtx) {
err := a.EditView(w, &a.Passwords[i])
if err != nil {
fmt.Println(err.Error())
} else {
pws[i] = newGPassword(a.Passwords[i])
w.Invalidate()
}
}
}
layout.Flex{
Axis: layout.Vertical,
Spacing: layout.SpaceEnd,
}.Layout(gtx,
layout.Rigid(
func(gtx layout.Context) layout.Dimensions {
return layout.Flex{
Axis: layout.Horizontal,
Spacing: layout.SpaceSides,
}.Layout(gtx,
layout.Flexed(1,
func(gtx layout.Context) layout.Dimensions {
txt := material.Editor(th, &searchBox, "Search")
searchBox.SingleLine = true
margins := layout.UniformInset(unit.Dp(10))
padding := layout.UniformInset(inputPadding)
border := widget.Border{
Color: borderColor,
CornerRadius: unit.Dp(1),
Width: unit.Dp(2),
}
return margins.Layout(gtx,
func(gtx layout.Context) layout.Dimensions {
return border.Layout(gtx,
func(gtx layout.Context) layout.Dimensions {
return padding.Layout(gtx, txt.Layout)
},
)
},
)
},
),
layout.Rigid(
func(gtx layout.Context) layout.Dimensions {
inset := layout.UniformInset(unit.Dp(10))
btn := material.Button(th, &searchBtn, "Search")
return inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return btn.Layout(gtx)
})
},
),
)
},
),
// Button
layout.Rigid(
func(gtx layout.Context) layout.Dimensions {
inset := layout.UniformInset(unit.Dp(10))
btn := material.Button(th, &addBtn, "+ Add New")
return inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return btn.Layout(gtx)
})
},
),
// Header
layout.Rigid(
func(gtx layout.Context) layout.Dimensions {
inset := layout.UniformInset(unit.Dp(2))
inset.Right = unit.Dp(24)
text := material.Body1(th, "")
text.MaxLines = 1
return inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Flex{
Axis: layout.Horizontal,
Spacing: layout.SpaceEnd,
}.Layout(gtx,
layout.Flexed(1,
func(gtx layout.Context) layout.Dimensions {
text.Text = ""
text.Font.Weight = font.Bold
text.Text = "Service Name"
return text.Layout(gtx)
},
),
layout.Flexed(1,
func(gtx layout.Context) layout.Dimensions {
text.Text = ""
text.Font.Weight = font.Bold
text.Text = "Username"
return text.Layout(gtx)
},
),
layout.Flexed(1,
func(gtx layout.Context) layout.Dimensions {
text.Text = ""
text.Font.Weight = font.Bold
text.Text = " Password"
return text.Layout(gtx)
},
),
)
})
},
),
// Password list
layout.Rigid(
func(gtx layout.Context) layout.Dimensions {
// var grid outlay.Grid
text := material.Body1(th, "")
text.MaxLines = 1
inset := layout.UniformInset(unit.Dp(2))
// dims := inset.Layout(gtx, text.Layout)
list := material.List(th, &pwlist)
return list.Layout(gtx, len(pws),
// Rows
func(gtx layout.Context, i int) layout.Dimensions {
p := pws[i]
return inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Flex{
Axis: layout.Horizontal,
Spacing: layout.SpaceEnd,
}.Layout(gtx,
layout.Flexed(1,
func(gtx layout.Context) layout.Dimensions {
text.Text = ""
text.Font.Weight = font.Normal
text.Text = p.ServiceName
return text.Layout(gtx)
},
),
layout.Flexed(1,
func(gtx layout.Context) layout.Dimensions {
text.Text = ""
text.Font.Weight = font.Normal
text.Text = p.Username
return text.Layout(gtx)
},
),
layout.Flexed(1,
func(gtx layout.Context) layout.Dimensions {
return layout.Flex{
Axis: layout.Horizontal,
Spacing: layout.SpaceEnd,
}.Layout(gtx,
layout.Flexed(4,
func(gtx layout.Context) layout.Dimensions {
text.Text = ""
text.Font.Weight = font.Normal
if p.Shown {
text.Text = p.Password
} else {
text.Text = strings.Repeat("*", len(p.Password))
}
return text.Layout(gtx)
},
),
layout.Rigid(
func(gtx layout.Context) layout.Dimensions {
var bi *widget.Icon
var bd string
if p.Shown {
bi = icons.ActionVisibilityOff
bd = "Hide"
} else {
bi = icons.ActionVisibility
bd = "Show"
}
btn := material.IconButton(th, p.ShowBtn, bi, bd)
return btn.Layout(gtx)
},
),
layout.Rigid(
func(gtx layout.Context) layout.Dimensions {
btn := material.IconButton(th, p.CopyBtn, icons.ContentContentCopy, "Copy Password")
return btn.Layout(gtx)
},
),
layout.Rigid(
func(gtx layout.Context) layout.Dimensions {
btn := material.IconButton(th, p.EditBtn, icons.ImageEdit, "Edit")
return btn.Layout(gtx)
},
),
)
},
),
)
})
})
}))
e.Frame(gtx.Ops)
case app.DestroyEvent:
fmt.Println("Syncing...")
a.sync()
return e.Err
}
}
}