Корпоративное 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 токенами:

  1. При входе:

    • Получает access и refresh токены
    • Сохраняет их в SecureStorage
    • Устанавливает в HTTP заголовки
  2. При запросах:

    • Автоматически добавляет Bearer токен
    • При 401/403 пытается обновить токен
    • Повторяет запрос после обновления
  3. При выходе:

    • Очищает токены из 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

📚 Документация

⚠️ Важные замечания

  1. SecureStorage - Токены хранятся в защищенном хранилище платформы
  2. Автоматический Refresh - Access токен обновляется прозрачно при 401/403
  3. WebSocket Reconnect - При разрыве соединения нужно реализовать переподключение
  4. 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.

📄 Лицензия

MIT

👥 Автор

Создано для корпоративного использования в компании.

📞 Поддержка

При возникновении проблем создайте issue в репозитории проекта.

Description
Мультиплатформенное приложение для портала "HiRo"
Readme 756 KiB
Languages
C# 97.4%
PowerShell 2.1%
Batchfile 0.5%