Розробка мобільного додатку для форуму
Форум у мобільному додатку — це ієрархічна структура: розділи → теми → пости. Головна технічна задача — правильна пагінація в багаторівневих списках, сортування тем (за активністю, датою, рейтингом), та відображення вложених цитат без розриву читабельності на маленькому екрані.
Структура даних
boards (id, slug, name, parent_board_id, position) -- розділи форуму
threads (id, board_id, author_id, title, views, replies_count, last_reply_at, is_pinned, is_locked)
posts (id, thread_id, author_id, content_html, quote_post_id, created_at, updated_at, is_deleted)
last_reply_at в threads — ключове поле для сортування за активністю. Оновлюється при кожному новому посту. Індекс (board_id, is_pinned DESC, last_reply_at DESC) — стандартна вибірка списку тем.
replies_count — денормалізоване поле, інкрементується через тригер. Не рахуємо COUNT(*) кожен раз.
Список тем: пагінація та сортування
На мобілі список тем — UITableView (iOS) або LazyColumn (Android). Сортування: «Нові», «Активні», «Популярні». Перемикання — SegmentedControl або TabRow.
Cursor-based пагінація для «Нових» та «Активних»:
- «Нові»: cursor по
created_at - «Активні»: cursor по
(is_pinned, last_reply_at)— закріплені завжди першими
Для «Популярних» (за переглядами або рейтингом за тиждень) — offset-пагінація допустима, так як список стабільний.
Закріплені теми (is_pinned = true) — завжди вгорі незалежно від сортування. На iOS через DiffableDataSourceSnapshot з двома секціями: закріплені та звичайні.
Тред: вложені пости та цитати
Пости в темі — плаский список з quote_post_id (не дерево, як Reddit). При цитуванні показуємо вложений блок:
┌─ Цитата автора X: ┐
│ "Текст цитати" │
└────────────────────────────┘
Відповідь на цитату...
На iOS: кастомний UIView всередині ячейки поста з backgroundColor(.systemGray6), layer.cornerRadius = 8, layer.borderWidth = 1. Тап на цитату скроллить до оригінального поста (аналогічно reply в чаті).
HTML-контент з бази рендеримо через WKWebView (для складного форматування) або через UILabel з NSAttributedString з NSAttributedString(data:options:[.documentType: NSAttributedString.DocumentType.html]). WKWebView важчий, але правильніше рендерить форматування. На Compose — AndroidView з WebView або HtmlText з Accompanist.
Навігація по розділам
Багаторівневі розділи: boards з parent_board_id. Навігація — стек: головний список розділів → підрозділ → список тем → тред.
На iOS: UINavigationController з push. Хлібні крихти вгорі — UIScrollView горизонтальний з кнопками «Розділ → Підрозділ». На Android: NavHost з NavController, TopAppBar з іконкою назад.
Редактор поста
Мінімум: UITextView з поддержкою жирний, курсив, код. Toolbar над клавіатурою з кнопками форматування — inputAccessoryView на iOS, Composable над TextField на Android з анімацією появи через AnimatedVisibility.
Цитування при відповіді — аналогічно reply в чаті: вибраний текст або кнопка «Цитувати» під постом вставляє блок цитати у поле введення.
Чорновик зберігається локально при кожній зміні (дебаунс 1 сек) — UserDefaults / DataStore.
Пошук
Пошук по форуму: GET /search?q=...&board_id=...&page=.... Full-text пошук через PostgreSQL tsvector/GIN або Elasticsearch. На мобілі: екран пошуку з UISearchBar / SearchBar composable, результати — теми та окремі пости, згруповані за типом.
Непрочитані теми та бейджи
Таблиця thread_reads (user_id, thread_id, last_read_post_id, read_at). Тема «непрочитана» якщо last_reply_at > thread_reads.read_at. Кількість непрочитаних розділів — бейдж на іконці розділу.
Оновлення thread_reads при відкритті треда: POST при досягненні кінця списку або при закритті екрану — через viewWillDisappear (iOS) / DisposableEffect (Compose).
Етапи роботи
Проектування структури розділів та схеми БД → API (розділи, теми, пости, пошук) → мобільний UI основних екранів → редактор з форматуванням → сповіщення про нові пости у підписаних темах → тестування.
Терміни
MVP (розділи, список тем, тред, простий редактор) — 2-3 тижні. Повноцінний форум з пошуком, непрочитаними, підписками, модерацією — 1-3 місяці. Вартість розраховується індивідуально після аналізу вимог.







