Реалізація спільного редагування кода в мобільному додатку
Collaborative code editor на мобілі — нішевий, але затребуваний продукт: мобільні IDE, coding interview додатки, навчальні платформи. Задача важча, ніж document-редактор: потрібен syntax highlighting з підтримкою десятків мов, bracket matching, автодополнення, і все це — у спільному режимі з коректною синхронізацією курсорів.
Code Mirror vs Monaco на мобілі
Обидва редактори — для вебу. У мобільному контексті вони працюють через WebView.
Monaco Editor (VS Code's editor): важкий, ~3MB JS bundle. У React Native через react-native-webview + кастомний HTML. Повноцінний IntelliSense при наявності language server, але Language Server Protocol (LSP) на мобілі — окрема історія. Вбудований collaborative режим: ні, потрібна інтеграція з Y.js через y-monaco.
CodeMirror 6: модульний, близько 200KB для базової конфігурації. Більше підходить для мобіля за вагою. Вбудований collaborative режим через @codemirror/collab — OT-based, вимагає сервера для трансформації операцій. Альтернатива: y-codemirror.next — Y.js binding.
Для React Native: WebView з CodeMirror 6 + Y.js — робочий підхід. Мост window.ReactNativeWebView.postMessage() / webViewRef.injectJavaScript() для комунікації між нативним кодом та редактором.
Для нативного підходу без WebView: react-native-code-editor — обмежений функціонал, тільки highlighting, немає code intelligence.
Y.js + CodeMirror: як це працює
y-codemirror.next — пакет, який зв'язує CodeMirror Text з Y.Text. Кожна зміна у редакторі (вставка, видалення) транслюється у Y.js операцію. Видалені Y.js операції застосовуються до CodeMirror через його транзакційний API.
import { yCollab } from 'y-codemirror.next';
const ytext = ydoc.getText('code');
const undoManager = new Y.UndoManager(ytext);
const extensions = [
yCollab(ytext, provider.awareness, { undoManager })
];
Awareness з провайдера Y.js автоматично транслює курсори та виділення інших користувачів у CodeMirror decorations. Кожен видалений курсор — WidgetDecoration з іменем користувача.
Undo/Redo: стандартний undoManager у CodeMirror працює локально — undo скасовує чужі зміни. Y.UndoManager — collaborative undo, скасовує тільки свої зміни. Обов'язково використовуйте Y.UndoManager.
Syntax Highlighting без LSP
Tree-sitter — парсер з інкрементальним обновленням AST. Працює у JavaScript через WebAssembly (web-tree-sitter). CodeMirror 6 використовує Lezer (аналог Tree-sitter, чистий JS) для вбудованого highlighting.
У WebView на мобілі: WASM працює у більшості сучасних WebView. На iOS WKWebView підтримує WASM з iOS 14. На Android WebView: WASM доступний з Chrome 57 (WebView API level 57). Для старих пристроїв — fallback на regex-based highlighting.
Продуктивність: Tree-sitter / Lezer парсить інкрементально — при зміні одного символу перепарсується тільки змінений регіон. Для великих файлів (1000+ строк) це критично.
Cursor position sync: позиція у коді
Позиція курсора у коді — {line, ch} або абсолютний offset. Абсолютний offset переважніше для CRDT (не залежить від розбивки на строки).
Y.js Awareness зберігає anchor та head — це діапазон виділення (при немає виділення — anchor === head). CodeMirror 6 представляє позицію як EditorSelection, y-codemirror транслює автоматично.
При merge конкурентних операцій (вставка перед позицією курсора іншого користувача) — Y.js коректує позиції через relativePosition. Абсолютний offset стає невалідним після видаленого insert. Y.createRelativePositionFromTypeIndex / Y.createAbsolutePositionFromRelativePosition — API для конвертації.
Виконання кода: опціональна фіча
Для coding interview або навчальних додатків потрібен запуск кода. На мобілі: sandbox через API (Judge0, Piston) — безпечніше, ніж локальне виконання. WebAssembly-рантайм (Wasmer, WasmEdge) для певних мов — працює у нативному окружінні.
Результат виконання синхронізувати через Y.js (у document) або окремий WebSocket канал (тільки для поточної сесії, не персистувати).
Оцінка
Collaborative code editor у WebView (CodeMirror + Y.js) для React Native — 8–12 тижнів. Нативний редактор з повноцінним syntax highlighting, bracket matching та LSP-інтеграцією — 20–36 тижнів. Важливо уточнити: потребує ли запуск кода, які мови, потребує ли автодополнення.







