Расширения Chrome с боковой панелью
Около года назад (30 мая 2023, если быть более точным) в Хроме появилась возможность отображать интерфейсные элементы расширений не только во всплывающем окне (popup.html), но и в боковой панели которая отображается сбоку (справа) от текущей отображаемой страницы. Внешне боковая панель расширения похожа на боковые панели, встроенные в сам браузер, такие как «Show all bookmarks» или «Grouped history». На мой взгляд, у этой фичи большой потенциал: В таком формате можно пробовать реализовать более сложные сценарии взаимодействия с пользователем, включающие как более сложный интерфейс расширения, так и стандартные возможности взаимодействия с текущей открытой страницей. При этом мне показалось что новость об этом релизе прошла ниже радаров и в публикациях тема использования этой боковой панели оказалась недостаточно раскрыта, так что я решил написать эту обзорную статью (в первую очередь, в надежде на содержательные комментарии по теме со стороны тех, у кого есть опыт в разработке расширений).
Вначале кратко скажу о технических аспектах. Затем будет небольшой обзор некоторых возможных вариантов использования. И в конце расскажу про небольшое расширение, которое я «разработал» сам.
Для желающих получить начальные представления о разработке расширений для Хрома думаю может быть полезно предварительно ознакомиться с этой статьей (хотя я наверно предложил бы для таких упражнений вместо ChatGPT попробовать использовать Курсор с Композером и новым Клодом).
Техническая сторона
С точки зрения реализации главные отличия «панельного» расширения от «обычного» заключаются в следующем:
Проект должен вместо файла popup.html включать в себя
sidepanel.html
. Это обычная веб-страница, которая, собственно, и отображается в боковой панели вместо попапа.В манифесте также нужно прописать sidepanel вместо попапа:
"side_panel": { "default_path": "sidepanel.html" }
и"permissions": [ "sidePanel" ]
Боковая панель расширения открывается также как и попап — по нажатию на кнопку этого расширения. В принципе можно реализовать ограничение что бы панель открывалась только если в текущей вкладке открыт определенный сайт (site-specific extension). Реализация показана в примере из документации. Но при копипасте этого когда в мое расширение это ограничение почему-то не заработало — панель продолжала открываться на всех сайтах. В итоге я воспользовался тем что мне написал Claude в Курсоре.
service_worker
const CHAT_ORIGIN = 'https://chatgpt.com';
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status === 'complete' && tab.url && tab.url.startsWith(CHAT_ORIGIN)) {
chrome.tabs.sendMessage(tabId, { action: "checkContentScriptInjected" }, response => {
if (chrome.runtime.lastError) {
// Content script is not injected, so inject it
chrome.scripting.executeScript({
target: { tabId: tabId },
files: ['content.js']
});
}
});
// Set side panel options
if (chrome.sidePanel) {
chrome.sidePanel.setOptions({
tabId,
path: 'sidepanel.html',
enabled: true
}).catch(error => console.error('Error setting side panel options:', error));
}
} else {
// Disable the side panel for other pages
if (chrome.sidePanel) {
chrome.sidePanel.setOptions({
tabId,
enabled: false
}).catch(error => console.error('Error disabling side panel:', error));
}
}
});
// Add this to ensure the side panel is opened when the extension icon is clicked
chrome.action.onClicked.addListener((tab) => {
if (tab.url && tab.url.startsWith(CHAT_ORIGIN)) {
chrome.sidePanel.open({tabId: tab.id}).catch(error => console.error('Error opening side panel:', error));
} else {
console.log('Not on the ChatGPT page');
}
});
Общий подход к реализации sidepanel.html такой же как и для попапа: sidepanel.js
может также взаимодействовать с Content Script, Chrome API, и т.д.
При этом в отличие от попапа панель автоматически не закрывается при каждом переключении фокуса с интерфейса расширения на основную страницу. Это может упростить некоторые моменты в сложных интерфейсах, связанные с удержанием состояния интерфейса и текущей информации (контекста) в нем.
Поддержка работы с боковой панелью также предлагается во фреймфорке WXT (при этом тут пишут что нужно не забыть вручную внести соответствующий пермишн в конфиг). Сам я пока что с этим фреймворком подробно не разбирался.
Примеры реализации
Вероятно, одно из самых простых и понятных применений боковой панели — это ее использование для открытия второй веб-страницы в дополнение к уже открытой «основной». В частности, это можно сделать с помощью расширения Page Sidebar. Оно в значительной мере воспроизводит функционал Split screen window в Microsoft Edge.
Split screen window на минималках
Одно из самых популярных расширений, использующих боковую панель (почти миллион пользователей), — это ChatGPT Sidebar. Насколько я понял, это самостоятельная интерфейсная обертка над API ChatGPT минимально связанная с содержимым основной страницы. Удобство в том что можно открыть чат не переключаясь с текущей страницы в другую вкладку, а также в том что в бесплатной версии предоставляется возможность сделать до 30 запросов к 4o-mini, включая веб-доступ и работу с картинками и PDF-файлами. Единственная связь межу основной страницей и чатом в боковике, которую я обнаружил, заключается в следующем: Если на основной странице начать печатать какой-то текст в текстовом поле, то появляется всплывающее меню, в котором можно выбрать различные действия такие как «Improve writing», выбор которых перебрасывает текст из основного окна в чат в боковике и добавляет к нему промпт, соответствующий выбранному действию. Про похожее по функционалу расширение на основе попапов ранее была статья на Хабре.
По аналогичному принципу устроены и некоторые другие расширения, размещающие функционал популярных приложений (таких как e-mail или календарь) в боковой панели.
Также есть смысл упомянуть пример из документации Google: прототип словаря, который позволяет выделить слово на странице и через контекстное меню отобразить его определение в боковой панели (реального словаря в этом прототипе под капотом нет — работает только для двух слов):
Картинка с github.com/GoogleChrome/chrome-extensions-samples
Кроме того, есть примеры расширений работающих только с API Хрома и не затрагивающих страницу, открытую в основной вкладке. Например, это расширение Tab Shelf. С его помощью можно отображать список текущих открытых вкладок браузера в формате вертикального списка.
Custom Instructions Library
На мой взгляд, основной потенциал «панельных» расширений заключается в том что бы с их помощью расширять и дополнять функционал конкретных сайтов (веб-приложений). На Хабре есть несколько статей, в которых авторы описывают такого типа расширения (например: раз, два, три, четыре).
Попробую продемонстрировать эту идею на примере функционала ChatGPT Custom Instructions. Небольшое введение в Custom Instructions я публиковал около года назад (+ есть документация). Повторю кратко: Custom Instructions — это «фоновые» настройки чата, которые применяются ко всем диалогам и состоят из двух текстовых элементов (до 1500 знаков каждый): «Обо мне» и «Как нужно отвечать». Таким образом, ChatGPT при каждом обращении принимает во внимание не только то что пользователь пишет в чате, но одновременно и то что задано в Custom Instructions. Насколько я понимаю, Custom Instructions до некоторой степени является аналогом «системного промпта» при работе через API.
Так вот, по моим наблюдениям Custom Instructions могут и должны быть разными в разных сценариях использования ChatGPT:
Если я использую ChatGPT для профессиональных целей, то настройка «Обо мне» должна содержать информацию из моего резюме
Если цель — поиск кулинарных рецептов, то в «Обо мне» должно быть сказано о моих пищевых предпочтениях, на что у меня аллергия и т.п.
Для целей изучения иностранного языка в «Обо мне» должна быть заполнена информация о моем текущем уровне, о моих целях и приоритетах при изучении этого языка
и т.д.
Сам по себе ChatGPT такой множественности вариантов не предусматривает. Нужно где-то отдельно держать блокнот с разными вариантами Custom Instructions и вручную их копипастить. Собственно, «продуктовая идея» моего расширения Custom Instructions Library заключается в том что бы оптимизировать эти манипуляции. Предполагается что на странице расширения в боковой панели будут храниться разные варианты «инструкций» и их копирование в/из ChatGPT будет требовать минимума телодвижений.
В частности, в него можно добавлять новые блоки (Add New Instruction), каждый из которых состоит из заголовка и двух упомянутых выше элементов Custom Instructions: «Обо мне» и «Как нужно отвечать». Последние можно либо заполнять вручную непосредственно в соответствующих текстовых полях, либо скопировать из текущего открытого окна Custom Instructions (кнопкой Update Library from ChatGPT). Все изменения во всех текстовых полях расширения автоматически сохраняются. Ранее сохраненные «инструкции» можно скопировать с помощью второй кнопки Copy CI to ChatGPT в обратном направлении — из расширения в открытое окно Custom Instructions ChatGPT.
На мой взгляд, такой подход в полной мере задействует все возможности:
развитой интерфейс «панельного» расширения
хранение данных, не предусмотренное в самом веб-приложении
двустороннее взаимодействие между веб-приложением (в моем случае ChatGPT) и расширением.
Заключение
Лично я для себя вижу цель в том что бы сформировать навыки быстрой «разработки» расширений, сопоставимых по сложности с описанным выше. Под «быстрой» имеется ввиду «меньше чем за час». А «разработка» — это использование чата/композера Курсора (видимо, в сочетании с новым Claude 3.5 Sonnet).
На первый взгляд кажется что такой навык может быть достаточно полезным в различных рабочих ситуациях (по аналогии с тем как это было описано в одной из статей про Tampermonkey).
Ну как вам и#дейка?
P.S.: Я, кстати, в бесплатной версии Курсора пока что ни с каким ограничениями не сталкивался — может что-то упустил?