+40
appview/pages/pages.go
+40
appview/pages/pages.go
···
296
296
return p.execute("user/settings/profile", w, params)
297
297
}
298
298
299
+
type NotificationsParams struct {
300
+
LoggedInUser *oauth.User
301
+
Notifications []*models.NotificationWithEntity
302
+
UnreadCount int
303
+
HasMore bool
304
+
NextOffset int
305
+
Limit int
306
+
}
307
+
308
+
func (p *Pages) Notifications(w io.Writer, params NotificationsParams) error {
309
+
return p.execute("notifications/list", w, params)
310
+
}
311
+
312
+
type NotificationItemParams struct {
313
+
Notification *models.Notification
314
+
}
315
+
316
+
func (p *Pages) NotificationItem(w io.Writer, params NotificationItemParams) error {
317
+
return p.executePlain("notifications/fragments/item", w, params)
318
+
}
319
+
320
+
type NotificationCountParams struct {
321
+
Count int
322
+
}
323
+
324
+
func (p *Pages) NotificationCount(w io.Writer, params NotificationCountParams) error {
325
+
return p.executePlain("notifications/fragments/count", w, params)
326
+
}
327
+
299
328
type UserKeysSettingsParams struct {
300
329
LoggedInUser *oauth.User
301
330
PubKeys []models.PublicKey
···
316
345
317
346
func (p *Pages) UserEmailsSettings(w io.Writer, params UserEmailsSettingsParams) error {
318
347
return p.execute("user/settings/emails", w, params)
348
+
}
349
+
350
+
type UserNotificationSettingsParams struct {
351
+
LoggedInUser *oauth.User
352
+
Preferences *models.NotificationPreferences
353
+
Tabs []map[string]any
354
+
Tab string
355
+
}
356
+
357
+
func (p *Pages) UserNotificationSettings(w io.Writer, params UserNotificationSettingsParams) error {
358
+
return p.execute("user/settings/notifications", w, params)
319
359
}
320
360
321
361
type UpgradeBannerParams struct {
+4
-11
appview/pages/templates/errors/500.html
+4
-11
appview/pages/templates/errors/500.html
···
5
5
<div class="bg-white dark:bg-gray-800 rounded-lg drop-shadow-sm p-8 max-w-lg mx-auto">
6
6
<div class="mb-6">
7
7
<div class="w-16 h-16 mx-auto mb-4 rounded-full bg-red-100 dark:bg-red-900/30 flex items-center justify-center">
8
-
{{ i "alert-triangle" "w-8 h-8 text-red-500 dark:text-red-400" }}
8
+
{{ i "triangle-alert" "w-8 h-8 text-red-500 dark:text-red-400" }}
9
9
</div>
10
10
</div>
11
11
···
14
14
500 — internal server error
15
15
</h1>
16
16
<p class="text-gray-600 dark:text-gray-300">
17
-
Something went wrong on our end. We've been notified and are working to fix the issue.
18
-
</p>
19
-
<div class="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded p-3 text-sm text-yellow-800 dark:text-yellow-200">
20
-
<div class="flex items-center gap-2">
21
-
{{ i "info" "w-4 h-4" }}
22
-
<span class="font-medium">we're on it!</span>
23
-
</div>
24
-
<p class="mt-1">Our team has been automatically notified about this error.</p>
25
-
</div>
17
+
We encountered an error while processing your request. Please try again later.
18
+
</p>
26
19
<div class="flex flex-col sm:flex-row gap-3 justify-center items-center mt-6">
27
20
<button onclick="location.reload()" class="btn-create gap-2">
28
21
{{ i "refresh-cw" "w-4 h-4" }}
29
22
try again
30
23
</button>
31
24
<a href="/" class="btn no-underline hover:no-underline gap-2">
32
-
{{ i "home" "w-4 h-4" }}
25
+
{{ i "arrow-left" "w-4 h-4" }}
33
26
back to home
34
27
</a>
35
28
</div>
+2
-1
appview/pages/templates/layouts/fragments/topbar.html
+2
-1
appview/pages/templates/layouts/fragments/topbar.html
···
10
10
<div id="right-items" class="flex items-center gap-2">
11
11
{{ with .LoggedInUser }}
12
12
{{ block "newButton" . }} {{ end }}
13
+
{{ template "notifications/fragments/bell" }}
13
14
{{ block "dropDown" . }} {{ end }}
14
15
{{ else }}
15
16
<a href="/login">login</a>
···
44
45
{{ define "dropDown" }}
45
46
<details class="relative inline-block text-left nav-dropdown">
46
47
<summary
47
-
class="cursor-pointer list-none flex items-center"
48
+
class="cursor-pointer list-none flex items-center gap-1"
48
49
>
49
50
{{ $user := didOrHandle .Did .Handle }}
50
51
{{ template "user/fragments/picHandle" $user }}
+11
appview/pages/templates/notifications/fragments/bell.html
+11
appview/pages/templates/notifications/fragments/bell.html
···
1
+
{{define "notifications/fragments/bell"}}
2
+
<div class="relative"
3
+
hx-get="/notifications/count"
4
+
hx-target="#notification-count"
5
+
hx-trigger="load, every 30s">
6
+
<a href="/notifications" class="text-gray-500 dark:text-gray-400 flex gap-1 items-center group ml-4 mr-2">
7
+
{{ i "bell" "w-5 h-5" }}
8
+
<span id="notification-count"></span>
9
+
</a>
10
+
</div>
11
+
{{end}}
+7
appview/pages/templates/notifications/fragments/count.html
+7
appview/pages/templates/notifications/fragments/count.html
···
1
+
{{define "notifications/fragments/count"}}
2
+
{{if and .Count (gt .Count 0)}}
3
+
<span class="absolute -top-1 -right-0.5 min-w-[16px] h-[16px] px-1 bg-red-500 text-white text-xs font-medium rounded-full flex items-center justify-center">
4
+
{{if gt .Count 99}}99+{{else}}{{.Count}}{{end}}
5
+
</span>
6
+
{{end}}
7
+
{{end}}
+212
appview/pages/templates/notifications/fragments/item.html
+212
appview/pages/templates/notifications/fragments/item.html
···
1
+
{{define "notifications/fragments/item"}}
2
+
<div class="border border-gray-200 dark:border-gray-700 rounded-sm p-3 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors {{if not .Read}}bg-blue-50 dark:bg-blue-900/20{{end}}">
3
+
{{if .Issue}}
4
+
{{template "issueNotification" .}}
5
+
{{else if .Pull}}
6
+
{{template "pullNotification" .}}
7
+
{{else if .Repo}}
8
+
{{template "repoNotification" .}}
9
+
{{else if eq .Type "followed"}}
10
+
{{template "followNotification" .}}
11
+
{{else}}
12
+
{{template "genericNotification" .}}
13
+
{{end}}
14
+
</div>
15
+
{{end}}
16
+
17
+
{{define "issueNotification"}}
18
+
{{$url := printf "/%s/%s/issues/%d" (resolve .Repo.Did) .Repo.Name .Issue.IssueId}}
19
+
<a
20
+
href="{{$url}}"
21
+
class="block no-underline hover:no-underline text-inherit -m-3 p-3"
22
+
>
23
+
<div class="flex items-center justify-between">
24
+
<div class="min-w-0 flex-1">
25
+
<!-- First line: icon + actor action -->
26
+
<div class="flex items-center gap-2 text-gray-900 dark:text-white">
27
+
{{if eq .Type "issue_created"}}
28
+
<span class="text-green-600 dark:text-green-500">
29
+
{{ i "circle-dot" "w-4 h-4" }}
30
+
</span>
31
+
{{else if eq .Type "issue_commented"}}
32
+
<span class="text-gray-500 dark:text-gray-400">
33
+
{{ i "message-circle" "w-4 h-4" }}
34
+
</span>
35
+
{{else if eq .Type "issue_closed"}}
36
+
<span class="text-gray-500 dark:text-gray-400">
37
+
{{ i "ban" "w-4 h-4" }}
38
+
</span>
39
+
{{end}}
40
+
{{template "user/fragments/picHandle" (resolve .ActorDid)}}
41
+
{{if eq .Type "issue_created"}}
42
+
<span class="text-gray-500 dark:text-gray-400">opened issue</span>
43
+
{{else if eq .Type "issue_commented"}}
44
+
<span class="text-gray-500 dark:text-gray-400">commented on issue</span>
45
+
{{else if eq .Type "issue_closed"}}
46
+
<span class="text-gray-500 dark:text-gray-400">closed issue</span>
47
+
{{end}}
48
+
{{if not .Read}}
49
+
<div class="w-2 h-2 bg-blue-500 rounded-full flex-shrink-0 ml-1"></div>
50
+
{{end}}
51
+
</div>
52
+
53
+
<div class="text-sm text-gray-600 dark:text-gray-400 mt-0.5 ml-6 flex items-center gap-1">
54
+
<span class="text-gray-500 dark:text-gray-400">#{{.Issue.IssueId}}</span>
55
+
<span class="text-gray-900 dark:text-white truncate">{{.Issue.Title}}</span>
56
+
<span>on</span>
57
+
<span class="font-medium text-gray-900 dark:text-white">{{resolve .Repo.Did}}/{{.Repo.Name}}</span>
58
+
</div>
59
+
</div>
60
+
61
+
<div class="text-xs text-gray-500 dark:text-gray-400 flex-shrink-0 ml-2">
62
+
{{ template "repo/fragments/time" .Created }}
63
+
</div>
64
+
</div>
65
+
</a>
66
+
{{end}}
67
+
68
+
{{define "pullNotification"}}
69
+
{{$url := printf "/%s/%s/pulls/%d" (resolve .Repo.Did) .Repo.Name .Pull.PullId}}
70
+
<a
71
+
href="{{$url}}"
72
+
class="block no-underline hover:no-underline text-inherit -m-3 p-3"
73
+
>
74
+
<div class="flex items-center justify-between">
75
+
<div class="min-w-0 flex-1">
76
+
<div class="flex items-center gap-2 text-gray-900 dark:text-white">
77
+
{{if eq .Type "pull_created"}}
78
+
<span class="text-green-600 dark:text-green-500">
79
+
{{ i "git-pull-request-create" "w-4 h-4" }}
80
+
</span>
81
+
{{else if eq .Type "pull_commented"}}
82
+
<span class="text-gray-500 dark:text-gray-400">
83
+
{{ i "message-circle" "w-4 h-4" }}
84
+
</span>
85
+
{{else if eq .Type "pull_merged"}}
86
+
<span class="text-purple-600 dark:text-purple-500">
87
+
{{ i "git-merge" "w-4 h-4" }}
88
+
</span>
89
+
{{else if eq .Type "pull_closed"}}
90
+
<span class="text-red-600 dark:text-red-500">
91
+
{{ i "git-pull-request-closed" "w-4 h-4" }}
92
+
</span>
93
+
{{end}}
94
+
{{template "user/fragments/picHandle" (resolve .ActorDid)}}
95
+
{{if eq .Type "pull_created"}}
96
+
<span class="text-gray-500 dark:text-gray-400">opened pull request</span>
97
+
{{else if eq .Type "pull_commented"}}
98
+
<span class="text-gray-500 dark:text-gray-400">commented on pull request</span>
99
+
{{else if eq .Type "pull_merged"}}
100
+
<span class="text-gray-500 dark:text-gray-400">merged pull request</span>
101
+
{{else if eq .Type "pull_closed"}}
102
+
<span class="text-gray-500 dark:text-gray-400">closed pull request</span>
103
+
{{end}}
104
+
{{if not .Read}}
105
+
<div class="w-2 h-2 bg-blue-500 rounded-full flex-shrink-0 ml-1"></div>
106
+
{{end}}
107
+
</div>
108
+
109
+
<div class="text-sm text-gray-600 dark:text-gray-400 mt-0.5 ml-6 flex items-center gap-1">
110
+
<span class="text-gray-500 dark:text-gray-400">#{{.Pull.PullId}}</span>
111
+
<span class="text-gray-900 dark:text-white truncate">{{.Pull.Title}}</span>
112
+
<span>on</span>
113
+
<span class="font-medium text-gray-900 dark:text-white">{{resolve .Repo.Did}}/{{.Repo.Name}}</span>
114
+
</div>
115
+
</div>
116
+
117
+
<div class="text-xs text-gray-500 dark:text-gray-400 flex-shrink-0 ml-2">
118
+
{{ template "repo/fragments/time" .Created }}
119
+
</div>
120
+
</div>
121
+
</a>
122
+
{{end}}
123
+
124
+
{{define "repoNotification"}}
125
+
{{$url := printf "/%s/%s" (resolve .Repo.Did) .Repo.Name}}
126
+
<a
127
+
href="{{$url}}"
128
+
class="block no-underline hover:no-underline text-inherit -m-3 p-3"
129
+
>
130
+
<div class="flex items-center justify-between">
131
+
<div class="flex items-center gap-2 min-w-0 flex-1">
132
+
<span class="text-yellow-500 dark:text-yellow-400">
133
+
{{ i "star" "w-4 h-4" }}
134
+
</span>
135
+
136
+
<div class="min-w-0 flex-1">
137
+
<!-- Single line for stars: actor action subject -->
138
+
<div class="flex items-center gap-1 text-gray-900 dark:text-white">
139
+
{{template "user/fragments/picHandle" (resolve .ActorDid)}}
140
+
<span class="text-gray-500 dark:text-gray-400">starred</span>
141
+
<span class="font-medium">{{resolve .Repo.Did}}/{{.Repo.Name}}</span>
142
+
{{if not .Read}}
143
+
<div class="w-2 h-2 bg-blue-500 rounded-full flex-shrink-0 ml-1"></div>
144
+
{{end}}
145
+
</div>
146
+
</div>
147
+
</div>
148
+
149
+
<div class="text-xs text-gray-500 dark:text-gray-400 flex-shrink-0 ml-2">
150
+
{{ template "repo/fragments/time" .Created }}
151
+
</div>
152
+
</div>
153
+
</a>
154
+
{{end}}
155
+
156
+
{{define "followNotification"}}
157
+
{{$url := printf "/%s" (resolve .ActorDid)}}
158
+
<a
159
+
href="{{$url}}"
160
+
class="block no-underline hover:no-underline text-inherit -m-3 p-3"
161
+
>
162
+
<div class="flex items-center justify-between">
163
+
<div class="flex items-center gap-2 min-w-0 flex-1">
164
+
<span class="text-blue-600 dark:text-blue-400">
165
+
{{ i "user-plus" "w-4 h-4" }}
166
+
</span>
167
+
168
+
<div class="min-w-0 flex-1">
169
+
<div class="flex items-center gap-1 text-gray-900 dark:text-white">
170
+
{{template "user/fragments/picHandle" (resolve .ActorDid)}}
171
+
<span class="text-gray-500 dark:text-gray-400">followed you</span>
172
+
{{if not .Read}}
173
+
<div class="w-2 h-2 bg-blue-500 rounded-full flex-shrink-0 ml-1"></div>
174
+
{{end}}
175
+
</div>
176
+
</div>
177
+
</div>
178
+
179
+
<div class="text-xs text-gray-500 dark:text-gray-400 flex-shrink-0 ml-2">
180
+
{{ template "repo/fragments/time" .Created }}
181
+
</div>
182
+
</div>
183
+
</a>
184
+
{{end}}
185
+
186
+
{{define "genericNotification"}}
187
+
<a
188
+
href="#"
189
+
class="block no-underline hover:no-underline text-inherit -m-3 p-3"
190
+
>
191
+
<div class="flex items-center justify-between">
192
+
<div class="flex items-center gap-2 min-w-0 flex-1">
193
+
<span class="{{if not .Read}}text-blue-600 dark:text-blue-400{{else}}text-gray-500 dark:text-gray-400{{end}}">
194
+
{{ i "bell" "w-4 h-4" }}
195
+
</span>
196
+
197
+
<div class="min-w-0 flex-1">
198
+
<div class="flex items-center gap-1 text-gray-900 dark:text-white">
199
+
<span>New notification</span>
200
+
{{if not .Read}}
201
+
<div class="w-2 h-2 bg-blue-500 rounded-full flex-shrink-0 ml-1"></div>
202
+
{{end}}
203
+
</div>
204
+
</div>
205
+
</div>
206
+
207
+
<div class="text-xs text-gray-500 dark:text-gray-400 flex-shrink-0 ml-2">
208
+
{{ template "repo/fragments/time" .Created }}
209
+
</div>
210
+
</div>
211
+
</a>
212
+
{{end}}
+46
appview/pages/templates/notifications/list.html
+46
appview/pages/templates/notifications/list.html
···
1
+
{{ define "title" }}notifications{{ end }}
2
+
3
+
{{ define "content" }}
4
+
<div class="p-6">
5
+
<div class="flex items-center justify-between mb-4">
6
+
<p class="text-xl font-bold dark:text-white">Notifications</p>
7
+
<a href="/settings/notifications" class="flex items-center gap-2">
8
+
{{ i "settings" "w-4 h-4" }}
9
+
preferences
10
+
</a>
11
+
</div>
12
+
</div>
13
+
14
+
<div class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
15
+
{{if .Notifications}}
16
+
<div class="flex flex-col gap-4" id="notifications-list">
17
+
{{range .Notifications}}
18
+
{{template "notifications/fragments/item" .}}
19
+
{{end}}
20
+
</div>
21
+
22
+
{{if .HasMore}}
23
+
<div class="mt-6 text-center">
24
+
<button
25
+
class="btn gap-2 group"
26
+
hx-get="/notifications?offset={{.NextOffset}}&limit={{.Limit}}"
27
+
hx-target="#notifications-list"
28
+
hx-swap="beforeend"
29
+
>
30
+
{{ i "chevron-down" "w-4 h-4 group-[.htmx-request]:hidden" }}
31
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
32
+
Load more
33
+
</button>
34
+
</div>
35
+
{{end}}
36
+
{{else}}
37
+
<div class="text-center py-12">
38
+
<div class="w-16 h-16 mx-auto mb-4 text-gray-300 dark:text-gray-600">
39
+
{{ i "bell-off" "w-16 h-16" }}
40
+
</div>
41
+
<h3 class="text-lg font-medium text-gray-900 dark:text-white mb-2">No notifications</h3>
42
+
<p class="text-gray-600 dark:text-gray-400">When you receive notifications, they'll appear here.</p>
43
+
</div>
44
+
{{end}}
45
+
</div>
46
+
{{ end }}
+1
-1
appview/pages/templates/strings/timeline.html
+1
-1
appview/pages/templates/strings/timeline.html
···
44
44
{{ $stat := .Stats }}
45
45
{{ $resolved := resolve .Did.String }}
46
46
<div class="text-gray-400 pt-4 text-sm font-mono inline-flex items-center gap-2 mt-auto">
47
-
<a href="/strings/{{ $resolved }}" class="flex items-center">
47
+
<a href="/strings/{{ $resolved }}" class="flex items-center gap-1">
48
48
{{ template "user/fragments/picHandle" $resolved }}
49
49
</a>
50
50
<span class="select-none [&:before]:content-['·']"></span>
+1
-1
appview/pages/templates/user/fragments/picHandle.html
+1
-1
appview/pages/templates/user/fragments/picHandle.html
+1
-1
appview/pages/templates/user/fragments/picHandleLink.html
+1
-1
appview/pages/templates/user/fragments/picHandleLink.html
+173
appview/pages/templates/user/settings/notifications.html
+173
appview/pages/templates/user/settings/notifications.html
···
1
+
{{ define "title" }}{{ .Tab }} settings{{ end }}
2
+
3
+
{{ define "content" }}
4
+
<div class="p-6">
5
+
<p class="text-xl font-bold dark:text-white">Settings</p>
6
+
</div>
7
+
<div class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white">
8
+
<section class="w-full grid grid-cols-1 md:grid-cols-4 gap-6">
9
+
<div class="col-span-1">
10
+
{{ template "user/settings/fragments/sidebar" . }}
11
+
</div>
12
+
<div class="col-span-1 md:col-span-3 flex flex-col gap-6">
13
+
{{ template "notificationSettings" . }}
14
+
</div>
15
+
</section>
16
+
</div>
17
+
{{ end }}
18
+
19
+
{{ define "notificationSettings" }}
20
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 items-center">
21
+
<div class="col-span-1 md:col-span-2">
22
+
<h2 class="text-sm pb-2 uppercase font-bold">Notification Preferences</h2>
23
+
<p class="text-gray-500 dark:text-gray-400">
24
+
Choose which notifications you want to receive when activity happens on your repositories and profile.
25
+
</p>
26
+
</div>
27
+
</div>
28
+
29
+
<form hx-put="/settings/notifications" hx-swap="none" class="flex flex-col gap-6">
30
+
31
+
<div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 w-full">
32
+
<div class="flex items-center justify-between p-2">
33
+
<div class="flex items-center gap-2">
34
+
<div class="flex flex-col gap-1">
35
+
<span class="font-bold">Repository starred</span>
36
+
<div class="flex text-sm items-center gap-1 text-gray-500 dark:text-gray-400">
37
+
<span>When someone stars your repository.</span>
38
+
</div>
39
+
</div>
40
+
</div>
41
+
<label class="flex items-center gap-2">
42
+
<input type="checkbox" name="repo_starred" {{if .Preferences.RepoStarred}}checked{{end}}>
43
+
</label>
44
+
</div>
45
+
46
+
<div class="flex items-center justify-between p-2">
47
+
<div class="flex items-center gap-2">
48
+
<div class="flex flex-col gap-1">
49
+
<span class="font-bold">New issues</span>
50
+
<div class="flex text-sm items-center gap-1 text-gray-500 dark:text-gray-400">
51
+
<span>When someone creates an issue on your repository.</span>
52
+
</div>
53
+
</div>
54
+
</div>
55
+
<label class="flex items-center gap-2">
56
+
<input type="checkbox" name="issue_created" {{if .Preferences.IssueCreated}}checked{{end}}>
57
+
</label>
58
+
</div>
59
+
60
+
<div class="flex items-center justify-between p-2">
61
+
<div class="flex items-center gap-2">
62
+
<div class="flex flex-col gap-1">
63
+
<span class="font-bold">Issue comments</span>
64
+
<div class="flex text-sm items-center gap-1 text-gray-500 dark:text-gray-400">
65
+
<span>When someone comments on an issue you're involved with.</span>
66
+
</div>
67
+
</div>
68
+
</div>
69
+
<label class="flex items-center gap-2">
70
+
<input type="checkbox" name="issue_commented" {{if .Preferences.IssueCommented}}checked{{end}}>
71
+
</label>
72
+
</div>
73
+
74
+
<div class="flex items-center justify-between p-2">
75
+
<div class="flex items-center gap-2">
76
+
<div class="flex flex-col gap-1">
77
+
<span class="font-bold">Issue closed</span>
78
+
<div class="flex text-sm items-center gap-1 text-gray-500 dark:text-gray-400">
79
+
<span>When an issue on your repository is closed.</span>
80
+
</div>
81
+
</div>
82
+
</div>
83
+
<label class="flex items-center gap-2">
84
+
<input type="checkbox" name="issue_closed" {{if .Preferences.IssueClosed}}checked{{end}}>
85
+
</label>
86
+
</div>
87
+
88
+
<div class="flex items-center justify-between p-2">
89
+
<div class="flex items-center gap-2">
90
+
<div class="flex flex-col gap-1">
91
+
<span class="font-bold">New pull requests</span>
92
+
<div class="flex text-sm items-center gap-1 text-gray-500 dark:text-gray-400">
93
+
<span>When someone creates a pull request on your repository.</span>
94
+
</div>
95
+
</div>
96
+
</div>
97
+
<label class="flex items-center gap-2">
98
+
<input type="checkbox" name="pull_created" {{if .Preferences.PullCreated}}checked{{end}}>
99
+
</label>
100
+
</div>
101
+
102
+
<div class="flex items-center justify-between p-2">
103
+
<div class="flex items-center gap-2">
104
+
<div class="flex flex-col gap-1">
105
+
<span class="font-bold">Pull request comments</span>
106
+
<div class="flex text-sm items-center gap-1 text-gray-500 dark:text-gray-400">
107
+
<span>When someone comments on a pull request you're involved with.</span>
108
+
</div>
109
+
</div>
110
+
</div>
111
+
<label class="flex items-center gap-2">
112
+
<input type="checkbox" name="pull_commented" {{if .Preferences.PullCommented}}checked{{end}}>
113
+
</label>
114
+
</div>
115
+
116
+
<div class="flex items-center justify-between p-2">
117
+
<div class="flex items-center gap-2">
118
+
<div class="flex flex-col gap-1">
119
+
<span class="font-bold">Pull request merged</span>
120
+
<div class="flex text-sm items-center gap-1 text-gray-500 dark:text-gray-400">
121
+
<span>When your pull request is merged.</span>
122
+
</div>
123
+
</div>
124
+
</div>
125
+
<label class="flex items-center gap-2">
126
+
<input type="checkbox" name="pull_merged" {{if .Preferences.PullMerged}}checked{{end}}>
127
+
</label>
128
+
</div>
129
+
130
+
<div class="flex items-center justify-between p-2">
131
+
<div class="flex items-center gap-2">
132
+
<div class="flex flex-col gap-1">
133
+
<span class="font-bold">New followers</span>
134
+
<div class="flex text-sm items-center gap-1 text-gray-500 dark:text-gray-400">
135
+
<span>When someone follows you.</span>
136
+
</div>
137
+
</div>
138
+
</div>
139
+
<label class="flex items-center gap-2">
140
+
<input type="checkbox" name="followed" {{if .Preferences.Followed}}checked{{end}}>
141
+
</label>
142
+
</div>
143
+
144
+
<div class="flex items-center justify-between p-2">
145
+
<div class="flex items-center gap-2">
146
+
<div class="flex flex-col gap-1">
147
+
<span class="font-bold">Email notifications</span>
148
+
<div class="flex text-sm items-center gap-1 text-gray-500 dark:text-gray-400">
149
+
<span>Receive notifications via email in addition to in-app notifications.</span>
150
+
</div>
151
+
</div>
152
+
</div>
153
+
<label class="flex items-center gap-2">
154
+
<input type="checkbox" name="email_notifications" {{if .Preferences.EmailNotifications}}checked{{end}}>
155
+
</label>
156
+
</div>
157
+
</div>
158
+
159
+
<div class="flex justify-end pt-2">
160
+
<button
161
+
type="submit"
162
+
class="btn-create flex items-center gap-2 group"
163
+
>
164
+
{{ i "save" "w-4 h-4" }}
165
+
save
166
+
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
167
+
</button>
168
+
</div>
169
+
<div id="settings-notifications-success"></div>
170
+
171
+
<div id="settings-notifications-error" class="error"></div>
172
+
</form>
173
+
{{ end }}