Files
Ikar/README.md
2026-05-17 22:23:43 +03:00

8.4 KiB

Ikar

Ikar is a working Telegram-like messenger MVP built in this folder with an ASP.NET Core backend, an Android MAUI client, and a dedicated WinUI 3 desktop client for Windows.

Stack

  • src/Ikar.Server: ASP.NET Core 10 Web API + SignalR + SQLite.
  • src/Ikar.Shared: shared DTO/contracts used by server and client.
  • src/Ikar.Client: .NET MAUI client targeting net10.0-android.
  • src/Ikar.WinUI: WinUI 3 desktop client targeting net10.0-windows10.0.19041.0.

Implemented

  • phone-based sign-in with one-time test codes
  • JWT access tokens with rotating refresh tokens
  • secure client-side session persistence
  • seeded demo accounts and sample chats
  • Android contact-book lookup against registered phone numbers
  • direct chats
  • group chats
  • channels with owner-only publishing
  • message history persisted in SQLite
  • file attachments with metadata persisted in SQLite
  • voice notes as audio-classified attachments
  • inline voice note playback in Android chat
  • message edit/delete with realtime updates
  • authenticated attachment download
  • real-time message delivery with SignalR
  • Android direct-chat audio/video calls with SignalR-based signaling and WebRTC media transport
  • dedicated Android call screen for incoming and outgoing audio calls
  • Android call ring/ringback tones and proximity-based screen blanking during active calls
  • Android push registration API and FCM-based push delivery pipeline
  • web admin panel for users, chats, attachments, and system status
  • public landing page at / with latest Android APK download
  • publishable Windows exe
  • publishable Android apk

Not Implemented

This is not full Telegram parity. The following are not implemented in this MVP:

  • microphone recording UI for voice notes
  • stickers and inline media previews
  • end-to-end encryption
  • advanced channel admin roles, granular moderation policies, multi-device sync edge cases
  • Windows cloud push notifications

Demo Accounts

  • alice, phone +10000000001
  • bob, phone +10000000002
  • carol, phone +10000000003

These are created automatically on first server start in src/Ikar.Server/Data/ikar.db.

Run

  1. Start the backend:
./scripts/run-server.ps1
  1. Run the Windows client from Visual Studio or CLI:
dotnet build .\src\Ikar.WinUI\Ikar.WinUI.csproj -f net10.0-windows10.0.19041.0 -p:Platform=x64
.\src\Ikar.WinUI\bin\x64\Debug\net10.0-windows10.0.19041.0\win-x64\Ikar.WinUI.exe
  1. Run the Android client from Visual Studio or install the generated APK:
dotnet build .\src\Ikar.Client\Ikar.Client.csproj -f net10.0-android

The Android client is hard-wired to the current production endpoint:

  • Android client default base URL: https://ikar.kusoft.xyz

The Android login screen no longer exposes a server URL field.

The production Docker deployment binds the backend to 127.0.0.1:5099 on the Raspberry Pi host. Public and LAN clients should use the reverse-proxied HTTPS endpoint instead of direct access to port 5099:

  • public Android / browser / admin URL: https://ikar.kusoft.xyz

Run In Docker

Docker assets for Raspberry Pi 5 are included in the repo:

  • Dockerfile.server
  • docker-compose.rpi5.yml
  • .env.example
  • .env.server
  • docs/raspberry-pi-5-docker.md

Quick start:

cp .env.example .env
docker compose -f docker-compose.rpi5.yml up -d --build

To place server data on an external disk, set IKAR_DATA_PATH before running Compose. The current production Pi uses /media/myDrive/ikar-data.

Health check:

curl http://127.0.0.1:5099/health

Admin panel:

  • /admin redirects to /admin/index.html
  • configure admin login through Admin__Username and Admin__Password
  • the admin surface uses its own cookie session and does not reuse messenger JWT tokens
  • / serves a public landing page with a button for the latest Android APK
  • /api/app-updates/android/download/latest returns the latest published Android APK
  • scripts/publish-android-update.ps1 keeps only the newest 3 Android APK files on the server by default; override with -KeepLatestCount <N> if needed

Publish

Windows EXE:

./scripts/publish-windows.ps1

Android APK:

./scripts/publish-android-apk.ps1

Smoke test against the running backend:

./scripts/smoke-test.ps1

Published Artifacts

  • Windows EXE: artifacts/winui-win64/Ikar.WinUI.exe
  • Android APK: src/Ikar.Client/bin/Release/net10.0-android/publish/com.seven.ikar.apk
  • Signed Android APK: src/Ikar.Client/bin/Release/net10.0-android/publish/com.seven.ikar-Signed.apk

Solutions

  • XML solution: Ikar.slnx
  • classic Visual Studio solution: IkarClassic.sln

Auth Notes

  • Android client auth is currently phone-only.
  • The current verification flow returns a temporary test code from the server and shows it in the client UI.
  • Real SMS delivery is not implemented yet; it can be connected later by adding an SMS provider.
  • Access tokens are short-lived JWTs.
  • Refresh tokens are rotated on refresh and stored as hashed server-side sessions.
  • Logout revokes the active session immediately, and the revoked access token stops working because the server validates the session id (sid) on authenticated requests.
  • Session LastSeenAt writes are throttled server-side to reduce unnecessary SQLite writes on every authenticated request.
  • The JWT signing key in src/Ikar.Server/appsettings.json is a development default. Replace it with a strong secret via configuration before any real deployment.

Contacts Notes

  • Android contact discovery requests READ_CONTACTS and only shows people from the device phone book.
  • Server-side contact resolution matches users by normalized phone number through api/users/contacts/resolve.
  • Users without a registered phone number do not appear in the Android contacts screen.

Attachment Notes

  • Attachments are stored on the server under src/Ikar.Server/Data/Attachments.
  • Metadata stored for each attachment: original file name, content type, file size, upload time, and owning message.
  • Audio files are classified as voice notes by MIME type / file extension and use the same secure attachment pipeline.
  • Attachment content is downloaded through an authenticated API route, not via a public static files directory.

Channel And Message Lifecycle Notes

  • Channels are broadcast rooms: the creator is the owner, selected users join as subscribers, and only owners can publish.
  • Message edit/delete is synchronized through SignalR MessageUpdated events.
  • Delete is implemented as a soft-delete on the message row with attachment cleanup on the server.

Call Notes

  • Calls are currently implemented only for Android and only in direct one-to-one chats.
  • The current call architecture uses SignalR for call lifecycle/signaling and WebRTC for audio/video media transport.
  • ICE servers are configured server-side through the WebRtc configuration section.
  • WinUI does not support calls in the current build.

Push Setup Notes

  • Android push in this repo is implemented through Firebase Cloud Messaging HTTP v1 on the server and FirebaseMessagingService on the Android client.
  • Server-side device registrations are stored in SQLite in the PushDevices table and managed through api/push/devices.
  • Push dispatch is queued through a background worker so message sends do not wait on outbound Firebase network latency.
  • To enable real Android delivery, set Push:FirebaseProjectId and either Push:ServiceAccountJsonPath or Push:ServiceAccountJson in src/Ikar.Server/appsettings.json or environment-specific configuration.
  • Before building the Android APK, fill src/Ikar.Client/Resources/Raw/firebase.android.json with the Android Firebase values: applicationId, projectId, apiKey, senderId.
  • If the Firebase configuration is left empty, the app still builds and the server still accepts device registrations, but actual FCM delivery is skipped.
  • The current Windows WinUI desktop target is unpackaged (WindowsPackageType=None), so this pass does not implement Windows cloud push.

Server Runtime Notes

  • Chat list loading now fetches only the latest message per chat for summary rendering instead of loading full message history.
  • The server exposes /health for container and deployment health checks.
  • The server exposes /admin/api/* plus static admin assets under /admin/* when admin credentials are configured.
  • Startup enables SQLite write-ahead logging and ensures an index on ChatMembers.UserId for chat list lookup.