Skip to content

Commit

Permalink
progress bar
Browse files Browse the repository at this point in the history
  • Loading branch information
stigoleg committed Dec 20, 2024
1 parent fc8fa4b commit f3e4f5d
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 76 deletions.
48 changes: 43 additions & 5 deletions internal/ui/style.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ type Style struct {
Help lipgloss.Style
Error lipgloss.Style
Countdown lipgloss.Style
Selected lipgloss.Style
Unselected lipgloss.Style
Awake lipgloss.Style
ProgressBar lipgloss.Style
ProgressBarContainer lipgloss.Style
}

// DefaultStyle returns the default style configuration
Expand All @@ -42,7 +47,10 @@ func DefaultStyle() Style {
return Style{
Title: base.Copy().
Bold(true).
Foreground(defaultColors.Highlight),
Foreground(lipgloss.Color("#FAFAFA")).
Background(defaultColors.Highlight).
PaddingLeft(2).
PaddingRight(2),

ActiveStatus: base.Copy().
Foreground(defaultColors.Special),
Expand All @@ -57,22 +65,52 @@ func DefaultStyle() Style {
Bold(true).
Foreground(defaultColors.Highlight),

Menu: base.Copy(),
Menu: base.Copy().
MarginLeft(2),

InputBox: base.Copy().
Border(lipgloss.RoundedBorder()).
BorderForeground(defaultColors.Highlight).
Padding(0, 1),

Help: base.Copy().
Foreground(defaultColors.Subtle),
Border(lipgloss.RoundedBorder()).
BorderForeground(defaultColors.Highlight).
Padding(1, 2),

Error: base.Copy().
Foreground(defaultColors.Error),
Foreground(lipgloss.Color("#FFFFFF")).
Background(lipgloss.Color("#FF4040")).
Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color("#FF4040")).
MarginTop(1).
MarginBottom(1).
Padding(0, 1).
Bold(true),

Countdown: base.Copy().
Foreground(defaultColors.Highlight).
Foreground(defaultColors.Special).
Bold(true),

Selected: base.Copy().
Foreground(defaultColors.Highlight).
PaddingLeft(2),

Unselected: base.Copy().
Foreground(lipgloss.Color("#FAFAFA")).
PaddingLeft(2),

Awake: base.Copy().
Foreground(defaultColors.Special).
PaddingLeft(2),

ProgressBar: base.Copy().
Height(1),

ProgressBarContainer: base.Copy().
Border(lipgloss.RoundedBorder()).
BorderForeground(defaultColors.Subtle).
Padding(0, 1),
}
}

Expand Down
140 changes: 69 additions & 71 deletions internal/ui/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,76 +8,31 @@ import (
"github.com/charmbracelet/lipgloss"
)

var (
titleStyle = lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("#FAFAFA")).
Background(lipgloss.Color("#7D56F4")).
PaddingLeft(2).
PaddingRight(2)

selectedStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("#7D56F4")).
PaddingLeft(2)

unselectedStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("#FAFAFA")).
PaddingLeft(2)

awakeStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("#43BF6D")).
PaddingLeft(2)

errorStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("#FF0000")).
PaddingLeft(2)

helpStyle = lipgloss.NewStyle().
Foreground(lipgloss.Color("#FAFAFA")).
PaddingLeft(2).
PaddingRight(2).
Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color("#7D56F4"))

inputBoxStyle = lipgloss.NewStyle().
Width(10).
PaddingLeft(2).
PaddingRight(2).
Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color("#7D56F4"))
)

// View renders the current state of the model to a string.
func View(m Model) string {
if m.ShowHelp {
return helpView()
}

var s strings.Builder

// Title
s.WriteString(titleStyle.Render("Keep-Alive"))
s.WriteString("\n\n")

switch m.State {
case stateMenu:
return menuView(m)
case stateTimedInput:
return timedInputView(m)
case stateRunning:
return runningView(m)
default:
return "Invalid state"
}

return ""
}

func menuView(m Model) string {
var b strings.Builder

b.WriteString(titleStyle.Render("Keep Alive Options"))
b.WriteString(Current.Title.Render("Keep Alive Options"))
b.WriteString("\n\n")

b.WriteString(unselectedStyle.Render("Select an option:"))
b.WriteString(Current.Unselected.Render("Select an option:"))
b.WriteString("\n\n")

menuItems := []string{
Expand All @@ -90,51 +45,47 @@ func menuView(m Model) string {
var menuLine strings.Builder

if i == m.Selected {
menuLine.WriteString(selectedStyle.Render("> "))
menuLine.WriteString(Current.Selected.Render("> "))
} else {
menuLine.WriteString(unselectedStyle.Render(" "))
menuLine.WriteString(Current.Unselected.Render(" "))
}

if i == m.Selected {
menuLine.WriteString(selectedStyle.Render(opt))
menuLine.WriteString(Current.Selected.Render(opt))
} else {
menuLine.WriteString(unselectedStyle.Render(opt))
menuLine.WriteString(Current.Unselected.Render(opt))
}

b.WriteString(menuLine.String() + "\n")
}

if m.ErrorMessage != "" {
b.WriteString("\n" + errorStyle.Render(m.ErrorMessage))
b.WriteString("\n" + Current.Error.Render(m.ErrorMessage))
}

b.WriteString("\n\n" + helpStyle.Render("j/k or ↑/↓ to select • enter to confirm • q to quit"))
b.WriteString("\n\n" + Current.Help.Render("j/k or ↑/↓ to select • enter to confirm • q to quit"))
return b.String()
}

func timedInputView(m Model) string {
var b strings.Builder

b.WriteString(titleStyle.Render("Enter Duration"))
b.WriteString(Current.Title.Render("Enter Duration"))
b.WriteString("\n\n")

b.WriteString(unselectedStyle.Render("Enter duration in minutes:"))
b.WriteString(Current.Unselected.Render("Enter duration in minutes:"))
b.WriteString("\n")
input := m.Input
if input == "" {
input = " "
}
b.WriteString(inputBoxStyle.Render(input))
// b.WriteString(Current.InputBox.Render(input))
b.WriteString(Current.InputBox.Render(input))
b.WriteString("\n\n")

// Help text
// b.WriteString(helpStyle.Render("Enter number of minutes"))
b.WriteString("\n")
b.WriteString(helpStyle.Render("Press enter to start • backspace to clear • esc to cancel"))
b.WriteString("\n" + Current.Help.Render("Press enter to start • backspace to clear • esc to cancel"))

if m.ErrorMessage != "" {
b.WriteString("\n\n" + errorStyle.Render(m.ErrorMessage))
b.WriteString("\n\n" + Current.Error.Render(m.ErrorMessage))
}

return b.String()
Expand All @@ -143,26 +94,73 @@ func timedInputView(m Model) string {
func runningView(m Model) string {
var b strings.Builder

b.WriteString(titleStyle.Render("Keep Alive Active"))
b.WriteString(Current.Title.Render("Keep Alive Active"))
b.WriteString("\n\n")

b.WriteString(awakeStyle.Render("System is being kept awake"))
b.WriteString(Current.Awake.Render("System is being kept awake"))
b.WriteString("\n")

// Show countdown if this is a timed session
// Show countdown and progress bar if this is a timed session
if m.Duration > time.Duration(0) {
remaining := m.TimeRemaining()
minutes := int(remaining.Minutes())
seconds := int(remaining.Seconds()) % 60
countdown := fmt.Sprintf("%d:%02d remaining", minutes, seconds)
b.WriteString(unselectedStyle.Render(countdown))
b.WriteString(Current.Unselected.Render(countdown))
b.WriteString("\n\n")

// Calculate progress
progress := 1.0 - (float64(remaining) / float64(m.Duration))
width := 20 // Width of the progress bar - adjusted to match help text width

// Create progress bar components
filled := int(progress * float64(width))
if filled > width {
filled = width
}

// Define gradient colors (from purple to green with more steps)
gradientColors := []string{
"#7D56F4", "#7857F4", "#7359F5", "#6E5AF5", "#695CF6",
"#645DF6", "#5F5FF7", "#5A60F7", "#5562F8", "#5063F8",
"#4B65F9", "#4666F9", "#4168FA", "#3C69FA", "#376BFB",
"#326CFB", "#2D6EFC", "#286FFC", "#2371FD", "#1E72FD",
"#1974FE", "#1475FE", "#0F77FF", "#0A78FF", "#057AFF",
"#007BFF", "#007DFA", "#007FF5", "#0081F0", "#0083EB",
"#0085E6", "#0087E1", "#0089DC", "#008BD7", "#008DD2",
"#008FCD", "#0091C8", "#0093C3", "#0095BE", "#0097B9",
"#0099B4", "#009BAF", "#009DAA", "#009FA5", "#00A1A0",
"#00A39B", "#00A596", "#00A791", "#00A98C", "#00AB87",
"#00AD82", "#00AF7D", "#00B178", "#00B373", "#00B56E",
"#00B769", "#00B964", "#00BB5F", "#00BD5A", "#00BF55",
"#43BF6D",
}

// Build the progress bar with smooth gradient
var bar strings.Builder
for i := 0; i < width; i++ {
if i < filled {
// Calculate color index for smooth gradient
colorIndex := int(float64(i) / float64(width) * float64(len(gradientColors)-1))
if colorIndex >= len(gradientColors) {
colorIndex = len(gradientColors) - 1
}
blockStyle := Current.ProgressBar.Copy().
Background(lipgloss.Color(gradientColors[colorIndex]))
bar.WriteString(blockStyle.Render(" "))
} else {
bar.WriteString(Current.ProgressBar.Copy().Render(" "))
}
}

b.WriteString(Current.ProgressBarContainer.Render(bar.String()))
b.WriteString("\n")
}

b.WriteString("\n" + helpStyle.Render("Press enter to stop and return to menu • q or esc to quit"))
b.WriteString("\n" + Current.Help.Render("Press enter to stop and return to menu • q or esc to quit"))

if m.ErrorMessage != "" {
b.WriteString("\n\n" + errorStyle.Render(m.ErrorMessage))
b.WriteString("\n\n" + Current.Error.Render(m.ErrorMessage))
}

return b.String()
Expand Down Expand Up @@ -193,5 +191,5 @@ Navigation:
Press 'q' or 'Esc' to close help`

return helpStyle.Render(help)
return Current.Help.Render(help)
}

0 comments on commit f3e4f5d

Please sign in to comment.