Skip to content

Commit cc752cf

Browse files
author
Philipp Heckel
committed
Screenshots
1 parent 4d48c5d commit cc752cf

10 files changed

+151
-2
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,4 @@ Third party libraries and resources:
183183
* [GoReleaser](https://goreleaser.com/) (MIT) is used to create releases
184184
* [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) (MIT) is used to provide the persistent message cache
185185
* [Firebase Admin SDK](https://github.com/firebase/firebase-admin-go) (Apache 2.0) is used to send FCM messages
186+
* [Lightbox with vanilla JS](https://yossiabramov.com/blog/vanilla-js-lightbox)

server/index.gohtml

+14-2
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,21 @@
4141
It allows you to send notifications <a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy">to your phone</a> or desktop via scripts from any computer,
4242
entirely <b>without signup or cost</b>. It's also <a href="https://github.com/binwiederhier/ntfy">open source</a> if you want to run your own.
4343
</p>
44+
45+
<div id="screenshots">
46+
<a href="static/img/screenshot-curl.png"><img src="static/img/screenshot-curl.png"/></a>
47+
<a href="static/img/screenshot-web-detail.png"><img src="static/img/screenshot-web-detail.png"/></a>
48+
<span class="nowrap">
49+
<a href="static/img/screenshot-phone-main.jpg"><img src="static/img/screenshot-phone-main.jpg"/></a>
50+
<a href="static/img/screenshot-phone-detail.jpg"><img src="static/img/screenshot-phone-detail.jpg"/></a>
51+
<a href="static/img/screenshot-phone-notification.jpg"><img src="static/img/screenshot-phone-notification.jpg"/></a>
52+
</span>
53+
</div>
54+
4455
<p>
45-
There are many ways to use ntfy. You can send yourself messages for all sorts of things: When a long process finishes or fails (a backup, a long rsync job, ...),
56+
There are many ways to use Ntfy. You can send yourself messages for all sorts of things: When a long process finishes or fails (a backup, a long rsync job, ...),
4657
or to notify yourself when somebody logs into your server(s). Or you may want to use it in your own app to distribute messages to subscribed clients.
47-
Endless possibilities 😀.
58+
Endless possibilities 😀. Be sure to check out the <a href="https://github.com/binwiederhier/ntfy/tree/main/examples">example on GitHub</a>!
4859
</p>
4960

5061
<h2>Publishing messages</h2>
@@ -239,6 +250,7 @@
239250
<div id="detailEventsList"></div>
240251
</div>
241252
</div>
253+
<div id="lightbox" class="lightbox"></div>
242254
<script src="static/js/app.js"></script>
243255
</body>
244256
</html>

server/static/css/app.css

+77
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,83 @@ code {
9595
color: #666;
9696
}
9797

98+
/* Screenshots */
99+
100+
#screenshots {
101+
text-align: center;
102+
}
103+
104+
#screenshots img {
105+
height: 190px;
106+
margin: 3px;
107+
border-radius: 5px;
108+
filter: drop-shadow(2px 2px 2px #ddd);
109+
}
110+
111+
#screenshots .nowrap {
112+
white-space: nowrap;
113+
}
114+
115+
/* Lightbox; thanks to https://yossiabramov.com/blog/vanilla-js-lightbox */
116+
117+
.lightbox {
118+
opacity: 0;
119+
visibility: hidden;
120+
position: fixed;
121+
left:0;
122+
right: 0;
123+
top: 0;
124+
bottom: 0;
125+
z-index: -1;
126+
display: flex;
127+
align-items: center;
128+
justify-content: center;
129+
transition: all 0.15s ease-in;
130+
}
131+
132+
.lightbox.show {
133+
background-color: rgba(0,0,0, 0.75);
134+
opacity: 1;
135+
visibility: visible;
136+
z-index: 1000;
137+
}
138+
139+
.lightbox img {
140+
max-width: 90%;
141+
max-height: 90%;
142+
filter: drop-shadow(5px 5px 10px #222);
143+
border-radius: 5px;
144+
}
145+
146+
.lightbox .close-lightbox {
147+
cursor: pointer;
148+
position: absolute;
149+
top: 30px;
150+
right: 30px;
151+
width: 20px;
152+
height: 20px;
153+
}
154+
155+
.lightbox .close-lightbox::after,
156+
.lightbox .close-lightbox::before {
157+
content: '';
158+
width: 3px;
159+
height: 20px;
160+
background-color: #ddd;
161+
position: absolute;
162+
border-radius: 5px;
163+
transform: rotate(45deg);
164+
}
165+
166+
.lightbox .close-lightbox::before {
167+
transform: rotate(-45deg);
168+
}
169+
170+
.lightbox .close-lightbox:hover::after,
171+
.lightbox .close-lightbox:hover::before {
172+
background-color: #fff;
173+
}
174+
98175
/* Subscribe box */
99176

100177
button {

server/static/img/screenshot-curl.png

253 KB
Loading
227 KB
Loading
225 KB
Loading
128 KB
Loading
Loading
113 KB
Loading

server/static/js/app.js

+59
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ const detailNoNotifications = document.getElementById("detailNoNotifications");
3232
const detailCloseButton = document.getElementById("detailCloseButton");
3333
const detailNotificationsDisallowed = document.getElementById("detailNotificationsDisallowed");
3434

35+
/* Screenshots */
36+
const lightbox = document.getElementById("lightbox");
37+
3538
const subscribe = (topic) => {
3639
if (Notification.permission !== "granted") {
3740
Notification.requestPermission().then((permission) => {
@@ -203,6 +206,54 @@ const showNotificationDeniedError = () => {
203206
showError("You have blocked desktop notifications for this website. Please unblock them and refresh to use the web-based desktop notifications.");
204207
};
205208

209+
const showScreenshotOverlay = (e, el, index) => {
210+
lightbox.classList.add('show');
211+
document.addEventListener('keydown', nextScreenshotKeyboardListener);
212+
return showScreenshot(e, index);
213+
};
214+
215+
const showScreenshot = (e, index) => {
216+
const actualIndex = resolveScreenshotIndex(index);
217+
lightbox.innerHTML = '<div class="close-lightbox"></div>' + screenshots[actualIndex].innerHTML;
218+
lightbox.querySelector('img').onclick = (e) => { return showScreenshot(e,actualIndex+1); };
219+
currentScreenshotIndex = actualIndex;
220+
e.stopPropagation();
221+
return false;
222+
};
223+
224+
const nextScreenshot = (e) => {
225+
return showScreenshot(e, currentScreenshotIndex+1);
226+
};
227+
228+
const previousScreenshot = (e) => {
229+
return showScreenshot(e, currentScreenshotIndex-1);
230+
};
231+
232+
const resolveScreenshotIndex = (index) => {
233+
if (index < 0) {
234+
return screenshots.length - 1;
235+
} else if (index > screenshots.length - 1) {
236+
return 0;
237+
}
238+
return index;
239+
};
240+
241+
const hideScreenshotOverlay = (e) => {
242+
lightbox.classList.remove('show');
243+
document.removeEventListener('keydown', nextScreenshotKeyboardListener);
244+
};
245+
246+
const nextScreenshotKeyboardListener = (e) => {
247+
switch (e.keyCode) {
248+
case 37:
249+
previousScreenshot(e);
250+
break;
251+
case 39:
252+
nextScreenshot(e);
253+
break;
254+
}
255+
};
256+
206257
// From: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
207258
async function* makeTextFileLineIterator(fileURL) {
208259
const utf8Decoder = new TextDecoder('utf-8');
@@ -248,6 +299,14 @@ detailCloseButton.onclick = () => {
248299
hideDetailView();
249300
};
250301

302+
let currentScreenshotIndex = 0;
303+
const screenshots = [...document.querySelectorAll("#screenshots a")];
304+
screenshots.forEach((el, index) => {
305+
el.onclick = (e) => { return showScreenshotOverlay(e, el, index); };
306+
});
307+
308+
lightbox.onclick = hideScreenshotOverlay;
309+
251310
// Disable Web UI if notifications of EventSource are not available
252311
if (!window["Notification"] || !window["EventSource"]) {
253312
showBrowserIncompatibleError();

0 commit comments

Comments
 (0)