Skip to content

Commit

Permalink
chore(event): better dynamic scaling
Browse files Browse the repository at this point in the history
  • Loading branch information
Topvennie committed Dec 23, 2024
1 parent cb8e231 commit 71f052a
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 96 deletions.
19 changes: 18 additions & 1 deletion tui/view/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ type Model struct {
passed []dto.Event
upcoming []dto.Event
today *dto.Event

width int
height int
}

// Msg represents the message to update the event view
Expand Down Expand Up @@ -51,6 +54,20 @@ func (m *Model) Name() string {
// Update updates the event model view
func (m *Model) Update(msg tea.Msg) (view.View, tea.Cmd) {
switch msg := msg.(type) {
case view.MsgSize:
// Size update!
// Check if it's relevant for this view
entry, ok := msg.Sizes[m.Name()]
if ok {
// Update all dependent styles
m.width = entry.Width
m.height = entry.Height

m.updateStyles()
}

return m, nil

case Msg:
m.passed = msg.passed
m.upcoming = msg.upcoming
Expand All @@ -66,7 +83,7 @@ func (m *Model) View() string {
return m.viewToday()
}

return m.viewNormal()
return m.viewOverview()
}

// GetUpdateDatas returns all the update function for the event model
Expand Down
115 changes: 75 additions & 40 deletions tui/view/event/style.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,8 @@
package event

import "github.com/charmbracelet/lipgloss"

// Widths
var (
widthToday = 45
widthImage = 32

widthOverview = 45
widthOverviewName = 35
widthOverviewImage = 32
)

// Base
var (
base = lipgloss.NewStyle()
baseToday = base.Width(widthToday).Align(lipgloss.Center)
)

// Margins
var (
mTodayWarning = 3
mOverview = 5
import (
"github.com/charmbracelet/lipgloss"
"github.com/zeusWPI/scc/tui/view"
)

// Color
Expand All @@ -32,26 +13,80 @@ var (
cUpcoming = lipgloss.Color("#FFBF00")
)

// Styles today
// Base style
var base = lipgloss.NewStyle()

// Styles for overview
var (
sTodayWarning = baseToday.Bold(true).Blink(true).Foreground(cWarning).Border(lipgloss.DoubleBorder(), true, false)
sTodayName = baseToday.Bold(true).Foreground(cZeus).BorderStyle(lipgloss.NormalBorder()).BorderBottom(true).BorderForeground(cBorder)
sTodayTime = baseToday
sTodayPlace = baseToday.Italic(true).Faint(true)
sToday = baseToday.MarginLeft(8).AlignVertical(lipgloss.Center)
wOvDate = 8 // Width of the date, for example '13/11' (with some padding after)
wOvTextMin = 20 // Minimum width of the event name
wOvPoster = 20 // Width of the poster
wOvGap = 2 // Width of the gap between the overview and the poster

sOvAll = base.Padding(0, 1) // Style for the overview and the poster
sOvPoster = base.AlignVertical(lipgloss.Center)
sOv = base.AlignVertical(lipgloss.Center).MarginRight(wOvGap) // Style for the overview of the events
sOvTitle = base.Bold(true).Foreground(cWarning).Align(lipgloss.Center).BorderStyle(lipgloss.NormalBorder()).BorderBottom(true).BorderForeground(cBorder)

// Styles for passed events
sOvPassedDate = base.Width(wOvDate).Faint(true)
sOvPassedText = base.Foreground(cZeus).Faint(true)

// Styles for next event
sOvNextDate = base.Width(wOvDate).Bold(true)
sOvNextText = base.Bold(true).Foreground(cZeus)
sOvNextLoc = base.Italic(true)

// Styles for the upcoming envets
sOvUpcomingDate = base.Width(wOvDate).Faint(true)
sOvUpcomingText = base.Foreground(cUpcoming)
sOvUpcomingLoc = base.Italic(true).Faint(true)
)

// Styles overview
// Styles for today
var (
sOverviewTotal = base.AlignVertical(lipgloss.Center)
sOverviewTitle = base.Bold(true).Foreground(cWarning).Width(widthOverview).Align(lipgloss.Center)
sOverview = base.Border(lipgloss.NormalBorder(), true, false, false, false).BorderForeground(cBorder).Width(widthOverview).MarginRight(mOverview)
sPassedName = base.Foreground(cZeus).Faint(true).Width(widthOverviewName)
sPassedTime = base.Faint(true)
sNextName = base.Bold(true).Foreground(cZeus).Width(widthOverviewName)
sNextTime = base.Bold(true)
sNextPlace = base.Italic(true).Width(widthOverviewName)
sUpcomingName = base.Width(widthOverviewName).Foreground(cUpcoming)
sUpcomingTime = base.Faint(true)
sUpcomingPlace = base.Italic(true).Faint(true).Width(widthOverviewName)
wTodayEvMin = 20 // Minimum width of the event
wTodayPoster = 20 // Width of the poster
wTodayGap = 2 // Width of the gap between the text and the poster

sTodayAll = base.Padding(0, 1) // Style for the text and the poster
sTodayPoster = base.AlignVertical(lipgloss.Center)
sToday = base.AlignVertical(lipgloss.Center).MarginLeft(wOvGap).Padding(1, 0).Border(lipgloss.DoubleBorder(), true, false) // Style for the event

sTodayDate = base.Align(lipgloss.Center)
sTodayText = base.Align(lipgloss.Center).Bold(true).Foreground(cZeus).BorderStyle(lipgloss.NormalBorder()).BorderBottom(true).BorderForeground(cBorder)
sTodayeLoc = base.Align(lipgloss.Center).Italic(true).Faint(true)
)

func (m *Model) updateStyles() {
// Adjust the styles for the overview
wOvPoster = (m.width - wOvGap - view.GetOuterWidth(sOvAll)) / 2
if wOvPoster <= wOvDate+wOvTextMin {
// Screen is too small, don't draw the poster for more space
wOvPoster = 0
}

wOv := wOvPoster
wOvText := wOv - wOvDate

sOv = sOv.Width(wOv)
sOvTitle = sOvTitle.Width(wOv)
sOvPassedText = sOvPassedText.Width(wOvText)
sOvNextText = sOvNextText.Width(wOvText)
sOvNextLoc = sOvNextLoc.Width(wOvText)
sOvUpcomingText = sOvUpcomingText.Width(wOvText)
sOvUpcomingLoc = sOvUpcomingLoc.Width(wOvText)

// Adjust the styles for today
wTodayPoster = (m.width - wTodayGap - view.GetOuterWidth(sTodayAll)) / 2
if wTodayPoster <= wTodayEvMin {
// Screen is too small, don't draw the poster for more space
wTodayPoster = 0
}

wTodayEv := wTodayPoster

sTodayDate = sTodayDate.Width(wTodayEv)
sTodayText = sTodayText.Width(wTodayEv)
sTodayeLoc = sTodayeLoc.Width(wTodayEv)
}
103 changes: 48 additions & 55 deletions tui/view/event/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,107 +10,100 @@ import (

func (m *Model) viewToday() string {
// Render image
im := ""
poster := ""
if m.today.Poster != nil {
i, _, err := image.Decode(bytes.NewReader(m.today.Poster))
if err == nil {
im = view.ImagetoString(widthImage, i)
poster = view.ImagetoString(wTodayPoster, i)
}
}

// Render text
warningTop := sTodayWarning.MarginBottom(mTodayWarning).Render("πŸ₯³ Event Today πŸ₯³")
warningBottom := sTodayWarning.MarginTop(mTodayWarning).Render("πŸ₯³ Event Today πŸ₯³")
name := sTodayText.Render(m.today.Name)
date := sTodayDate.Render("πŸ•™ " + m.today.Date.Format("15:04"))
location := sTodayeLoc.Render("πŸ“ " + m.today.Location)

name := sTodayName.Render(m.today.Name)
time := sTodayTime.Render("πŸ•™ " + m.today.Date.Format("15:04"))
location := sTodayPlace.Render("πŸ“ " + m.today.Location)
event := lipgloss.JoinVertical(lipgloss.Left, name, date, location)
event = sToday.Render(event)

text := lipgloss.JoinVertical(lipgloss.Left, warningTop, name, time, location, warningBottom)

// Resize so it's centered
if lipgloss.Height(im) > lipgloss.Height(text) {
sToday = sToday.Height(lipgloss.Height(im))
if lipgloss.Height(poster) > lipgloss.Height(event) {
event = sTodayPoster.Height(lipgloss.Height(poster)).Render(event)
} else {
poster = sTodayPoster.Height(lipgloss.Height(event)).Render(poster)
}
text = sToday.Render(text)

return lipgloss.JoinHorizontal(lipgloss.Top, im, text)
view := lipgloss.JoinHorizontal(lipgloss.Top, poster, event)

return sTodayAll.Render(view)
}

func (m *Model) viewNormal() string {
func (m *Model) viewOverview() string {
// Poster if present
im := ""
poster := ""
if len(m.upcoming) > 0 && m.upcoming[0].Poster != nil {
i, _, err := image.Decode(bytes.NewReader(m.upcoming[0].Poster))
if err == nil {
im = view.ImagetoString(widthOverviewImage, i)
poster = view.ImagetoString(wOvPoster, i)
}
}

// Overview
events := m.viewGetEvents()

// Filthy hack to avoid the last event being centered by the cammie screen
events = append(events, "\n")
events := m.viewGetEventOverview()

// Render events overview
overview := lipgloss.JoinVertical(lipgloss.Left, events...)
overview = sOverview.Render(overview)

title := sOverviewTitle.Render("Events")
overview = lipgloss.JoinVertical(lipgloss.Left, title, overview)

// Center the overview
if lipgloss.Height(im) > lipgloss.Height(overview) {
overview = sOverviewTotal.Height(lipgloss.Height(im)).Render(overview)
if lipgloss.Height(poster) > lipgloss.Height(events) {
events = sOv.Height(lipgloss.Height(poster)).Render(events)
} else {
poster = sOvPoster.Height(lipgloss.Height(events)).Render(poster)
}

// Combine image and overview
view := lipgloss.JoinHorizontal(lipgloss.Top, overview, im)
view := lipgloss.JoinHorizontal(lipgloss.Top, events, poster)

return view
return sOvAll.Render(view)
}

func (m *Model) viewGetEvents() []string {
events := make([]string, 0, len(m.passed)+len(m.upcoming))
func (m *Model) viewGetEventOverview() string {
events := make([]string, 0, len(m.passed)+len(m.upcoming)+1)

title := sOvTitle.Render("Events")
events = append(events, title)

// Passed
for _, event := range m.passed {
time := sPassedTime.Render(event.Date.Format("02/01") + "\t")
name := sPassedName.Render(event.Name)
text := lipgloss.JoinHorizontal(lipgloss.Top, time, name)
date := sOvPassedDate.Render(event.Date.Format("02/01"))
name := sOvPassedText.Render(event.Name)
text := lipgloss.JoinHorizontal(lipgloss.Top, date, name)

events = append(events, text)
}

if len(m.upcoming) == 0 {
return events
}

// Next
name := sNextName.Render(m.upcoming[0].Name)
time := sNextTime.Render(m.upcoming[0].Date.Format("02/01") + "\t")
location := sNextPlace.Render("πŸ“ " + m.upcoming[0].Location)
if len(m.upcoming) > 0 {
// Next
date := sOvNextDate.Render(m.upcoming[0].Date.Format("02/01"))
name := sOvNextText.Render(m.upcoming[0].Name)
location := sOvNextLoc.Render("πŸ“ " + m.upcoming[0].Location)

text := lipgloss.JoinVertical(lipgloss.Left, name, location)
text = lipgloss.JoinHorizontal(lipgloss.Top, time, text)
text := lipgloss.JoinVertical(lipgloss.Left, name, location)
text = lipgloss.JoinHorizontal(lipgloss.Top, date, text)

events = append(events, text)
events = append(events, text)
}

// Upcoming
for i := 1; i < len(m.upcoming); i++ {
time := sUpcomingTime.Render(m.upcoming[i].Date.Format("02/01") + "\t")
name := sUpcomingName.Render(m.upcoming[i].Name)
date := sOvUpcomingDate.Render(m.upcoming[i].Date.Format("02/01"))
name := sOvUpcomingText.Render(m.upcoming[i].Name)
text := name
if i < 3 {
location := sUpcomingPlace.Render("πŸ“ " + m.upcoming[i].Location)
location := sOvNextLoc.Render("πŸ“ " + m.upcoming[i].Location)
text = lipgloss.JoinVertical(lipgloss.Left, name, location)
}

text = lipgloss.JoinHorizontal(lipgloss.Top, time, text)
text = lipgloss.JoinHorizontal(lipgloss.Top, date, text)

events = append(events, text)
}

return events
view := lipgloss.JoinVertical(lipgloss.Left, events...)

return sOv.Render(view)
}

0 comments on commit 71f052a

Please sign in to comment.