Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
diamondburned
GitHub Repository: diamondburned/gtkcord4
Path: blob/main/internal/sidebar/direct/channel.go
366 views
1
package direct
2
3
import (
4
"context"
5
"fmt"
6
"log/slog"
7
8
"github.com/diamondburned/arikawa/v3/discord"
9
"github.com/diamondburned/gotk4/pkg/gtk/v4"
10
"github.com/diamondburned/gotk4/pkg/pango"
11
"github.com/diamondburned/gotkit/components/onlineimage"
12
"github.com/diamondburned/gotkit/gtkutil/cssutil"
13
"github.com/diamondburned/gotkit/gtkutil/imgutil"
14
"github.com/diamondburned/ningen/v3"
15
"libdb.so/dissent/internal/gtkcord"
16
)
17
18
// Channel is an individual direct messaging channel.
19
type Channel struct {
20
*gtk.ListBoxRow
21
box *gtk.Box
22
avatar *onlineimage.Avatar
23
name *gtk.Label
24
readIndicator *gtk.Label
25
26
ctx context.Context
27
id discord.ChannelID
28
}
29
30
var channelCSS = cssutil.Applier("direct-channel", `
31
.direct-channel {
32
padding: 4px 6px;
33
}
34
.direct-channel-avatar {
35
margin-right: 6px;
36
}
37
`)
38
39
// NewChannel creates a new Channel.
40
func NewChannel(ctx context.Context, id discord.ChannelID) *Channel {
41
ch := Channel{
42
ctx: ctx,
43
id: id,
44
}
45
46
ch.name = gtk.NewLabel("")
47
ch.name.AddCSSClass("direct-channel-name")
48
ch.name.SetXAlign(0)
49
ch.name.SetHExpand(true)
50
ch.name.SetEllipsize(pango.EllipsizeEnd)
51
ch.name.SetSingleLineMode(true)
52
53
ch.avatar = onlineimage.NewAvatar(ctx, imgutil.HTTPProvider, gtkcord.ChannelIconSize)
54
ch.avatar.AddCSSClass("direct-channel-avatar")
55
56
ch.readIndicator = gtk.NewLabel("")
57
ch.readIndicator.AddCSSClass("direct-channel-readindicator")
58
59
ch.box = gtk.NewBox(gtk.OrientationHorizontal, 0)
60
ch.box.Append(ch.avatar)
61
ch.box.Append(ch.name)
62
ch.box.Append(ch.readIndicator)
63
64
ch.ListBoxRow = gtk.NewListBoxRow()
65
ch.SetChild(ch.box)
66
ch.SetName(id.String())
67
channelCSS(ch)
68
69
return &ch
70
}
71
72
// Invalidate fetches the same channel from the state and updates itself.
73
func (ch *Channel) Invalidate() {
74
state := gtkcord.FromContext(ch.ctx)
75
76
channel, err := state.Cabinet.Channel(ch.id)
77
if err != nil {
78
slog.Error(
79
"Failed to fetch direct channel from state",
80
"channel_id", ch.id,
81
"err", err)
82
return
83
}
84
85
ch.Update(channel)
86
}
87
88
// Update updates the channel to show information from the instance given. ID is
89
// not checked.
90
func (ch *Channel) Update(channel *discord.Channel) {
91
name := gtkcord.ChannelName(channel)
92
ch.name.SetText(name)
93
94
if channel.Type == discord.DirectMessage && len(channel.DMRecipients) > 0 {
95
u := channel.DMRecipients[0]
96
ch.avatar.SetText(name)
97
ch.avatar.SetFromURL(gtkcord.InjectAvatarSize(u.AvatarURL()))
98
} else {
99
ch.avatar.SetIconName("avatar-default-symbolic")
100
ch.avatar.SetFromURL(gtkcord.InjectAvatarSize(channel.IconURL()))
101
}
102
103
ch.updateReadIndicator(channel)
104
}
105
106
func (ch *Channel) updateReadIndicator(channel *discord.Channel) {
107
state := gtkcord.FromContext(ch.ctx)
108
unread := state.ChannelCountUnreads(channel.ID, ningen.UnreadOpts{})
109
110
if unread == 0 {
111
ch.readIndicator.SetText("")
112
} else {
113
ch.readIndicator.SetText(fmt.Sprintf("(%d)", unread))
114
}
115
116
ch.InvalidateSort()
117
}
118
119
// LastMessageID queries the local state for the channel's last message ID.
120
func (ch *Channel) LastMessageID() discord.MessageID {
121
state := gtkcord.FromContext(ch.ctx)
122
return state.LastMessage(ch.id)
123
}
124
125
// Name returns the current displaying name of the channel.
126
func (ch *Channel) Name() string {
127
return ch.name.Text()
128
}
129
130
// InvalidateSort invalidates the sorting position of this channel within the
131
// major channel list.
132
func (ch *Channel) InvalidateSort() {
133
ch.Changed()
134
}
135
136