Реалізація спільного редагування таблиці в реальному часі в мобільному додатку
Таблиця — не текст. Вона має структуру: строки, стовпці, клітинки, формули, залежності між клітинками. Алгоритми синхронізації, які працюють для текстових документів (Y.js YText, CRDT для послідовностей), тут застосовуються інакше. Конкурентна зміна клітинки B3 й одночасна зміна формули =SUM(B1:B5) в C1 — два незалежних события з залежністю за даними.
Модель даних: не масив строк, а Map клітинок
Таблиця в CRDT-поданні — це Y.Map (або аналог), де ключ — "row:col" строка, значення — об'єкт клітинки. Y.js YMap підтримує конкурентні операції на рівні окремих ключів: два користувачі редагують різні клітинки одночасно — конфлікту нема. Два редагують одну клітинку — переважає остання запис (Last-Write-Wins семантика).
const ycells = ydoc.getMap('cells');
ycells.set('3:2', { value: '=SUM(A1:A3)', formatted: '15', style: { bold: true } });
ycells.observe(event => {
event.changes.keys.forEach((change, key) => {
if (change.action === 'update' || change.action === 'add') {
const [row, col] = key.split(':').map(Number);
recalculateAffectedFormulas(row, col);
rerenderCell(row, col);
}
});
});
Last-Write-Wins для клітинок — прийнятно у більшості сценаріїв. Для критичних даних (фінансові таблиці) потрібен детектор конфліктів і UI для ручного розв'язання.
Додавання та видалення строк/стовпців: структурні зміни
Це складніше, ніж зміна клітинки. Вставка строки перед строкою 5 повинна зсунути всі посилання у формулах: =B5 стає =B6. Конкурентна вставка строки двома користувачами — порядок вставки впливає на фінальну структуру.
Y.js YArray для списку строк з YMap для кожної строки — класична схема. При вставці в YArray CRDT гарантує детерміністичний порядок merge (на основі clientId та clock). Формули після структурних змін потребують пересчету через dependency graph.
Пересчет формул — окрема тема. HyperFormula (hyperformula.js) — open-source движок формул (аналог Excel), працює у JavaScript. Підтримує 400+ функцій. Інтегрується з Y.js: при отриманні CRDT-обновлення застосуємо його до HyperFormula через setSheetContent() та отримаємо пересчитані значення.
Мобільний рендеринг таблиці
FlashList (React Native) з двовимірною прокруткою — нестандартний кейс. Стандартний FlatList / ScrollView не оптимізований для великих таблиць з заморозкою заголовків та віртуалізацією клітинок.
Рішення:
-
react-native-table-component— простий, немає віртуалізації, не для великих таблиць. -
react-native-spreadsheet— існує, але давно не оновлювався. - Кастомний рендерер на
react-native-gesture-handler+react-native-reanimated— повний контроль, віртуалізація вручну.
На нативному Android: RecyclerView з GridLayoutManager, віртуалізація вбудована. На iOS: UICollectionView з UICollectionViewCompositionalLayout для двовимірної прокрутки зі свободними розмірами клітинок.
Кастомна клітинка-редактор: TextInput з підтримкою формул (починається з = — переключаємо режим). На iOS autocorrect ломає формули (=SUM стає =Sum або підкреслюється). Потрібен autocorrectionType = .no та spellCheckingType = .no для клітинок у режимі формули.
Виділення діапазону: B2:D5
При введенні формули користувач повинен кліцнути на клітинку та перетягти для вибору діапазону — класичний Excel-UX. На мобілі: кастомний gesture recognizer поверх таблиці, що відслідковує pan gesture та вичислює діапазон клітинок за координатами. Потрібен hitTest для визначення клітинки за точкою дотику.
Одночасно кілька користувачів можуть вибирати діапазони — показуємо через Awareness Protocol (як курсори у текстовому редакторі), але з кольоровою кодуванням за користувачем.
Синхронізація через WebSocket: оптимістичне обновлення
Локальна зміна клітинки застосовується до UI відразу (optimistic update). Паралельно Y.js кодує операцію в update binary та відправляє на сервер. Сервер розсилає update іншим клієнтам. Якщо прийшов конфліктуючий update — Y.js merge застосовується, UI перерисовується.
Для великих таблиць (1000+ строк) важливо не перерисовувати всю таблицю при кожному remote-обновленні. Відслідковуємо event.changes.keys в observer'і та перерисовуємо лише змінені клітинки + залежні формули.
Оцінка
MVP з Y.js + HyperFormula на React Native (до 100 строк, базові формули, 2–3 одночасних користувачі) — 10–16 тижнів. Повноцінний Google Sheets-подібний мобільний редактор з тисячами строк, складними формулами та структурними змінами — 6–12 місяців.







