Skip to content

Commit

Permalink
Add export log option to mister gui (#113)
Browse files Browse the repository at this point in the history
* Almost working upload log in mister gui

* Fix gui glitches
  • Loading branch information
wizzomafizzo authored Nov 9, 2024
1 parent 1db3e87 commit ac60fc1
Show file tree
Hide file tree
Showing 2 changed files with 210 additions and 85 deletions.
267 changes: 182 additions & 85 deletions cmd/mister/gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,15 @@ along with TapTo. If not, see <http://www.gnu.org/licenses/>.
package main

import (
"fmt"
"os/exec"
"path"
"strings"

"github.com/rs/zerolog/log"
"github.com/rthornton128/goncurses"
"github.com/wizzomafizzo/mrext/pkg/curses"
mrextMister "github.com/wizzomafizzo/mrext/pkg/mister"
"github.com/wizzomafizzo/tapto/pkg/assets"
"github.com/wizzomafizzo/tapto/pkg/config"
"github.com/wizzomafizzo/tapto/pkg/database/gamesdb"
"github.com/wizzomafizzo/tapto/pkg/platforms"
"github.com/wizzomafizzo/tapto/pkg/platforms/mister"
"github.com/wizzomafizzo/tapto/pkg/utils"
Expand Down Expand Up @@ -75,13 +74,13 @@ func tryAddStartup(stdscr *goncurses.Window) error {
if ch == goncurses.KEY_LEFT {
if selected == 0 {
selected = 1
} else if selected == 1 {
} else {
selected = 0
}
} else if ch == goncurses.KEY_RIGHT {
if selected == 0 {
selected = 1
} else if selected == 1 {
} else {
selected = 0
}
} else if ch == goncurses.KEY_ENTER || ch == 10 || ch == 13 {
Expand All @@ -108,105 +107,210 @@ func tryAddStartup(stdscr *goncurses.Window) error {
return nil
}

func generateIndexWindow(pl platforms.Platform, cfg *config.UserConfig, stdscr *goncurses.Window) error {
win, err := curses.NewWindow(stdscr, 4, 46, "", -1)
func copyLogToSd(pl platforms.Platform, stdscr *goncurses.Window) error {
width := 46
win, err := curses.NewWindow(stdscr, 6, width, "", -1)
if err != nil {
return err
}
defer win.Delete()
defer func(win *goncurses.Window) {
err := win.Delete()
if err != nil {
log.Error().Msgf("failed to delete window: %s", err)
}
}(win)

_, width := win.MaxYX()
logPath := path.Join(pl.LogFolder(), config.LogFilename)
newPath := path.Join("/media/fat", config.LogFilename)
err = utils.CopyFile(logPath, newPath)

drawProgressBar := func(current int, total int) {
pct := int(float64(current) / float64(total) * 100)
progressWidth := width - 4
progressPct := int(float64(pct) / float64(100) * float64(progressWidth))
if progressPct < 1 {
progressPct = 1
}
for i := 0; i < progressPct; i++ {
win.MoveAddChar(2, 2+i, goncurses.ACS_BLOCK)
printCenter := func(y int, text string) {
win.MovePrint(y, (width-len(text))/2, text)
}

if err != nil {
printCenter(1, "Unable to copy log file to SD card.")
log.Error().Err(err).Msgf("error copying log file")
} else {
printCenter(1, "Copied tapto.log to root of SD card.")
}
win.NoutRefresh()

curses.DrawActionButtons(win, []string{"OK"}, 0, 2)
win.NoutRefresh()

err = goncurses.Update()
if err != nil {
return err
}

_ = win.GetChar()
return nil
}

func uploadLog(pl platforms.Platform, stdscr *goncurses.Window) error {
width := 46
win, err := curses.NewWindow(stdscr, 6, width, "", -1)
if err != nil {
return err
}
defer func(win *goncurses.Window) {
err := win.Delete()
if err != nil {
log.Error().Msgf("failed to delete window: %s", err)
}
win.NoutRefresh()
}(win)

logPath := path.Join(pl.LogFolder(), config.LogFilename)

printCenter := func(y int, text string) {
win.MovePrint(y, (width-len(text))/2, text)
}

clearText := func() {
win.MovePrint(1, 2, strings.Repeat(" ", width-4))
clearLine := func(y int) {
win.MovePrint(y, 2, strings.Repeat(" ", width-3))
}

status := struct {
Step int
Total int
SystemName string
DisplayText string
Complete bool
Error error
}{
Step: 1,
Total: 100,
DisplayText: "Finding games folders...",
printCenter(1, "Uploading log file...")
win.NoutRefresh()
err = goncurses.Update()
if err != nil {
return err
}

// TODO: this should index via the API as well
go func() {
_, err = gamesdb.NewNamesIndex(pl, cfg, gamesdb.AllSystems(), func(is gamesdb.IndexStatus) {
systemName := is.SystemId
system, err := gamesdb.GetSystem(is.SystemId)
if err == nil {
md, err := assets.GetSystemMetadata(system.Id)
if err == nil {
systemName = md.Name
}
}
uploadCmd := "cat '" + logPath + "' | nc termbin.com 9999"
out, err := exec.Command("bash", "-c", uploadCmd).Output()
clearLine(1)
clearLine(2)
if err != nil {
printCenter(1, "Unable to upload log file.")
log.Error().Err(err).Msgf("error uploading log file to termbin")
} else {
printCenter(1, "Log file URL:")
printCenter(2, strings.TrimSpace(string(out)))
}
// no idea why but if i don't draw this box part of the windows border is
// cleared by the url being displayed
_ = win.Box(goncurses.ACS_VLINE, goncurses.ACS_HLINE)
win.NoutRefresh()

text := fmt.Sprintf("Indexing %s...", systemName)
if is.Step == 1 {
text = "Finding games folders..."
} else if is.Step == is.Total {
text = "Writing database to disk..."
}
curses.DrawActionButtons(win, []string{"OK"}, 0, 2)
win.NoutRefresh()

status.Step = is.Step
status.Total = is.Total
status.SystemName = systemName
status.DisplayText = text
})
err = goncurses.Update()
if err != nil {
return err
}

status.Error = err
status.Complete = true
}()
_ = win.GetChar()
return nil
}

spinnerSeq := []string{"|", "/", "-", "\\"}
spinnerCount := 0
func exportLog(pl platforms.Platform, stdscr *goncurses.Window) error {
width := 46
win, err := curses.NewWindow(stdscr, 6, width, "", -1)
if err != nil {
return err
}
defer func(win *goncurses.Window) {
err := win.Delete()
if err != nil {
log.Error().Msgf("failed to delete window: %s", err)
}
}(win)

for {
if status.Complete || status.Error != nil {
break
printLeft := func(y int, text string) {
win.MovePrint(y, 2, text)
}

clearLine := func(y int) {
win.MovePrint(y, 2, strings.Repeat(" ", width-4))
}

var ch goncurses.Key
selectedButton := 1
selectedMenu := 0
display := true

for display {
menuOnline := "Upload to termbin.com"
clearLine(1)
if selectedMenu == 0 {
printLeft(1, "> "+menuOnline)
} else {
printLeft(1, " "+menuOnline)
}
win.NoutRefresh()

clearText()
menuSd := "Copy to SD card"
clearLine(2)
if selectedMenu == 1 {
printLeft(2, "> "+menuSd)
} else {
printLeft(2, " "+menuSd)
}
win.NoutRefresh()

spinnerCount++
if spinnerCount == len(spinnerSeq) {
spinnerCount = 0
curses.DrawActionButtons(win, []string{"Cancel", "OK"}, selectedButton, 2)
win.NoutRefresh()

err := goncurses.Update()
if err != nil {
return err
}

win.MovePrint(1, width-3, spinnerSeq[spinnerCount])
ch = win.GetChar()

win.MovePrint(1, 2, status.DisplayText)
drawProgressBar(status.Step, status.Total)
switch ch {
case goncurses.KEY_LEFT:
if selectedButton == 0 {
selectedButton = 1
} else {
selectedButton = 0
}
case goncurses.KEY_RIGHT:
if selectedButton == 1 {
selectedButton = 0
} else {
selectedButton = 1
}
case goncurses.KEY_UP:
if selectedMenu == 0 {
selectedMenu = 1
} else {
selectedMenu = 0
}
case goncurses.KEY_DOWN:
if selectedMenu == 0 {
selectedMenu = 1
} else {
selectedMenu = 0
}
case goncurses.KEY_ESC:
return nil
case goncurses.KEY_ENTER, 10, 13:
if selectedButton == 0 {
return nil
} else {
display = false
}
}
}

win.NoutRefresh()
_ = goncurses.Update()
goncurses.Nap(100)
if selectedButton == 1 {
if selectedMenu == 0 {
return uploadLog(pl, stdscr)
} else {
return copyLogToSd(pl, stdscr)
}
}

return status.Error
return nil
}

func displayServiceInfo(pl platforms.Platform, cfg *config.UserConfig, stdscr *goncurses.Window, service *mister.Service) error {
width := 50
height := 9
height := 8

win, err := curses.NewWindow(stdscr, height, width, "", -1)
if err != nil {
Expand Down Expand Up @@ -271,15 +375,8 @@ func displayServiceInfo(pl platforms.Platform, cfg *config.UserConfig, stdscr *g
clearLine(4)
printLeft(4, "Device address: "+ipDisplay)

clearLine(5)
dbExistsDisplay := "NOT CREATED"
if gamesdb.Exists(pl) {
dbExistsDisplay = "CREATED"
}
printLeft(5, "Games DB: "+dbExistsDisplay)

clearLine(height - 2)
curses.DrawActionButtons(win, []string{"Update Games DB", "Exit"}, selected, 2)
curses.DrawActionButtons(win, []string{"Export Log", "Exit"}, selected, 2)

win.NoutRefresh()
err = goncurses.Update()
Expand All @@ -303,11 +400,11 @@ func displayServiceInfo(pl platforms.Platform, cfg *config.UserConfig, stdscr *g
}
} else if ch == goncurses.KEY_ENTER || ch == 10 || ch == 13 {
if selected == 0 {
err := generateIndexWindow(pl, cfg, stdscr)
err := exportLog(pl, stdscr)
if err != nil {
log.Error().Msgf("failed to display gamesdb window: %s", err)
log.Error().Msgf("failed to display export log window: %s", err)
}
} else if selected == 1 {
} else {
break
}
} else if ch == goncurses.KEY_ESC {
Expand Down
28 changes: 28 additions & 0 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,31 @@ func RandomElem[T any](xs []T) (T, error) {
return item, nil
}
}

func CopyFile(sourcePath, destPath string) error {
inputFile, err := os.Open(sourcePath)
if err != nil {
return err
}
defer func(inputFile *os.File) {
_ = inputFile.Close()
}(inputFile)

outputFile, err := os.Create(destPath)
if err != nil {
return err
}
defer func(outputFile *os.File) {
_ = outputFile.Close()
}(outputFile)

_, err = io.Copy(outputFile, inputFile)
if err != nil {
return err
}
err = outputFile.Sync()
if err != nil {
return err
}
return inputFile.Close()
}

0 comments on commit ac60fc1

Please sign in to comment.