Š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,40 @@
|
||||
import 'package:sepot/core/constants/app_constants.dart';
|
||||
import 'package:sepot/core/errors.dart';
|
||||
import 'package:sepot/core/storage/secure_storage.dart' show DecoyPinConflict;
|
||||
import 'package:sepot/l10n/generated/app_localizations.dart';
|
||||
|
||||
/// Přeloží chybu na větu pro uživatele.
|
||||
///
|
||||
/// Typované chyby (`SepotUserError`, `DecoyPinConflict`) mají vlastní
|
||||
/// lokalizované hlášky; cokoli neznámého spadne do obecné hlášky
|
||||
/// s technickým popisem — radši ošklivá pravda než němé selhání.
|
||||
String describeError(AppLocalizations l10n, Object error) => switch (error) {
|
||||
TrustRootChangedError() => l10n.errorTrustRootChanged,
|
||||
RelayUnavailableError() => l10n.errorRelayUnavailable,
|
||||
AttachmentTooLargeError(:final maxMb) =>
|
||||
l10n.errorAttachmentTooLarge(maxMb),
|
||||
GroupNeedsMemberError() => l10n.errorGroupNeedsMember,
|
||||
GroupTooLargeError(:final maxMembers) =>
|
||||
l10n.errorGroupMaxMembers(maxMembers),
|
||||
MemberNoDeliveryAddressError(:final displayName) =>
|
||||
l10n.errorMemberNoDeliveryAddress(displayName),
|
||||
ContactNoDeliveryAddressError() => l10n.errorContactNoDeliveryAddress,
|
||||
IdentityKeyMismatchError() => l10n.errorIdentityKeyMismatch,
|
||||
MnemonicWordCountError(:final count, :final expected) =>
|
||||
l10n.restoreErrorMnemonicWordCount(count, expected),
|
||||
MnemonicInvalidError(:final detail) =>
|
||||
l10n.restoreErrorInvalidMnemonic(detail),
|
||||
BackupCorruptedError() => l10n.backupErrorCorruptedFile,
|
||||
BackupUnknownFormatError() => l10n.backupErrorUnknownFormat,
|
||||
BackupWrongIdentityError() => l10n.backupErrorWrongIdentity,
|
||||
ContactAlreadyExistsError() => l10n.contactsErrorAlreadyExists,
|
||||
ReportEmptyDescriptionError() => l10n.reportErrorEmptyDescription,
|
||||
ReportConnectionError() =>
|
||||
l10n.reportErrorConnection(AppConstants.supportEmail),
|
||||
ReportRateLimitedError() =>
|
||||
l10n.reportErrorRateLimited(AppConstants.supportEmail),
|
||||
ReportServerError(:final statusCode) =>
|
||||
l10n.reportErrorServer(statusCode, AppConstants.supportEmail),
|
||||
DecoyPinConflict() => l10n.settingsDecoyPinConflict,
|
||||
_ => l10n.errorGeneric(error.toString()),
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:sepot/l10n/generated/app_localizations.dart';
|
||||
|
||||
export 'package:sepot/l10n/generated/app_localizations.dart';
|
||||
|
||||
/// Zkratka pro přístup k lokalizovaným textům: `context.l10n.klic`.
|
||||
extension L10nX on BuildContext {
|
||||
AppLocalizations get l10n => AppLocalizations.of(this);
|
||||
}
|
||||
|
||||
/// Lokalizace mimo widget tree (notifikace, headless push start).
|
||||
///
|
||||
/// Preferuje ruční volbu jazyka (`override`, typicky
|
||||
/// `LocaleNotifier.readStored()`), jinak jazyk systému; nepodporovaný
|
||||
/// jazyk spadne na angličtinu — stejné pořadí jako `supportedLocales`.
|
||||
AppLocalizations l10nFor(Locale? override) {
|
||||
final locale = override ?? PlatformDispatcher.instance.locale;
|
||||
final lang = Locale(locale.languageCode);
|
||||
final supported = AppLocalizations.delegate.isSupported(lang);
|
||||
return lookupAppLocalizations(supported ? lang : const Locale('en'));
|
||||
}
|
||||
Reference in New Issue
Block a user