Šepot — end-to-end encrypted messenger

Initial public release. Anonymous on-device identity (no phone number,
e-mail, or password), Signal-protocol cryptography (X3DH + PQXDH, Double
Ratchet, sealed sender) via libsignal, a metadata-minimizing relay,
group chats, disappearing messages, encrypted local storage, optional
Tor transport, and a UI localized into Czech, English, German, Russian,
and Italian.

Monorepo: Flutter client (app/), Rust relay + wire types (rust/),
protobuf definitions (proto/), self-host deploy (deploy/).

Licensed under AGPL-3.0 with an app-store distribution exception (§7).
This commit is contained in:
Julius Joska
2026-07-11 17:06:39 +02:00
commit 8081d98c67
309 changed files with 44102 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
private var apnsChannel: FlutterMethodChannel?
// Token dorazí asynchronně z APNs; když si o něj Dart řekne dřív, podržíme ho.
private var pendingToken: String?
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(
name: "cz.sepot.sepot/apns", binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler { [weak self] call, result in
switch call.method {
case "register":
// Nativní APNs registrace (bez Firebase) — token přijde v callbacku
application.registerForRemoteNotifications()
result(nil)
case "getToken":
result(self?.pendingToken)
default:
result(FlutterMethodNotImplemented)
}
}
apnsChannel = channel
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// APNs vydal device token → předáme Dartu (ten ho pošle relayi).
override func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let token = deviceToken.map { String(format: "%02x", $0) }.joined()
pendingToken = token
apnsChannel?.invokeMethod("onToken", arguments: token)
}
override func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
NSLog("APNs registrace selhala: \(error.localizedDescription)")
}
// Tichý „background" budíček z relaye (content-available:1). Probudí Dart,
// ať se připojí na WS a vyleje frontu. Obsah nikdy neneseme.
override func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
apnsChannel?.invokeMethod("onWake", arguments: nil)
// Dej WS chvíli na doručení; iOS background okno je krátké.
DispatchQueue.main.asyncAfter(deadline: .now() + 8) {
completionHandler(.newData)
}
}
}