1
0
mirror of https://github.com/taigrr/crocgui synced 2025-01-18 04:03:16 -08:00

add debug log ability

puts recent debug lines on screen (with wrapping) #8
ability to save logfile #10
also made settings scrollable for small screens #9
This commit is contained in:
Chris Howey 2021-03-26 15:45:31 -05:00
parent 048a293e98
commit b89b59aacf
7 changed files with 159 additions and 25 deletions

View File

@ -5,7 +5,6 @@ import (
"bytes" "bytes"
_ "embed" _ "embed"
"fmt" "fmt"
"net/url"
"strings" "strings"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
@ -14,11 +13,6 @@ import (
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
) )
func parseURL(s string) *url.URL {
link, _ := url.Parse(s)
return link
}
//go:embed metadata/en-US/full_description.txt //go:embed metadata/en-US/full_description.txt
var longdesc string var longdesc string

1
go.mod
View File

@ -5,6 +5,7 @@ go 1.16
require ( require (
fyne.io/fyne/v2 v2.0.0 fyne.io/fyne/v2 v2.0.0
github.com/schollz/croc/v8 v8.6.7 github.com/schollz/croc/v8 v8.6.7
github.com/schollz/logger v1.2.0 // indirect
) )
replace fyne.io/fyne/v2 => ./fyne-uri-name replace fyne.io/fyne/v2 => ./fyne-uri-name

40
main.go
View File

@ -1,22 +1,57 @@
package main package main
import ( import (
"bytes"
_ "embed" _ "embed"
"strings"
"time"
log "github.com/schollz/logger"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/app" "fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/data/binding"
"fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/layout"
) )
//go:embed metadata/en-US/images/featureGraphic.png //go:embed metadata/en-US/images/featureGraphic.png
var textlogobytes []byte var textlogobytes []byte
type logwriter struct {
buf bytes.Buffer
lastlines []string
lastupdate time.Time
}
const LOG_LINES = 20
func (lw *logwriter) Write(p []byte) (n int, err error) {
n, err = lw.buf.Write(p)
lw.lastlines = append([]string{string(p)}, lw.lastlines...)
if len(lw.lastlines) > LOG_LINES {
lw.lastlines = lw.lastlines[:LOG_LINES]
}
if time.Since(lw.lastupdate) > time.Second {
logbinding.Set(strings.Join(lw.lastlines, ""))
lw.lastupdate = time.Now()
}
return
}
var logoutput logwriter
var logbinding binding.String
func main() { func main() {
a := app.NewWithID("com.github.howeyc.crocgui") a := app.NewWithID("com.github.howeyc.crocgui")
w := a.NewWindow("croc") w := a.NewWindow("croc")
logbinding = binding.NewString()
log.SetOutput(&logoutput)
// Defaults // Defaults
a.Preferences().SetString("relay-address", a.Preferences().StringWithFallback("relay-address", "croc.schollz.com:9009")) a.Preferences().SetString("relay-address", a.Preferences().StringWithFallback("relay-address", "croc.schollz.com:9009"))
a.Preferences().SetString("relay-password", a.Preferences().StringWithFallback("relay-password", "pass123")) a.Preferences().SetString("relay-password", a.Preferences().StringWithFallback("relay-password", "pass123"))
@ -26,8 +61,10 @@ func main() {
a.Preferences().SetBool("disable-multiplexing", a.Preferences().BoolWithFallback("disable-multiplexing", false)) a.Preferences().SetBool("disable-multiplexing", a.Preferences().BoolWithFallback("disable-multiplexing", false))
a.Preferences().SetBool("disable-compression", a.Preferences().BoolWithFallback("disable-compression", false)) a.Preferences().SetBool("disable-compression", a.Preferences().BoolWithFallback("disable-compression", false))
a.Preferences().SetString("theme", a.Preferences().StringWithFallback("theme", "light")) a.Preferences().SetString("theme", a.Preferences().StringWithFallback("theme", "light"))
a.Preferences().SetString("debug-level", a.Preferences().StringWithFallback("debug-level", "error"))
setTheme(a.Preferences().String("theme")) setTheme(a.Preferences().String("theme"))
log.SetLevel(a.Preferences().String("debug-level"))
textlogores := fyne.NewStaticResource("text-logo", textlogobytes) textlogores := fyne.NewStaticResource("text-logo", textlogobytes)
textlogo := canvas.NewImageFromResource(textlogores) textlogo := canvas.NewImageFromResource(textlogores)
@ -41,5 +78,8 @@ func main() {
aboutTabItem(), aboutTabItem(),
))) )))
w.Resize(fyne.NewSize(800, 600)) w.Resize(fyne.NewSize(800, 600))
setDebugObjects()
w.ShowAndRun() w.ShowAndRun()
} }

View File

@ -0,0 +1,2 @@
- Settings are scrollable
- Add debug logging

41
recv.go
View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"io" "io"
"io/fs" "io/fs"
"log"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
@ -12,24 +11,42 @@ import (
"sync" "sync"
"time" "time"
log "github.com/schollz/logger"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"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/theme" "fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
"github.com/schollz/croc/v8/src/croc" "github.com/schollz/croc/v8/src/croc"
) )
func recvTabItem(a fyne.App, w fyne.Window) *container.TabItem { func recvTabItem(a fyne.App, w fyne.Window) *container.TabItem {
logInfo := widget.NewLabelWithData(logbinding)
logInfo.Wrapping = fyne.TextWrapWord
status := widget.NewLabel("") status := widget.NewLabel("")
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
status.SetText(fmt.Sprint(r)) logInfo.SetText(fmt.Sprint(r))
} }
}() }()
recvDir, _ := os.MkdirTemp("", "crocgui-recv") recvDir, _ := os.MkdirTemp("", "crocgui-recv")
debugBox := container.NewHBox(widget.NewLabel("Debug log:"), layout.NewSpacer(), widget.NewButton("Export full log", func() {
savedialog := dialog.NewFileSave(func(f fyne.URIWriteCloser, e error) {
if f != nil {
logoutput.buf.WriteTo(f)
f.Close()
}
}, w)
savedialog.SetFileName("crocdebuglog.txt")
savedialog.Show()
}))
debugObjects = append(debugObjects, debugBox)
prog := widget.NewProgressBar() prog := widget.NewProgressBar()
prog.Hide() prog.Hide()
recvEntry := widget.NewEntry() recvEntry := widget.NewEntry()
@ -42,7 +59,7 @@ func recvTabItem(a fyne.App, w fyne.Window) *container.TabItem {
receiver, err := croc.New(croc.Options{ receiver, err := croc.New(croc.Options{
IsSender: false, IsSender: false,
SharedSecret: recvEntry.Text, SharedSecret: recvEntry.Text,
Debug: false, Debug: crocDebugMode(),
RelayAddress: a.Preferences().String("relay-address"), RelayAddress: a.Preferences().String("relay-address"),
RelayPassword: a.Preferences().String("relay-password"), RelayPassword: a.Preferences().String("relay-password"),
Stdout: false, Stdout: false,
@ -53,8 +70,12 @@ func recvTabItem(a fyne.App, w fyne.Window) *container.TabItem {
NoCompress: a.Preferences().Bool("disable-compression"), NoCompress: a.Preferences().Bool("disable-compression"),
}) })
if err != nil { if err != nil {
log.Println("Receive setup error:", err) log.Error("Receive setup error:", err)
return
} }
log.SetLevel(crocDebugLevel())
log.Trace("croc receiver created")
prog.Show() prog.Show()
donechan := make(chan bool) donechan := make(chan bool)
var filename string var filename string
@ -81,7 +102,7 @@ func recvTabItem(a fyne.App, w fyne.Window) *container.TabItem {
}() }()
cderr := os.Chdir(recvDir) cderr := os.Chdir(recvDir)
if cderr != nil { if cderr != nil {
log.Println("Unable to change to dir:", recvDir, cderr) log.Error("Unable to change to dir:", recvDir, cderr)
} }
status.SetText("") status.SetText("")
rerr := receiver.Receive() rerr := receiver.Receive()
@ -90,7 +111,7 @@ func recvTabItem(a fyne.App, w fyne.Window) *container.TabItem {
prog.SetValue(0) prog.SetValue(0)
topline.SetText("Enter code to download") topline.SetText("Enter code to download")
if rerr != nil { if rerr != nil {
status.Text = "Receive failed: " + rerr.Error() log.Error("Receive failed: " + rerr.Error())
} else { } else {
filesReceived := make([]string, len(receivednames)) filesReceived := make([]string, len(receivednames))
var i int var i int
@ -120,18 +141,20 @@ func recvTabItem(a fyne.App, w fyne.Window) *container.TabItem {
ofile = f ofile = f
oerr = e oerr = e
if oerr != nil { if oerr != nil {
status.SetText(oerr.Error()) log.Error(oerr.Error())
return return
} }
ifile, ierr := os.Open(path) ifile, ierr := os.Open(path)
if ierr != nil { if ierr != nil {
status.SetText(ierr.Error()) log.Error(ierr.Error())
return return
} }
io.Copy(ofile, ifile) io.Copy(ofile, ifile)
ifile.Close() ifile.Close()
ofile.Close() ofile.Close()
os.Remove(path) os.Remove(path)
log.Tracef("saved (%s) to user path %s", path, f.URI().String())
log.Tracef("remove internal cache file %s", path)
diagwg.Done() diagwg.Done()
}, w) }, w)
savedialog.SetFileName(filepath.Base(path)) savedialog.SetFileName(filepath.Base(path))
@ -144,6 +167,8 @@ func recvTabItem(a fyne.App, w fyne.Window) *container.TabItem {
}), }),
prog, prog,
status, status,
debugBox,
logInfo,
)) ))
} }

39
send.go
View File

@ -3,12 +3,13 @@ package main
import ( import (
"fmt" "fmt"
"io" "io"
"log"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
log "github.com/schollz/logger"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/dialog"
@ -20,10 +21,13 @@ import (
) )
func sendTabItem(a fyne.App, w fyne.Window) *container.TabItem { func sendTabItem(a fyne.App, w fyne.Window) *container.TabItem {
logInfo := widget.NewLabelWithData(logbinding)
logInfo.Wrapping = fyne.TextWrapWord
status := widget.NewLabel("") status := widget.NewLabel("")
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
status.SetText(fmt.Sprint(r)) log.Error(fmt.Sprint(r))
} }
}() }()
prog := widget.NewProgressBar() prog := widget.NewProgressBar()
@ -45,21 +49,23 @@ func sendTabItem(a fyne.App, w fyne.Window) *container.TabItem {
addFileButton := widget.NewButtonWithIcon("", theme.FileIcon(), func() { addFileButton := widget.NewButtonWithIcon("", theme.FileIcon(), func() {
dialog.ShowFileOpen(func(f fyne.URIReadCloser, e error) { dialog.ShowFileOpen(func(f fyne.URIReadCloser, e error) {
if e != nil { if e != nil {
log.Errorf("Open dialog error: %s", e.Error())
return return
} }
if f != nil { if f != nil {
nfile, oerr := os.Create(filepath.Join(sendDir, f.URI().Name())) nfile, oerr := os.Create(filepath.Join(sendDir, f.URI().Name()))
if oerr != nil { if oerr != nil {
status.SetText(fmt.Sprintf("Unable to copy file, error: %s - %s", sendDir, oerr.Error())) log.Errorf("Unable to copy file, error: %s - %s\n", sendDir, oerr.Error())
return return
} }
io.Copy(nfile, f) io.Copy(nfile, f)
nfile.Close() nfile.Close()
fpath := nfile.Name() fpath := nfile.Name()
log.Tracef("Android URI (%s), copied to internal cache %s", f.URI().String(), nfile.Name())
_, sterr := os.Stat(fpath) _, sterr := os.Stat(fpath)
if sterr != nil { if sterr != nil {
status.SetText(fmt.Sprintf("Stat error: %s - %s", fpath, sterr.Error())) log.Errorf("Stat error: %s - %s\n", fpath, sterr.Error())
return return
} }
labelFile := widget.NewLabel(filepath.Base(fpath)) labelFile := widget.NewLabel(filepath.Base(fpath))
@ -67,6 +73,7 @@ func sendTabItem(a fyne.App, w fyne.Window) *container.TabItem {
if fe, ok := fileentries[fpath]; ok { if fe, ok := fileentries[fpath]; ok {
boxholder.Remove(fe) boxholder.Remove(fe)
os.Remove(fpath) os.Remove(fpath)
log.Tracef("Removed file from internal cache: %s", fpath)
delete(fileentries, fpath) delete(fileentries, fpath)
} }
})) }))
@ -76,6 +83,18 @@ func sendTabItem(a fyne.App, w fyne.Window) *container.TabItem {
}, w) }, w)
}) })
debugBox := container.NewHBox(widget.NewLabel("Debug log:"), layout.NewSpacer(), widget.NewButton("Export full log", func() {
savedialog := dialog.NewFileSave(func(f fyne.URIWriteCloser, e error) {
if f != nil {
logoutput.buf.WriteTo(f)
f.Close()
}
}, w)
savedialog.SetFileName("crocdebuglog.txt")
savedialog.Show()
}))
debugObjects = append(debugObjects, debugBox)
return container.NewTabItemWithIcon("Send", theme.MailSendIcon(), return container.NewTabItemWithIcon("Send", theme.MailSendIcon(),
container.NewVBox( container.NewVBox(
container.NewHBox(topline, layout.NewSpacer(), addFileButton), container.NewHBox(topline, layout.NewSpacer(), addFileButton),
@ -91,7 +110,7 @@ func sendTabItem(a fyne.App, w fyne.Window) *container.TabItem {
sender, err := croc.New(croc.Options{ sender, err := croc.New(croc.Options{
IsSender: true, IsSender: true,
SharedSecret: randomName, SharedSecret: randomName,
Debug: false, Debug: crocDebugMode(),
RelayAddress: a.Preferences().String("relay-address"), RelayAddress: a.Preferences().String("relay-address"),
RelayPorts: strings.Split(a.Preferences().String("relay-ports"), ","), RelayPorts: strings.Split(a.Preferences().String("relay-ports"), ","),
RelayPassword: a.Preferences().String("relay-password"), RelayPassword: a.Preferences().String("relay-password"),
@ -103,9 +122,12 @@ func sendTabItem(a fyne.App, w fyne.Window) *container.TabItem {
NoCompress: a.Preferences().Bool("disable-compression"), NoCompress: a.Preferences().Bool("disable-compression"),
}) })
if err != nil { if err != nil {
status.SetText("croc error: " + err.Error()) log.Errorf("croc error: %s\n", err.Error())
return return
} }
log.SetLevel(crocDebugLevel())
log.Trace("croc sender created")
var filename string var filename string
status.SetText("Receive Code: " + randomName) status.SetText("Receive Code: " + randomName)
currentCode = randomName currentCode = randomName
@ -148,6 +170,7 @@ func sendTabItem(a fyne.App, w fyne.Window) *container.TabItem {
if fe, ok := fileentries[fpath]; ok { if fe, ok := fileentries[fpath]; ok {
boxholder.Remove(fe) boxholder.Remove(fe)
os.Remove(fpath) os.Remove(fpath)
log.Tracef("Removed file from internal cache: %s", fpath)
delete(fileentries, fpath) delete(fileentries, fpath)
} }
} }
@ -155,7 +178,7 @@ func sendTabItem(a fyne.App, w fyne.Window) *container.TabItem {
topline.SetText("Pick a file to send") topline.SetText("Pick a file to send")
addFileButton.Show() addFileButton.Show()
if serr != nil { if serr != nil {
log.Println("Send failed:", serr) log.Errorf("Send failed: %s\n", serr)
} else { } else {
status.SetText(fmt.Sprintf("Sent file %s", filename)) status.SetText(fmt.Sprintf("Sent file %s", filename))
} }
@ -165,5 +188,7 @@ func sendTabItem(a fyne.App, w fyne.Window) *container.TabItem {
}), }),
prog, prog,
container.NewHBox(status, copyCodeButton), container.NewHBox(status, copyCodeButton),
debugBox,
logInfo,
)) ))
} }

View File

@ -3,6 +3,8 @@ package main
import ( import (
"crocgui/internal/croctheme" "crocgui/internal/croctheme"
log "github.com/schollz/logger"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/data/binding"
@ -25,6 +27,32 @@ func setTheme(themeName string) {
} }
} }
func crocDebugMode() bool {
switch fyne.CurrentApp().Preferences().String("debug-level") {
case "trace", "debug":
return true
default:
return false
}
}
func crocDebugLevel() string {
return fyne.CurrentApp().Preferences().String("debug-level")
}
var debugObjects []fyne.CanvasObject
func setDebugObjects() {
debugging := crocDebugMode()
for _, obj := range debugObjects {
if debugging {
obj.Show()
} else {
obj.Hide()
}
}
}
func settingsTabItem(a fyne.App) *container.TabItem { func settingsTabItem(a fyne.App) *container.TabItem {
themeBinding := binding.BindPreferenceString("theme", a.Preferences()) themeBinding := binding.BindPreferenceString("theme", a.Preferences())
themeSelect := widget.NewSelect([]string{"light", "dark", "black"}, func(selection string) { themeSelect := widget.NewSelect([]string{"light", "dark", "black"}, func(selection string) {
@ -33,7 +61,26 @@ func settingsTabItem(a fyne.App) *container.TabItem {
}) })
currentTheme, _ := themeBinding.Get() currentTheme, _ := themeBinding.Get()
themeSelect.SetSelected(currentTheme) themeSelect.SetSelected(currentTheme)
return container.NewTabItemWithIcon("Settings", theme.SettingsIcon(), container.NewVBox(
debugLevelBinding := binding.BindPreferenceString("debug-level", a.Preferences())
debugCheck := widget.NewCheck("Enable Debug Log", func(debug bool) {
if debug {
log.SetLevel("trace")
debugLevelBinding.Set("trace")
} else {
log.SetLevel("error")
debugLevelBinding.Set("error")
}
setDebugObjects()
})
debugCheck.SetChecked(crocDebugMode())
return container.NewTabItemWithIcon("Settings", theme.SettingsIcon(), container.NewVScroll(container.NewVBox(
widget.NewLabelWithStyle("Appearance", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
widget.NewForm(
widget.NewFormItem("Theme", themeSelect),
),
widget.NewSeparator(),
widget.NewLabelWithStyle("Relay", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), widget.NewLabelWithStyle("Relay", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
widget.NewForm( widget.NewForm(
widget.NewFormItem("Address", widget.NewEntryWithData(binding.BindPreferenceString("relay-address", a.Preferences()))), widget.NewFormItem("Address", widget.NewEntryWithData(binding.BindPreferenceString("relay-address", a.Preferences()))),
@ -53,9 +100,9 @@ func settingsTabItem(a fyne.App) *container.TabItem {
widget.NewFormItem("", widget.NewCheckWithData("Disable Compression", binding.BindPreferenceBool("disable-compression", a.Preferences()))), widget.NewFormItem("", widget.NewCheckWithData("Disable Compression", binding.BindPreferenceBool("disable-compression", a.Preferences()))),
), ),
widget.NewSeparator(), widget.NewSeparator(),
widget.NewLabelWithStyle("Appearance", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), widget.NewLabelWithStyle("Debug", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
widget.NewForm( widget.NewForm(
widget.NewFormItem("Theme", themeSelect), widget.NewFormItem("", debugCheck),
), ),
)) )))
} }