Path: blob/main/internal/sidebar/direct/channel.go
366 views
package direct12import (3"context"4"fmt"5"log/slog"67"github.com/diamondburned/arikawa/v3/discord"8"github.com/diamondburned/gotk4/pkg/gtk/v4"9"github.com/diamondburned/gotk4/pkg/pango"10"github.com/diamondburned/gotkit/components/onlineimage"11"github.com/diamondburned/gotkit/gtkutil/cssutil"12"github.com/diamondburned/gotkit/gtkutil/imgutil"13"github.com/diamondburned/ningen/v3"14"libdb.so/dissent/internal/gtkcord"15)1617// Channel is an individual direct messaging channel.18type Channel struct {19*gtk.ListBoxRow20box *gtk.Box21avatar *onlineimage.Avatar22name *gtk.Label23readIndicator *gtk.Label2425ctx context.Context26id discord.ChannelID27}2829var channelCSS = cssutil.Applier("direct-channel", `30.direct-channel {31padding: 4px 6px;32}33.direct-channel-avatar {34margin-right: 6px;35}36`)3738// NewChannel creates a new Channel.39func NewChannel(ctx context.Context, id discord.ChannelID) *Channel {40ch := Channel{41ctx: ctx,42id: id,43}4445ch.name = gtk.NewLabel("")46ch.name.AddCSSClass("direct-channel-name")47ch.name.SetXAlign(0)48ch.name.SetHExpand(true)49ch.name.SetEllipsize(pango.EllipsizeEnd)50ch.name.SetSingleLineMode(true)5152ch.avatar = onlineimage.NewAvatar(ctx, imgutil.HTTPProvider, gtkcord.ChannelIconSize)53ch.avatar.AddCSSClass("direct-channel-avatar")5455ch.readIndicator = gtk.NewLabel("")56ch.readIndicator.AddCSSClass("direct-channel-readindicator")5758ch.box = gtk.NewBox(gtk.OrientationHorizontal, 0)59ch.box.Append(ch.avatar)60ch.box.Append(ch.name)61ch.box.Append(ch.readIndicator)6263ch.ListBoxRow = gtk.NewListBoxRow()64ch.SetChild(ch.box)65ch.SetName(id.String())66channelCSS(ch)6768return &ch69}7071// Invalidate fetches the same channel from the state and updates itself.72func (ch *Channel) Invalidate() {73state := gtkcord.FromContext(ch.ctx)7475channel, err := state.Cabinet.Channel(ch.id)76if err != nil {77slog.Error(78"Failed to fetch direct channel from state",79"channel_id", ch.id,80"err", err)81return82}8384ch.Update(channel)85}8687// Update updates the channel to show information from the instance given. ID is88// not checked.89func (ch *Channel) Update(channel *discord.Channel) {90name := gtkcord.ChannelName(channel)91ch.name.SetText(name)9293if channel.Type == discord.DirectMessage && len(channel.DMRecipients) > 0 {94u := channel.DMRecipients[0]95ch.avatar.SetText(name)96ch.avatar.SetFromURL(gtkcord.InjectAvatarSize(u.AvatarURL()))97} else {98ch.avatar.SetIconName("avatar-default-symbolic")99ch.avatar.SetFromURL(gtkcord.InjectAvatarSize(channel.IconURL()))100}101102ch.updateReadIndicator(channel)103}104105func (ch *Channel) updateReadIndicator(channel *discord.Channel) {106state := gtkcord.FromContext(ch.ctx)107unread := state.ChannelCountUnreads(channel.ID, ningen.UnreadOpts{})108109if unread == 0 {110ch.readIndicator.SetText("")111} else {112ch.readIndicator.SetText(fmt.Sprintf("(%d)", unread))113}114115ch.InvalidateSort()116}117118// LastMessageID queries the local state for the channel's last message ID.119func (ch *Channel) LastMessageID() discord.MessageID {120state := gtkcord.FromContext(ch.ctx)121return state.LastMessage(ch.id)122}123124// Name returns the current displaying name of the channel.125func (ch *Channel) Name() string {126return ch.name.Text()127}128129// InvalidateSort invalidates the sorting position of this channel within the130// major channel list.131func (ch *Channel) InvalidateSort() {132ch.Changed()133}134135136