Docs docs docs
|
@ -4,9 +4,9 @@ I love free software and I'm doing this because it's fun and to give back. I hav
|
|||
never monetize or sell your information. This service will always stay free and open.
|
||||
|
||||
Neither the server nor the app record any personal information, or share any of the messages and topics with
|
||||
any outside service. All data is exclusively used to make the service function properly. The one exception
|
||||
is the Firebase Cloud Messaging (FCM) service, which is required to provide instant Android notifications (see
|
||||
[FAQ](faq.md) for details).
|
||||
any outside service. All data is exclusively used to make the service function properly. The only external service
|
||||
I use is Firebase Cloud Messaging (FCM) service, which is required to provide instant Android notifications (see
|
||||
[FAQ](faq.md) for details). To avoid FCM altogether, download the F-Droid version.
|
||||
|
||||
The web server does not log or otherwise store request paths, remote IP addresses or even topics or messages,
|
||||
aside from a short on-disk cache to support service restarts.
|
||||
|
|
79
docs/static/css/extra.css
vendored
|
@ -1,3 +1,7 @@
|
|||
.md-header__button.md-logo :is(img, svg) {
|
||||
width: unset !important;
|
||||
}
|
||||
|
||||
article {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
@ -16,3 +20,78 @@ figure img {
|
|||
.remove-md-box td {
|
||||
padding: 0 10px
|
||||
}
|
||||
|
||||
/* Lightbox; thanks to https://yossiabramov.com/blog/vanilla-js-lightbox */
|
||||
|
||||
.screenshots {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.screenshots img {
|
||||
height: 230px;
|
||||
margin: 3px;
|
||||
border-radius: 5px;
|
||||
filter: drop-shadow(2px 2px 2px #ddd);
|
||||
}
|
||||
|
||||
.screenshots .nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.lightbox {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
position: fixed;
|
||||
left:0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.15s ease-in;
|
||||
}
|
||||
|
||||
.lightbox.show {
|
||||
background-color: rgba(0,0,0, 0.75);
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.lightbox img {
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
filter: drop-shadow(5px 5px 10px #222);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.lightbox .close-lightbox {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 30px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.lightbox .close-lightbox::after,
|
||||
.lightbox .close-lightbox::before {
|
||||
content: '';
|
||||
width: 3px;
|
||||
height: 20px;
|
||||
background-color: #ddd;
|
||||
position: absolute;
|
||||
border-radius: 5px;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.lightbox .close-lightbox::before {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.lightbox .close-lightbox:hover::after,
|
||||
.lightbox .close-lightbox:hover::before {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
|
BIN
docs/static/img/android-notification-settings.png
vendored
Normal file
After Width: | Height: | Size: 111 KiB |
BIN
docs/static/img/android-screenshot-add-instant.jpg
vendored
Normal file
After Width: | Height: | Size: 297 KiB |
BIN
docs/static/img/android-screenshot-add-other.jpg
vendored
Normal file
After Width: | Height: | Size: 300 KiB |
BIN
docs/static/img/android-screenshot-add.jpg
vendored
Normal file
After Width: | Height: | Size: 236 KiB |
BIN
docs/static/img/android-screenshot-detail.jpg
vendored
Normal file
After Width: | Height: | Size: 255 KiB |
BIN
docs/static/img/android-screenshot-main.jpg
vendored
Normal file
After Width: | Height: | Size: 149 KiB |
BIN
docs/static/img/android-screenshot-pause.jpg
vendored
Normal file
After Width: | Height: | Size: 212 KiB |
BIN
docs/static/img/android-video-overview.mp4
vendored
Normal file
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 253 KiB |
BIN
docs/static/img/screenshot-phone-add.jpg
vendored
Normal file
After Width: | Height: | Size: 227 KiB |
BIN
docs/static/img/screenshot-phone-detail.jpg
vendored
Normal file
After Width: | Height: | Size: 225 KiB |
BIN
docs/static/img/screenshot-phone-main.jpg
vendored
Normal file
After Width: | Height: | Size: 128 KiB |
BIN
docs/static/img/screenshot-phone-notification.jpg
vendored
Normal file
After Width: | Height: | Size: 224 KiB |
BIN
docs/static/img/screenshot-web.png
vendored
Before Width: | Height: | Size: 41 KiB |
BIN
docs/static/img/web-detail.png
vendored
Normal file
After Width: | Height: | Size: 116 KiB |
BIN
docs/static/img/web-notification.png
vendored
Normal file
After Width: | Height: | Size: 297 KiB |
BIN
docs/static/img/web-subscribe.png
vendored
Normal file
After Width: | Height: | Size: 31 KiB |
68
docs/static/js/extra.js
vendored
|
@ -29,3 +29,71 @@ for (const tab of tabs) {
|
|||
tab.checked = true
|
||||
}
|
||||
}
|
||||
|
||||
// Lightbox for screenshot
|
||||
|
||||
const lightbox = document.createElement('div');
|
||||
lightbox.classList.add('lightbox');
|
||||
document.body.appendChild(lightbox);
|
||||
|
||||
const showScreenshotOverlay = (e, el, group, index) => {
|
||||
lightbox.classList.add('show');
|
||||
document.addEventListener('keydown', nextScreenshotKeyboardListener);
|
||||
return showScreenshot(e, group, index);
|
||||
};
|
||||
|
||||
const showScreenshot = (e, group, index) => {
|
||||
const actualIndex = resolveScreenshotIndex(group, index);
|
||||
lightbox.innerHTML = '<div class="close-lightbox"></div>' + screenshots[group][actualIndex].innerHTML;
|
||||
lightbox.querySelector('img').onclick = (e) => { return showScreenshot(e, group, actualIndex+1); };
|
||||
currentScreenshotGroup = group;
|
||||
currentScreenshotIndex = actualIndex;
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
|
||||
const nextScreenshot = (e) => {
|
||||
return showScreenshot(e, currentScreenshotGroup, currentScreenshotIndex+1);
|
||||
};
|
||||
|
||||
const previousScreenshot = (e) => {
|
||||
return showScreenshot(e, currentScreenshotGroup, currentScreenshotIndex-1);
|
||||
};
|
||||
|
||||
const resolveScreenshotIndex = (group, index) => {
|
||||
if (index < 0) {
|
||||
return screenshots[group].length - 1;
|
||||
} else if (index > screenshots[group].length - 1) {
|
||||
return 0;
|
||||
}
|
||||
return index;
|
||||
};
|
||||
|
||||
const hideScreenshotOverlay = (e) => {
|
||||
lightbox.classList.remove('show');
|
||||
document.removeEventListener('keydown', nextScreenshotKeyboardListener);
|
||||
};
|
||||
|
||||
const nextScreenshotKeyboardListener = (e) => {
|
||||
switch (e.keyCode) {
|
||||
case 37:
|
||||
previousScreenshot(e);
|
||||
break;
|
||||
case 39:
|
||||
nextScreenshot(e);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
let currentScreenshotGroup = '';
|
||||
let currentScreenshotIndex = 0;
|
||||
let screenshots = {};
|
||||
Array.from(document.getElementsByClassName('screenshots')).forEach((sg) => {
|
||||
const group = sg.id;
|
||||
screenshots[group] = [...sg.querySelectorAll('a')];
|
||||
screenshots[group].forEach((el, index) => {
|
||||
el.onclick = (e) => { return showScreenshotOverlay(e, el, group, index); };
|
||||
});
|
||||
});
|
||||
|
||||
lightbox.onclick = hideScreenshotOverlay;
|
||||
|
|
|
@ -4,12 +4,51 @@ notifications directly on your phone. Just like the server, this app is also [op
|
|||
Since I don't have an iPhone or a Mac, I didn't make an iOS app yet. I'd be awesome if [someone else could help out](https://github.com/binwiederhier/ntfy/issues/4).
|
||||
|
||||
## Android
|
||||
<a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy"><img src="../../static/img/badge-googleplay.png"></a>
|
||||
<a href="https://f-droid.org/en/packages/io.heckel.ntfy/"><img src="../../static/img/badge-fdroid.png"></a>
|
||||
|
||||
You can get the Android app from both [Google Play](https://play.google.com/store/apps/details?id=io.heckel.ntfy) and
|
||||
from [F-Droid](https://f-droid.org/en/packages/io.heckel.ntfy/). Both are largely identical, with the one exception that
|
||||
the F-Droid flavor does not use Firebase.
|
||||
|
||||
<a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy"><img src="../../static/img/badge-googleplay.png"></a>
|
||||
<a href="https://f-droid.org/en/packages/io.heckel.ntfy/"><img src="../../static/img/badge-fdroid.png"></a>
|
||||
### Overview
|
||||
A picture is worth a thousand words. Here are a few screenshots showing what the app looks like. It's all pretty
|
||||
straight forward. You can add topics and as soon as you add them, you can [publish messages](../publish.md) to them.
|
||||
|
||||
<div id="android-screenshots" class="screenshots">
|
||||
<a href="../../static/img/android-screenshot-main.jpg"><img src="../../static/img/android-screenshot-main.jpg"/></a>
|
||||
<a href="../../static/img/android-screenshot-detail.jpg"><img src="../../static/img/android-screenshot-detail.jpg"/></a>
|
||||
<a href="../../static/img/android-screenshot-add.jpg"><img src="../../static/img/android-screenshot-add.jpg"/></a>
|
||||
<a href="../../static/img/android-screenshot-add-instant.jpg"><img src="../../static/img/android-screenshot-add-instant.jpg"/></a>
|
||||
<a href="../../static/img/android-screenshot-add-other.jpg"><img src="../../static/img/android-screenshot-add-other.jpg"/></a>
|
||||
</div>
|
||||
|
||||
If those screenshots are still not enough, here's a video:
|
||||
|
||||
<figure>
|
||||
<video controls muted autoplay loop width="650" src="../../static/img/overview.mp4"></video>
|
||||
<figcaption>Sending push notifications to your Android phone</figcaption>
|
||||
</figure>
|
||||
|
||||
### Message priority
|
||||
When you [publish messages](../publish.md#message-priority) to a topic, you can define a priority. This priority defines
|
||||
how urgently Android will notify you about the notification, and whether they make a sound and/or vibrate.
|
||||
|
||||
By default, messages with default priority or higher (>= 3) will vibrate and make a sound. Messages with high or urgent
|
||||
priority (>= 4) will also show as pop-over, like so:
|
||||
|
||||
<figure markdown>
|
||||
![priority notification](../static/img/priority-notification.png){ width=500 }
|
||||
<figcaption>High and urgent notifications show as pop-over</figcaption>
|
||||
</figure>
|
||||
|
||||
You can change these settings in Android by long-pressing on the app, and tapping "Notifications". You can then configure
|
||||
the settings (and custom sounds or vibration) for each of the priorities:
|
||||
|
||||
<figure markdown>
|
||||
![notification settings](../static/img/android-notification-settings.png){ width=500 }
|
||||
<figcaption>Per-priority sound/vibration settings</figcaption>
|
||||
</figure>
|
||||
|
||||
### Instant delivery
|
||||
Instant delivery is allows you to receive messages on your phone instantly, **even when your phone is in doze mode**, i.e.
|
||||
|
|
|
@ -3,9 +3,12 @@ You can use the Web UI to subscribe to topics as well. If you do, and you keep t
|
|||
pop up as desktop notifications**. Simply type in the topic name and click the *Subscribe* button. The browser will
|
||||
keep a connection open and listen for incoming notifications.
|
||||
|
||||
<figure markdown>
|
||||
![web subscribe](../static/img/screenshot-web.png){ width=300 }
|
||||
<figcaption>Subscribe via Web UI</figcaption>
|
||||
</figure>
|
||||
To learn how to send messages, check out the [publishing page](../publish.md).
|
||||
|
||||
<div id="web-screenshots" class="screenshots">
|
||||
<a href="../../static/img/web-subscribe.png"><img src="../../static/img/web-subscribe.png"/></a>
|
||||
<a href="../../static/img/web-notification.png"><img src="../../static/img/web-notification.png"/></a>
|
||||
<a href="../../static/img/web-detail.png"><img src="../../static/img/web-detail.png"/></a>
|
||||
</div>
|
||||
|
||||
|
||||
Once subscribed, you can [publish messages](../publish.md) via `curl` or from without any of your scripts.
|
||||
|
|
|
@ -33,7 +33,7 @@ theme:
|
|||
- search.highlight
|
||||
- search.share
|
||||
- navigation.sections
|
||||
- navigation.instant
|
||||
# - navigation.instant
|
||||
- toc.integrate
|
||||
- content.tabs.link
|
||||
extra:
|
||||
|
@ -67,6 +67,8 @@ markdown_extensions:
|
|||
|
||||
plugins:
|
||||
- search
|
||||
- minify:
|
||||
minify_html: true
|
||||
|
||||
nav:
|
||||
- "Getting started": index.md
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<meta property="og:type" content="website" />
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta property="og:site_name" content="ntfy.sh" />
|
||||
<meta property="og:title" content="ntfy.sh | send push notifications to your phone via simple PUT/POST requests" />
|
||||
<meta property="og:title" content="ntfy.sh | send push notifications to your phone or desktop via PUT/POST" />
|
||||
<meta property="og:description" content="ntfy is a simple HTTP-based pub-sub notification service. It allows you to send desktop notifications via scripts from any computer, entirely without signup or cost. Made with ❤ by Philipp C. Heckel, Apache License 2.0, source at https://heckel.io/ntfy." />
|
||||
<meta property="og:image" content="/static/img/ntfy.png" />
|
||||
<meta property="og:url" content="https://ntfy.sh" />
|
||||
|
@ -104,7 +104,7 @@
|
|||
<p id="error"></p>
|
||||
<p>
|
||||
Subscribe to topics here and receive messages as <b>desktop notification</b>. Topics are not password-protected,
|
||||
so choose a name that's not easy to guess. Once subscribed, you can publish messages via PUT/POST.
|
||||
so choose a name that's not easy to guess.
|
||||
</p>
|
||||
<form id="subscribeForm">
|
||||
<p>
|
||||
|
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 297 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 116 KiB |