Skip to content

Commit ca5318f

Browse files
committed
Notification implemenation
1 parent c9a4231 commit ca5318f

File tree

5 files changed

+202
-6
lines changed

5 files changed

+202
-6
lines changed

bar.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package main
22

33
import (
44
"fmt"
5+
"strconv"
56
"time"
67

78
"github.com/MiracleOS-Team/desktoplib/batteryHandler"
89
"github.com/MiracleOS-Team/desktoplib/foreignToplevel"
910
"github.com/MiracleOS-Team/desktoplib/networkManagerHandler"
1011
"github.com/MiracleOS-Team/desktoplib/volumeHandler"
12+
"github.com/MiracleOS-Team/libxdg-go/notificationDaemon"
1113
"github.com/dlasky/gotk3-layershell/layershell"
1214
"github.com/gotk3/gotk3/gdk"
1315
"github.com/gotk3/gotk3/glib"
@@ -31,7 +33,7 @@ func getDateInfo() (string, string) {
3133
return curDayCal, curTimeInString
3234
}
3335

34-
func createSidestuff() *gtk.Box {
36+
func createSidestuff(nDaemon *notificationDaemon.Daemon) *gtk.Box {
3537
sideBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
3638
sideBox.SetHAlign(gtk.ALIGN_END)
3739
sc, _ := sideBox.GetStyleContext()
@@ -144,9 +146,21 @@ func createSidestuff() *gtk.Box {
144146
sc, _ = notificationImage.GetStyleContext()
145147
sc.AddClass("notification-bell")
146148

147-
notificationBox.PackStart(notificationImage, false, false, 0)
149+
notificationText, _ := gtk.LabelNew(strconv.Itoa(len(nDaemon.Notifications)))
150+
sc, _ = notificationText.GetStyleContext()
151+
sc.AddClass("h2")
152+
153+
notificationBox.PackStart(notificationText, false, false, 0)
148154
notificationButton.Add(notificationBox)
149155

156+
glib.TimeoutAdd(uint(100), func() bool {
157+
// Get new date/time info.
158+
notificationText.SetText(strconv.Itoa(len(nDaemon.Notifications)))
159+
160+
// Return true to keep the timeout active.
161+
return true
162+
})
163+
150164
sideBox.PackStart(otherIcons, false, false, 0)
151165
sideBox.PackStart(statusBox, false, false, 0)
152166
sideBox.PackStart(clock, false, false, 0)
@@ -216,7 +230,7 @@ func createMainIcons() *gtk.Box {
216230
return box
217231
}
218232

219-
func createBar() *gtk.Window {
233+
func createBar(nDaemon *notificationDaemon.Daemon) *gtk.Window {
220234
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
221235
win.SetTitle("Main Bar")
222236
win.SetDecorated(false)
@@ -245,7 +259,7 @@ func createBar() *gtk.Window {
245259
sc.AddClass("bar")
246260
box.PackStart(createWorkspaces(), false, false, 0)
247261
box.SetCenterWidget(createMainIcons())
248-
box.PackEnd(createSidestuff(), false, false, 0)
262+
box.PackEnd(createSidestuff(nDaemon), false, false, 0)
249263

250264
glib.TimeoutAdd(uint(500), func() bool {
251265
chil := box.GetChildren()

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.22.2
44

55
require (
66
github.com/MiracleOS-Team/desktoplib v0.0.0-20250208145244-91c183a6941e
7-
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250203122932-0d6a9fc71582
7+
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250214180153-81dbe745c61a
88
github.com/dlasky/gotk3-layershell v0.0.0-20240515133811-5c5115f0d774
99
github.com/gotk3/gotk3 v0.6.5-0.20240618185848-ff349ae13f56
1010
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ github.com/MiracleOS-Team/libxdg-go v0.0.0-20250130123149-66a2b3e59a66 h1:zax0cv
1616
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250130123149-66a2b3e59a66/go.mod h1:mKskdRQzPihHpgc1aUN06dlR2ECTxQWgPzOY3u2To+I=
1717
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250203122932-0d6a9fc71582 h1:Ce5u6O6M1586/JQxVvGr/GCClbxUJbtRPckg4ZfFawY=
1818
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250203122932-0d6a9fc71582/go.mod h1:mKskdRQzPihHpgc1aUN06dlR2ECTxQWgPzOY3u2To+I=
19+
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250214174651-a76479f5ae9b h1:AFndsH1gdz3zJLP0cWGtnywP8zbk+gwCGKAxZTPads8=
20+
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250214174651-a76479f5ae9b/go.mod h1:GA/p+ukjyXCsrcpGvs0/gFp1NeHAMtJG/sYT0JcImfE=
21+
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250214180153-81dbe745c61a h1:0JcWX9wXTvCl/Q4qYln8hjv6fOXUAo2jiduJqzxgJC8=
22+
github.com/MiracleOS-Team/libxdg-go v0.0.0-20250214180153-81dbe745c61a/go.mod h1:GA/p+ukjyXCsrcpGvs0/gFp1NeHAMtJG/sYT0JcImfE=
1923
github.com/bep/godartsass v1.2.0 h1:E2VvQrxAHAFwbjyOIExAMmogTItSKodoKuijNrGm5yU=
2024
github.com/bep/godartsass v1.2.0/go.mod h1:6LvK9RftsXMxGfsA0LDV12AGc4Jylnu6NgHL+Q5/pE8=
2125
github.com/bep/godartsass/v2 v2.3.2 h1:meuc76J1C1soSCAnlnJRdGqJ5S4m6/GW+8hmOe9tOog=

main.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,14 @@ func main() {
7272
//win := createMainMenu()
7373
//win.ShowAll()
7474

75-
bar := createBar()
75+
daemon := listenNotifications()
76+
defer daemon.Stop()
77+
78+
bar := createBar(daemon)
7679
bar.ShowAll()
7780

81+
//notificationBar := createNotificationBar(daemon)
82+
//notificationBar.ShowAll()
83+
7884
gtk.Main()
7985
}

notifications.go

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"strconv"
7+
"strings"
8+
9+
"github.com/MiracleOS-Team/libxdg-go/notificationDaemon"
10+
"github.com/dlasky/gotk3-layershell/layershell"
11+
"github.com/gotk3/gotk3/gdk"
12+
"github.com/gotk3/gotk3/glib"
13+
"github.com/gotk3/gotk3/gtk"
14+
)
15+
16+
func createNotification(notification *notificationDaemon.Notification, nDaemon *notificationDaemon.Daemon) *gtk.Box {
17+
notificationBox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 15)
18+
sc, _ := notificationBox.GetStyleContext()
19+
sc.AddClass("ntf_main_div")
20+
21+
ntfTopBar, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 15)
22+
23+
sc, _ = ntfTopBar.GetStyleContext()
24+
sc.AddClass("ntf_top_bar")
25+
26+
ntfTopBarText, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 15)
27+
28+
sc, _ = ntfTopBarText.GetStyleContext()
29+
sc.AddClass("nf_topbar_text")
30+
31+
ntfTopBarImage, _ := gtk.ImageNewFromIconName(notification.AppIcon, gtk.ICON_SIZE_BUTTON)
32+
33+
ntfTopBarTextLabel, _ := gtk.LabelNew(notification.AppName)
34+
35+
ntfTopBarDeleteButtonBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 15)
36+
37+
ntfTopBarDeleteButton, _ := gtk.ButtonNew()
38+
39+
sc, _ = ntfTopBarDeleteButton.GetStyleContext()
40+
sc.AddClass("button")
41+
42+
ntfTopBarDeleteButtonLabel, _ := gtk.LabelNew("Close")
43+
44+
ntfTopBarDeleteButton.Connect("clicked", func() {
45+
nDaemon.CloseNotificationAsUser(notification.ID)
46+
})
47+
48+
ntfTopBarDeleteButton.Add(ntfTopBarDeleteButtonLabel)
49+
ntfTopBarDeleteButtonBox.PackEnd(ntfTopBarDeleteButton, false, false, 0)
50+
ntfTopBar.PackEnd(ntfTopBarDeleteButtonBox, false, false, 0)
51+
ntfTopBarText.PackStart(ntfTopBarImage, false, false, 0)
52+
ntfTopBarText.PackStart(ntfTopBarTextLabel, false, false, 0)
53+
ntfTopBar.PackStart(ntfTopBarText, false, false, 0)
54+
notificationBox.PackStart(ntfTopBar, false, false, 0)
55+
56+
notificationBody, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 15)
57+
58+
//TODO: Handle notification Image
59+
60+
notificationTextBody, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 15)
61+
62+
sc, _ = notificationTextBody.GetStyleContext()
63+
sc.AddClass("ntf_text_contents")
64+
65+
if notification.Summary != "" {
66+
notificationSummary, _ := gtk.LabelNew(notification.Summary)
67+
notificationSummary.SetXAlign(0)
68+
sc, _ = notificationSummary.GetStyleContext()
69+
sc.AddClass("h2")
70+
notificationTextBody.PackStart(notificationSummary, false, false, 0)
71+
}
72+
73+
if notification.Body != "" {
74+
notificationBody, _ := gtk.LabelNew(notification.Body)
75+
notificationBody.SetXAlign(0)
76+
notificationTextBody.PackStart(notificationBody, false, false, 0)
77+
78+
}
79+
80+
hours, minutes, _ := notification.Timestamp.Clock()
81+
82+
timeLabel, _ := gtk.LabelNew(fmt.Sprintf("%d:%02d", hours, minutes))
83+
timeLabel.SetXAlign(0)
84+
sc, _ = timeLabel.GetStyleContext()
85+
sc.AddClass("h4")
86+
87+
notificationTextBody.PackEnd(timeLabel, false, false, 0)
88+
89+
notificationBody.PackStart(notificationTextBody, false, false, 0)
90+
notificationBox.PackStart(notificationBody, false, false, 0)
91+
92+
return notificationBox
93+
}
94+
95+
func createNotificationBarTitle(nDaemon *notificationDaemon.Daemon) *gtk.Box {
96+
tBox, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
97+
98+
title, _ := gtk.LabelNew(strings.Join([]string{strconv.Itoa(len(nDaemon.Notifications)), " Notifications"}, ""))
99+
sc, _ := title.GetStyleContext()
100+
sc.AddClass("h1")
101+
102+
glib.TimeoutAdd(uint(100), func() bool {
103+
// Get new date/time info.
104+
title.SetText(strings.Join([]string{strconv.Itoa(len(nDaemon.Notifications)), " Notifications"}, ""))
105+
106+
// Return true to keep the timeout active.
107+
return true
108+
})
109+
110+
closeAllButtonText, _ := gtk.LabelNew("Clear all")
111+
sc, _ = closeAllButtonText.GetStyleContext()
112+
sc.AddClass("button")
113+
114+
closeAllButton, _ := gtk.ButtonNew()
115+
closeAllButton.Add(closeAllButtonText)
116+
117+
closeAllButton.Connect("clicked", func() {
118+
for _, elem := range nDaemon.Notifications {
119+
nDaemon.CloseNotificationAsUser(elem.ID)
120+
}
121+
})
122+
123+
tBox.PackStart(title, false, false, 0)
124+
tBox.PackEnd(closeAllButton, false, false, 0)
125+
return tBox
126+
}
127+
128+
func createNotificationBar(nDaemon *notificationDaemon.Daemon) *gtk.Window {
129+
win, _ := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
130+
win.SetTitle("Notification Bar")
131+
win.SetDecorated(false)
132+
win.SetResizable(false)
133+
134+
layershell.InitForWindow(win)
135+
layershell.SetNamespace(win, "miracleos")
136+
137+
layershell.SetAnchor(win, layershell.LAYER_SHELL_EDGE_BOTTOM, true)
138+
layershell.SetAnchor(win, layershell.LAYER_SHELL_EDGE_RIGHT, true)
139+
140+
layershell.SetLayer(win, layershell.LAYER_SHELL_LAYER_TOP)
141+
layershell.SetMargin(win, layershell.LAYER_SHELL_EDGE_TOP, 0)
142+
layershell.SetMargin(win, layershell.LAYER_SHELL_EDGE_LEFT, 0)
143+
layershell.SetMargin(win, layershell.LAYER_SHELL_EDGE_RIGHT, 0)
144+
145+
layershell.SetKeyboardMode(win, layershell.LAYER_SHELL_KEYBOARD_MODE_NONE)
146+
disp, _ := gdk.DisplayGetDefault()
147+
mon, _ := disp.GetMonitor(0)
148+
layershell.SetMonitor(win, mon)
149+
150+
mBox, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 10)
151+
152+
for _, nt := range nDaemon.Notifications {
153+
mBox.PackEnd(createNotification(&nt, nDaemon), false, false, 0)
154+
}
155+
156+
mBox.PackStart(createNotificationBarTitle(nDaemon), false, false, 0)
157+
158+
win.Add(mBox)
159+
160+
return win
161+
}
162+
163+
func listenNotifications() *notificationDaemon.Daemon {
164+
daemon := notificationDaemon.NewDaemon(notificationDaemon.Config{
165+
Capabilities: []string{"body", "actions", "actions-ions", "icon-static"},
166+
})
167+
if err := daemon.Start(); err != nil {
168+
log.Fatalf("Failed to start notification daemon: %v", err)
169+
}
170+
171+
return daemon
172+
}

0 commit comments

Comments
 (0)