~f4814n/frost

f24bed839d110c53c734527b35e1ac8d9bb9ad53 — Fabian Geiselhart 3 months ago c4497e8
Add functional buttons to bar
2 files changed, 142 insertions(+), 47 deletions(-)

M cmd/frost/app.go
M util/time.go
M cmd/frost/app.go => cmd/frost/app.go +133 -47
@@ 34,6 34,14 @@ type (
	d = layout.Dimensions
)

type format int

const (
	small format = iota
	medium
	large
)

type App struct {
	window *app.Window



@@ 61,6 69,8 @@ type App struct {
	// regardless of screen size
	singleView bool

	format format

	modalLayer *materials.ModalLayer
	drawer     *materials.ModalNavDrawer
	theme      *material.Theme


@@ 99,7 109,6 @@ func newApp() *App {

	a.bar = materials.NewAppBar(a.modalLayer)
	a.bar.Title = "Frost"
	a.bar.NavigationIcon = util.MustIcon(icons.NavigationMenu)

	a.drawer = materials.NewModalNav(a.modalLayer, "Frost", "Here be dragons")



@@ 174,36 183,15 @@ func (a *App) handleEvents() error {
		case roomhistory.Show:
			a.currentRoom = e.Room

			a.stopView(2)
			a.stopView(1)

			self, _ := a.cli.User()

			id, rx, tx := a.mux.Register()
			a.views[1] = registeredView{
				id: id,
				View: roomhistory.New(
					self,
					e.Room,
					a.theme,
					a.logger.Named("roomhistory"),
				),
			}

			a.bar.Title = e.Room.Displayname()
			a.bar.SetActions([]materials.AppBarAction{
				materials.SimpleIconAction(
					a.theme,
					a.userListButton,
					util.MustIcon(icons.ActionViewList),
					materials.OverflowAction{
						Name: "View room members",
						Tag:  a.userListButton,
					},
				),
			}, nil)

			go a.views[1].Run(rx, tx)

			view := roomhistory.New(
				self, e.Room, a.theme, a.logger.Named("roomhistory"),
			)
			a.stopView(2)
			a.startView(1, view)
		case frost.InvalidationEvent:
			a.window.Invalidate()
		}


@@ 212,30 200,113 @@ func (a *App) handleEvents() error {
	return nil
}

func (a *App) startView(i int, view frost.View) {
	a.stopView(i)

	if a.format == small && i >= 1 {
		a.bar.NavigationIcon = util.MustIcon(icons.NavigationArrowBack)
	}

	id, rx, tx := a.mux.Register()
	a.views[i] = registeredView{
		id:   id,
		View: view,
	}
	go a.views[i].Run(rx, tx)
	a.updateBar(a.format)
}

func (a *App) stopView(i int) {
	if a.views[i].View != nil {
		a.views[i].Stop()
		a.mux.Unregister(a.views[i].id)
		a.views[i].View = nil
	}

	a.updateBar(a.format)
}

func (a *App) back() {
	if a.views[2].View != nil {
		a.stopView(2)
	} else {
		a.stopView(1)
	}
}

func (a *App) update(gtx g) {
	for _, event := range a.bar.Events(gtx) {
		switch event.(type) {
		case materials.AppBarNavigationClicked:
			a.drawer.Appear(gtx.Now)
			if a.format == small && a.views[1].View != nil ||
				a.format == medium && a.views[2].View != nil {
				a.back()
			} else {
				a.drawer.Appear(gtx.Now)
			}
		}
	}

	if a.userListButton.Clicked() && a.views[2].View == nil {
		print("memberlist")
		id, rx, tx := a.mux.Register()
		a.views[2] = registeredView{
			id:   id,
			View: memberlist.New(a.currentRoom, a.theme, a.logger.Named("memberlist")),
	if a.userListButton.Clicked() {
		if a.views[2].View == nil {
			view := memberlist.New(a.currentRoom, a.theme, a.logger.Named("memberlist"))
			a.startView(2, view)
		} else {
			a.stopView(2)
		}
	}

	switch {
	case gtx.Constraints.Max.X < gtx.Px(unit.Dp(720)):
		if a.format != small {
			a.updateBar(small)
		}
		a.format = small
	case gtx.Constraints.Max.X < gtx.Px(unit.Dp(1100)):
		if a.format != medium {
			a.updateBar(small)
		}
		a.format = medium
	case gtx.Constraints.Max.X >= gtx.Px(unit.Dp(1100)):
		if a.format != large {
			a.updateBar(large)
		}
		a.format = large
	}
}

func (a *App) updateBar(f format) {
	if a.views[1].View != nil && a.views[2].View == nil {
		a.bar.SetActions([]materials.AppBarAction{
			materials.SimpleIconAction(
				a.theme,
				a.userListButton,
				util.MustIcon(icons.ActionViewList),
				materials.OverflowAction{
					Name: "View room members",
					Tag:  a.userListButton,
				},
			),
		}, nil)
	} else {
		a.bar.SetActions(nil, nil)
	}

	switch f {
	case small:
		if a.views[1].View == nil {
			a.bar.NavigationIcon = util.MustIcon(icons.ActionSettings)
		} else {
			a.bar.NavigationIcon = util.MustIcon(icons.NavigationArrowBack)
		}
	case medium:
		if a.views[2].View == nil {
			a.bar.NavigationIcon = util.MustIcon(icons.ActionSettings)
		} else {
			a.bar.NavigationIcon = util.MustIcon(icons.NavigationArrowBack)
		}
		go a.views[2].Run(rx, tx)
	case large:
		a.bar.NavigationIcon = util.MustIcon(icons.ActionSettings)
	}
}



@@ 244,12 315,14 @@ func (a *App) Layout(gtx layout.Context) layout.Dimensions {
		layout.Rigid(fwidget.LayoutTheme(a.bar.Layout, a.theme)),
		layout.Flexed(1, func(gtx g) d {
			switch {
			case gtx.Constraints.Max.X < gtx.Px(unit.Dp(720)):
			case a.format == small:
				return a.layoutSmall(gtx)
			case gtx.Constraints.Max.X < gtx.Px(unit.Dp(1100)):
			case a.format == medium:
				return a.layoutMedium(gtx)
			default:
			case a.format == large:
				return a.layoutLarge(gtx)
			default:
				panic("invalid format")
			}
		}),
	)


@@ 269,15 342,28 @@ func (a *App) layoutSmall(gtx g) d {
}

func (a *App) layoutMedium(gtx g) d {
	children := []layout.FlexChild{
		layout.Rigid(func(gtx g) d {
			gtx.Constraints.Max.X = gtx.Px(unit.Dp(400))
			return a.views[0].Layout(gtx)
		}),
	}
	var children []layout.FlexChild

	if len(a.views) >= 2 {
		children = append(children, layout.Flexed(1, a.focused().Layout))
	if a.views[2].View != nil {
		children = []layout.FlexChild{
			layout.Flexed(1, a.views[1].Layout),
			layout.Rigid(func(gtx g) d {
				gtx.Constraints.Max.X = gtx.Px(unit.Dp(400))
				gtx.Constraints.Min.X = gtx.Px(unit.Dp(400))
				return a.views[2].Layout(gtx)
			}),
		}
	} else {
		children = []layout.FlexChild{
			layout.Rigid(func(gtx g) d {
				gtx.Constraints.Max.X = gtx.Px(unit.Dp(400))
				return a.views[0].Layout(gtx)
			}),
		}

		if a.views[1].View != nil {
			children = append(children, layout.Flexed(1, a.views[1].Layout))
		}
	}

	return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, children...)

M util/time.go => util/time.go +9 -0
@@ 2,6 2,7 @@ package util

import (
	"time"

	"git.sr.ht/~f4814n/matrix"
)



@@ 27,3 28,11 @@ func FormatTime(t time.Time) string {
	}
	return t.Format(format)
}

func MustParseDuration(s string) time.Duration {
	dur, err := time.ParseDuration(s)
	if err != nil {
		panic(err)
	}
	return dur
}