883 lines
32 KiB
Markdown
883 lines
32 KiB
Markdown
# ТЗ: мессенджер в стиле Икар
|
||
|
||
## Назначение документа
|
||
|
||
Этот документ является техническим заданием для нейросети или команды разработки, которой нужно создать полноценный мессенджер, функционально и визуально близкий к проекту Икар.
|
||
|
||
Цель: получить современный мобильный мессенджер с серверной частью, Android-клиентом, real-time сообщениями, медиа-вложениями, звонками, сторис, ботами, каналами, группами, push-уведомлениями, настройками приватности, админкой и механизмом обновления приложения.
|
||
|
||
Документ нужно читать как product + engineering brief. Если какие-то детали не указаны явно, нужно выбирать решения, близкие к Telegram-подобному пользовательскому опыту: быстрый чат, аккуратные пузырьки, плотная мобильная навигация, удобные вложения, плавная работа с медиа и надежная доставка сообщений.
|
||
|
||
## Рабочее название
|
||
|
||
Икар.
|
||
|
||
## Ключевая идея
|
||
|
||
Икар - это самостоятельный мессенджер с мобильным Android-клиентом и собственным сервером. Он должен поддерживать личные чаты, группы, каналы, медиа, звонки, сторис, ботов и обновления клиента через собственный каталог релизов.
|
||
|
||
Пользователь должен воспринимать приложение как быстрый, легкий и приватный мессенджер:
|
||
|
||
- открыл приложение;
|
||
- увидел список чатов;
|
||
- вошел в чат;
|
||
- написал текст;
|
||
- отправил фото, видео, файл или голосовое;
|
||
- получил push;
|
||
- открыл фото на весь экран;
|
||
- позвонил;
|
||
- настроил приватность;
|
||
- обновил приложение через встроенный механизм.
|
||
|
||
## Платформы
|
||
|
||
Минимальный обязательный состав:
|
||
|
||
- Backend: ASP.NET Core Web API.
|
||
- Realtime: SignalR или аналогичный WebSocket transport.
|
||
- Android client: Kotlin + Jetpack Compose.
|
||
- Storage: локальное файловое хранилище на сервере для вложений и аватаров.
|
||
- Database: реляционная БД через ORM, желательно Entity Framework Core или аналог.
|
||
- Push: Firebase Cloud Messaging.
|
||
- Admin UI: веб-админка, доступная через сервер.
|
||
- Distribution: публикация Android APK через каталог обновлений Argus-like.
|
||
|
||
Дополнительно допустимо:
|
||
|
||
- Docker-окружение для сервера.
|
||
- Отдельный shared-модуль с контрактами API.
|
||
- Локальный кэш сообщений и вложений на Android.
|
||
|
||
## Главные пользовательские сценарии
|
||
|
||
### Регистрация и вход
|
||
|
||
Пользователь должен иметь возможность:
|
||
|
||
- зарегистрироваться по номеру телефона;
|
||
- войти по номеру телефона через одноразовый код;
|
||
- войти или подтвердить аккаунт через email-код;
|
||
- получить JWT/access token;
|
||
- восстановить сессию после перезапуска приложения;
|
||
- выйти из аккаунта;
|
||
- видеть список активных устройств;
|
||
- завершать сессии на других устройствах.
|
||
|
||
В dev/smoke окружении можно использовать тестовые коды, но в production нужно иметь реальную отправку SMS/email или подключаемые провайдеры.
|
||
|
||
### Профиль пользователя
|
||
|
||
Пользователь должен иметь:
|
||
|
||
- display name;
|
||
- username или публичный идентификатор, если нужен;
|
||
- avatar;
|
||
- about/status;
|
||
- настройки приватности;
|
||
- настройки уведомлений;
|
||
- настройки интерфейса чатов.
|
||
|
||
Нужно поддерживать загрузку аватара с Android-клиента, хранение на сервере и отдачу с авторизацией.
|
||
|
||
### Список чатов
|
||
|
||
Главный экран после авторизации - список чатов.
|
||
|
||
В списке чатов должны отображаться:
|
||
|
||
- аватар чата или пользователя;
|
||
- название;
|
||
- последний текст или превью вложения;
|
||
- дата/время последнего сообщения;
|
||
- бейдж непрочитанных;
|
||
- индикатор pinned/muted/archived, если реализовано;
|
||
- превью фото для последнего медиа-сообщения;
|
||
- статус онлайн для личных чатов.
|
||
|
||
Список должен обновляться в real-time при новых сообщениях.
|
||
|
||
### Личные чаты
|
||
|
||
Пользователь должен иметь возможность:
|
||
|
||
- создать личный чат с другим пользователем;
|
||
- отправлять текст;
|
||
- отправлять вложения;
|
||
- отвечать на сообщение;
|
||
- пересылать сообщение;
|
||
- копировать текст;
|
||
- удалять сообщение;
|
||
- редактировать свое сообщение;
|
||
- ставить реакции;
|
||
- искать по сообщениям;
|
||
- видеть статус доставки.
|
||
|
||
Статусы доставки:
|
||
|
||
- sending;
|
||
- sent;
|
||
- delivered;
|
||
- read;
|
||
- failed.
|
||
|
||
### Группы
|
||
|
||
Групповой чат должен поддерживать:
|
||
|
||
- создание группы;
|
||
- добавление участников;
|
||
- удаление участников;
|
||
- роли участников;
|
||
- права отправки сообщений;
|
||
- название и аватар группы;
|
||
- список участников;
|
||
- уведомления;
|
||
- поиск;
|
||
- media/materials view.
|
||
|
||
Минимальные роли:
|
||
|
||
- owner;
|
||
- admin;
|
||
- member.
|
||
|
||
### Каналы
|
||
|
||
Каналы должны отличаться от групп:
|
||
|
||
- подписчики читают публикации;
|
||
- писать могут только владелец/админы;
|
||
- у публикаций могут быть просмотры;
|
||
- у публикаций могут быть комментарии через discussion group;
|
||
- канал может иметь invite link;
|
||
- канал может быть публичным или приватным.
|
||
|
||
Для каналов нужны:
|
||
|
||
- создание канала;
|
||
- управление участниками/подписчиками;
|
||
- публикация постов;
|
||
- пересылка постов;
|
||
- счетчик просмотров;
|
||
- переход в обсуждение.
|
||
|
||
### Сообщения
|
||
|
||
Сообщение должно поддерживать:
|
||
|
||
- id;
|
||
- chatId;
|
||
- sender;
|
||
- text;
|
||
- sentAt;
|
||
- editedAt;
|
||
- deletedAt;
|
||
- replyTo;
|
||
- forwardedFrom;
|
||
- attachments;
|
||
- reactions;
|
||
- deliveryState;
|
||
- hasProtectedContent;
|
||
- viewCount для каналов;
|
||
- discussionMessageId для каналов;
|
||
- mediaAlbumId для альбомов.
|
||
|
||
Текст должен поддерживать:
|
||
|
||
- переносы строк;
|
||
- ссылки;
|
||
- inline preview для ссылок на изображения;
|
||
- spoiler-style разметку, если реализуется;
|
||
- большие emoji-сообщения, если сообщение состоит только из 1-3 emoji.
|
||
|
||
### Вложения
|
||
|
||
Нужно поддерживать вложения:
|
||
|
||
- изображения: jpg, jpeg, png, webp, gif, bmp, heic, heif;
|
||
- видео: mp4, mov, webm, mkv и похожие;
|
||
- аудио;
|
||
- голосовые сообщения;
|
||
- документы/файлы;
|
||
- встроенные GIF;
|
||
- стикеры.
|
||
|
||
Ограничение размера по умолчанию: 25 MB на файл, если не задано другое.
|
||
|
||
У вложения должны быть:
|
||
|
||
- id;
|
||
- fileName;
|
||
- contentType;
|
||
- fileSizeBytes;
|
||
- downloadPath;
|
||
- kind;
|
||
- sortOrder.
|
||
|
||
Типы kind:
|
||
|
||
- File;
|
||
- VoiceNote;
|
||
- Image;
|
||
- Video;
|
||
- Sticker;
|
||
- Gif.
|
||
|
||
Если backend не хранит kind явно для всех типов, клиент должен уметь определять тип по contentType и расширению файла.
|
||
|
||
### Отправка фото
|
||
|
||
Отправка фото должна работать надежно.
|
||
|
||
Требования:
|
||
|
||
- пользователь выбирает фото через системный picker;
|
||
- фото копируется во временный локальный файл приложения;
|
||
- приложение отображает preview перед отправкой;
|
||
- при отправке файл передается на сервер multipart/form-data;
|
||
- сервер сохраняет оригинал;
|
||
- сервер возвращает сообщение с attachment metadata;
|
||
- получатели видят фото в чате без перезапуска;
|
||
- при нажатии фото открывается полноэкранный просмотр.
|
||
|
||
Важное визуальное требование:
|
||
|
||
- одиночное фото в чате должно отображаться как media-сообщение без обычного белого текстового пузыря;
|
||
- не должно быть широких белых полей вокруг фото;
|
||
- preview в чате должно сохранять корректное соотношение сторон;
|
||
- если изображение очень широкое или очень высокое, нужно ограничивать максимальную высоту, но не показывать белую пустую область как часть сообщения;
|
||
- фон загрузки не должен выглядеть как белый прямоугольник;
|
||
- если файл еще не докачан, нельзя показывать частично скачанный JPEG как готовое изображение.
|
||
|
||
Техническое требование для кэша:
|
||
|
||
- вложения скачивать сначала во временный файл, например `filename.part`;
|
||
- после полной загрузки и проверки размера атомарно переносить во финальный cache-файл;
|
||
- UI должен считать cache-файл готовым только если он существует, не пустой и, если известен ожидаемый размер, совпадает с `fileSizeBytes`;
|
||
- при несовпадении размера старый cache-файл нужно игнорировать или перекачивать;
|
||
- image loader не должен кэшировать частично скачанные изображения.
|
||
|
||
### Фотоальбомы
|
||
|
||
Если пользователь отправляет несколько изображений/видео одновременно:
|
||
|
||
- файлы должны отправляться одним album-сообщением, если все вложения являются media;
|
||
- у всех вложений должен быть общий mediaAlbumId;
|
||
- в чате нужно показывать collage/grid;
|
||
- порядок должен соответствовать выбору пользователя;
|
||
- при нажатии открывается просмотрщик с навигацией по фото альбома.
|
||
|
||
### Просмотр фото
|
||
|
||
Фото-просмотрщик должен:
|
||
|
||
- открываться на весь экран;
|
||
- иметь черный фон;
|
||
- показывать фото целиком через ContentScale/Fit;
|
||
- поддерживать pinch-to-zoom;
|
||
- поддерживать drag при увеличении;
|
||
- иметь кнопку закрытия/назад;
|
||
- иметь имя отправителя и время;
|
||
- поддерживать переход к предыдущему/следующему фото в контексте чата или альбома;
|
||
- иметь меню: сохранить, поделиться, открыть внешне, если разрешено.
|
||
|
||
### Видео
|
||
|
||
Видео-сообщение должно:
|
||
|
||
- отображаться карточкой с preview/play;
|
||
- открываться в full-screen player;
|
||
- проигрываться через Media3/ExoPlayer или аналог;
|
||
- поддерживать авторизованные URL;
|
||
- иметь play/pause;
|
||
- иметь закрытие назад.
|
||
|
||
### Голосовые сообщения
|
||
|
||
Нужно поддерживать:
|
||
|
||
- запись голосового;
|
||
- таймер записи;
|
||
- отмену записи;
|
||
- отправку как attachment kind VoiceNote;
|
||
- воспроизведение в чате;
|
||
- progress bar;
|
||
- stop/play;
|
||
- паузу внешней музыки при записи или воспроизведении, если настройка включена.
|
||
|
||
### Реакции
|
||
|
||
Сообщения должны поддерживать реакции:
|
||
|
||
- пользователь может поставить emoji-реакцию;
|
||
- повторное нажатие может убрать или сменить реакцию;
|
||
- счетчики реакций обновляются real-time;
|
||
- реакции отображаются компактно под сообщением.
|
||
|
||
### Ответы, пересылка, редактирование, удаление
|
||
|
||
Нужно реализовать:
|
||
|
||
- reply preview над composer;
|
||
- reply preview внутри сообщения;
|
||
- переход к исходному сообщению по tap на reply;
|
||
- edit mode для своих сообщений;
|
||
- delete для себя или для всех, если разрешено;
|
||
- forward flow с выбором чата;
|
||
- protected content: если сообщение защищено, запретить копирование/пересылку/сохранение.
|
||
|
||
### Поиск
|
||
|
||
Нужен глобальный поиск:
|
||
|
||
- по пользователям;
|
||
- по чатам;
|
||
- по сообщениям;
|
||
- по вложениям;
|
||
- по медиа;
|
||
- по файлам.
|
||
|
||
Нужен поиск внутри чата:
|
||
|
||
- строка поиска в header;
|
||
- подсветка результатов;
|
||
- навигация вверх/вниз по результатам;
|
||
- загрузка старых сообщений при необходимости.
|
||
|
||
|
||
|
||
### Уведомления
|
||
|
||
Push-уведомления должны приходить для:
|
||
|
||
- новых сообщений;
|
||
- входящих звонков;
|
||
- важных системных событий.
|
||
|
||
Требования:
|
||
|
||
- Firebase token registration;
|
||
- настройка звука;
|
||
- mute per chat;
|
||
- глобальное включение/выключение preview;
|
||
- не показывать уведомление, если пользователь уже находится в активном чате;
|
||
- действия в уведомлении: открыть чат, принять/отклонить звонок.
|
||
|
||
### Приватность и безопасность
|
||
|
||
Нужно реализовать:
|
||
|
||
- JWT auth;
|
||
- авторизацию на всех API;
|
||
- проверку членства в чате перед доступом к сообщениям и вложениям;
|
||
- запрет скачивания вложений неучастниками;
|
||
- privacy settings;
|
||
- protected content;
|
||
- secure window option на Android;
|
||
- rate limiting на API;
|
||
- удаление пользователя админом;
|
||
- удаление чата и файлов;
|
||
- server-side validation для всех upload.
|
||
|
||
Настройки приватности:
|
||
|
||
- кто видит номер телефона;
|
||
- кто видит avatar;
|
||
- кто видит online;
|
||
- кто может звонить;
|
||
- кто может добавлять в группы;
|
||
- показывать или скрывать message preview.
|
||
|
||
### Настройки приложения
|
||
|
||
Нужны настройки:
|
||
|
||
- язык/локаль;
|
||
- тема/цвета, если реализуется;
|
||
- размер текста сообщений;
|
||
- радиус пузырьков;
|
||
- обои чата;
|
||
- layout списка чатов;
|
||
- автоскачивание фото;
|
||
- автоскачивание видео по Wi-Fi;
|
||
- автоскачивание файлов по Wi-Fi;
|
||
- сохранять медиа в галерею;
|
||
- защищенный экран;
|
||
- push settings;
|
||
- настройки звонков.
|
||
|
||
### Кэш и offline
|
||
|
||
Android-клиент должен:
|
||
|
||
- кэшировать последние сообщения;
|
||
- показывать кэш при старте;
|
||
- хранить scroll position;
|
||
- хранить draft text;
|
||
- кэшировать скачанные вложения;
|
||
- иметь политику очистки кэша;
|
||
- поддерживать очередь upload/download через WorkManager;
|
||
- показывать прогресс больших передач;
|
||
- повторять неудачные передачи.
|
||
|
||
### Архитектура Android-клиента
|
||
|
||
Рекомендуемый стек:
|
||
|
||
- Kotlin;
|
||
- Jetpack Compose;
|
||
- Material 3;
|
||
- Navigation Compose;
|
||
- ViewModel;
|
||
- StateFlow;
|
||
- Room для локального кэша;
|
||
- DataStore для настроек;
|
||
- OkHttp для API;
|
||
- Kotlin serialization;
|
||
- SignalR client для realtime;
|
||
- Coil для изображений;
|
||
- Media3 для видео;
|
||
- WorkManager для фоновых upload/download;
|
||
- Firebase Messaging.
|
||
|
||
Структура клиента:
|
||
|
||
- `app` - dependency container, app bootstrap;
|
||
- `core/network` - ApiClient, ServerConfig;
|
||
- `core/model` - DTO/model classes;
|
||
- `core/realtime` - realtime service;
|
||
- `core/local` - Room entities/DAO/cache;
|
||
- `core/settings` - DataStore settings;
|
||
- `core/push` - Firebase/push;
|
||
- `feature/login`;
|
||
- `feature/chats`;
|
||
- `feature/chat`;
|
||
- `feature/profile`;
|
||
- `feature/settings`;
|
||
- `feature/stories`;
|
||
- `feature/call`;
|
||
- `feature/bots`;
|
||
- `feature/search`;
|
||
- `feature/forward`;
|
||
- `feature/chatinfo`;
|
||
- `feature/transfer`.
|
||
|
||
### Архитектура backend
|
||
|
||
Рекомендуемый стек:
|
||
|
||
- ASP.NET Core;
|
||
- Controllers для REST API;
|
||
- SignalR Hub для realtime;
|
||
- EF Core;
|
||
- JWT Bearer auth;
|
||
- SQLite/PostgreSQL;
|
||
- hosted services для фоновых задач;
|
||
- local file storage для uploads;
|
||
- Dockerfile.
|
||
|
||
Структура backend:
|
||
|
||
- `Controllers/AuthController`;
|
||
- `Controllers/UsersController`;
|
||
- `Controllers/ChatsController`;
|
||
- `Controllers/StoriesController`;
|
||
- `Controllers/BotsController`;
|
||
- `Controllers/BotApiController`;
|
||
- `Controllers/PushController`;
|
||
- `Controllers/AppUpdatesController`;
|
||
- `Controllers/AdminController`;
|
||
- `Infrastructure/Hubs/MessengerHub`;
|
||
- `Infrastructure/Storage/AttachmentStorageService`;
|
||
- `Infrastructure/Storage/AvatarStorageService`;
|
||
- `Infrastructure/Auth/TokenService`;
|
||
- `Infrastructure/Push`;
|
||
- `Infrastructure/Calls`;
|
||
- `Infrastructure/Bots`;
|
||
- `Infrastructure/Admin`;
|
||
- `Data/IkarDbContext`;
|
||
- `Data/Entities`.
|
||
|
||
### Основные backend entities
|
||
|
||
Нужно спроектировать сущности:
|
||
|
||
- User;
|
||
- UserSession;
|
||
- Chat;
|
||
- ChatMember;
|
||
- Message;
|
||
- MessageAttachment;
|
||
- MessageReaction;
|
||
- MessageReadReceipt;
|
||
- ChatInviteLink;
|
||
- ChatTopic;
|
||
- Story;
|
||
- StoryAttachment;
|
||
- Bot;
|
||
- BotCommand;
|
||
- BotUpdate;
|
||
- PushDevice;
|
||
- CallSession;
|
||
- Admin/moderation logs.
|
||
|
||
### REST API
|
||
|
||
Минимальные API группы:
|
||
|
||
#### Auth
|
||
|
||
- `POST /api/auth/phone/request-code`;
|
||
- `POST /api/auth/phone/verify`;
|
||
- `POST /api/auth/email/request-code`;
|
||
- `POST /api/auth/email/verify`;
|
||
- `POST /api/auth/refresh`;
|
||
- `POST /api/auth/logout`;
|
||
- `GET /api/auth/sessions`;
|
||
- `DELETE /api/auth/sessions/{id}`.
|
||
|
||
#### Users
|
||
|
||
- `GET /api/users/me`;
|
||
- `PUT /api/users/me`;
|
||
- `POST /api/users/me/avatar`;
|
||
- `GET /api/users/{id}`;
|
||
- `GET /api/users/search?q=...`;
|
||
- `GET /api/users/{id}/avatar`.
|
||
|
||
#### Chats
|
||
|
||
- `GET /api/chats`;
|
||
- `POST /api/chats/direct`;
|
||
- `POST /api/chats/groups`;
|
||
- `POST /api/chats/channels`;
|
||
- `GET /api/chats/{chatId}`;
|
||
- `PUT /api/chats/{chatId}`;
|
||
- `DELETE /api/chats/{chatId}`;
|
||
- `GET /api/chats/{chatId}/messages`;
|
||
- `POST /api/chats/{chatId}/messages`;
|
||
- `PUT /api/chats/{chatId}/messages/{messageId}`;
|
||
- `DELETE /api/chats/{chatId}/messages/{messageId}`;
|
||
- `POST /api/chats/{chatId}/messages/{messageId}/reactions`;
|
||
- `POST /api/chats/{chatId}/attachments`;
|
||
- `POST /api/chats/{chatId}/attachments/album`;
|
||
- `GET /api/chats/{chatId}/attachments/{attachmentId}/content`;
|
||
- `POST /api/chats/{chatId}/members`;
|
||
- `DELETE /api/chats/{chatId}/members/{userId}`;
|
||
- `GET /api/chats/{chatId}/search`.
|
||
|
||
|
||
|
||
#### Push
|
||
|
||
- `POST /api/push/devices`;
|
||
- `DELETE /api/push/devices/{id}`;
|
||
- `PUT /api/push/settings`.
|
||
|
||
|
||
|
||
#### Admin
|
||
|
||
- `GET /admin/api/status`;
|
||
- `GET /admin/api/users`;
|
||
- `GET /admin/api/chats`;
|
||
- `GET /admin/api/messages`;
|
||
- `GET /admin/api/attachments`;
|
||
- `GET /admin/api/attachments/{id}/content`;
|
||
- `DELETE /admin/api/attachments/{id}`;
|
||
- `DELETE /admin/api/users/{id}`;
|
||
- `DELETE /admin/api/chats/{id}`.
|
||
|
||
### Realtime hub
|
||
|
||
Realtime должен поддерживать:
|
||
|
||
- подключение авторизованного пользователя;
|
||
- join/leave chat groups;
|
||
- отправку нового сообщения всем участникам;
|
||
- обновление сообщения;
|
||
- удаление сообщения;
|
||
- reaction update;
|
||
- typing indicator;
|
||
- read receipts;
|
||
- online/presence;
|
||
- call signaling;
|
||
- story changed notification;
|
||
- chat list invalidation.
|
||
|
||
Пример событий:
|
||
|
||
- `MessageCreated`;
|
||
- `MessageUpdated`;
|
||
- `MessageDeleted`;
|
||
- `ReactionUpdated`;
|
||
- `TypingChanged`;
|
||
- `ChatUpdated`;
|
||
- `UserPresenceChanged`;
|
||
- `IncomingCall`;
|
||
- `CallAccepted`;
|
||
- `CallDeclined`;
|
||
- `CallEnded`;
|
||
- `WebRtcOffer`;
|
||
- `WebRtcAnswer`;
|
||
- `IceCandidate`;
|
||
- `StoriesChanged`.
|
||
|
||
### UI/UX стиль
|
||
|
||
Общее направление:
|
||
|
||
- Telegram-like;
|
||
- чистый светлый интерфейс;
|
||
- быстрые списки;
|
||
- минимум декоративности;
|
||
- акцентный голубой цвет;
|
||
- аккуратные rounded shapes;
|
||
- сообщения компактные;
|
||
- медиа без лишних рамок;
|
||
- настройки плотные и понятные;
|
||
- нижняя composer-панель всегда удобная.
|
||
|
||
Цвета можно использовать примерно такие:
|
||
|
||
- accent blue: `#3390EC`;
|
||
- text dark: `#17212B`;
|
||
- muted text: `#6C7883`;
|
||
- incoming bubble: `#FFFFFF`;
|
||
- outgoing bubble: `#E7F7C8`;
|
||
- app background: `#F3F7FA`;
|
||
- media placeholder: лучше прозрачный или нейтральный, но не белый прямоугольник вокруг фото.
|
||
|
||
### Экран чата
|
||
|
||
Экран чата должен включать:
|
||
|
||
- header с back, avatar, title, subtitle/online, menu;
|
||
- список сообщений;
|
||
- date separators;
|
||
- pinned message banner;
|
||
- search mode;
|
||
- selection mode;
|
||
- reply/edit panel;
|
||
- composer;
|
||
- attach button;
|
||
- emoji/GIF/sticker picker;
|
||
- voice record button;
|
||
- send button;
|
||
- scroll-to-bottom button;
|
||
- active transfer cards;
|
||
- call banner.
|
||
|
||
Поведение:
|
||
|
||
- новые сообщения добавляются снизу;
|
||
- автоскролл вниз, если пользователь уже внизу;
|
||
- если пользователь выше по истории, показывать кнопку вниз;
|
||
- свайп сообщения влево/вправо для reply;
|
||
- long press для selection/context actions;
|
||
- double tap для reaction, если реализуется.
|
||
|
||
### Composer
|
||
|
||
Composer должен поддерживать:
|
||
|
||
- многострочный ввод;
|
||
- attach picker;
|
||
- отправку текста;
|
||
- отправку вложений;
|
||
- preview выбранного файла;
|
||
- preview альбома;
|
||
- remove attachment;
|
||
- reply state;
|
||
- edit state;
|
||
- emoji/sticker/GIF panel;
|
||
- voice recording.
|
||
|
||
### Встроенный image loader
|
||
|
||
Для авторизованных картинок:
|
||
|
||
- использовать access token в Authorization header;
|
||
- иметь disk/memory cache key, зависящий от URL и token;
|
||
- поддерживать callback успешной загрузки, чтобы UI мог узнать intrinsic size;
|
||
- не показывать частично скачанный файл;
|
||
- для full-screen использовать fit;
|
||
- для chat preview использовать crop только когда aspect ratio контейнера отличается от изображения.
|
||
|
||
### Admin panel
|
||
|
||
Admin UI должен быть web-страницей внутри сервера.
|
||
|
||
Возможности:
|
||
|
||
- dashboard server status;
|
||
- список пользователей;
|
||
- список чатов;
|
||
- список сообщений;
|
||
- список вложений;
|
||
- скачивание вложения;
|
||
- удаление вложения;
|
||
- удаление пользователя;
|
||
- удаление чата;
|
||
- фильтры и поиск;
|
||
- отображение размера файлов и количества записей.
|
||
|
||
### Обновления приложения
|
||
|
||
Нужен механизм обновления Android-клиента:
|
||
|
||
- сервер или отдельный catalog endpoint отдает manifest;
|
||
- приложение проверяет latest release;
|
||
- сравнивает versionName/versionCode;
|
||
- скачивает APK;
|
||
- проверяет SHA-256;
|
||
- запускает Android package installer;
|
||
- записывает установленную версию только после успешной установки.
|
||
|
||
Manifest должен содержать:
|
||
|
||
- slug;
|
||
- name;
|
||
- version;
|
||
- androidVersionCode;
|
||
- channel;
|
||
- platform;
|
||
- packageKind;
|
||
- downloadPath;
|
||
- packageSizeBytes;
|
||
- sha256;
|
||
- notes;
|
||
- publishedAt.
|
||
|
||
Важно:
|
||
|
||
- все APK-обновления должны быть подписаны одним и тем же release/upload key;
|
||
- нельзя публиковать APK с новым случайным ключом поверх уже установленного приложения.
|
||
|
||
### Хранение файлов
|
||
|
||
Сервер должен:
|
||
|
||
- сохранять вложения в отдельную директорию;
|
||
- генерировать безопасные имена файлов;
|
||
- хранить оригинальное имя отдельно;
|
||
- не доверять client filename;
|
||
- определять content type по заголовку и расширению;
|
||
- удалять физический файл при удалении attachment/message/chat/user;
|
||
- запрещать path traversal;
|
||
- отдавать файл только авторизованным участникам чата.
|
||
|
||
### Docker и deployment
|
||
|
||
Нужно подготовить:
|
||
|
||
- `Dockerfile.server`;
|
||
- docker-compose для сервера и БД, если нужно;
|
||
- appsettings для production/development;
|
||
- переменные окружения для JWT, storage path, admin password, SMTP, Firebase;
|
||
- scripts для smoke tests;
|
||
- scripts для публикации Android APK.
|
||
|
||
### Тестирование
|
||
|
||
Обязательные тесты backend:
|
||
|
||
- auth flow;
|
||
- create direct chat;
|
||
- send message;
|
||
- upload attachment;
|
||
- download attachment access control;
|
||
- group member permissions;
|
||
- channel post permissions;
|
||
- reactions;
|
||
- stories visibility;
|
||
- bot sendMessage/sendPhoto;
|
||
- admin delete user/chat/attachment;
|
||
- push dispatcher.
|
||
|
||
Обязательные проверки Android:
|
||
|
||
- compileDebugKotlin;
|
||
- assembleRelease;
|
||
- отправка текста;
|
||
- отправка фото;
|
||
- фото в чате без белого прямоугольника;
|
||
- full-screen preview открывает полное фото;
|
||
- получатель видит фото без частичного JPEG;
|
||
- отправка альбома;
|
||
- voice note;
|
||
- video preview/player;
|
||
- push notification;
|
||
- login/session restore.
|
||
|
||
### Критерии приемки MVP
|
||
|
||
MVP считается готовым, если:
|
||
|
||
- пользователь может зарегистрироваться/войти;
|
||
- видит список чатов;
|
||
- может создать личный чат;
|
||
- может отправить и получить текст в real-time;
|
||
- может отправить фото;
|
||
- фото отображается в чате без белого пузыря и без поломанного partial preview;
|
||
- фото открывается на весь экран;
|
||
- можно отправить файл;
|
||
- можно отправить voice note;
|
||
- есть push для новых сообщений;
|
||
- есть локальный кэш сообщений;
|
||
- backend проверяет права доступа;
|
||
- Android APK собирается release-сборкой;
|
||
- APK обновляется через manifest/catalog.
|
||
|
||
### Критерии приемки полной версии
|
||
|
||
Полная версия считается готовой, если дополнительно есть:
|
||
|
||
- группы;
|
||
- каналы;
|
||
- обсуждения каналов;
|
||
- сторис;
|
||
- аудио/видео звонки;
|
||
- боты;
|
||
- глобальный поиск;
|
||
- админка;
|
||
- настройки приватности;
|
||
- настройки чатов;
|
||
- media gallery/materials;
|
||
- transfer queue;
|
||
- Argus-like publication flow;
|
||
- smoke tests;
|
||
- базовая документация для запуска.
|
||
|
||
## Особые требования к качеству
|
||
|
||
- Приложение должно ощущаться быстрым.
|
||
- Все сетевые ошибки должны иметь понятное сообщение.
|
||
- Нельзя блокировать UI во время upload/download.
|
||
- Нельзя показывать недокачанный файл как готовый.
|
||
- Нельзя терять draft при повороте/перезапуске.
|
||
- Нельзя отдавать вложения неучастникам чата.
|
||
- Нельзя публиковать Android update с другим signing certificate.
|
||
- Нужно очищать временные файлы.
|
||
- Нужно избегать больших белых полей вокруг медиа.
|
||
- Нужно хранить секреты только в env/local ignored files.
|
||
|
||
## Подсказка для нейросети-разработчика
|
||
|
||
Если ты создаешь проект по этому ТЗ, сначала сгенерируй архитектуру и каркас:
|
||
|
||
1. Backend API + database entities.
|
||
2. Android app shell + auth/session.
|
||
3. Chat list + chat screen.
|
||
4. Realtime messages.
|
||
5. Attachments upload/download.
|
||
6. Correct image rendering and cache safety.
|
||
7. Push notifications.
|
||
8. Groups/channels/stories/calls/bots.
|
||
9. Admin panel.
|
||
10. Release/update flow.
|
||
|
||
Не начинай с лендинга. Первый экран приложения после входа - список чатов. Если пользователь не авторизован - экран входа.
|
||
|
||
Главный UX-ориентир: это должен быть рабочий мессенджер, а не демонстрационная страница.
|