~f4814n/frost

32a1fe2cbee0878f22f37aa8f3aa9894e0a78e72 — Fabian Geiselhart 3 months ago fd8e3b5
widget: Implement ListElement
3 files changed, 107 insertions(+), 103 deletions(-)

M view/memberlist/memberlist.go
M view/roomlist/roomlist.go
M widget/list.go
M view/memberlist/memberlist.go => view/memberlist/memberlist.go +5 -12
@@ 9,7 9,6 @@ import (
	"unicode"

	"gioui.org/layout"
	"gioui.org/unit"
	"gioui.org/widget/material"
	"git.sr.ht/~f4814n/frost"
	"git.sr.ht/~f4814n/frost/component/cache"


@@ 190,20 189,14 @@ func (v *view) listElem(gtx g, index int) d {

	icon := fwidget.InitialSign{Initial: initial, Theme: v.theme}.Layout
	if img, ok := v.avatars[user.ID]; ok {
		icon = func(gtx g) d {
			gtx.Constraints = layout.Exact(image.Point{
				X: gtx.Px(unit.Dp(46)),
				Y: gtx.Px(unit.Dp(46)),
			})
			return fwidget.RoundImage{Image: img}.Layout(gtx)
		}
		icon = fwidget.RoundImage{Image: img}.Layout
	}

	elem := fwidget.IconListElement{
		Icon:    icon,
		Content: material.Body1(v.theme, user.Displayname()).Layout,
	elem := fwidget.ListElement{
		Before: icon,
		Lines:  [2]string{user.Displayname()},
	}
	return elem.Layout(gtx)
	return elem.Layout(gtx, v.theme)
}

func (v *view) Stop() {

M view/roomlist/roomlist.go => view/roomlist/roomlist.go +41 -69
@@ 2,24 2,20 @@ package roomlist

import (
	"fmt"
	// "image"
	"sync"
	"unicode"

	"go.uber.org/zap"
	// "golang.org/x/exp/shiny/materialdesign/icons"

	"gioui.org/gesture"
	"gioui.org/layout"
	"gioui.org/text"
	"gioui.org/unit"
	// "gioui.org/widget"
	"gioui.org/widget"
	"gioui.org/widget/material"
	"gioui.org/x/component"
	"git.sr.ht/~f4814n/frost"
	"git.sr.ht/~f4814n/frost/util"
	"git.sr.ht/~f4814n/frost/view/roomhistory"
	fwidget "git.sr.ht/~f4814n/frost/widget"
	"git.sr.ht/~f4814n/matrix"
	"gioui.org/x/component"
)

type (


@@ 28,6 24,8 @@ type (
)

type view struct {
	sync.Mutex

	rx, tx chan frost.Event

	cli *matrix.Client


@@ 68,6 66,9 @@ func (l *view) Run(rx, tx chan frost.Event) {
}

func (l *view) handleMatrixEvent(event matrix.Event) {
	l.Lock()
	defer l.Unlock()

	var room matrix.Room

	switch event := event.(type) {


@@ 81,14 82,21 @@ func (l *view) handleMatrixEvent(event matrix.Event) {

	for _, elem := range l.rooms {
		if elem.room == room {
			elem.MatrixEvent(event)
			return
		}
	}
	l.rooms = append([]roomListElement{NewRoomListElement(room, event, l.theme)}, l.rooms...)

	l.rooms = append([]roomListElement{NewRoomListElement(room, l.theme)}, l.rooms...)
	l.rooms[0].MatrixEvent(event)

	l.tx <- frost.InvalidationEvent{}
}

func (l *view) Layout(gtx layout.Context) layout.Dimensions {
	l.Lock()
	defer l.Unlock()

	l.update(gtx)

	return l.list.Layout(gtx, len(l.rooms), func(gtx g, index int) d {


@@ 98,11 106,9 @@ func (l *view) Layout(gtx layout.Context) layout.Dimensions {

func (l *view) update(gtx g) {
	for _, room := range l.rooms {
		for _, e := range room.click.Events(gtx) {
			if e.Type == gesture.TypeClick {
				l.tx <- roomhistory.Show{
					Room: room.room,
				}
		if room.Click.Clicked() {
			l.tx <- roomhistory.Show{
				Room: room.room,
			}
		}
	}


@@ 113,71 119,37 @@ func (l *view) Stop() {

// roomListElement is a element in the room list
type roomListElement struct {
	theme     *material.Theme
	room      matrix.Room
	lastEvent matrix.Event
	click     *gesture.Click
	fwidget.ListElement
	room matrix.Room
	th   *material.Theme
}

func NewRoomListElement(room matrix.Room, event matrix.Event, theme *material.Theme) roomListElement {
	return roomListElement{
		room:      room,
		lastEvent: event,
		theme:     theme,
		click:     new(gesture.Click),
	}
}

func (w *roomListElement) Layout(gtx g) d {
	return fwidget.IconListElement{Click: w.click, Icon: w.layoutIcon, Content: func(gtx g) d {
		return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
			layout.Rigid(w.layoutUpper),
			layout.Rigid(w.layoutLastEvent),
		)
	}}.Layout(gtx)
}

func (w *roomListElement) layoutIcon(gtx g) d {
func NewRoomListElement(room matrix.Room, th *material.Theme) roomListElement {
	var initial string
	for _, c := range w.room.Displayname() {
	for _, c := range room.Displayname() {
		initial = string(unicode.ToUpper(c))
		break
	}

	return fwidget.InitialSign{Initial: initial, Theme: w.theme}.Layout(gtx)
	return roomListElement{
		ListElement: fwidget.ListElement{
			Click:     new(widget.Clickable),
			Before:    fwidget.InitialSign{Initial: initial, Theme: th}.Layout,
			AfterText: "yap",
			Lines:     [2]string{room.Displayname(), "Messages"},
		},
		room: room,
		th:   th,
	}
}

func (w *roomListElement) layoutUpper(gtx g) d {
	bgtextcol := util.NRGB(0xbbbbbb)
	return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Baseline}.Layout(gtx,
		layout.Rigid(func(gtx g) d {
			lbl := material.H6(w.theme, w.room.Displayname())
			lbl.MaxLines = 1
			return lbl.Layout(gtx)
		}),
		layout.Flexed(1, func(gtx g) d {
			gtx.Constraints.Min.X = gtx.Constraints.Max.X
			in := layout.Inset{Left: unit.Dp(2)}
			return in.Layout(gtx, func(gtx g) d {
				lbl := material.Caption(w.theme, util.FormatTime(util.EventTime(w.lastEvent)))
				lbl.MaxLines = 1
				lbl.Color = bgtextcol
				lbl.Alignment = text.End
				return lbl.Layout(gtx)
			})
		}),
	)
func (w *roomListElement) MatrixEvent(event matrix.Event) {
	w.Lines[1] = formatEvent(event)
	w.AfterText = util.FormatTime(util.EventTime(event))
}

func (w *roomListElement) layoutLastEvent(gtx g) d {
	bgtextcol := util.NRGB(0xbbbbbb)
	in := layout.Inset{Top: unit.Dp(6)}
	return in.Layout(gtx, func(gtx g) d {
		lbl := material.Body2(w.theme, formatEvent(w.lastEvent))
		lbl.Color = bgtextcol
		lbl.MaxLines = 1
		return lbl.Layout(gtx)
	})
func (w *roomListElement) Layout(gtx g) d {
	return w.ListElement.Layout(gtx, w.th)
}

func formatEvent(event matrix.Event) string {


@@ 191,7 163,7 @@ func formatEvent(event matrix.Event) string {
			return fmt.Sprintf("Unsupported message type: %s", event.Content["msgtype"])
		}
	case matrix.StateEvent:
		return fmt.Sprintf("State event: %s", event.Type)
	}

	return fmt.Sprintf("%#v", event)
	return "event"
}

M widget/list.go => widget/list.go +61 -22
@@ 4,43 4,82 @@ import (
	"image"
	"image/color"

	"gioui.org/gesture"
	"gioui.org/io/pointer"
	"gioui.org/layout"
	"gioui.org/unit"
	"gioui.org/widget"
	"gioui.org/widget/material"
	"git.sr.ht/~f4814n/frost/util"
)

type IconListElement struct {
	Icon    layout.Widget
	Content layout.Widget
	Click   *gesture.Click
type ListElement struct {
	Before    layout.Widget
	Lines     [2]string
	AfterText string
	Click     *widget.Clickable
}

func (w IconListElement) Layout(gtx g) d {
func (w ListElement) Layout(gtx g, th *material.Theme) d {
	gtx.Constraints.Max.Y = gtx.Px(unit.Dp(84))
	if w.Click != nil {
		return material.Clickable(gtx, w.Click, LayoutTheme(w.content, th))
	}

	return w.content(gtx, th)
}

func (w ListElement) content(gtx g, th *material.Theme) d {
	in := layout.Inset{
		Left:  unit.Dp(16),
		Right: unit.Dp(16),
		Left:   unit.Dp(16),
		Right:  unit.Dp(16),
		Top:    unit.Dp(16),
		Bottom: unit.Dp(16),
	}

	return in.Layout(gtx, func(gtx g) d {
		in := layout.Inset{Top: unit.Dp(16), Bottom: unit.Dp(16)}
		dims := in.Layout(gtx, func(gtx g) d {
			return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
				layout.Rigid(func(gtx g) d {
					in := layout.Inset{Right: unit.Dp(12)}
					return in.Layout(gtx, w.Icon)
				}),
				layout.Rigid(w.Content),
			)
		})
		pointer.Rect(image.Rectangle{Max: dims.Size}).Add(gtx.Ops)
		w.Click.Add(gtx.Ops)
		return dims
		return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
			layout.Rigid(func(gtx g) d {
				gtx.Constraints = layout.Exact(image.Point{
					X: gtx.Px(unit.Dp(40)),
					Y: gtx.Px(unit.Dp(40)),
				})
				return w.Before(gtx)
			}),
			layout.Rigid(layout.Spacer{Width: unit.Dp(16)}.Layout),
			layout.Flexed(1, func(gtx g) d {
				children := []layout.FlexChild{
					layout.Rigid(func(gtx g) d {
						main := singleLine(material.H6(th, w.Lines[0]))
						after := body1(th, w.AfterText)

						return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
							layout.Flexed(1, main.Layout),
							layout.Rigid(after.Layout),
						)
					}),
				}

				if w.Lines[1] != "" {
					children = append(children, layout.Rigid(body1(th, w.Lines[1]).Layout))
				}

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

func body1(th *material.Theme, text string) material.LabelStyle {
	lbl := material.Body1(th, text)
	lbl.Color = util.NRGB(0x977787)
	lbl.MaxLines = 1
	return lbl
}

func singleLine(style material.LabelStyle) material.LabelStyle {
	style.MaxLines = 1
	return style
}

var contactColors = []color.NRGBA{
	{A: 0xff, R: 0xef, G: 0x6c, B: 0x00},
	{A: 0xff, R: 0x00, G: 0x57, B: 0x9b},