use crate::actions::AppAction;
use crate::state::{AppState, MutualGroupsSnapshot, PeerProfileDebugSnapshot};
use crate::DesktopNearbySnapshot;
use flume::Sender;
use nostr_sdk::prelude::{Event, RelayStatus};
#[derive(uniffi::Enum, Clone, Debug)]
#[allow(clippy::large_enum_variant)]
pub enum AppUpdate {
CallMedia {
call_id: String,
kind: u8,
sequence: u32,
timestamp_us: u64,
key_frame: bool,
data: Vec<u8>,
},
FullState(AppState),
PersistAccountBundle {
rev: u64,
owner_nsec: Option<String>,
owner_pubkey_hex: String,
device_nsec: String,
},
PersistPendingDeviceLink {
device_nsec: String,
approval_bootstrap_json: String,
},
ClearPendingDeviceLink,
SignerLoginSignEvent {
request_id: String,
owner_pubkey_hex: String,
unsigned_event_json: String,
},
NearbyPublishedEvent {
event_id: String,
kind: u32,
created_at_secs: u64,
event_json: String,
},
NearbyPeersChanged {
snapshot: DesktopNearbySnapshot,
bluetooth_peer_ids: Vec<String>,
lan_peer_ids: Vec<String>,
},
}
pub(crate) fn enqueue_update_for_delivery(
update: AppUpdate,
latest_full_state: &mut Option<AppUpdate>,
before_full_state: &mut Vec<AppUpdate>,
after_full_state: &mut Vec<AppUpdate>,
) {
match update {
full @ AppUpdate::FullState(_) => *latest_full_state = Some(full),
nearby @ (AppUpdate::CallMedia { .. }
| AppUpdate::NearbyPublishedEvent { .. }
| AppUpdate::NearbyPeersChanged { .. }) => after_full_state.push(nearby),
other => before_full_state.push(other),
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct FipsNearbyLinkSnapshot {
pub(crate) device_pubkey_hex: String,
pub(crate) transport_type: String,
pub(crate) transport_addr: Option<String>,
}
#[derive(Debug)]
pub(crate) enum CoreMsg {
Action(AppAction),
AcceptDirectFiles {
chat_id: String,
transfer_id: String,
destination: std::sync::Arc<dyn crate::DirectFileDestination>,
},
Internal(Box<InternalEvent>),
ExportSupportBundle(Sender<String>),
PeerProfileDebug {
owner_input: String,
reply_tx: Sender<Option<PeerProfileDebugSnapshot>>,
},
MutualGroups {
owner_input: String,
reply_tx: Sender<MutualGroupsSnapshot>,
},
AttachHostBle {
attachment: crate::core::HostBleAttachment,
reply_tx: Sender<Result<(), String>>,
},
DetachHostBle {
ownership: crate::core::HostBleOwnership,
reply_tx: Sender<()>,
},
HostBleActivity {
ownership: crate::core::HostBleOwnership,
generation: u64,
active: bool,
reply_tx: Sender<bool>,
},
PrepareForSuspend(Sender<()>),
CorePerfCounters(Sender<CorePerfCountersSnapshot>),
Shutdown(Option<Sender<()>>),
#[cfg(test)]
PanicForTest,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct CorePerfCountersSnapshot {
pub debug_snapshot_builds: u64,
}
#[derive(Debug)]
pub(crate) enum InternalEvent {
PrivateInviteUploaded {
request_id: String,
owner: String,
device: String,
result: Result<String, String>,
},
PrivateInviteResolved {
request_id: String,
owner: String,
result: Result<crate::invite_record::InviteRecord, String>,
},
DeviceLinkSignerRepair {
token: String,
heads: Vec<Event>,
reply: tokio::sync::oneshot::Sender<Result<Event, String>>,
},
DeviceLinkSignerRequest {
token: String,
unsigned_event_json: String,
previous: Option<Event>,
reply: tokio::sync::oneshot::Sender<
Result<(Event, crate::core::device_link_signer::DeviceLinkInfo), String>,
>,
},
DeviceLinkSignerFinished {
token: String,
success: bool,
error: Option<String>,
},
PrivateContactSyncTick {
generation: u64,
},
FollowUpdateReady {
request_id: String,
result: Result<Vec<Event>, String>,
},
RemoteSignerProgress {
token: String,
phase: crate::RemoteSignerPhase,
auth_url: Option<String>,
},
RemoteSignerConnected {
token: String,
owner_pubkey_hex: String,
},
RemoteSignerSigned {
token: String,
request_id: String,
signed_event_json: String,
link_info: Option<crate::core::device_link_signer::DeviceLinkInfo>,
},
RemoteSignerFailed {
token: String,
message: String,
},
DirectFilesPrepared {
generation: u64,
device: String,
result: Result<crate::core::direct_files::Record, String>,
},
DirectFile {
generation: u64,
event: crate::core::direct_file_tcp::DirectFileEvent,
},
CallPacket {
source_pubkey_hex: String,
source_port: u16,
data: Vec<u8>,
},
CallMediaBatch {
packets: Vec<(String, u16, Vec<u8>)>,
received_at: std::time::Instant,
_permit: tokio::sync::OwnedSemaphorePermit,
},
CallRecoveryTick {
call_id: String,
},
CallTick {
call_id: String,
},
SignerLoginFetched {
request_id: String,
result: Result<Option<Event>, String>,
},
SignerLoginPublished {
request_id: String,
result: Result<Event, String>,
},
SignerLoginTimedOut {
request_id: String,
},
RelayEvent(Event),
MeshEvent(Event),
FipsNearbyPacket {
source_pubkey_hex: String,
source_port: u16,
data: Vec<u8>,
},
FipsNearbyPeersChanged {
generation: u64,
peers: Vec<FipsNearbyLinkSnapshot>,
},
FipsPeerDiscoveryNeeded {
generation: u64,
author: nostr::PublicKey,
requires_pending_work: bool,
},
FetchTrackedPeerCatchUp {
token: u64,
},
ProtocolSubscriptionLivenessCheck {
token: u64,
},
RetryReadyProtocolWork {
due_at: tokio::time::Instant,
},
PollPendingDeviceInvites {
token: u64,
},
PollPendingDeviceLink {
token: u64,
},
PendingDeviceLinkRefreshFinished {
token: u64,
events: Vec<Event>,
},
ExpireChatMutes {
token: u64,
},
PruneExpiredMessages {
token: u64,
},
FetchCatchUpEvents(Vec<Event>),
ProfileMetadataFetchFinished {
owner_pubkey_hex: String,
events: Vec<Event>,
error: Option<String>,
},
DirectChatCapabilityFetchFinished {
generation: u64,
token: u64,
owner_pubkey_hex: String,
result: Result<Vec<Event>, String>,
},
UserDiscoveryFetchFinished {
token: u64,
result: crate::core::UserDiscoveryFetchResult,
},
ProfileSearchRequested {
query: String,
},
ProfileSearchDebounceElapsed {
token: u64,
query: String,
},
ProfileSearchFetchFinished {
token: u64,
query: String,
result: Result<crate::core::ProfileSearchFetchResult, String>,
},
ProfileSearchCapabilitiesReady {
token: u64,
query: String,
events: Vec<Event>,
},
RelayStatusChanged {
relay_url: String,
status: RelayStatus,
generation: u64,
},
ProtocolSubscriptionReconcileCompleted {
generation: u64,
token: u64,
reason: String,
plan: Option<crate::core::ProtocolSubscriptionPlan>,
success: bool,
error: Option<String>,
relay_statuses: Vec<(String, RelayStatus)>,
connected_before: u64,
connected_after: u64,
filter_count: u64,
},
RelayTransportConnectionFinished {
token: u64,
reason: String,
relay_statuses: Vec<(String, RelayStatus)>,
connected_count: u64,
},
#[cfg(not(target_os = "ios"))]
DebugSnapshotWriteFinished {
generation: u64,
},
DebugLog {
category: String,
detail: String,
},
TypingIndicatorExpired {
chat_id: String,
author: String,
},
FlushPendingDeliveredReceipts {
token: u64,
},
RelayPublishDrainFinished {
token: u64,
results: Vec<RelayPublishDrainResult>,
},
RelayPublishDrainProgress {
token: u64,
result: RelayPublishDrainResult,
},
SessionStartupFollowUp,
RetryPendingRelayPublishes {
reason: String,
},
AttachmentReceiptsUpdated,
AttachmentUploadFinished {
store_id: u64,
chat_id: String,
result: Result<String, String>,
},
AttachmentUploadProgress {
store_id: u64,
bytes_uploaded: u64,
total_bytes: u64,
},
ProfilePictureUploadFinished {
result: Result<String, String>,
},
GroupPictureUploadFinished {
group_id: String,
result: Result<String, String>,
},
SyncComplete,
OwnerRegistrationLookupFinished {
generation: u64,
owner: nostr::PublicKey,
device: nostr::PublicKey,
completed: usize,
queried: usize,
events: Vec<Event>,
},
ProtocolAuthorBackfillComplete {
reason: String,
},
OpenChatFinalize {
chat_id: String,
},
DeviceSyncPacket {
source_pubkey_hex: String,
source_port: u16,
data: Vec<u8>,
},
}
#[derive(Debug)]
pub(crate) struct RelayPublishDrainResult {
pub(crate) event_id: String,
pub(crate) success: bool,
pub(crate) relay_urls: Vec<String>,
pub(crate) detail: String,
}