feature/ui - zatim ne uplne uhlazena ale celkem pouzitelna appka #1
@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
func NewUI() (stprageDir string, window fyne.Window) {
|
func NewUI() (stprageDir string, window fyne.Window) {
|
||||||
// App + storage dir
|
// App + storage dir
|
||||||
a := app.New()
|
a := app.NewWithID("fckeuspy")
|
||||||
w := a.NewWindow("Encryptor (Fyne)")
|
w := a.NewWindow("Encryptor (Fyne)")
|
||||||
prefs := a.Preferences()
|
prefs := a.Preferences()
|
||||||
width := prefs.IntWithFallback("winW", 1100)
|
width := prefs.IntWithFallback("winW", 1100)
|
||||||
|
|||||||
198
ui.go
198
ui.go
@ -12,6 +12,7 @@ import (
|
|||||||
"fyne.io/fyne/v2/canvas"
|
"fyne.io/fyne/v2/canvas"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/dialog"
|
"fyne.io/fyne/v2/dialog"
|
||||||
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/storage"
|
"fyne.io/fyne/v2/storage"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
@ -113,12 +114,15 @@ var forceDark = true
|
|||||||
|
|
||||||
// Build key section
|
// Build key section
|
||||||
func buildIdentityTab(parts *uiParts, svc ServiceFacade, vaultPath string) fyne.CanvasObject {
|
func buildIdentityTab(parts *uiParts, svc ServiceFacade, vaultPath string) fyne.CanvasObject {
|
||||||
btnCopyPub := widget.NewButton("Copy public.pem", func() { copyClip(svc.PublicPEM(), parts) })
|
// Toolbar actions
|
||||||
btnCopyCrt := widget.NewButton("Copy identity.crt", func() { copyClip(svc.PublicCert(), parts) })
|
identityToggle := widget.NewToolbarAction(theme.VisibilityOffIcon(), nil)
|
||||||
btnShowPub := widget.NewButton("Show pub", func() { parts.outKey.SetText(svc.PublicPEM()) })
|
identityToolbar := widget.NewToolbar(
|
||||||
btnShowCrt := widget.NewButton("Show crt", func() { parts.outKey.SetText(svc.PublicCert()) })
|
widget.NewToolbarAction(theme.ContentCopyIcon(), func() { copyClip(svc.PublicPEM()+"\n"+svc.PublicCert(), parts) }),
|
||||||
btnClear := widget.NewButton("Clear", func() { parts.outKey.SetText("") })
|
widget.NewToolbarAction(theme.ContentPasteIcon(), func() { parts.outKey.SetText(fyne.CurrentApp().Clipboard().Content()) }),
|
||||||
btnPaste := widget.NewButton("Paste", func() { parts.outKey.SetText(fyne.CurrentApp().Clipboard().Content()) })
|
widget.NewToolbarAction(theme.ContentClearIcon(), func() { parts.outKey.SetText("") }),
|
||||||
|
widget.NewToolbarSeparator(),
|
||||||
|
identityToggle,
|
||||||
|
)
|
||||||
|
|
||||||
deleteBtn := widget.NewButton("Smazat identitu", func() {
|
deleteBtn := widget.NewButton("Smazat identitu", func() {
|
||||||
pwEntry := widget.NewPasswordEntry()
|
pwEntry := widget.NewPasswordEntry()
|
||||||
@ -175,10 +179,7 @@ func buildIdentityTab(parts *uiParts, svc ServiceFacade, vaultPath string) fyne.
|
|||||||
}
|
}
|
||||||
|
|
||||||
identityContainer := container.NewVBox()
|
identityContainer := container.NewVBox()
|
||||||
|
rebuild := func() {
|
||||||
toggleBtn := widget.NewButton("", nil)
|
|
||||||
var rebuild func()
|
|
||||||
rebuild = func() {
|
|
||||||
identityContainer.Objects = nil
|
identityContainer.Objects = nil
|
||||||
if parts.showQR {
|
if parts.showQR {
|
||||||
updateQRImages()
|
updateQRImages()
|
||||||
@ -193,26 +194,18 @@ func buildIdentityTab(parts *uiParts, svc ServiceFacade, vaultPath string) fyne.
|
|||||||
}
|
}
|
||||||
identityContainer.Refresh()
|
identityContainer.Refresh()
|
||||||
if parts.showQR {
|
if parts.showQR {
|
||||||
toggleBtn.SetText("Zobrazit plaintext")
|
identityToggle.SetIcon(theme.VisibilityOffIcon())
|
||||||
} else {
|
} else {
|
||||||
toggleBtn.SetText("Zobrazit QR")
|
identityToggle.SetIcon(theme.VisibilityIcon())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toggleBtn.OnTapped = func() { parts.showQR = !parts.showQR; rebuild() }
|
identityToggle.OnActivated = func() { parts.showQR = !parts.showQR; rebuild() }
|
||||||
rebuild()
|
rebuild()
|
||||||
|
|
||||||
// Group buttons by function: data viewing vs clipboard vs destructive
|
// Header with toolbar and content + destructive action
|
||||||
clipboardRow := buttonTile(btnCopyPub, btnCopyCrt, btnPaste, btnClear)
|
header := container.NewHBox(widget.NewLabelWithStyle("Moje identita", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), layout.NewSpacer(), identityToolbar)
|
||||||
viewRow := buttonTile(btnShowPub, btnShowCrt, toggleBtn)
|
content := container.NewVBox(header, identityContainer, buttonTile(deleteBtn))
|
||||||
destroyRow := buttonTile(deleteBtn)
|
return container.NewVScroll(content)
|
||||||
group := container.NewVBox(
|
|
||||||
widget.NewLabelWithStyle("Moje identita", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
|
|
||||||
viewRow,
|
|
||||||
identityContainer,
|
|
||||||
clipboardRow,
|
|
||||||
destroyRow,
|
|
||||||
)
|
|
||||||
return container.NewVScroll(group)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions separated to avoid circular dependency with encrypt.Service
|
// Helper functions separated to avoid circular dependency with encrypt.Service
|
||||||
@ -240,14 +233,10 @@ func copyClip(s string, parts *uiParts) {
|
|||||||
// Tab: Encrypt
|
// Tab: Encrypt
|
||||||
func buildEncryptTab(parts *uiParts, svc ServiceFacade) fyne.CanvasObject {
|
func buildEncryptTab(parts *uiParts, svc ServiceFacade) fyne.CanvasObject {
|
||||||
parts.cipherOut.Disable()
|
parts.cipherOut.Disable()
|
||||||
peerBtns := buttonTile(
|
|
||||||
widget.NewButton("Paste", func() { parts.peer.SetText(fyne.CurrentApp().Clipboard().Content()) }),
|
|
||||||
widget.NewButton("Clear", func() { parts.peer.SetText("") }),
|
|
||||||
widget.NewButton("Copy", func() { copyClip(parts.peer.Text, parts) }),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
// Peer section with QR/Text toggle
|
||||||
peerContainer := container.NewVBox()
|
peerContainer := container.NewVBox()
|
||||||
peerToggle := widget.NewButton("", nil)
|
peerToggleAction := widget.NewToolbarAction(theme.VisibilityOffIcon(), nil)
|
||||||
var updatePeer func()
|
var updatePeer func()
|
||||||
updatePeerQR := func(text string) {
|
updatePeerQR := func(text string) {
|
||||||
if text == "" {
|
if text == "" {
|
||||||
@ -271,20 +260,24 @@ func buildEncryptTab(parts *uiParts, svc ServiceFacade) fyne.CanvasObject {
|
|||||||
if parts.showPeerQR {
|
if parts.showPeerQR {
|
||||||
updatePeerQR(parts.peer.Text)
|
updatePeerQR(parts.peer.Text)
|
||||||
peerContainer.Add(container.NewVBox(parts.peerQR, widget.NewButton("Copy", func() { copyClip(parts.peer.Text, parts) })))
|
peerContainer.Add(container.NewVBox(parts.peerQR, widget.NewButton("Copy", func() { copyClip(parts.peer.Text, parts) })))
|
||||||
peerToggle.SetText("Zobrazit plaintext")
|
peerToggleAction.SetIcon(theme.VisibilityOffIcon())
|
||||||
} else {
|
} else {
|
||||||
peerContainer.Add(parts.peer)
|
peerContainer.Add(parts.peer)
|
||||||
peerToggle.SetText("Zobrazit QR")
|
peerToggleAction.SetIcon(theme.VisibilityIcon())
|
||||||
}
|
}
|
||||||
peerContainer.Refresh()
|
peerContainer.Refresh()
|
||||||
}
|
}
|
||||||
peerToggle.OnTapped = func() { parts.showPeerQR = !parts.showPeerQR; updatePeer() }
|
peerToggleAction.OnActivated = func() { parts.showPeerQR = !parts.showPeerQR; updatePeer() }
|
||||||
parts.peer.OnChanged = func(string) {
|
parts.peer.OnChanged = func(string) {
|
||||||
if parts.showPeerQR {
|
if parts.showPeerQR {
|
||||||
updatePeerQR(parts.peer.Text)
|
updatePeerQR(parts.peer.Text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updatePeer()
|
updatePeer()
|
||||||
|
|
||||||
|
// Output section with QR/Text toggle
|
||||||
|
outputContainer := container.NewVBox()
|
||||||
|
outputToggleAction := widget.NewToolbarAction(theme.VisibilityOffIcon(), nil)
|
||||||
updateQR := func(text string) {
|
updateQR := func(text string) {
|
||||||
if text == "" {
|
if text == "" {
|
||||||
parts.cipherQR.Image = nil
|
parts.cipherQR.Image = nil
|
||||||
@ -304,6 +297,21 @@ func buildEncryptTab(parts *uiParts, svc ServiceFacade) fyne.CanvasObject {
|
|||||||
parts.cipherQR.Image = img
|
parts.cipherQR.Image = img
|
||||||
parts.cipherQR.Refresh()
|
parts.cipherQR.Refresh()
|
||||||
}
|
}
|
||||||
|
updateMode := func() {
|
||||||
|
outputContainer.Objects = nil
|
||||||
|
if parts.showQR {
|
||||||
|
updateQR(parts.cipherOut.Text)
|
||||||
|
outputContainer.Add(container.NewVBox(parts.cipherQR, widget.NewButton("Copy", func() { copyClip(parts.cipherOut.Text, parts) })))
|
||||||
|
outputToggleAction.SetIcon(theme.VisibilityOffIcon())
|
||||||
|
} else {
|
||||||
|
outputContainer.Add(parts.cipherOut)
|
||||||
|
outputToggleAction.SetIcon(theme.VisibilityIcon())
|
||||||
|
}
|
||||||
|
outputContainer.Refresh()
|
||||||
|
}
|
||||||
|
outputToggleAction.OnActivated = func() { parts.showQR = !parts.showQR; updateMode() }
|
||||||
|
updateMode()
|
||||||
|
|
||||||
encAction := func() {
|
encAction := func() {
|
||||||
m := parts.msg.Text
|
m := parts.msg.Text
|
||||||
p := parts.peer.Text
|
p := parts.peer.Text
|
||||||
@ -326,6 +334,7 @@ func buildEncryptTab(parts *uiParts, svc ServiceFacade) fyne.CanvasObject {
|
|||||||
})
|
})
|
||||||
}(m, p)
|
}(m, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
importPeerQR := func() {
|
importPeerQR := func() {
|
||||||
fd := dialog.NewFileOpen(func(r fyne.URIReadCloser, err error) {
|
fd := dialog.NewFileOpen(func(r fyne.URIReadCloser, err error) {
|
||||||
if err != nil || r == nil {
|
if err != nil || r == nil {
|
||||||
@ -348,46 +357,37 @@ func buildEncryptTab(parts *uiParts, svc ServiceFacade) fyne.CanvasObject {
|
|||||||
fd.SetFilter(storage.NewExtensionFileFilter([]string{".png"}))
|
fd.SetFilter(storage.NewExtensionFileFilter([]string{".png"}))
|
||||||
fd.Show()
|
fd.Show()
|
||||||
}
|
}
|
||||||
outputContainer := container.NewVBox()
|
|
||||||
toggleBtn := widget.NewButton("", nil)
|
|
||||||
var updateMode func()
|
|
||||||
updateMode = func() {
|
|
||||||
outputContainer.Objects = nil
|
|
||||||
if parts.showQR {
|
|
||||||
updateQR(parts.cipherOut.Text)
|
|
||||||
outputContainer.Add(container.NewVBox(parts.cipherQR, widget.NewButton("Copy", func() { copyClip(parts.cipherOut.Text, parts) })))
|
|
||||||
} else {
|
|
||||||
outputContainer.Add(parts.cipherOut)
|
|
||||||
}
|
|
||||||
if parts.showQR {
|
|
||||||
toggleBtn.SetText("Zobrazit plaintext")
|
|
||||||
} else {
|
|
||||||
toggleBtn.SetText("Zobrazit QR")
|
|
||||||
}
|
|
||||||
outputContainer.Refresh()
|
|
||||||
}
|
|
||||||
toggleBtn.OnTapped = func() { parts.showQR = !parts.showQR; updateMode() }
|
|
||||||
updateMode()
|
|
||||||
|
|
||||||
msgBtns := buttonTile(
|
// Toolbars
|
||||||
widget.NewButton("Clear+Paste", func() { parts.msg.SetText(""); parts.msg.SetText(fyne.CurrentApp().Clipboard().Content()) }),
|
peerToolbar := widget.NewToolbar(
|
||||||
widget.NewButton("Encrypt", func() { encAction(); updateMode() }),
|
widget.NewToolbarAction(theme.ContentPasteIcon(), func() { parts.peer.SetText(fyne.CurrentApp().Clipboard().Content()) }),
|
||||||
widget.NewButton("Copy", func() { copyClip(parts.cipherOut.Text, parts) }),
|
widget.NewToolbarAction(theme.ContentClearIcon(), func() { parts.peer.SetText("") }),
|
||||||
widget.NewButton("Import Key QR", importPeerQR),
|
widget.NewToolbarAction(theme.ContentCopyIcon(), func() { copyClip(parts.peer.Text, parts) }),
|
||||||
|
widget.NewToolbarAction(theme.FolderOpenIcon(), importPeerQR),
|
||||||
|
widget.NewToolbarSeparator(),
|
||||||
|
peerToggleAction,
|
||||||
|
)
|
||||||
|
outputToolbar := widget.NewToolbar(
|
||||||
|
widget.NewToolbarAction(theme.ContentCopyIcon(), func() { copyClip(parts.cipherOut.Text, parts) }),
|
||||||
|
widget.NewToolbarSeparator(),
|
||||||
|
outputToggleAction,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Primary CTA
|
||||||
|
encryptBtn := widget.NewButtonWithIcon("Zašifrovat", theme.ConfirmIcon(), func() { encAction(); updateMode() })
|
||||||
|
|
||||||
|
// Sections
|
||||||
peerSection := container.NewVBox(
|
peerSection := container.NewVBox(
|
||||||
container.NewHBox(widget.NewLabel("Veřejný klíč příjemce"), peerToggle),
|
container.NewHBox(widget.NewLabel("Veřejný klíč příjemce"), layout.NewSpacer(), peerToolbar),
|
||||||
peerContainer,
|
peerContainer,
|
||||||
peerBtns,
|
|
||||||
)
|
)
|
||||||
msgSection := container.NewVBox(
|
msgSection := container.NewVBox(
|
||||||
widget.NewLabel("Zpráva"),
|
widget.NewLabel("Zpráva"),
|
||||||
parts.msg,
|
parts.msg,
|
||||||
msgBtns,
|
container.NewHBox(layout.NewSpacer(), encryptBtn),
|
||||||
)
|
)
|
||||||
outputSection := container.NewVBox(
|
outputSection := container.NewVBox(
|
||||||
container.NewHBox(widget.NewLabel("Výstup"), toggleBtn),
|
container.NewHBox(widget.NewLabel("Výstup"), layout.NewSpacer(), outputToolbar),
|
||||||
outputContainer,
|
outputContainer,
|
||||||
)
|
)
|
||||||
group := container.NewVBox(
|
group := container.NewVBox(
|
||||||
@ -460,8 +460,33 @@ func buildDecryptTab(parts *uiParts, svc ServiceFacade) fyne.CanvasObject {
|
|||||||
fd.SetFilter(storage.NewExtensionFileFilter([]string{".png"}))
|
fd.SetFilter(storage.NewExtensionFileFilter([]string{".png"}))
|
||||||
fd.Show()
|
fd.Show()
|
||||||
}
|
}
|
||||||
payloadBtns := buttonTile(
|
// Toolbar toggle action for payload section
|
||||||
widget.NewButton("Paste+Decrypt", func() {
|
payloadToggleAction := widget.NewToolbarAction(theme.VisibilityOffIcon(), nil)
|
||||||
|
|
||||||
|
payloadContainer := container.NewVBox()
|
||||||
|
updateMode := func() {
|
||||||
|
payloadContainer.Objects = nil
|
||||||
|
if parts.showPayloadQR {
|
||||||
|
updatePayloadQR(parts.payload.Text)
|
||||||
|
payloadContainer.Add(container.NewVBox(parts.payloadQR, widget.NewButton("Copy", func() { copyClip(parts.payload.Text, parts) })))
|
||||||
|
payloadToggleAction.SetIcon(theme.VisibilityOffIcon())
|
||||||
|
} else {
|
||||||
|
payloadContainer.Add(parts.payload)
|
||||||
|
payloadToggleAction.SetIcon(theme.VisibilityIcon())
|
||||||
|
}
|
||||||
|
payloadContainer.Refresh()
|
||||||
|
}
|
||||||
|
payloadToggleAction.OnActivated = func() { parts.showPayloadQR = !parts.showPayloadQR; updateMode() }
|
||||||
|
parts.payload.OnChanged = func(string) {
|
||||||
|
if parts.showPayloadQR {
|
||||||
|
updatePayloadQR(parts.payload.Text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateMode()
|
||||||
|
|
||||||
|
// Build payload toolbar
|
||||||
|
payloadToolbar := widget.NewToolbar(
|
||||||
|
widget.NewToolbarAction(theme.ContentPasteIcon(), func() {
|
||||||
clip := fyne.CurrentApp().Clipboard().Content()
|
clip := fyne.CurrentApp().Clipboard().Content()
|
||||||
parts.payload.SetText(clip)
|
parts.payload.SetText(clip)
|
||||||
if parts.showPayloadQR {
|
if parts.showPayloadQR {
|
||||||
@ -469,48 +494,33 @@ func buildDecryptTab(parts *uiParts, svc ServiceFacade) fyne.CanvasObject {
|
|||||||
}
|
}
|
||||||
decryptAction()
|
decryptAction()
|
||||||
}),
|
}),
|
||||||
widget.NewButton("Clear", func() {
|
widget.NewToolbarAction(theme.ContentClearIcon(), func() {
|
||||||
parts.payload.SetText("")
|
parts.payload.SetText("")
|
||||||
parts.plainOut.SetText("")
|
parts.plainOut.SetText("")
|
||||||
if parts.showPayloadQR {
|
if parts.showPayloadQR {
|
||||||
updatePayloadQR("")
|
updatePayloadQR("")
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
widget.NewButton("QR Import", importPayloadQR),
|
widget.NewToolbarAction(theme.FolderOpenIcon(), importPayloadQR),
|
||||||
|
widget.NewToolbarSeparator(),
|
||||||
|
payloadToggleAction,
|
||||||
)
|
)
|
||||||
|
|
||||||
payloadContainer := container.NewVBox()
|
// Build result toolbar
|
||||||
payloadToggle := widget.NewButton("", nil)
|
resultToolbar := widget.NewToolbar(
|
||||||
var updateMode func()
|
widget.NewToolbarAction(theme.ContentCopyIcon(), func() { copyClip(parts.plainOut.Text, parts) }),
|
||||||
updateMode = func() {
|
)
|
||||||
payloadContainer.Objects = nil
|
|
||||||
if parts.showPayloadQR {
|
// Primary CTA for decryption
|
||||||
updatePayloadQR(parts.payload.Text)
|
decryptBtn := widget.NewButtonWithIcon("Dešifrovat", theme.ConfirmIcon(), func() { decryptAction() })
|
||||||
payloadContainer.Add(container.NewVBox(parts.payloadQR, widget.NewButton("Copy", func() { copyClip(parts.payload.Text, parts) })))
|
|
||||||
payloadToggle.SetText("Zobrazit plaintext")
|
|
||||||
} else {
|
|
||||||
payloadContainer.Add(parts.payload)
|
|
||||||
payloadToggle.SetText("Zobrazit QR")
|
|
||||||
}
|
|
||||||
payloadContainer.Refresh()
|
|
||||||
}
|
|
||||||
payloadToggle.OnTapped = func() { parts.showPayloadQR = !parts.showPayloadQR; updateMode() }
|
|
||||||
parts.payload.OnChanged = func(string) {
|
|
||||||
if parts.showPayloadQR {
|
|
||||||
updatePayloadQR(parts.payload.Text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateMode()
|
|
||||||
plainBtns := buttonTile(widget.NewButton("Copy", func() { copyClip(parts.plainOut.Text, parts) }))
|
|
||||||
payloadSection := container.NewVBox(
|
payloadSection := container.NewVBox(
|
||||||
container.NewHBox(widget.NewLabel("Payload"), payloadToggle),
|
container.NewHBox(widget.NewLabel("Payload"), layout.NewSpacer(), payloadToolbar),
|
||||||
payloadContainer,
|
payloadContainer,
|
||||||
payloadBtns,
|
container.NewHBox(layout.NewSpacer(), decryptBtn),
|
||||||
)
|
)
|
||||||
resultSection := container.NewVBox(
|
resultSection := container.NewVBox(
|
||||||
widget.NewLabel("Výsledek"),
|
container.NewHBox(widget.NewLabel("Výsledek"), layout.NewSpacer(), resultToolbar),
|
||||||
parts.plainOut,
|
parts.plainOut,
|
||||||
plainBtns,
|
|
||||||
)
|
)
|
||||||
group := container.NewVBox(
|
group := container.NewVBox(
|
||||||
widget.NewLabelWithStyle("Dešifrování", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
|
widget.NewLabelWithStyle("Dešifrování", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user