Шаблон Microsoft Power Automate
Отправка уведомления при получении ответов Microsoft Forms
By Сообщество Microsoft Power Automate
Отправка push-уведомления при каждом получении ответа в Microsoft Forms.
Работайте меньше, достигайте большего
Объедините свои любимые приложения, чтобы автоматизировать повторяющиеся задачи.
Узнайте, как это работает
Посмотрите короткое видео о Microsoft Power Automate.
Узнайте, как легко создавать потоки любой сложности.
Другие шаблоны
![]()
Запись ответов для формы в SharePoint
By Microsoft Power Automate Community
![]()
Send an email to responder when response submitted in Microsoft Forms
By Microsoft Flow Community
![]()
Обработка формы с использованием электронной почты и SharePoint
![]()
Отправка ответов формы на утверждение
By Microsoft Power Automate Community
Начало работы
Power Platform
Обзор
Загрузки
Обучение
- Свяжитесь с нами
- Торговые знаки
- Конфиденциальность и файлы cookie
- Управление файлами cookie
- Условия использования
- Условия
- русский
- العربية
- български
- català
- čeština
- dansk
- Deutsch (Österreich)
- Deutsch (Schweiz)
- Deutsch (Deutschland)
- Ελληνικά
- English (Australia)
- English (Canada)
- English (Cyprus)
- English (UK)
- English (Ireland)
- English (India)
- English (Malaysia)
- English (New Zealand)
- English (Singapore)
- English (US)
- English (South Africa)
- español (España)
- español (México)
- eesti (Eesti)
- euskara (euskara)
- suomi
- français (Belgique)
- français (Canada)
- français (Suisse)
- français (France)
- galego
- עברית
- हिन्दी
- hrvatski
- magyar
- Indonesia
- italiano (Svizzera)
- italiano (Italia)
- 日本語
- 한국어
- қазақ тілі
- lietuvių
- latviešu
- Melayu
- norsk bokmål
- Nederlands (België)
- Nederlands (Nederland)
- polski
- português (Brasil)
- português (Portugal)
- română
- русский
- slovenčina
- slovenščina
- српски (Србија)
- srpski (Srbija)
- svenska
- ไทย
- Türkçe
- українська
- Tiếng Việt
- 中文(简体)
- 中文(繁體)
Web PUSH Notifications быстро и просто
Добрый день. В этой небольшой заметке я хочу рассказать как быстро и просто настроить push-уведомления на вашем сайте. Эта статья ни в коем случае не претендует на звание исчерпывающего руководства, но, я надеюсь, что она даст точку старта для дальнейшего изучения.
Информации по этой теме в интернете полно, но она фрагментирована, разбросана по разным ресурсам и перемешена с уведомлениями для мобильных устройств с примерами на Java, C++ и Python. Нас же, как веб-разработчиков, интересует JavaScript. В этой статье я постараюсь саккумулировать всю необходимую и полезную информацию.

Я думаю, вы уже знаете что такое push-уведомления, но я всё же напишу коротко о главном.
Пользователь, заходя на сайт, вытягивает (pull) с него данные. Это удобно и безопасно, но с развитием интернет ресурсов, появилась необходимость оперативно доставлять информацию пользователям не дожидаясь пока те сами сделают запрос. Так и появилась технология принудительной доставки (push) данных с сервера клиенту.
Push-уведомления работают только если у вас на сайте есть HTTPS.
Без валидного SSL сертификата запустить не получится. Так что если у вас еще нет поддержки HTTPS, то пришло время её сделать. Рекомендую воспользоваться Let’s Encrypt.
Для запуска на localhost нужно прибегать к хитростям. Я же тестировал скрипты на Github Pages.Оглавление
- Хорошие уведомления
- Теория
- Что же происходит на стороне клиента?
- Сложности на серверной стороне
- Приступаем к написанию клиента
- Отправка уведомлений с сервера
- Проект на GitHub Pages
Хорошие уведомления
Сразу хочу оговориться, что push-уведомления не для рекламных рассылок. Отправлять нужно только то, что действительно нужно конкретному пользователю и на что он действительно должен оперативно отреагировать.
- Отправка уведомления об изменении статуса обращения пользователя в службу техподдержки;
- Отправка уведомления об изменении статуса заказа;
- Появление на складе товара, который ждал пользователь;
- Ответили на комментарий пользователя к статье;
- Новая задача в багтрекере со статусом Bug или Critical.
- Новые поступления на склад;
- Скидки и акции на товары;
- Новая статья на сайте;
- Ответили на комментарий пользователя к статье, который он написал год назад.
Плохие примеры тоже требуют уведомления, но на них не нужно реагировать оперативно. Эти уведомления можно отправить на почту. Вообще, все важные уведомления рекомендуется дублировать на почту, так-как push-уведомления могут не дойти до пользователя по разным, не зависящих от вас, причинам. Также важным фактором является актуальность события. Об этом я еще поговорю чуть позже. Рекомендую к прочтению:
- Хорошие уведомления по мнению Google
- Рекламная статья от PushAll
Вернемся к нашим баранам. Так как же всё это работает? Для начала немного теории.
Теория
Среди непосвященных бытует мнение что push-уведомления это простая технология, не требующая для реализации особых ресурсов. В действительности же это целый пул технологий.
Для начала небольшая схема того как все это работает (анимированная схема):

- Сервер отдает страницу пользователю;
- Клиент подключается к серверу сообщений, регистрируется и получает ID;
- Клиент отправляет полученный ID на сервер и сервер привязывает конкретного пользователя к конкретному устройству используя ID устройства;
- Сервер отправляет сообщение клиенту через сервер сообщений используя полученный ранее ID.
К сожалению, мне не удалось выяснить кто и как создает ID устройства и как сервер сообщений привязывается к конкретному устройству. Я использовал сервер сообщений Firebase Cloud Messaging от Google и его библиотеку. К сожалению, я не смог выяснить можно ли его заменить на свой сервер и как это сделать.
Изначально для отправки сообщений использовали:
Cloud to Device MessagingПотом его заменили на:
Google Cloud MessagingА потом еще раз поменяли на:
Firebase Cloud MessagingИнтересно, что дальше.
Что же происходит на стороне клиента?
- JavaScript запрашивает у пользователя разрешение на показ уведомлений;
- Если пользователь одобрил, то подключаемся к серверу сообщений и получаем ID устройства;
- Отправляем идентификатор на наш сервер, чтобы мы идентифицировали пользователя;
- Инициализируем JavaScript воркер который будет работать в фоне, получать сообщения от сервера сообщений и показывать их пользователю;
- Подключаемся к серверу сообщений и ждем новых поступлений.

Google рекомендует использовать переключатель для подписки и отписки от уведомлений. Таким образом, инициация процедуры подписки на уведомления исходит от пользователя, а не от сайта.
Принудительно подписывать на уведомления каждого приходящего пользователя, это плохая практика. Не делайте так.Это все выглядит очень сложно, но на сервере все не проще.
Сложности на серверной стороне
- Понятно, что идентификатор устройства, присылаемый пользователем, мы сохраняем в базу данных;
- Идентификатор устройства хорошо бы привязывать к пользователю, чтобы отправлять персонализированные сообщения;
- Стоит помнить, что пользователь у нас один, а устройств у него может быть несколько, также одним устройством могут пользоваться несколько пользователей;
- Отправка уведомлений пользователям не самая дешевая операция и поэтому событие, инициирующее отправку уведомления, нужно ставить в очередь на отправку;
- Только маленькие проекты с малым числом получателей могут позволить себе отправлять уведомления по событию, в течении того-же HTTP запроса;
- Так у нас появляется система очередей на RabbitMQ, Redis и т.д.;
- Появляются демоны/воркеры которые разбирают очередь и другие инструменты поддержки очередей;
- Для увеличения скорости отправки можно распараллелить процесс и разнести его на несколько нод.
Практика
Наконец-то, мы перешли к самому главному. Как я уже говорил ранее, в качестве сервера сообщений мы будем использовать Firebase Cloud Messaging, поэтому мы начинаем с регистрации и создания проекта на Firebase.
- Заходим на сайт;
- Регистрируемся;
- Жмём кнопку Create new project или Import Google project, если у вас уже есть проект;
- При создании указываем название проекта и страну;
- После создания проекта попадаем на его dashboard;
- В меню наводим на колесико рядом с Overview и выбираем Project settings;
- На открывшейся странице переходим во вкладку Cloud Messaging;
- Нас интересует Server key, который будет использоваться для отправки сообщений с сервера и Sender ID который будет использоваться для получения сообщений на стороне клиента.
Можно еще покопаться в настройках и поиграться с разделением прав доступа, но, в общем-то, работа с сайтом Firebase закончена.
Приступаем к написанию клиента
Начнем с того что создадим Service Worker для получения push-уведомлений.
Создаем файл firebase-messaging-sw.js с следующим содержимым.// firebase-messaging-sw.js importScripts('https://www.gstatic.com/firebasejs/3.6.8/firebase-app.js'); importScripts('https://www.gstatic.com/firebasejs/3.6.8/firebase-messaging.js'); firebase.initializeApp(< messagingSenderId: '' >); const messaging = firebase.messaging();- — это Sender ID который мы получили после регистрации в Firebase.
Файл Service Worker-а должен называться именно firebase-messaging-sw.js и обязательно должен находиться в корне проекта, то есть доступен по адресу https://example.com/firebase-messaging-sw.js. Путь к этому файлу жестко прописан в библиотеке Firebase.
Написанного кода достаточно для того чтобы показывать уведомления. О дополнительных возможностях поговорим чуть позже. Теперь добавим библиотеку Firebase и скрипт подписки в наш шаблон страницы.
Добавляем на страницу кнопку для подписки на уведомления
Подписка на уведомления
// firebase_subscribe.js firebase.initializeApp(< messagingSenderId: '' >); // браузер поддерживает уведомления // вообще, эту проверку должна делать библиотека Firebase, но она этого не делает if ('Notification' in window) < var messaging = firebase.messaging(); // пользователь уже разрешил получение уведомлений // подписываем на уведомления если ещё не подписали if (Notification.permission === 'granted') < subscribe(); >// по клику, запрашиваем у пользователя разрешение на уведомления // и подписываем его $('#subscribe').on('click', function () < subscribe(); >); > function subscribe() < // запрашиваем разрешение на получение уведомлений messaging.requestPermission() .then(function () < // получаем ID устройства messaging.getToken() .then(function (currentToken) < console.log(currentToken); if (currentToken) < sendTokenToServer(currentToken); >else < console.warn('Не удалось получить токен.'); setTokenSentToServer(false); >>) .catch(function (err) < console.warn('При получении токена произошла ошибка.', err); setTokenSentToServer(false); >); >) .catch(function (err) < console.warn('Не удалось получить разрешение на показ уведомлений.', err); >); > // отправка ID на сервер function sendTokenToServer(currentToken) < if (!isTokenSentToServer(currentToken)) < console.log('Отправка токена на сервер. '); var url = ''; // адрес скрипта на сервере который сохраняет ID устройства $.post(url, < token: currentToken >); setTokenSentToServer(currentToken); > else < console.log('Токен уже отправлен на сервер.'); >> // используем localStorage для отметки того, // что пользователь уже подписался на уведомления function isTokenSentToServer(currentToken) < return window.localStorage.getItem('sentFirebaseMessagingToken') == currentToken; >function setTokenSentToServer(currentToken)Вот и все. Это весь код который требуется для получения push-уведомлений.
Отправка уведомлений с сервера
В общем виде отправка уведомления выглядит так:
POST /fcm/send HTTP/1.1 Host: fcm.googleapis.com Authorization: key=YOUR-SERVER-KEY Content-Type: application/json < "notification": < "title": "Ералаш", "body": "Начало в 21:00", "icon": "https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=40&height=40", "click_action": "http://eralash.ru/" >, "to": "YOUR-TOKEN-ID" >- YOUR-SERVER-KEY — это Server key который мы получили при регистрации в Firebase;
- YOUR-TOKEN-ID — это ID устройства конкретного пользователя.
Все поля по порядку:
- notification — параметры уведомления;
- title — заголовок уведомления. Лимит 30 символов;
- body — текст уведомление. Лимит 120 символов;
- icon — иконка уведомления. Есть некоторые стандарты размеров иконок, но я использую 192×192. Иконки меньшего размера плохо смотрятся на мобильных устройствах;
- click_action — URL адрес страницы на которую перейдет пользователь кликнув по уведомлению;
- to — ID устройства получателя уведомления;
- Полный список параметров здесь.

Это пример отправки одного уведомления одному получателю. Можно отправить одно уведомление сразу нескольким получателям. Вплоть до 1000 получателей за раз.
< "notification": < "title": "Ералаш", "body": "Начало в 21:00", "icon": "https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=192&height=192", "click_action": "http://eralash.ru/" >, "registration_ids": [ "YOUR-TOKEN-ID-1", "YOUR-TOKEN-ID-2" "YOUR-TOKEN-ID-3" ] >Пример ответов от сервера сообщений:
Отправка уведомления в Chrome
Отправка уведомления в FireFox
Ошибка отправки уведомленияМы не привязаны к какому-то конкретному языку программирования и для простоты примера будем использовать PHP с расширением cURL. Скрипт отправки уведомления нужно запускать из консоли.
#!/usr/bin/env php $YOUR_TOKEN_ID, 'notification' => [ 'title' => 'Ералаш', 'body' => sprintf('Начало в %s.', date('H:i')), 'icon' => 'https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=192&height=192', 'click_action' => 'http://eralash.ru/', ], ]; $fields = json_encode($request_body); $request_headers = [ 'Content-Type: application/json', 'Authorization: key=' . $YOUR_API_KEY, ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers); curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $response = curl_exec($ch); curl_close($ch); echo $response;messaging.onMessage
Обработчик messaging.onMessage стоит отдельного упоминания, так как он относится как раз к категории подводных камней. В примерах от Firebase я не видел примера использование этого обработчика. О нем мне рассказал FluorescentHallucinogen, за что ему отдельное спасибо, но он не упомянул о некоторых особенностях его использования.
Что же это за обработчик и как он работает. Из документации мы знаем, что этот обработчик вызывается если мы получаем push-уведомление и находимся в этот момент на странице сайта с которого отправлено уведомление (желающие использовать нативное решение могут посмотреть пример реализации). Эта функциональность очень полезна тем, что мы можем отобразить уведомление на странице сделав красивую модалку или еще что-то. У меня такой необходимости нет, потому я просто отображу стандартное уведомление.
if ('Notification' in window) < var messaging = firebase.messaging(); messaging.onMessage(function(payload) < console.log('Message received. ', payload); new Notification(payload.notification.title, payload.notification); >); // . > // .Вроде все просто, но есть подводный камень. Дело все в том что на мобильных устройствах запрещено использовать конструктор Notification. И для решения этой проблемы нужно использовать ServiceWorkerRegistration.showNotification() и обработчик в этом случае будет иметь виде:
// . messaging.onMessage(function(payload) < console.log('Message received. ', payload); // регистрируем пустой ServiceWorker каждый раз navigator.serviceWorker.register('messaging-sw.js'); // запрашиваем права на показ уведомлений если еще не получили их Notification.requestPermission(function(result) < if (result === 'granted') < navigator.serviceWorker.ready.then(function(registration) < // теперь мы можем показать уведомление return registration.showNotification(payload.notification.title, payload.notification); >).catch(function(error) < console.log('ServiceWorker registration failed', error); >); > >); >); // .Теперь уведомления работают и на мобильных устройствах. Казалось бы уже все, но нет. Не смотря на заверения некоторых, ServiceWorker не должен быть пустым. Мы же хотим, что бы по клику пользователь переходил на нужную нам страницу. Для этого нам нужно добавить обработчик клика по уведомлению в ServiceWorker.
Сохраняем параметры уведомления для доступа свойству click_action в ServiceWorker-е.
// . navigator.serviceWorker.ready.then(function(registration) < payload.notification.data = payload.notification; // параметры уведомления registration.showNotification(payload.notification.title, payload.notification); >).catch(function(error) < console.log('ServiceWorker registration failed', error); >); // .Обрабатываем клик по уведомлению в ServiceWorker-е.
// messaging-sw.js self.addEventListener('notificationclick', function(event) < const target = event.notification.data.click_action || '/'; event.notification.close(); // этот код должен проверять список открытых вкладок и переключатся на открытую // вкладку с ссылкой если такая есть, иначе открывает новую вкладку event.waitUntil(clients.matchAll(< type: 'window', includeUncontrolled: true >).then(function(clientList) < // clientList почему-то всегда пуст!? for (var i = 0; i < clientList.length; i++) < var client = clientList[i]; if (client.url == target && 'focus' in client) < return client.focus(); >> // Открываем новое окно return clients.openWindow(target); >)); >);TTL и дополнительный контроль над уведомлением
Важным свойством для уведомления может является время его актуальности. Это зависит от ваших бизнес процессов. По умолчанию время жизни уведомлений 4 недели. Это очень много для уведомлений такого характера. Например, уведомление «Ваша любимая передача начинается через 15 минут» актуально в течении 15 минут. После этого сообщение уже не актуально и показываться не должно. За контроль над временем жизни отвечает свойство time_to_live со значением от 0 до 2419200 секунд. Подробней читать в документации. Сообщение с указанным TTL будет иметь вид:
< "notification": < "title": "Ералаш", "body": "Начало через 15 минут", "icon": "https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=192&height=192", "click_action": "http://eralash.ru/" >, "time_to_live": 900, "to": "YOUR-TOKEN-ID" >Сообщение вида «Ваша любимая передача начинается через 15 минут» актуально в течении 15 минут, но уже через минуту после отправки оно станет не корректным. Потому что передача начнется не через 15 минут, а уже через 14. Контролировать такие ситуации нужно на стороне клиента.
Для этого мы поменяем отправляемое с сервера сообщение:
< "data": < "title": "Ералаш", "time": 1489006800, "icon": "https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=192&height=192", "click_action": "http://eralash.ru/" >, "time_to_live": 900, "to": "YOUR-TOKEN-ID" >Обратите внимание что поле notification поменялось на data . Теперь не будет вызываться обработчик по умолчанию Firebase и нам нужно самостоятельно сделать это. Добавим в конце файла firebase-messaging-sw.js следующие строки:
// регистрируем свой обработчик уведомлений messaging.setBackgroundMessageHandler(function(payload) < if (typeof payload.data.time != 'undefined') < var time = new Date(payload.data.time * 1000); var now = new Date(); if (time < now) < // истек срок годности уведомления return null; >var diff = Math.round((time.getTime() - now.getTime()) / 1000); // показываем реальное время в уведомлении // будет сгенерировано сообщение вида: "Начало через 14 минут, в 21:00" payload.data.body = 'Начало через ' + Math.round(diff / 60) + ' минут, в ' + time.getHours() + ':' + (time.getMinutes() > 9 ? time.getMinutes() : '0' + time.getMinutes()) ; > // Сохраяем data для получения пареметров в обработчике клика payload.data.data = payload.data; // Показываем уведомление return self.registration.showNotification(payload.data.title, payload.data); >); // свой обработчик клика по уведомлению self.addEventListener('notificationclick', function(event) < // извлекаем адрес перехода из параметров уведомления const target = event.notification.data.click_action || '/'; event.notification.close(); // этот код должен проверять список открытых вкладок и переключатся на открытую // вкладку с ссылкой если такая есть, иначе открывает новую вкладку event.waitUntil(clients.matchAll(< type: 'window', includeUncontrolled: true >).then(function(clientList) < // clientList почему-то всегда пуст!? for (var i = 0; i < clientList.length; i++) < var client = clientList[i]; if (client.url == target && 'focus' in client) < return client.focus(); >> // Открываем новое окно return clients.openWindow(target); >)); >);Вот таким незамысловатым образом мы получили полный контроль над уведомлением. Что самое интересное, пользователю мы показываем время уведомления в его часовом поясе. Это актуально для сервисов который работают по всему миру или регионах с широким разбросом часовых поясов как у матушки-России.
Заключение
А теперь поговорим о грустном. Не смотря на все прелести технологии, у неё есть ряд недостатков:
- Самая главная проблема это, как всегда, поддержка в браузерах. Полноценная поддержка есть в Chrome, Firefox и Opera последних версий. IE, Safari, Opera Mini, UC Browser, Dolphin и прочая братия остаются за бортом. Но зато работает в мобильных версиях браузеров Chrome, Firefox и Opera.
- Открытый сайт и работающий Service Worker не гарантируют доставку сообщения. Хотя уведомления могут дойти и при закрытом браузере.
Библиотека Firebase скрывает в себе много тайн и её исследование могло бы дать ответы на некоторые вопросы, но это уже выходит за рамки этой статьи.
Поиграться
Проект на GitHub Pages
Так как для запуска Service Worker-а нужен HTTPS, то самым простым решением было разместить проект на GitHub Pages, что я и сделал.
Проект представляет из себя полноценное приложение для отправки и получения уведомлений. Для того что бы получить уведомление надо:
- Зайти на страницу;
- Нажать кнопку Register;
- Браузер запросит разрешение на показ уведомлений;
- Подтверждаем разрешение;
- На странице и в консоли браузера будет напечатан ID вашего устройства;
- Появится кнопка Delete Token для удаления существующего токена и повторной регистрации;
- Появится форма с параметрами уведомления которое можно отправить нажав на кнопку Send;
- Меняем параметры по усмотрению и получаем разные уведомления.
Можно отправить уведомление через любой инструмент для отправки HTTP запросов. Можно использовать сURL, я предпочитаю приложение Postman для Chrome.
Запрос такой же как и описанный ранее:
POST /fcm/send HTTP/1.1 Host: fcm.googleapis.com Authorization: key=AAAAaGQ_q2M:APA91bGCEOduj8HM6gP24w2LEnesqM2zkL_qx2PJUSBjjeGSdJhCrDoJf_WbT7wpQZrynHlESAoZ1VHX9Nro6W_tqpJ3Aw-A292SVe_4Ho7tJQCQxSezDCoJsnqXjoaouMYIwr34vZTs Content-Type: application/json < "data": < "title": "Ералаш", "body": "Начало в 21:00", "icon": "https://eralash.ru.rsz.io/sites/all/themes/eralash_v5/logo.png?width=192&height=192", "click_action": "http://eralash.ru/" >, "to": "YOUR-TOKEN-ID" >- YOUR-TOKEN-ID — это ID устройства который вы получили на странице приложения.
Вот и все. Получаем уведомление и радуемся жизни.
Ссылки
Спиок ссылок по теме
- Про PUSH
- Wikipedia о технологии PUSH
- Хорошие уведомления по мнению Google
- Рекламная статья от PushAll
- Web Push Book
- Web Push from ServiceWorker
- Поддержка в браузерах
- HTTPS на localhost
- Тестирование SSL сертификата
- Let’s Encrypt
- Статья по настройке Let’s Encrypt
- Подписка на уведомления
- Стратегия определения состояния для фложка подписки
- Видео-инструкция по настройке Firebase
- Notification
- ServiceWorker
- Использование Service Worker
- localStorage
- Promise
- Фокусирование на открытом окне по клику на уведомление
- Руководство
- Проект из документации
- Параметры сообщения
- Список кодов ошибок
- TTL
- Размер иконок
- Приложение Postman для Chrome
- Quickstart от Firebase
- Оригинал
- Мой форк
- На GitHub Pages
- Проект
- Исходники
- Проект
- Исходники
Updated at 2018-06-09
Обнаружились некоторые «особенности» в работе уведомлений.
Дубликаты уведомлений
Ко мне несколько раз обращались с вопросом: «Как исправить дублирующиеся уведомления?»
Проявляется эта проблема если открыть сайт отправляющий уведомления одновременно в нескольких вкладках. В этом случае Service Worker отправляет уведомление в обе вкладки и в обоих вкладках срабатывает метод messaging.onMessage. Наблюдать эту проблему можно на моем Demo проекте.
Что бы решить эту проблему, нужно в методе messaging.onMessage знать, что уведомление уже показывалось в другой вкладке. В качестве единого хранилища можно использовать localStorage , а идентифицировать уведомления по хеш сумме уведомления или присваивать уникальный id. Только стоит помнить, что localStorage не резиновый и id уже показанных уведомлений нужно подчищать через некоторое время.
Могу порекомендовать для этих целей библиотеку pamelafox/lscache.
Если у вас есть другой метод решения проблемы, напишите в комментариях.Картинки в уведомлениях
Сегодня ко мне обратился пользователь CTterorist, заметивший, что не отображаются картинки (image) в уведомлениях.

Немножко потестировав, мне удалось разобраться. Не смотря на то, что поле image отправляется в Firebase, вместе с другими параметрами уведомления, но обратно от Firebase поле image не приходит. Решается проблема очень просто. Можно отправлять картунку в поле data , а в обработчике показа уведомления вытягивать картинку из data и вставлять ее на место в уведомление.
То есть, если вы отправите сообщение в таком виде, то Firebase потеряет картинку.
< "notification": < "title": "Bubble Nebula", "body": "It's found today at 21:00", "icon": "https://peter-gribanov.github.io/serviceworker/Bubble-Nebula.jpg", "image": "https://peter-gribanov.github.io/serviceworker/Bubble-Nebula_big.jpg", "click_action": "https://www.nasa.gov/feature/goddard/2016/hubble-sees-a-star-inflating-a-giant-bubble" >, "to": "YOUR-TOKEN-ID" >Но если передать картинку в data , то она дойдет.
< "data": < "title": "Bubble Nebula", "body": "It's found today at 21:00", "icon": "https://peter-gribanov.github.io/serviceworker/Bubble-Nebula.jpg", "image": "https://peter-gribanov.github.io/serviceworker/Bubble-Nebula_big.jpg", "click_action": "https://www.nasa.gov/feature/goddard/2016/hubble-sees-a-star-inflating-a-giant-bubble" >, "to": "YOUR-TOKEN-ID" >Обработчики показа уведомления такие же как в примерах выше.
messaging.onMessage(function(payload) < console.log('Message received. ', payload); // регистрируем пустой ServiceWorker каждый раз navigator.serviceWorker.register('firebase-messaging-sw.js'); // запрашиваем права на показ уведомлений если еще не получили их Notification.requestPermission(function(result) < if (result === 'granted') < navigator.serviceWorker.ready.then(function(registration) < // своя логика как в примере с TTL и т.д. // копируем объект data payload.data.data = JSON.parse(JSON.stringify(payload.data)); registration.showNotification(payload.data.title, payload.data); >).catch(function(error) < console.log('ServiceWorker registration failed', error); >); > >); >);Аналогично в Service Worker ( firebase-messaging-sw.js )
messaging.setBackgroundMessageHandler(function(payload) < console.log('Handling background message', payload); // своя логика как в примере с TTL и т.д. // копируем объект data payload.data.data = JSON.parse(JSON.stringify(payload.data)); registration.showNotification(payload.data.title, payload.data); >);Saved searches
Use saved searches to filter your results more quickly
Cancel Create saved search
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
Ajax feedback form for Joomla! Works everywhere and suits to every Joomla! theme
License
Delo-Design/radicalform
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Switch branches/tags
Branches Tags
Could not load branches
Nothing to show
Could not load tags
Nothing to showName already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Cancel Create
- Local
- Codespaces
HTTPS GitHub CLI
Use Git or checkout with SVN using the web URL.
Work fast with our official CLI. Learn more about the CLI.Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
Latest commit message
Commit timeREADME.md
RadicalForm
Радикально новый подход к созданию форм обратной связи на основе чистого Javascript

Минимальная версия Joomla 3.7
Минимальная версия php 5.6
Поддерживаются браузеры: Internet Explorer 11 и все современные версии браузеров (включая Safari).
- Это бесплатный плагин, который таким и останется.
- Не требует для своей работы jQuery!
- Работает в любом месте сайта, нет никаких ограничений. (актуально для различных конструкторов сайтов, интернет магазинов и т.д.)
- Это аякс плагин.
- Прекрасно работает во всплывающих окнах. Есть возможность их закрывать после отправки формы.
- Можно удобно вставлять цели яндекс метрики в интерфейсе плагина.
- Количество форм обратной связи на странице не ограничено! (удобно для лендингов)
- Можно отправлять фото и другие файлы (контроль вложений есть).
- Полей для отправки вложений может быть несколько.
- Корректно работает с кешированием Joomla.
- Проверяется CSRF токен.
- Есть интеграция с мессенджером телеграм.
- Используется встроенная возможность джумлы делать многоязычные формы (для каждого языка свою)
- Есть функция логирования отправленных форм
- Есть функция выбора адресата для каждой формы
- Возможно использовать в качестве кнопки «Заказ в один клик» в интернет магазинах и других продающих страницах
- Есть возможность вставки в тему письма любого поля формы
- Предусмотрена валидация HTML5 полей формы
- Есть возможность изменения поля Reply To
- Есть возможность переопределения шаблона отправляемых писем
- Корректно работает с полями со множественными значениями (checkbox, select multiple)
- Есть интеграция с сервисом Jivosite
- Есть возможность расширения за счет своего кода
- Есть возможность экспортировать историю отправленных форм в CSV
- Есть возможность расширения с помощью плагинов Joomla
- Есть возможность загружать файлы на сервер и отправлять файлы в виде ссылок
Подробнее можно прочитать здесь
Если есть проблемы со скачиванием с github — резервная ссылка для скачивания:
A radically new approach to creating feedback forms
- This is a free plug-in that will remain so.
- You don’t need jQuery for this plugin!
- Works anywhere on the site, there are no restrictions. (relevant for various page builder, online stores, etc.)
- This is ajax plugin.
- Works great in pop-up windows. It is possible to close them after submitting the form.
- You can conveniently insert the yandex metrics in the plugin interface.
- The number of feedback forms on the page is unlimited! (convenient for landings)
- You can send photos and other files (there is control of attachments).
- There are several fields for sending attachments.
- Correctly works with Joomla caching.
- The CSRF token is checked.
- There is an integration with the messenger messaging.
- Using the built-in ability of Joomla to make multilingual forms (for each language its own)
- There is a function of logging sent forms
- There is a function for selecting a destination for each form
- It is possible to use the «One-Click Order» button in online stores and other selling pages
- There is a possibility of inserting in the subject of a letter of any form field
- HTML5 validation of form fields is provided
- You can change the Reply To field.
- There is a possibility to redefine the template of sent messages
- Correctly works with fields with multiple values (checkbox, select multiple)
- Added integration with the Jivosite service.
- You can add your custom code
- Export to CSV file
- There is a possibility of expansion using Joomla plug-ins
- It is possible to upload files to the server and send files as links
You can read more here
If there are problems with downloading from github — a backup link for download:
Вопросы с меткой [android-notification]
Android Notification – сообщение, которое может быть выведено на экран за пределами обычного пользовательского интерфейса приложения. Используется для уведомления пользователя о разных событиях.
121 вопрос
Конкурсные
Неотвеченные- Конкурсные 0
- Неотвеченные
- Цитируемые
- Рейтинг
- Неотвеченные (мои метки)
10 показов
Как сделать actionButton для уведомления которая будет удалять уведомления?
Всем привет, я делаю приложение заметки, где по назначенному времени приходит уведомление,в уведомлении есть кнопка завершить которая должна закрывать уведомление, уведомления создаются в .
- android
- android-notification
задан 14 окт в 22:17
39 показовНе работает NotificationCompat.Builder
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) < NotificationChannel notificationChannel = NotificationManagerCompat.getNotificationChannel("MyID"); .
задан 13 апр в 18:32
127 показовПочему не работает notification в Android на Kotlin?
Приложение запускается без ошибок, но при нажатии на кнопку — уведомление не появляется. В настройках телефона по умолчанию — показ уведомлений разрешен class MainActivity : AppCompatActivity() < .
задан 2 янв в 20:08
30 показовНе отображается Custom Notification
Если нотификация показана единственной в списке, то пропадает ее вид. Но как только появляется еще одна — сразу отображается как нужно. Как исправить? А вот так отображается если уже есть какие-то .
задан 13 дек 2022 в 15:21
27 показовВыполнение фоновой задачи по нажатию на уведомление android
Мне нужно, чтобы впн туннель выключался при нажатии на уведомление. Я нашел такой код, но не понимаю где писать код, выполняющий, собственно, действие. Если писать в notify_intent, он выполняется .
задан 28 ноя 2022 в 9:14
69 показовНе работают уведомления на Android 8 и выше
Я пытаюсь вывести самое простое тестовое уведомление в своем андроид приложении, но сталкиваюсь с тем что уведомление просто не выводится. Вот текст метода: public void notification(View view) < .
задан 9 авг 2022 в 13:54
40 показовНе показывается уведомление на Xiaomi, хотя на avd все работает
Я пытаюсь сделать плеер на андроид и работаю над уведомлением для него. На виртуальном pixel2 API30 уведомление отображается но на смартфоне xiaomi Redmi 9C c 10 андроидом уведомление не приходит. .
задан 26 июн 2022 в 14:28
Android: напоминание посетить приложение после длительного простоя [закрыт]
Довольно часто во всяких обучающих или игровых приложениях наблюдаю напоминалку (нотификацию) с призывами возобновить пользование. Стало интересно как подобное можно реализовать без сервера к примеру .
- android
- android-notification
задан 23 мая 2022 в 18:28
Как решить проблему: Attempt to invoke virtual method on a null object reference
Всем привет. Я тут решил в своё android-приложение календаря добавить уведомления (Notifications) по времени с помощью AlarmManager. Но у меня появилась проблема: при вызове функции notifyUser() по .
- java
- android
- android-notification
- android-alarm-manager
задан 9 янв 2022 в 9:13
153 показаКак реализовать уведомление в Android по времени?
У меня есть приложение с заметками. Я добавил туда уведомления (которые появляются в строке состояния). Для теста я сделал так, чтобы при нажатии на кнопку «Green» приложение не только .
задан 8 янв 2022 в 8:22
298 показовНе появляется Notification в Android 11 (sdk 30)
Notification работал отлично, появлялся (sdk 28, android 9). Решила попробовать на эмуляторе под 11 андроид, как следствие уведомления не появляются. private void createNotificationChannel()< .
задан 5 ноя 2021 в 18:14
Отправка уведомлений по дням недели
Нужно, чтобы приложение отправляло уведомление, к примеру, только по понедельникам в определенное время. Для этого лучше использовать AlarmManager или Notification или Push-notification или есть более .
- android
- android-notification
- android-alarm-manager
задан 29 авг 2021 в 13:44
76 показовНе могу понять, почему не отображаются уведомления моего приложения
Не могу понять в чем проблема, делал уведомления по видео, у него все работает, у меня нет. Я пытался делать уведомления и по другим видосам, код примерно один и тот же, но уведомления все равно никак .
задан 20 июл 2021 в 13:29
59 показовСоздается два экземпляра NotificationListenerService. Как их можно использовать в DependencyInjection?
Есть приложение со встроенным сервисом прослушки уведомлений. Т.к я использую prism, мне необходимо регистрировать этот сервис, который наследуется от моего интерфейса INotificationListenerService. .
задан 3 июн 2021 в 9:14
Рамки вокруг кастомного уведомления и фоновое изображение
В кастомном уведомлении отображаются рамки вокруг и если новое уведомление приходит, то мое уведомление по высоте сужается. Как можно исправить эти две ошибки? if (Build.VERSION.SDK_INT > Build.
- android
- android-notification