feat: Basic UI for Pominal
This commit is contained in:
parent
0f19832fca
commit
45ad772818
5 changed files with 105 additions and 33 deletions
7
go.mod
7
go.mod
|
@ -1,5 +1,8 @@
|
||||||
module gitlab.com/dananglin/Pominal
|
module gitlab.com/dananglin/Pominal
|
||||||
|
|
||||||
go 1.12
|
go 1.13
|
||||||
|
|
||||||
require github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21
|
require (
|
||||||
|
github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21
|
||||||
|
github.com/rivo/tview v0.0.0-20191129065140-82b05c9fb329
|
||||||
|
)
|
||||||
|
|
21
go.sum
21
go.sum
|
@ -1,2 +1,23 @@
|
||||||
github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21 h1:moSC7ACaTejHmVRRwfDTMgByRSwjg2vZooncdWLj7o8=
|
github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21 h1:moSC7ACaTejHmVRRwfDTMgByRSwjg2vZooncdWLj7o8=
|
||||||
github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21/go.mod h1:NtXa9WwQsukMHZpjNakTTz0LArxvGYdPA9CjIcUSZ6s=
|
github.com/0xAX/notificator v0.0.0-20181105090803-d81462e38c21/go.mod h1:NtXa9WwQsukMHZpjNakTTz0LArxvGYdPA9CjIcUSZ6s=
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
|
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||||
|
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||||
|
github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM=
|
||||||
|
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||||
|
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
|
github.com/rivo/tview v0.0.0-20191129065140-82b05c9fb329 h1:MubHhHJ4mB0A5wMcc2am0/51RydztIDoumyOd0r0yBw=
|
||||||
|
github.com/rivo/tview v0.0.0-20191129065140-82b05c9fb329/go.mod h1:/rBeY22VG2QprWnEqG57IBC8biVu3i0DOIjRLc9I8H0=
|
||||||
|
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
||||||
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191018095205-727590c5006e h1:ZtoklVMHQy6BFRHkbG6JzK+S6rX82//Yeok1vMlizfQ=
|
||||||
|
golang.org/x/sys v0.0.0-20191018095205-727590c5006e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|
27
main.go
27
main.go
|
@ -22,8 +22,9 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/rivo/tview"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -83,22 +84,14 @@ func main() {
|
||||||
maxWorkSessions,
|
maxWorkSessions,
|
||||||
)
|
)
|
||||||
|
|
||||||
pominal.Run()
|
app := tview.NewApplication()
|
||||||
|
infoUI := newInfoUI()
|
||||||
|
timerUI := newTimerUI(app)
|
||||||
|
flex := newFlex(infoUI, timerUI)
|
||||||
|
|
||||||
|
go pominal.Run(infoUI, timerUI)
|
||||||
|
if err := app.SetRoot(flex, true).SetFocus(flex).Run(); err != nil {
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// printScreen prints the details of the Pominal session on screen including
|
|
||||||
// the current work session number, the timer's current label and the current countdoen.
|
|
||||||
// TODO: To be removed when TUI is implemented.
|
|
||||||
func printScreen(countdown float64, pominalCount, workSessionCount, maxWorkSession int, label string) {
|
|
||||||
clearScreen()
|
|
||||||
fmt.Printf("Pominal cycle: %d\nWork session: %d of %d\n\n", pominalCount, workSessionCount, maxWorkSession)
|
|
||||||
fmt.Printf("Session: %s\nTime remaining: %02d:%02d", label, int(countdown)/60, int(countdown)%60)
|
|
||||||
}
|
|
||||||
|
|
||||||
// clearScreen clears the terminal screen
|
|
||||||
// TODO: To be removed when TUI is implemented
|
|
||||||
func clearScreen() {
|
|
||||||
cmd := exec.Command("clear")
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Run()
|
|
||||||
}
|
}
|
||||||
|
|
24
pominal.go
24
pominal.go
|
@ -19,11 +19,12 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/rivo/tview"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Pominal struct {
|
type Pominal struct {
|
||||||
|
@ -70,35 +71,29 @@ func NewPominal(w, s, l float64, m int) Pominal {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run Pominal
|
// Run Pominal
|
||||||
func (p *Pominal) Run() {
|
func (p *Pominal) Run(infoUI, timerUI *tview.TextView) {
|
||||||
s := make(chan os.Signal, 1)
|
s := make(chan os.Signal, 1)
|
||||||
signal.Notify(s, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(s, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
p.UpdateSession()
|
p.UpdateSession(infoUI)
|
||||||
t := time.NewTicker(1 * time.Second)
|
t := time.NewTicker(1 * time.Second)
|
||||||
|
|
||||||
infinite:
|
infinite:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case sig := <-s:
|
case <-s:
|
||||||
fmt.Printf("\n\nReceived signal '%s'. Closing Pominal.\n", sig)
|
// fmt.Printf("\n\nReceived signal '%s'. Closing Pominal.\n", sig)
|
||||||
t.Stop()
|
t.Stop()
|
||||||
break infinite
|
break infinite
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
p.countdown--
|
p.countdown--
|
||||||
if p.countdown < 0 {
|
if p.countdown < 0 {
|
||||||
fmt.Printf("\n%s session has finished.\n", p.label)
|
|
||||||
t.Stop()
|
t.Stop()
|
||||||
p.UpdateSession()
|
p.UpdateSession(infoUI)
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
t = time.NewTicker(1 * time.Second)
|
t = time.NewTicker(1 * time.Second)
|
||||||
} else {
|
} else {
|
||||||
printScreen(p.countdown,
|
drawTimer(timerUI, p.countdown)
|
||||||
p.cycle,
|
|
||||||
p.workSession,
|
|
||||||
p.maxWorkSessions,
|
|
||||||
p.label,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +105,7 @@ infinite:
|
||||||
// If a 'long break' session is over then the Pominal cycle
|
// If a 'long break' session is over then the Pominal cycle
|
||||||
// is incremented and the work session counter is reset
|
// is incremented and the work session counter is reset
|
||||||
// to 1.
|
// to 1.
|
||||||
func (p *Pominal) UpdateSession() {
|
func (p *Pominal) UpdateSession(i *tview.TextView) {
|
||||||
switch p.label {
|
switch p.label {
|
||||||
case workTimerLabel:
|
case workTimerLabel:
|
||||||
if p.workSession >= p.maxWorkSessions {
|
if p.workSession >= p.maxWorkSessions {
|
||||||
|
@ -133,6 +128,7 @@ func (p *Pominal) UpdateSession() {
|
||||||
p.countdown = p.work
|
p.countdown = p.work
|
||||||
p.label = workTimerLabel
|
p.label = workTimerLabel
|
||||||
}
|
}
|
||||||
|
drawInfo(i, p.cycle, p.workSession, p.maxWorkSessions, p.label)
|
||||||
alert(p.label)
|
alert(p.label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
59
ui.go
Normal file
59
ui.go
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
Pominal
|
||||||
|
Copyright (C) 2019 Daniel Anglin
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/rivo/tview"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newInfoUI() *tview.TextView {
|
||||||
|
i := tview.NewTextView()
|
||||||
|
i.SetBorder(true)
|
||||||
|
i.SetTitle(" Pominal ")
|
||||||
|
i.SetTitleAlign(tview.AlignLeft)
|
||||||
|
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTimerUI(app *tview.Application) *tview.TextView {
|
||||||
|
t := tview.NewTextView().SetTextAlign(tview.AlignCenter).SetChangedFunc(func() {
|
||||||
|
app.Draw()
|
||||||
|
})
|
||||||
|
t.SetBorder(true)
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFlex(info, timer *tview.TextView) *tview.Flex {
|
||||||
|
f := tview.NewFlex().AddItem(info, 30, 1, false).AddItem(timer, 50, 1, false)
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawInfo(t *tview.TextView, pominalCycle, workSessions, maxWorkSessions int, label string) {
|
||||||
|
t.Clear()
|
||||||
|
fmt.Fprintf(t, "\nPominal cycle: %d\nWork session: %d of %d\nSession: %s", pominalCycle, workSessions, maxWorkSessions, label)
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawTimer(t *tview.TextView, countdown float64) {
|
||||||
|
t.Clear()
|
||||||
|
fmt.Fprintf(t, "\nTime remaining:\n%02d:%02d", int(countdown)/60, int(countdown)%60)
|
||||||
|
}
|
Loading…
Reference in a new issue