Корпоративное MAUI приложение
Кроссплатформенное корпоративное приложение для общения между сотрудниками компании, построенное на .NET MAUI.
📱 Возможности
- ✅ Аутентификация - безопасный вход в систему
- ✅ Список сотрудников - просмотр всех пользователей с фильтрацией и поиском
- ✅ Личные сообщения - обмен сообщениями между сотрудниками в реальном времени
- ✅ WebSocket подключение - мгновенная доставка сообщений
- ✅ Статусы пользователей - отображение онлайн/оффлайн статуса
- ✅ Индикатор набора текста - видно, когда собеседник печатает
- ✅ Профиль пользователя - просмотр информации о себе
- ✅ Поддержка Android, iOS, Windows, MacCatalyst
🏗️ Архитектура
Структура проекта
CORP-MAUI/
├── Models/ # Модели данных
│ ├── User.cs
│ ├── Message.cs
│ └── AuthResponse.cs
├── Services/ # Бизнес-логика
│ ├── ApiService.cs # REST API клиент
│ └── WebSocketService.cs # WebSocket клиент
├── Pages/ # Страницы приложения
│ ├── LoginPage.xaml
│ ├── UsersPage.xaml
│ ├── ChatPage.xaml
│ └── ProfilePage.xaml
├── ServiceProvider.cs # Singleton для сервисов
├── App.xaml.cs # Точка входа
└── AppShell.xaml # Навигация
Компоненты
1. ApiService - REST API клиент
Отвечает за HTTP запросы к серверу:
- Аутентификация (
POST /auth/login) - Получение списка пользователей (
GET /users) - Получение сообщений (
GET /messages) - Отправка сообщений (
POST /messages) - Поиск пользователей (
GET /users/search) - Обновление статуса (
PUT /users/status)
2. WebSocketService - WebSocket клиент
Обеспечивает real-time коммуникацию:
- Подключение к WebSocket серверу
- Отправка/получение сообщений
- Индикаторы набора текста
- Обновление статусов пользователей
- Автоматическое переподключение
3. ServiceProvider - Singleton провайдер
Централизованное управление сервисами приложения.
🔌 API Endpoints
Базовый URL: https://corp.robotail.pro/api/v1/
REST API
# Аутентификация
POST /auth/login
Content-Type: application/json
{
"username": "user",
"password": "pass"
}
# Получить список пользователей
GET /users
Authorization: Bearer {token}
# Получить текущего пользователя
GET /users/me
Authorization: Bearer {token}
# Поиск пользователей
GET /users/search?q={query}
Authorization: Bearer {token}
# Получить сообщения
GET /messages?userId={id}
Authorization: Bearer {token}
# Отправить сообщение
POST /messages
Authorization: Bearer {token}
Content-Type: application/json
{
"receiverId": 123,
"content": "Текст сообщения"
}
# Обновить статус
PUT /users/status
Authorization: Bearer {token}
Content-Type: application/json
{
"isOnline": true
}
WebSocket
URL: wss://corp.robotail.pro/api/v1/ws
Headers: Authorization: Bearer {token}
# Отправка сообщения
{
"type": "message",
"data": {
"receiverId": 123,
"content": "Текст сообщения"
}
}
# Индикатор набора текста
{
"type": "typing",
"data": {
"recipientId": 123,
"isTyping": true
}
}
# Получение сообщения (от сервера)
{
"type": "message",
"data": {
"id": 456,
"senderId": 789,
"senderName": "Иван Иванов",
"content": "Привет!",
"timestamp": "2026-01-08T10:30:00Z"
}
}
# Обновление статуса пользователя (от сервера)
{
"type": "user_status",
"data": {
"id": 123,
"isOnline": true
}
}
🚀 Установка и запуск
Требования
- .NET 9.0 SDK
- Visual Studio 2022 / JetBrains Rider
- Для Android: Android SDK (см. ANDROID_SETUP.md)
- Для iOS: Xcode и Mac
⚙️ Настройка Android SDK
Если Android SDK установлен по нестандартному пути, создан файл Directory.Build.props в корне решения:
<Project>
<PropertyGroup>
<AndroidSdkDirectory>D:\Applications\Android\SDK</AndroidSdkDirectory>
</PropertyGroup>
</Project>
Важно: Измените путь на ваш, если SDK установлен в другом месте.
Подробная инструкция: ANDROID_SETUP.md
Скрипты сборки для Android
Для удобной сборки Android используйте готовые скрипты:
# PowerShell (рекомендуется)
.\build-android.ps1
# Batch
.\build-android.bat
Скрипты автоматически настроят переменные окружения и соберут проект.
Установка зависимостей
# CORP-MAUI - Корпоративное приложение для сотрудников
Мобильное приложение для внутрикорпоративного общения между сотрудниками компании.
## 🚀 Технологии
- **.NET MAUI 9.0** - Кросс-платформенный фреймворк
- **C# 12** - Язык программирования
- **WebSocket** - Обмен сообщениями в реальном времени
- **REST API** - Взаимодействие с сервером
- **JWT Authentication** - Безопасная аутентификация
- **SecureStorage** - Безопасное хранение токенов
## 📱 Возможности
### Аутентификация
- Вход по email и паролю
- Автоматическое сохранение JWT токенов
- Автоматическое обновление access токена при истечении
- Безопасное хранение токенов в SecureStorage
### Профиль пользователя
- Просмотр личной информации
- Отображение статуса (в сети/не в сети)
- Выход из системы
### Список сотрудников
- Просмотр всех сотрудников компании
- Поиск по имени, отделу, должности
- Отображение статуса онлайн/офлайн
- Pull-to-refresh для обновления списка
### Чат
- Обмен личными сообщениями
- Обмен в реальном времени через WebSocket
- Отображение истории сообщений
- Индикатор набора текста
- Резервная отправка через REST API
## 🏗️ Архитектура
CORP-MAUI/ ├── Models/ # Модели данных │ ├── User.cs # Модель пользователя │ ├── Message.cs # Модель сообщения │ └── AuthResponse.cs # Ответ аутентификации ├── Services/ # Сервисы │ ├── ApiService.cs # HTTP-клиент для REST API │ └── WebSocketService.cs # WebSocket-клиент ├── Pages/ # Страницы приложения │ ├── LoginPage.xaml # Страница входа │ ├── ProfilePage.xaml # Профиль пользователя │ ├── UsersPage.xaml # Список сотрудников │ └── ChatPage.xaml # Чат с сотрудником └── ServiceProvider.cs # Глобальный провайдер сервисов
## 🔌 API Endpoints
**Базовый URL:** `https://corp.robotail.pro`
### Аутентификация
```http
POST /api/auth/token/
Body: { "email": "user@example.com", "password": "password" }
Response: { "access": "token", "refresh": "token" }
POST /api/auth/token/refresh/
Body: { "refresh": "token" }
Response: { "access": "new_token" }
Пользователи
GET /api/v1/employees/
Response: [{ "id": 1, "username": "user", ... }]
GET /api/v1/employees/me/
Response: { "id": 1, "username": "user", ... }
GET /api/v1/users/search/?q=query
Response: [{ "id": 1, "username": "user", ... }]
PUT /api/v1/users/status/
Body: { "isOnline": true }
Сообщения
GET /api/v1/messages/
Response: [{ "id": 1, "content": "Hello", ... }]
GET /api/v1/messages/?user_id=1
Response: [{ "id": 1, "content": "Hello", ... }]
POST /api/v1/messages/
Body: { "senderId": 1, "receiverId": 2, "content": "Hello" }
WebSocket
Поддерживаются следующие варианты URL (автоматический подбор):
- wss://corp.robotail.pro/ws (основной)
- ws://corp.robotail.pro/ws (без SSL)
- wss://corp.robotail.pro/ws/ (со слешем)
- и другие варианты...
ВАЖНО! Обязательный заголовок при подключении:
Authorization: Bearer {access_token}
Пример подключения:
var ws = new ClientWebSocket();
ws.Options.SetRequestHeader("Authorization", $"Bearer {token}");
await ws.ConnectAsync(new Uri("wss://corp.robotail.pro/ws"), cancellationToken);
Типы сообщений:
- message: Новое сообщение
- user_status: Изменение статуса пользователя
- typing: Индикатор набора текста
Формат сообщений:
{
"type": "message",
"data": {
"senderId": 1,
"receiverId": 2,
"content": "Текст сообщения",
"timestamp": "2026-01-09T12:00:00Z"
}
}
Примечание:
- WebSocketService автоматически пробует разные варианты URL и подключается к первому работающему
- Заголовок Authorization устанавливается автоматически при вызове
ConnectAsync(token) - Токен передается в формате JWT Bearer token
🔐 Система управления токенами
ApiService автоматически управляет JWT токенами:
-
При входе:
- Получает access и refresh токены
- Сохраняет их в SecureStorage
- Устанавливает в HTTP заголовки
-
При запросах:
- Автоматически добавляет Bearer токен
- При 401/403 пытается обновить токен
- Повторяет запрос после обновления
-
При выходе:
- Очищает токены из SecureStorage
- Удаляет заголовки авторизации
📝 Использование
Пример авторизации
var result = await ServiceProvider.ApiService.LoginAsync(email, password);
if (result.Success)
{
// Токены автоматически сохранены
var user = result.User;
await ServiceProvider.WebSocketService.ConnectAsync(result.Token);
Application.Current.MainPage = new AppShell();
}
Пример получения данных
// Автоматически обновит токен при необходимости
var employees = await ServiceProvider.ApiService.GetEmployeesAsync();
var currentUser = await ServiceProvider.ApiService.GetCurrentUserAsync();
Пример отправки сообщения
var message = new Message
{
SenderId = currentUser.Id,
ReceiverId = recipient.Id,
Content = "Hello!",
Timestamp = DateTime.Now,
Type = MessageType.Personal
};
// Через WebSocket (приоритет)
if (ServiceProvider.WebSocketService.IsConnected)
{
await ServiceProvider.WebSocketService.SendMessageAsync(message);
}
else
{
// Резервный метод через REST API
await ServiceProvider.ApiService.SendMessageAsync(message);
}
Пример выхода
await ServiceProvider.ApiService.UpdateStatusAsync(false);
await ServiceProvider.WebSocketService.DisconnectAsync();
ServiceProvider.ApiService.Logout(); // Очищает токены
Application.Current.MainPage = new NavigationPage(new LoginPage());
🔧 Конфигурация
Вы можете настроить ApiService при создании:
var config = new ApiConfig
{
BaseUrl = "https://your-api.com/api",
TokenObtainPath = "/auth/token/",
TokenRefreshPath = "/auth/token/refresh/",
Timeout = 30,
DefaultHeaders = new Dictionary<string, string>
{
{ "Accept", "application/json" },
{ "X-Custom-Header", "value" }
}
};
var apiService = new ApiService(config);
🛠️ Сборка и запуск
Требования
- Visual Studio 2022 или JetBrains Rider
- .NET 9.0 SDK
- Android SDK (для Android)
- Xcode (для iOS/macOS)
Запуск
# Android
dotnet build -t:Run -f net9.0-android
# iOS
dotnet build -t:Run -f net9.0-ios
# Windows
dotnet build -t:Run -f net9.0-windows10.0.19041.0
📚 Документация
- API_REFACTORING.md - Подробное описание рефакторинга ApiService
- .NET MAUI Documentation
⚠️ Важные замечания
- SecureStorage - Токены хранятся в защищенном хранилище платформы
- Автоматический Refresh - Access токен обновляется прозрачно при 401/403
- WebSocket Reconnect - При разрыве соединения нужно реализовать переподключение
- Offline Mode - Можно добавить локальное кэширование сообщений
🤝 Вклад
Проект находится в разработке. Приветствуются pull requests и issue reports.
📄 Лицензия
Корпоративное приложение для внутреннего использования.
Версия: 1.0.0
Дата обновления: 2026-01-09
dotnet restore
### Сборка проекта
```powershell
# Для Android
dotnet build -f net9.0-android
# Для Windows
dotnet build -f net9.0-windows10.0.19041.0
# Для iOS
dotnet build -f net9.0-ios
# Для MacCatalyst
dotnet build -f net9.0-maccatalyst
Запуск приложения
# Android
dotnet run -f net9.0-android
# Windows
dotnet run -f net9.0-windows10.0.19041.0
🔧 Конфигурация
Изменение API URL
В файле Services/ApiService.cs:
private const string BaseUrl = "https://corp.robotail.pro/api/v1/";
В файле Services/WebSocketService.cs:
private const string WebSocketUrl = "wss://corp.robotail.pro/api/v1/ws";
📚 Используемые технологии
- .NET 9.0 - фреймворк
- .NET MAUI - UI фреймворк
- Newtonsoft.Json - JSON сериализация
- System.Net.WebSockets - WebSocket клиент
- SecureStorage - безопасное хранение данных
🎨 UI/UX особенности
- Material Design стиль
- Адаптивный дизайн для разных экранов
- Плавные анимации и переходы
- Индикаторы загрузки
- Обработка ошибок с user-friendly сообщениями
- Pull-to-refresh для обновления данных
🔐 Безопасность
- Токены хранятся в SecureStorage
- HTTPS для REST API
- WSS (WebSocket Secure) для real-time коммуникации
- Автоматический выход при истечении токена
📝 Примеры использования
Отправка сообщения через WebSocket
var message = new Message
{
SenderId = currentUser.Id,
ReceiverId = recipient.Id,
Content = "Привет!",
Timestamp = DateTime.Now
};
await ServiceProvider.WebSocketService.SendMessageAsync(message);
Поиск пользователей
var users = await ServiceProvider.ApiService.SearchUsersAsync("Иван");
Подписка на новые сообщения
ServiceProvider.WebSocketService.MessageReceived += (sender, message) =>
{
// Обработка нового сообщения
Console.WriteLine($"Новое сообщение от {message.SenderName}: {message.Content}");
};
🐛 Известные проблемы
- WebSocket может разрываться при неактивности (реализовано автоматическое переподключение)
- На iOS требуются дополнительные разрешения для фоновой работы
🤝 Вклад в проект
Пул-реквесты приветствуются! Для крупных изменений, пожалуйста, сначала откройте issue.
📄 Лицензия
👥 Автор
Создано для корпоративного использования в компании.
📞 Поддержка
При возникновении проблем создайте issue в репозитории проекта.