Path: blob/main/internal/sidebar/guilds/folder.go
366 views
package guilds12import (3"context"45"github.com/diamondburned/arikawa/v3/discord"6"github.com/diamondburned/arikawa/v3/gateway"7"github.com/diamondburned/gotk4/pkg/gtk/v4"8"github.com/diamondburned/gotkit/gtkutil/cssutil"9"libdb.so/dissent/internal/sidebar/sidebutton"10)1112const (13FolderSize = 3214FolderMiniSize = 1615)1617// Folder is the widget containing the folder icon on top and a child list of18// guilds beneath it.19type Folder struct {20*gtk.Box2122Button struct {23*gtk.Overlay24Pill *sidebutton.Pill25Folder *FolderButton26}2728Revealer *gtk.Revealer29GuildBox *gtk.Box30Guilds []*Guild3132ctx context.Context33open bool3435// TODO: if we ever track the unread indicator, then our unread container36// will need to count the guilds for us for SetGuildOpen to work37// correctly.38}3940var folderCSS = cssutil.Applier("guild-folder", `41.guild-folder .guild-guild > button {42padding: 0px 12px;43}44.guild-folder .guild-guild > button > * {45padding: 4px 0;46transition: 200ms ease;47background-color: @theme_bg_color;48}49.guild-folder .guild-guild > button avatar {50padding: 0;51}52.guild-folder .guild-guild > button avatar,53.guild-folder .guild-guild > button:hover avatar {54background-color: @theme_bg_color;55}56.guild-folder .guild-guild:last-child > button {57padding-bottom: 4px;58}59.guild-folder .guild-guild:last-child > button > * {60padding: 0;61padding-top: 4px;62border-radius: 0 0 99px 99px;63}64`)6566// NewFolder creates a new Folder.67func NewFolder(ctx context.Context) *Folder {68f := Folder{69ctx: ctx,70}7172f.Button.Folder = NewFolderButton(ctx)73f.Button.Folder.SetRevealed(false)74f.Button.Folder.ConnectClicked(f.toggle)7576f.Button.Pill = sidebutton.NewPill()7778f.Button.Overlay = gtk.NewOverlay()79f.Button.Overlay.SetChild(f.Button.Folder)80f.Button.Overlay.AddOverlay(f.Button.Pill)8182f.GuildBox = gtk.NewBox(gtk.OrientationVertical, 0)8384f.Revealer = gtk.NewRevealer()85f.Revealer.SetTransitionType(gtk.RevealerTransitionTypeSlideDown)86f.Revealer.SetRevealChild(false)87f.Revealer.SetChild(f.GuildBox)8889f.Box = gtk.NewBox(gtk.OrientationVertical, 0)90f.Box.Append(f.Button.Overlay)91f.Box.Append(f.Revealer)92f.AddCSSClass("guild-folder-collapsed")93folderCSS(f.Box)9495return &f96}9798// Unselect unselects the folder visually.99func (f *Folder) Unselect() {100f.setGuildOpen(false)101}102103// SetSelected sets the folder's selected state.104func (f *Folder) SetSelected(selected bool) {105f.setGuildOpen(selected)106}107108func (f *Folder) setGuildOpen(open bool) {109f.open = open110111if f.Revealer.RevealChild() {112f.Button.Pill.State = sidebutton.PillOpened113} else {114if open {115f.Button.Pill.State = sidebutton.PillActive116} else {117f.Button.Pill.State = sidebutton.PillInactive118}119}120121f.Button.Pill.Invalidate()122}123124func (f *Folder) toggle() {125reveal := !f.Revealer.RevealChild()126f.Revealer.SetRevealChild(reveal)127f.Button.Folder.SetRevealed(reveal)128f.Button.Folder.Mentions.SetRevealChild(!reveal)129f.setGuildOpen(f.open)130131if reveal {132f.RemoveCSSClass("guild-folder-collapsed")133} else {134f.AddCSSClass("guild-folder-collapsed")135}136}137138// Set sets a fresh list of guilds.139func (f *Folder) Set(folder *gateway.GuildFolder) {140f.Button.Folder.SetIcons(folder.GuildIDs)141if folder.Color != discord.NullColor {142f.Button.Folder.SetColor(folder.Color)143}144145for _, guild := range f.Guilds {146f.GuildBox.Remove(guild)147}148149f.Guilds = make([]*Guild, len(folder.GuildIDs))150151for i, id := range folder.GuildIDs {152g := NewGuild(f.ctx, id)153g.SetParentFolder(f)154155f.Guilds[i] = g156f.GuildBox.Append(g)157}158159// Invalidate after, since guilds can call back onto our Folder list.160for _, g := range f.Guilds {161g.Invalidate()162}163164// After guilds are loaded, read their labels and set the folder name if unset.165folderName := folder.Name166if folderName == "" {167for i, g := range f.Guilds {168folderName += g.Name()169if (i + 1) < len(f.Guilds) {170folderName += ", "171}172if len(folderName) > 40 {173folderName += "..."174break175}176}177}178179f.Button.SetTooltipText(folderName)180}181182// Remove removes the given guild by its ID.183func (f *Folder) Remove(id discord.GuildID) {184for i, guild := range f.Guilds {185if guild.ID() == id {186f.GuildBox.Remove(guild)187f.Guilds = append(f.Guilds[:i], f.Guilds[i+1:]...)188return189}190}191}192193func (f *Folder) viewChild() {}194195// InvalidateUnread invalidates the folder's unread state.196func (f *Folder) InvalidateUnread() {197f.Button.Pill.Attrs = 0198for _, guild := range f.Guilds {199f.Button.Pill.Attrs |= guild.Pill.Attrs200}201202f.Button.Pill.Invalidate()203204var mentions int205for _, guild := range f.Guilds {206mentions += guild.Mentions.Count()207}208209f.Button.Folder.Mentions.SetCount(mentions)210}211212213