Работа с уведомлениями с помощью потоков данных PubNub

Уведомления — отличный способ показать, что у приложения появилась новая информация, например, что вы получили сообщение в Твиттере.

Спецификация W3C Web Notifications API позволяет браузерам тоже создавать уведомления: это отличный способ привлечь внимание пользователя, ведь уведомления показываются даже если страница неактивна — однако надо иметь в виду, что она все же должна быть открыта в одной из фоновых вкладок, чтобы создать уведомление. W3C не оговаривает, как уведомления должны выглядеть, так что Opera решила использовать нативные уведомления, чтобы браузер казался полностью интегрированным в операционную систему.

Скриншот

Уведомления поддерживаются в Opera начиная с 25-й версии. Статья «Уведомления в 25 версии Opera для разработчиков» содержит базовые принципы использования их API.

Сегодня я покажу, как использовать уведомления, создав многопользовательское приложение c использованием JavaScript API PubNub для потоковой передачи данных в реальном времени.

Что такое сеть передачи данных PubNub?

PubNub это защищенная глобальная сеть потоковой передачи данных, которая позволяет разработчикам в реальном времени создавать, масштабировать и управлять функциональностью приложений и устройств в интернете вещей. (Признаюсь: я работаю в PubNub)

Схема Обобщенная парадигма обмена сообщениями на основе подписки и их публикации

Что мы напишем

Для этой статьи я разработала альтернативу приложения «Yo», которое позволяет отправлять друзьям сообщение «Yo». Мы напишем приложение «Oi».

Начнем!

Проверим поддерживается ли API

Первым шагом будет проверка поддержки браузером Web Notifications API. Проверка возможностей браузера это хорошая и, на сегодняшний день, необходимая практика, так как ещё не все браузеры этот API поддерживают.

Давайте будем просто заканчивать работу приложения, если браузер не поддерживает API, так как приложение без уведомлений станет полностью бесполезным. Когда вы создаете реальное приложение, естественно, стоит для удобства пользователя обеспечить его мягкую деградацию.

if (!window.Notification) {
  alert('Ой, браузер не поддерживает Web Notifications API!');
} else {
  // Вперед, используй Web Notification API.
}

Запрос разрешения

Каждый браузер, поддерживающий уведомления, имеет встроенный механизм запроса разрешения использования Web Notification API страницей, чтобы пользователь мог контролировать, сможет ли она отправлять ему уведомления. Когда страница загружается в первый раз, пользователь получает запрос на использование API страницей. После того, как пользователь дает такое разрешение, страница может отправлять ему уведомления, в противном случае (пользователь не дал разрешение) — нет.

Скриншот

Notification.requestPermission(function() {
  if (Notification.permission === 'granted') {
    // Теперь страница может отправлять пользователю уведомления!
  }
});

Попробуйте и все сами увидите. Всегда можно сбросить настройки разрешений, открыв opera://settings, выбрав раздел «Сайты» в левой колонке и прокрутив вниз до раздела уведомлений.

Скринкаст

Соединяем пользователей используя потоки данных PubNub

После того, как пользователь дал свое разрешение, он должен ввести свое имя, чтобы начать работу со страницей.

<input type="text" placeholder="Наберите имя, чтобы начать работу" autofocus>

Когда пользователь набирает имя и нажимает кнопку ввода (мы будем отлавливать событие keyup с кодом клавиши keyCode === 13), отправляем имя в поток PubNub, чтобы зарегистрировать пользователя.

document.querySelector('[type="text"]').addEventListener('keyup', function(event) {
  if (event.keyCode !== 13) return;
  if (!input.value) return;
  username = input.value;
  // Соединяемся с PubNub и регистрируем пользователя …
});

Инициализируем PubNub, используя реквизиты пользователя

Это потребует ввода вашего собственного ключа для PubNub API, так что придется создать бесплатную учетную запись. Кнопки опубликовать и подписаться находятся в панели управления разработчика.

Затем, подключите библиотеку PubNub в HTML.

<script src="https://cdn.pubnub.com/pubnub.min.js"></script>

Теперь, давайте инициализируем клиентское API PubNub с именем пользователя в качестве uuid (уникального идентификатора). А ещё, давайте создадим канал под названием «oi».

var channel = 'oi';
var pubnub = PUBNUB.init({
  subscribe_key: 'your_sub_key',
  publish_key: 'your_pub_key',
  uuid: username
});

Заполняем список пользователей с помощью API определяющего их присутствие

Теперь можно подписаться на канал сети PubNub, что бы создать TCP-сокет и начать принимать сообщения.

Кроме того, PubNub обеспечивает «определение присутствия», которое позволит проверить присутствует ли пользователь, например, когда он переходит в онлайн или офлайн. Это полезно для того, чтобы поддерживать список пользователей, подписанных на канал, в актуальном состоянии.

В этом примере мы обновляем в DOM список пользователей, которым можно послать «Oi», используя метод here_now API PubNub. Он вызывается каждый раз, когда пользователь приходит или покидает канал. (Разберемся с API подписки позже).

var updateList = function() {
  pubnub.here_now({
    channel: channel,
    callback: function(m) {
      // получаем актуальный список пользователей и обновляем DOM
    }
  });
};

Чтобы упростить статью и сфокусироваться на важном, я упускаю детали процесса определения присутствия, но вы всегда можете заглянуть в исходники и разобраться как оно работает!

Отправка сообщений

Когда пользователь кликает на имя в списке, приложение публикует сообщение. Функция publish() используется для его отправки всем подписчикам канала. Можно просто передать в качестве сообщения объект. В этом примере он содержит только атрибуты from и to, но может быть любым.

var list = document.querySelector('.list');
list.addEventListener('click', function(event) {
  if (!event.target.id) return;
  pubnub.publish({
    channel: channel,
    message: {
      from: username,
      to: event.target.id
    }
  });
});

В качестве сообщения можно передавать объект с любыми данными, которые захотите туда поместить. Так что можете изменить скрипт так, чтобы вместо отправляемого по умолчанию сообщения «Oi!» пользователи могли отправлять любые сообщения.

Получение сообщений

Когда кто-то отправляет пользователю сообщение, веб-приложение будет создавать уведомление.

Чтобы максимально упростить пример, вместо того, чтобы получать приватное p2p-соединение между пользователями, давайте передавать сообщение сразу всем. Однако, уведомление получит только выбранный при его отправке пользователь.

Схема

Чтобы получать сообщения в реальном времени просто вызовите метод subscribe() PubNub API. Когда сообщение придет выбранному вами пользователю, он увидит уведомление.

pubnub.subscribe({
  channel: channel,
  callback: function(message) {
    if (message.to === username) {
      showNotification(message);
    }
  }
});

Создание уведомления

Создание уведомлений элементарно: просто вызовите конструктор Notification.

var notification = new Notification(title, options);

Аргумент title должен быть строкой, options может содержать объект, имеющий следующие свойства:

Давайте допишем функцию showNotification. Следующий код показывает уведомление и закрывает его через 30 секунд. Если хотите оставить его открытым до тех пор, пока пользователь сам его не закроет — просто пропустите последнюю часть.

Тег, присвоенный каждому экземпляру уведомления, используется чтобы контролировать количество уведомлений, которые будут отображаться. Например, даже если приложение открыто в множестве вкладок с одинаковым именем пользователя вы получите только одно уведомление, если у них будет один и тот же тег.

function showNotification(data) {
  var notification = new Notification('Oi!', {
    body: 'From: ' + data.from,
    tag: channel,
    icon: 'images/oi.png'
  });
  notification.onshow = function() {
    setTimeout(notification.close, 30000);
  };
}

Скриншот

Та-дам! Теперь вы можете доставать случайных людей отправляя им сообщение «Oi!». Исходный код доступен на GitHub.

Это очень примитивный и, откровенно говоря, довольно дурацкий пример, но уведомления могут быть действительно полезным инструментом, если использовать их с умом.