8081d98c67
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).
76 lines
2.3 KiB
Dart
76 lines
2.3 KiB
Dart
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,
|
|
);
|
|
}
|
|
}
|