Синхронизация вкладок: один документ в каждой вкладке
Один документ остаётся актуальным во всех вкладках браузера, без сервера.
Что это
Откройте один документ в двух вкладках одного браузера. Изменение в одной вкладке появится в остальных. Сервер для этого не нужен.
Синхронизация вкладок включена по умолчанию. tabSync: false выключает её. tabSync: { settings: false } оставляет синхронизацию документа, но перестаёт передавать язык, режим темы и ширину.
Если задан collaboration, синхронизация вкладок не включается. Сервер совместной работы и так держит все вкладки в актуальном состоянии.
Откуда взять id документа
Вкладки находят друг друга по id документа. Передайте его в documentId. Возьмите id, по которому ваше приложение уже загружает и сохраняет документ:
- Параметр маршрута, например
/notes/:id. - Id из адресов в вашем
persistence. - Ключ записи в базе данных.
- Постоянное имя, например
'notes', если на сайте один редактор. - Новый уникальный id для нового документа.
Для нового id подойдёт crypto.randomUUID() на HTTPS и на localhost. На странице по обычному http его нет, потому что ему нужен защищённый контекст. Любая уникальная строка подойдёт не хуже.
Id должен быть уникальным на всём сайте. Если у двух ваших клиентов может совпасть id, добавьте префикс, например 'acme:42'. Пустая строка не принимается, и isReady отклоняется с ошибкой.
Без documentId Blok берёт id, который сам записывает в сохранённые данные, и добавляет к нему путь страницы. Так работает документ, который загружает persistence. Документ без сохранённого id подключается после первого сохранения через persistence.
Документ, переданный в data со своим id, сам не подключается. Не подключается и документ, который сохраняется только через onSave, и пустой документ. В этих случаях передайте documentId.
Что синхронизируется
Между вкладками с одним документом передаются:
- Содержимое документа.
- Ширина контента.
- Открыт ли каждый переключатель. Это личное состояние браузера, оно не сохраняется в документе.
Язык и режим темы передаются во все вкладки того же origin, где работает Blok. Недавние цвета, ссылки и языки кода, оттенок кожи эмодзи, а также громкость, скорость и повтор медиа хранит сам браузер. Они общие при любом значении tabSync.
Никогда не синхронизируются:
- Выделение и каретка.
- Позиция прокрутки.
- Открытые меню и всплывающие окна.
- Поиск по странице.
- Режим только для чтения.
- Токены темы и прочие настройки хоста.
- Позиция воспроизведения медиа.
Сохраняет вкладка, в которой вы работаете
Сохраняет только одна вкладка: та, в которой вы работаете. Она вызывает persistence.save и onSave, включая обработчики сохранения внутри адаптеров фреймворков. Фоновые вкладки пассивны.
Когда вы переходите в другую вкладку, она берёт эту роль, обычно за полсекунды. Вкладка, которую вы покинули, сначала сохраняет то, что ещё держит. Если сохранение ещё идёт, новая вкладка ждёт его, и это может занять несколько секунд.
Поэтому привязка, которая работает через onSave, актуальна во вкладке, где вы работаете:
- Vue
v-model:data. - Angular
[formControl]. - React
onSave, который обновляет ваше состояние.
В фоновой вкладке такая привязка может отставать. Чтобы прочитать там документ, используйте editor.save().
Вкладка только для чтения никогда не сохраняет. Когда сохраняющая вкладка закрывается, её роль берёт другая открытая вкладка.
onChange по-прежнему срабатывает во всех вкладках. Его события несут origin, и для изменения из другой вкладки это 'tab'.
Переключатели
Открыт ли переключатель, каждый браузер запоминает сам. Это состояние не сохраняется в документе. То же касается сворачиваемых заголовков.
- Переключатель появляется свёрнутым.
- Переключатель, который создали вы, у вас открыт в этом браузере.
- Если синхронизация вкладок включена, переключатель, открытый в одной вкладке, откроется и в других вкладках этого браузера с тем же документом.
Состояние хранится по documentId, по doc из collaboration или по id документа. Если приложение теряет id при сохранении документа, состояние пропадает после перезагрузки. Копии с одним id делят и состояние.
isOpen больше не сохраняется и не читается. Документ, сохранённый с isOpen, открывается со свёрнутыми переключателями. Состояние хранится в api.viewState под ключом 'open'.
Ограничения
Документ остаётся отдельным в каждой вкладке в таких случаях:
- Внутри стороннего iframe в Chrome и Firefox. Эти браузеры разделяют каналы вкладок по сайту верхнего уровня.
- На странице по обычному http. Web Locks нужен защищённый контекст, а localhost считается защищённым.
- Между версиями Blok с разными протоколами синхронизации вкладок.
- Во вкладке, где пользователь начал печатать до подключения. Она остаётся отдельной до перезагрузки.
Отдельная вкладка сохраняет сама, параллельно с сохраняющей вкладкой. Роль сохраняющей она не берёт, даже когда вы в ней работаете. Поймать такой конфликт может только persistence, у которого load возвращает версию.
Вкладка, открытая, пока сохраняющая вкладка заморожена в фоне, работает сама по себе. Она подключится, когда та вкладка проснётся, если в ней за это время ничего не напечатали.
Если сохраняющая вкладка заморожена, когда вы переходите в другую вкладку, та вкладка берёт её роль примерно через 4 секунды.
Набранный текст доходит до других вкладок примерно за 400 мс.
Если приложение копирует сохранённые документы и открывает все документы по одному пути, у копий совпадает id. Передайте documentId или удаляйте id при копировании.
documentId и tabSync задаются на всю жизнь редактора. Чтобы переключить документ, создайте редактор заново. В React измените его key или зависимости useBlok. В Vue и Angular измените recreateKey.