Браузерный редактор с live-синхронизацией liveshare.py между двумя компьютерами в одной локальной сети.
Учитель (macOS/Linux):
./start_teacher.sh
# или
python start_teacher.pyУченик (Windows):
start_student.bat 192.168.0.102# или
python start_student.py 192.168.0.102Если IP не передавать, скрипт спросит адрес и запомнит его на следующий раз в ~/.liveshare/config.json.
livecode/
├── config.json ← все настройки (лимит строк, порты и т.д.)
│
├── server/ ← серверная часть (запускается только у учителя)
│ ├── config.py ← чтение config.json, типизированные константы
│ ├── network.py ← определение LAN IP
│ ├── ws_server.py ← WebSocket-сервер синхронизации
│ └── http_server.py ← HTTP-сервер, раздающий frontend/dist
│
├── client/ ← клиентская часть (запускается у обоих)
│ ├── bridge.py ← локальный HTTP-мост 127.0.0.1:8765 ↔ liveshare.py
│ └── startup.py ← общие утилиты запуска (ожидание URL, thread-обёртки)
│
├── frontend/ ← React + Vite + CodeMirror
│ └── src/
│ ├── App.tsx ← главный компонент
│ ├── types.ts ← TypeScript-типы
│ ├── styles.css ← светлая и тёмная тема
│ └── components/
│ └── Editor.tsx ← CodeMirror-обёртка
│
├── start_teacher.py ← запуск режима учителя
├── start_student.py ← запуск режима ученика
├── start_teacher.sh ← bash-обёртка с активацией venv
├── start_student.bat ← Windows-обёртка для ученика
├── liveshare.py ← синхронизируемый файл (редактируется совместно)
├── requirements.txt
└── build/ ← PyInstaller spec-файлы
Как данные движутся:
Браузер учителя
└─ WebSocket → ws_server.py → WebSocket → Браузер ученика
│
(каждый браузер)
│
bridge.py (127.0.0.1:8765)
│
liveshare.py (на диске)
Все параметры живут в config.json в корне проекта:
{
"max_lines": 150,
"http_port": 8000,
"ws_port": 5678,
"bridge_port": 8765,
"debounce_ms": 75,
"autosave_ms": 10000,
"shared_file": "liveshare.py"
}| Поле | Описание |
|---|---|
max_lines |
Максимальное кол-во строк в редакторе |
http_port |
Порт web UI |
ws_port |
Порт WebSocket-синхронизации |
bridge_port |
Порт локального bridge |
debounce_ms |
Задержка перед отправкой (мс) |
autosave_ms |
Интервал автосохранения (мс) |
shared_file |
Имя синхронизируемого файла |
Python 3.8+
pip install -r requirements.txt
Node.js 18+ (только для сборки фронтенда)
cd frontend
npm install
npm run build
cd ..- 🔄 Live-синхронизация по WebSocket с debounce из
config.json - 💾 Автосохранение в
liveshare.pyс интервалом изconfig.json+ при закрытии вкладки - 🌙 Тёмная тема с кнопкой переключения, запоминается в localStorage
- 👥 Счётчик участников в строке статуса
- ✍️ Индикатор «кто-то печатает» — пропадает через 2 секунды после остановки
- 📏 Лимит строк из
config.json— блокирует ввод сверх лимита, предупреждает за 13 строк до предела - 🔗 Copy Link — одна кнопка, чтобы скопировать ссылку для ученика
- 📋 Copy Code — скопировать весь текст редактора в буфер
- 🔒 Race condition на сервере решена через
asyncio.Lockвws_server.py
| Порт | Назначение |
|---|---|
8000 |
Web UI (настраивается в config.json) |
5678 |
WebSocket-синхронизация |
8765 |
Локальный bridge (только 127.0.0.1) |
На машине учителя HTTP-сервер и WebSocket-сервер слушают 0.0.0.0, то есть принимают подключения со всех сетевых интерфейсов. Это нужно, чтобы ученик мог открыть редактор по LAN-ссылке, но вместе с этим порты http_port и ws_port становятся доступны другим устройствам в той же сети, если firewall их пропускает.
Локальный bridge слушает только 127.0.0.1 и наружу не открывается.
- Стратегия конфликтов — last write wins (для двух участников этого достаточно). При внешнем обновлении редактор показывает уведомление, но не выполняет merge конфликтующих правок.
- Синхронизируется только один файл (
shared_fileизconfig.json). - Локальный bridge (
8765) слушает только на127.0.0.1— снаружи недоступен.
alias liveshare='~/projects/livecode/start_teacher.sh'
