Реализация совместного редактирования кода в мобильном приложении
Collaborative code editor на мобиле — нишевый, но востребованный продукт: мобильные IDE, coding interview приложения, учебные платформы. Задача тяжелее, чем документ-редактор: нужен 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 недель. Важно уточнить: нужен ли запуск кода, какие языки, нужна ли автодополнение.







