Skip to content

Commit

Permalink
tlock: Show loading spinner while the image is being processed
Browse files Browse the repository at this point in the history
  • Loading branch information
eklairs committed May 10, 2024
1 parent 7be0b81 commit d82f463
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 13 deletions.
92 changes: 80 additions & 12 deletions tlock/models/dashboard/tokens/from_screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package tokens

import (
"fmt"
"time"

"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/eklairs/tlock/tlock-internal/components"
Expand All @@ -17,12 +19,35 @@ import (
"github.com/pquerna/otp"
)

var MeterV2 = spinner.Spinner{
Frames: []string{
"▱▱▱▱",
"▰▱▱▱",
"▰▰▱▱",
"▰▰▰▱",
"▰▰▰▰",
"▱▰▰▰",
"▱▱▰▰",
"▱▱▱▰",
},
FPS: time.Second / 8, //nolint:gomnd
}

// Channel to send the token read from the screen
var dataFromScreenChan = make(chan *string)

// Message stating that a data has been recved
type dataRecievedMsg struct {
data *string
}

var fromScreenAsciiArt = `
█▀ █▀▀ █▀█ █▀▀ █▀▀ █▄ █
▄█ █▄▄ █▀▄ ██▄ ██▄ █ ▀█`

const (
stateTake = iota
stateGathering
stateConfirm
)

Expand All @@ -45,6 +70,14 @@ func (k fromScreenKeyMap) FullHelp() [][]key.Binding {
}
}

func pollDataFetched() tea.Cmd {
return func() tea.Msg {
return dataRecievedMsg{
data: <-dataFromScreenChan,
}
}
}

// Keys
var fromScreenKeys = fromScreenKeyMap{
GoBack: key.NewBinding(
Expand Down Expand Up @@ -97,6 +130,9 @@ type TokenFromScreen struct {
// Vault
vault *tlockvault.Vault

// Spinner
spinner spinner.Model

// Token read from string
token *string

Expand All @@ -109,16 +145,23 @@ type TokenFromScreen struct {

// Initializes a new instance of fromScreen from screen
func InitializeTokenFromScreen(vault *tlockvault.Vault, folder tlockvault.Folder) TokenFromScreen {
// Initialize spinner
s := spinner.New()
s.Spinner = MeterV2
s.Style = tlockstyles.Styles.Title

// Return
return TokenFromScreen{
state: stateTake,
vault: vault,
spinner: s,
folder: folder,
}
}

// Init
func (screen TokenFromScreen) Init() tea.Cmd {
return nil
return pollDataFetched()
}

// Update
Expand All @@ -132,23 +175,35 @@ func (screen TokenFromScreen) Update(msg tea.Msg, manager *modelmanager.ModelMan
manager.PopScreen()

case key.Matches(msgType, fromScreenKeys.Start) && screen.state == stateTake:
if image, err := screenshot.CaptureRect(screenshot.GetDisplayBounds(0)); err == nil {
if bmp, err := gozxing.NewBinaryBitmapFromImage(image); err == nil {
qrReader := qrcode.NewQRCodeReader()
screen.state = stateGathering

if result, err := qrReader.Decode(bmp, nil); err == nil {
uri := result.String()
// Start spinner
cmds = append(cmds, screen.spinner.Tick)

screen.token = &uri
}
}
}
go func() {
if image, err := screenshot.CaptureRect(screenshot.GetDisplayBounds(0)); err == nil {
if bmp, err := gozxing.NewBinaryBitmapFromImage(image); err == nil {
qrReader := qrcode.NewQRCodeReader()

if result, err := qrReader.Decode(bmp, nil); err == nil {
uri := result.String()

dataFromScreenChan <- &uri;
return
}
}
}

screen.state = stateConfirm
dataFromScreenChan <- nil
}()

case key.Matches(msgType, confirmScreenKeys.Retake):
case key.Matches(msgType, confirmScreenKeys.Retake):
if screen.state == stateConfirm {
// Set state
screen.state = stateTake

// Restart poll
cmds = append(cmds, pollDataFetched())
}

case key.Matches(msgType, confirmScreenKeys.Continue) && screen.state == stateConfirm:
Expand All @@ -168,8 +223,18 @@ func (screen TokenFromScreen) Update(msg tea.Msg, manager *modelmanager.ModelMan

manager.PopScreen()
}

case dataRecievedMsg:
screen.token = msgType.data
screen.state = stateConfirm
}

if screen.state == stateGathering {
var cmd tea.Cmd
screen.spinner, cmd = screen.spinner.Update(msg)
cmds = append(cmds, cmd)
}

return screen, tea.Batch(cmds...)
}

Expand All @@ -189,6 +254,9 @@ func (screen TokenFromScreen) View() string {
tlockstyles.Help.View(fromScreenKeys),
)

case stateGathering:
return screen.spinner.View()

case stateConfirm:
items := []string{
tlockstyles.Styles.Title.Render(fromScreenAsciiArt), "",
Expand Down
2 changes: 1 addition & 1 deletion tlock/models/dashboard/tokens/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ func (tokens *Tokens) Update(msg tea.Msg, manager *modelmanager.ModelManager) te

case key.Matches(msgType, tokens.context.Config.Tokens.AddScreen.Binding):
if tokens.folder != nil {
manager.PushScreen(InitializeTokenFromScreen(tokens.vault, *tokens.folder))
cmds = append(cmds, manager.PushScreen(InitializeTokenFromScreen(tokens.vault, *tokens.folder)))
}
}

Expand Down

0 comments on commit d82f463

Please sign in to comment.