Š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:
@@ -0,0 +1,75 @@
|
||||
import 'package:sepot/models/identity.dart';
|
||||
|
||||
/// Kontakt — osoba, se kterou můžeme chatovat
|
||||
///
|
||||
/// Odpovídá Rust: Contact
|
||||
class Contact {
|
||||
String displayName;
|
||||
final PublicIdentity publicIdentity;
|
||||
final DateTime addedAt;
|
||||
bool verified;
|
||||
String? notes;
|
||||
|
||||
/// Blokovaný kontakt: příchozí zprávy se zahodí (ACKnou, ale neuloží ani
|
||||
/// nezobrazí) a odesílání je v UI zablokované.
|
||||
bool blocked;
|
||||
|
||||
Contact({
|
||||
required this.displayName,
|
||||
required this.publicIdentity,
|
||||
required this.addedAt,
|
||||
this.verified = false,
|
||||
this.notes,
|
||||
this.blocked = false,
|
||||
});
|
||||
|
||||
/// ID kontaktu = fingerprint identity klíče (identita = klíč).
|
||||
///
|
||||
/// Dřív náhodné UUID — vznikly tím DVĚ klíčové soustavy (konverzace se
|
||||
/// ukládaly pod UUID, UI ale routovalo fingerprintem), takže konverzace
|
||||
/// otevřená z kontaktů neuměla odeslat zprávu a chat list nenašel jméno.
|
||||
/// Bez datové migrace (žádná produkční data; testovací zařízení se
|
||||
/// re-párují — stejný precedens jako S9).
|
||||
String get id => publicIdentity.id;
|
||||
|
||||
/// Vytvoř nový kontakt z veřejné identity
|
||||
factory Contact.fromPublicIdentity(
|
||||
PublicIdentity identity, {
|
||||
bool verified = false,
|
||||
}) {
|
||||
return Contact(
|
||||
displayName: identity.displayName,
|
||||
publicIdentity: identity,
|
||||
addedAt: DateTime.now(),
|
||||
verified: verified,
|
||||
);
|
||||
}
|
||||
|
||||
/// Šepot ID kontaktu
|
||||
String get sepotId => publicIdentity.sepotId;
|
||||
|
||||
/// Otisk kontaktu (plné Crockford base32 zobrazení)
|
||||
String get fingerprint => publicIdentity.fingerprint.display;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'displayName': displayName,
|
||||
'publicIdentity': publicIdentity.toJson(),
|
||||
'addedAt': addedAt.toIso8601String(),
|
||||
'verified': verified,
|
||||
'notes': notes,
|
||||
'blocked': blocked,
|
||||
};
|
||||
|
||||
factory Contact.fromJson(Map<String, dynamic> json) {
|
||||
return Contact(
|
||||
displayName: json['displayName'] as String,
|
||||
publicIdentity: PublicIdentity.fromJson(
|
||||
json['publicIdentity'] as Map<String, dynamic>,
|
||||
),
|
||||
addedAt: DateTime.parse(json['addedAt'] as String),
|
||||
verified: json['verified'] as bool? ?? false,
|
||||
notes: json['notes'] as String?,
|
||||
blocked: json['blocked'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user