Разработка системы комментариев в мобильном приложении
Комментарии сложнее лайков в разы: вложенность (или её отсутствие по дизайну), пагинация, клавиатура перекрывает поле ввода, @упоминания внутри текста, модерация. Самая частая жалоба на самописные реализации — «при открытии комментариев скролл прыгает» или «клавиатура перекрывает последний комментарий». Начнём именно с этого.
Проблема с клавиатурой
На iOS UITableView или UICollectionView со списком комментариев + UITextField внизу. При появлении клавиатуры нужно поднять весь контент. Правильный способ — не трогать contentInset вручную, а использовать KeyboardLayoutGuide (iOS 15+): view.keyboardLayoutGuide.topAnchor.constraint(equalTo: inputView.bottomAnchor). На iOS 14 и ниже — подписка на UIResponder.keyboardWillShowNotification и обновление tableView.contentInset.bottom.
После добавления нового комментария — прокрутить к нему: tableView.scrollToRow(at: lastIndexPath, at: .bottom, animated: true). Проблема: если scrollToRow вызван до того как UITableView обработал вставку (insertRows(at:with:)), крашим на NSInternalInconsistencyException. Порядок: сначала beginUpdates → insertRows → endUpdates, потом scrollToRow.
На Android с Compose — LazyColumn с reverseLayout = true (новые сообщения снизу) и imePadding() на уровне колонки. reverseLayout избавляет от ручного скролла вниз при добавлении комментария.
Структура данных и вложенность
Flat-структура (все комментарии на одном уровне) — проще и работает для большинства приложений. Instagram так и сделан: один уровень комментариев + replies внутри каждого через отдельный запрос.
Если нужна вложенность: хранить parent_comment_id (nullable). Отображать максимум 2 уровня — глубже не читают. Загрузку replies делать lazy: по умолчанию показываем «N ответов», по тапу загружаем.
Пагинация — cursor-based: GET /posts/{id}/comments?cursor=<last_id>&limit=20. Для вложенных replies — отдельный endpoint GET /comments/{id}/replies.
Добавление комментария
Оптимистичное добавление — обязательно. Локально генерируем client_comment_id, добавляем в список с isPending = true, показываем spinner или серый текст. При успехе — заменяем на серверный объект. При ошибке — показываем кнопку «Повторить» рядом с комментарием.
Поле ввода — UITextView с авторасширением (не UITextField): комментарии бывают длинными. Лимит 500-1000 символов с счётчиком. Кнопка «Отправить» — активна при непустом тексте.
Удаление и модерация
Удаление своего комментария — свайп (iOS) или лонг-тап с bottom sheet. Удалённый комментарий не убираем из ленты полностью, если у него есть replies — заменяем текст на «Комментарий удалён». Иначе дочерние ответы теряют контекст.
Жалоба на комментарий — report_comment_id → очередь модерации. Автоматический скрытие при N жалобах (настраивается) + ручная проверка.
Счётчик комментариев в ленте
Денормализованное поле comments_count в таблице поста, инкрементируется/декрементируется триггером или очередью. При добавлении комментария через приложение — обновляем счётчик в UI оптимистично.
Сроки
Flat-комментарии с пагинацией, оптимистичным добавлением, удалением — 2-3 рабочих дня. С вложенными replies, упоминаниями, модерацией — 5-7 дней. Стоимость рассчитывается индивидуально.







