Николай Ланец
11 янв. 2019 г., 23:18

Превращаем @prisma-cms-компонент в chrome-плагин в несколько строк.

Всем привет!

Сегодня будет довольно интересная статья с минимумом кода.

Задача
Разработать для браузера плагин, чтобы он сообщал о наличии непрочитанных уведомлений на сайте (чтобы не приходилось постоянно на сайте сидеть и не переживать, что пропустишь сообщение из-за того, что не в той вкладке находишься).

Требования
Наличие git, node-js, yarn и хотя бы 1.5 Gb свободной оперативки (делать мы мало будем, но сам компонент исходный немаленький и сборка его требует ресурсов).

Внимание: я не проверял на окнах, работаю в убунте. Если у кого какие сложности возникнут, указывайте версию своей ОСи. В окнах работа совсем не гарантируется, но фикс проблемы не должен быть сложным (как правило сводится к настройке cross-env)

Если у вас не стоит yarn, поставить его очень просто:
sudo npm i -g yarn
За лайфхак спасибо Олегу Косныреву.

Выполнение
За основу возьмем @prisma-cms/society (про него и не только я писал здесь). Это самостоятельный компонента. Задача состоит в том, чтобы он мог в браузере работать как плагин, и чуть-чуть его видоизменить (нам же не нужен целый сайт в тулбаре? :))

1. Качаем себе исходный проект.
git clone https://github.com/prisma-cms/society society-extention cd society-extention
2. Устанавливаем зависимости.
yarn
3. Скачиваем API-схему MODX-Клуба.

Про этот прием я писал здесь. И хотя в том случае мы качали схему для локальной копии сайта Клуба, здесь примерно то же самое, только меньше, потому что мы не будем настраивать проксирование, а укажим .
# Получаем API-схему yarn get-api-schema -e https://modxclub.ru/api/ # Билдим фрагменты запросов yarn build-api-fragments
4. Меняем API-адрес компонента.

Для этого открываем файл/src/dev/App.js и меняем
return <PrismaCmsApp Renderer={DevRenderer} // pure={true} {...other} />
на
return <PrismaCmsApp Renderer={DevRenderer} apolloOptions={{ endpoint:"https://modxclub.ru/api/" }} // pure={true} {...other} />
то есть дописываем свой эндпоинт.

Вообще в примере с клонированием сайта Клуба мы вносили правку в другом месте и совершенно другую, но здесь делаем именно так. Объясню: в том случае для работы сайта мы запускали node-сервис и там мы редактировали проксирование запросов, то есть все API-запросы и запросы картинок шли на локальный адрес /api/, а node-процесс уже проксировал их на конечный сайт, получая api-ответы и картинки. В нашем случае плагин будет работать без node-js и никаких прокси не будет, запросы будут напрямую слаться на сайт Клуба. Минус тут только в том, что картинок мы не получим, но это не столько важно, нам главное сейчас - уведомления.

5. Тестовый запуск компонента.

Сначала мы проверим, что компонент в принципе работает, выполняется авторизация и мы можем видеть чат-комнаты и сообщения в них (и если у вас есть активные уведомления, то и их тоже). Для этого выполним
yarn start
Если все ОК, то у вас откроется браузер с адресом http://localhost:3000 и вы увидите мини-сайт, где сможете авторизоваться со своим modxclub-аккаунтом или зарегистрироваться (прям там, а аккаунт будет создан в базе MODX-Клуба) и можете посмотреть список чат-комнат и сообщений в них. Если все так и произошло, то можно переходить непосредственно к модификации компонента и упаковке его в гугл-плагин.

6. Создаем манифест.

В корне проекта создаем файл manifest.json с таком содержимым:
{ "manifest_version": 2, "name": "modxclub.ru", "description": "MODX-Клуб", "version": "1.0.0", "icons": {"128": "public/favicon.ico"}, "browser_action": { "default_icon": "public/favicon.ico", "default_popup": "build/index.html" }, "content_security_policy": "script-src 'self' 'unsafe-eval' 'sha256-IThiKMnsg0UHaLmP7sJxZpd/ohvINImwjxFJyxGFSlk='; object-src 'self'", "background": { }, "content_scripts": [ ], "permissions": ["activeTab", "debugger", "<all_urls>", "webNavigation", "notifications"] }
Все:) Да-да, теперь это можно билдить и заливать в браузер.

7. Билд плагина.

Выполняем в корне проекта команду
PUBLIC_URL="./" yarn build-app
8. Заливаем в браузер.

В хроме заходим во вкладку "Настройки -> Дополнительные инструменты -> Расширения" chrome://extensions/. Включаем режим разработчика (в правом верхнем углу страницы есть переключатель). Слева появится кнопка "Загрузить распакованное расширение". Жмем эту кнопку, в проводнике находим папку с нашим приложением и жмем Открыть. Если ОК, то в списке расширений у вас появится MODX-Клуб а в панели браузера появится приложение с дефолтной иконкой. Кликните его, должно открыться вот такое безобразие. Это нормально. Просто здесь нет минимальной ширины экрана, поэтому оформление идет по содержимому, а у нас там сейчас почти ничего нет. Если в меню перейти в chat-rooms, то окно расширится по содержимому и уже будет больше похоже на правду.

9. Кастомизация.

Ну а теперь нам надо его немного подогнать под себя, чтобы он обеспечил необходимый функционал и выглядел чуть получше. Мне по суди надо только две функции:
1. Авторизация.
2. Чтобы менялась иконка в браузере, показывая, что есть непрочтенные уведомления (и кол-во этих уведомлений).
3. Быстрый переход на сайт в целевую тему.

Пока мы заниматься будем доработками, лучше это делать в обычном режиме веб-страницы, а не гугл-плагина. Упакуем мы его потом, когда все сделаем. Для этого, как и обычно, запустим через yarn start. В этом режиме при внесении любых изменений в код у нас автоматически страница в браузере будет перезагружаться и отладка кода более подробная.

Зададим минимальную ширину и высоту. Вот сюда дописываем
minWidth: 750, minHeight: 550,
Теперь у нас всплывающее окошко не будет слишком мелким.

Пункт меню Graphql Voyager удалим, так как в этом режиме он не работает и нет смысла разбираться почему.

Добавляем абсолютные ссылки на комнаты и сообщения

Это одно из парочки относительно больших изменений, хотя на самом деле не прям так чтобы вообще. Смысл в том, чтобы к относительным ссылкам на комнаты и сообщения добавить абсолютные ссылки, чтобы можно было перейти к ним непосредственно на сайт Клуба. Для этого открываем вот этот файл и меняем его содержимое на такое:
import React, { Component, Fragment } from 'react' import PropTypes from 'prop-types' import Typography from "material-ui/Typography"; import Context from "@prisma-cms/context"; import OpenInBrowserIcon from "material-ui-icons/OpenInBrowser"; export class ChatRoomLink extends Component { static contextType = Context; render() { const { object, children, ...other } = this.props; if (!object) { return null; } const { Link, Grid, } = this.context; let { id, name, } = object; name = name || id; if (!name || !id) { return null; } const url = `/chat-rooms/${id}`; return <Grid container > <Grid item > <Link to={url} title={name} {...other} > {children || <Typography component="span" > {name} </Typography>} </Link> </Grid> <Grid item > <a href={`https://modxclub.ru${url}`} title={name} target="_blank" > <Typography component="span" > <OpenInBrowserIcon /> </Typography> </a> </Grid> </Grid> } } export default ChatRoomLink;
Для тех, кто уже успел поработать с реактом, наверняка не составит труда понять что здесь для чего меняется. Примерно то же самое делаем и для ссылок на сообщения.
Все, теперь есть внешние ссылки у комнат и сообщений.

Вместо заключения

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

Если себе хотите такие же уведомления, вот готовое расширение для хрома: https://yadi.sk/d/9hWkWOL0ZtGwrQ. Как его устанавливать, я писал выше. Распаковываете его и устанавливаете. После установки надо будет нажать иконку и авторизоваться в интерфейсе. После этого надо перезапустить приложение там же в списке расширений браузера (это чтобы веб-сокетное соединение установилось). К сожалению удобней пока не сделал, но перезапустить надо будет только один раз после авторизации. В итоге вы должны тогда увидеть сообщение "Приложение активировано".

Исходники проекта здесь: https://github.com/prisma-cms/society-chrome-extension.
Николай,привет! Я (какая неожиданность) пошел по самому простому пути:) Все встало ровно, единственное - аватарки не отображаются http://joxi.ru/a2XenkQt1G9nDA
Дима, привет!
Скачай новую версию плагина (оттуда же). Пофиксил.

Ну а так-то я в топике сразу про это писал:

Вообще в примере с клонированием сайта Клуба мы вносили правку в другом месте и совершенно другую, но здесь делаем именно так. Объясню: в том случае для работы сайта мы запускали node-сервис и там мы редактировали проксирование запросов, то есть все API-запросы и запросы картинок шли на локальный адрес /api/, а node-процесс уже проксировал их на конечный сайт, получая api-ответы и картинки. В нашем случае плагин будет работать без node-js и никаких прокси не будет, запросы будут напрямую слаться на сайт Клуба. Минус тут только в том, что картинок мы не получим, но это не столько важно, нам главное сейчас - уведомления.

Видимо ты не достаточно внимательно читал ;)

Ну а так, недоработка была на базе @prisma-cms/front, в аватарках пути только относительные писались. Добавил возможность указывать assetsBaseUrl. Теперь в плагине просто достаточно указать УРЛ на сайт Клуба.

Добавить комментарий