Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
diamondburned
GitHub Repository: diamondburned/gtkcord4
Path: blob/main/internal/window/window_login.go
450 views
1
package window
2
3
import (
4
"fmt"
5
"log/slog"
6
"sync"
7
8
"github.com/diamondburned/arikawa/v3/discord"
9
"github.com/diamondburned/arikawa/v3/gateway"
10
"github.com/diamondburned/arikawa/v3/utils/ws"
11
"github.com/diamondburned/gotk4/pkg/glib/v2"
12
"github.com/diamondburned/gotkit/app/notify"
13
"github.com/diamondburned/ningen/v3"
14
"libdb.so/dissent/internal/gtkcord"
15
)
16
17
type loginWindow struct {
18
*Window
19
readyOnce sync.Once
20
}
21
22
func (w *loginWindow) Hook(state *gtkcord.State) {
23
w.ctx = gtkcord.InjectState(w.ctx, state)
24
25
w.Reconnecting()
26
var reconnecting glib.SourceHandle
27
28
// When the websocket closes, the screen must be changed to a busy one. The
29
// websocket may close if it's disconnected unexpectedly.
30
state.BindWidget(w, func(ev gateway.Event) {
31
switch ev := ev.(type) {
32
case *ningen.ConnectedEvent:
33
slog.Info(
34
"Discord gateway connected",
35
"event", ev.EventType())
36
37
// Cancel the 3s delay if we're already connected during that.
38
if reconnecting != 0 {
39
glib.SourceRemove(reconnecting)
40
reconnecting = 0
41
}
42
43
w.Connected()
44
45
case *ws.BackgroundErrorEvent:
46
slog.Warn(
47
"Discord gateway background error",
48
"err", ev.Err)
49
50
case *ws.CloseEvent:
51
slog.Info(
52
"Discord gateway closed",
53
"err", ev.Err,
54
"code", ev.Code)
55
56
case *ningen.DisconnectedEvent:
57
slog.Info(
58
"Discord gateway disconnected",
59
"err", ev.Err,
60
"code", ev.Code)
61
62
if ev.IsLoggedOut() {
63
w.PromptLogin()
64
return
65
}
66
67
// Add a 3s delay in case we have a sudden disruption that
68
// immediately recovers.
69
reconnecting = glib.TimeoutSecondsAdd(3, func() {
70
w.Reconnecting()
71
reconnecting = 0
72
})
73
74
case *gateway.ReadyEvent:
75
if ev.UserSettings != nil {
76
switch ev.UserSettings.Theme {
77
case "dark":
78
SetPreferDarkTheme(true)
79
case "light":
80
SetPreferDarkTheme(false)
81
}
82
}
83
84
case *gateway.MessageCreateEvent:
85
mentions := state.MessageMentions(&ev.Message)
86
if mentions == 0 {
87
return
88
}
89
90
if state.Status() == discord.DoNotDisturbStatus {
91
return
92
}
93
94
avatarURL := gtkcord.InjectAvatarSize(ev.Author.AvatarURL())
95
96
notify.Send(w.ctx, notify.Notification{
97
ID: notify.HashID(ev.ChannelID),
98
Title: fmt.Sprintf(
99
"%s (%s)",
100
state.AuthorDisplayName(ev),
101
gtkcord.ChannelNameFromID(w.ctx, ev.ChannelID),
102
),
103
Body: state.MessagePreview(&ev.Message),
104
Icon: notify.IconURL(w.ctx, avatarURL, notify.IconName("avatar-default-symbolic")),
105
Sound: notify.MessageSound,
106
Action: notify.Action{
107
ActionID: "app.open-channel",
108
Argument: gtkcord.NewChannelIDVariant(ev.ChannelID),
109
},
110
})
111
}
112
})
113
}
114
115
func (w *loginWindow) Ready(state *gtkcord.State) {
116
app := w.Application()
117
app.ConnectShutdown(func() {
118
slog.Info("Closing Discord session...")
119
120
if err := state.Close(); err != nil {
121
slog.Error("error closing session", "err", err)
122
}
123
})
124
}
125
126
func (w *loginWindow) Reconnecting() {
127
w.Stack.SetVisibleChild(w.Loading)
128
w.SetTitle("Connecting")
129
}
130
131
func (w *loginWindow) Connected() {
132
w.readyOnce.Do(func() {
133
w.initChatPage()
134
w.initActions()
135
})
136
w.Window.SwitchToChatPage()
137
}
138
139
func (w *loginWindow) PromptLogin() {
140
w.Window.SwitchToLoginPage()
141
}
142
143