Skip to content

Commit

Permalink
Fix race condition on countdown and simplify logic
Browse files Browse the repository at this point in the history
  • Loading branch information
lcmaqueda committed Nov 19, 2016
1 parent ab575c6 commit d8028d1
Showing 1 changed file with 51 additions and 29 deletions.
80 changes: 51 additions & 29 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,26 @@ import (
"os"
"time"

"sync"

"github.com/atotto/clipboard"
"github.com/limetext/qml-go"
)

const (
timeoutTickDuration = 10 * time.Millisecond
clipboardTimeout = 15 * time.Second
)

// UI is the model for the password UI
type UI struct {
Status string
query string

Countdown float64
countingDown bool
countdownDone chan bool
lock sync.Mutex
Countdown float64
countingDown bool
resetCountdown chan bool

ShowMetadata bool

Expand All @@ -29,6 +37,18 @@ type UI struct {
}
}

func (ui *UI) isCountingDown() bool {
ui.lock.Lock()
defer ui.lock.Unlock()
return ui.countingDown
}

func (ui *UI) setCountingDown(value bool) {
ui.lock.Lock()
defer ui.lock.Unlock()
ui.countingDown = value
}

// Passwords is the model for the password list
type Passwords struct {
Selected int
Expand Down Expand Up @@ -66,33 +86,35 @@ func (p *Passwords) Get(index int) Password {

// ClearClipboard clears the clipboard
func (ui *UI) ClearClipboard() {
if ui.countingDown {
ui.countdownDone <- true

if ui.isCountingDown() {
ui.resetCountdown <- true
return
}
ui.countingDown = true
tick := 10 * time.Millisecond
t := time.NewTicker(tick)
remaining := 15.0
for {
select {
case <-ui.countdownDone:
t.Stop()
ui.countingDown = false
return
case <-t.C:
ui.setCountdown(remaining)
ui.setStatus(fmt.Sprintf("Will clear in %.f seconds", remaining))
remaining -= tick.Seconds()
if remaining <= 0 {
clipboard.WriteAll("")
ui.Clearmetadata()
ui.setStatus("Clipboard cleared")
ui.countingDown = false
t.Stop()
return

ui.setCountingDown(true)
go func() {
defer ui.setCountingDown(false)
t := time.NewTicker(timeoutTickDuration)
remaining := clipboardTimeout
for {
select {
case <-ui.resetCountdown:
remaining = clipboardTimeout
case <-t.C:
ui.setCountdown(remaining.Seconds())
ui.setStatus(fmt.Sprintf("Will clear in %.f seconds", remaining.Seconds()))
remaining -= timeoutTickDuration
if remaining <= 0 {
clipboard.WriteAll("")
ui.Clearmetadata()
ui.setStatus("Clipboard cleared")
t.Stop()
return
}
}
}
}
}()
}

// CopyToClipboard copies the selected password to the system clipboard
Expand All @@ -112,7 +134,7 @@ func (p *Passwords) CopyToClipboard(selected int) {
panic(err)
}
ui.setStatus("Copied to clipboard")
go ui.ClearClipboard()
ui.ClearClipboard()
p.Update("") // Trigger a manual update, since the key is probably unlocked now
}

Expand Down Expand Up @@ -183,7 +205,7 @@ var passwords Passwords
var ps *PasswordStore

func main() {
ui.countdownDone = make(chan bool)
ui.resetCountdown = make(chan bool, 1)
ps = NewPasswordStore()
passwords.store = ps
ps.Subscribe(passwords.Update)
Expand Down

0 comments on commit d8028d1

Please sign in to comment.