use super::storage::SaveSnapshot;
use super::*;
impl AppCore {
pub(super) fn debug_snapshot_path(&self) -> PathBuf {
self.data_dir.join(DEBUG_SNAPSHOT_FILENAME)
}
pub(super) fn load_persisted(&mut self) -> anyhow::Result<Option<PersistedState>> {
self.app_store.delete_expired_messages(unix_now().get())?;
self.chat_deletions = self.app_store.load_chat_deletions()?;
self.chat_read_states = self.app_store.load_chat_read_states()?;
self.chat_mute_states = self.app_store.load_chat_mute_states()?;
self.chat_pin_states = self.app_store.load_chat_pin_states()?;
self.app_store.load_state()
}
pub(super) fn persist_best_effort(&mut self) {
if self.batch.depth > 0 {
self.batch.dirty_persist = true;
return;
}
self.persist_best_effort_inner();
}
pub(super) fn persist_best_effort_inner(&mut self) {
if self.logged_in.is_none() {
if let Err(error) = self.app_store.save_preferences(&self.preferences) {
self.push_debug_log("storage.save_preferences_failed", error.to_string());
}
self.persist_debug_snapshot_best_effort();
return;
}
if let Err(error) = self.persist_app_state() {
self.push_debug_log("storage.save_failed", error.to_string());
}
self.persist_debug_snapshot_best_effort();
}
pub(super) fn persist_app_state(&mut self) -> anyhow::Result<()> {
let authorization_state = self
.logged_in
.as_ref()
.map(|logged_in| logged_in.authorization_state.into());
let snapshot = SaveSnapshot {
active_chat_id: self.active_chat_id.as_deref(),
next_message_id: self.next_message_id,
authorization_state,
preferences: &self.preferences,
owner_profiles: &self.owner_profiles,
chat_message_ttl_seconds: &self.chat_message_ttl_seconds,
app_keys: &self.app_keys,
groups: &self.groups,
group_pictures: &self.group_pictures,
threads: &self.threads,
seen_event_order: &self.seen_event_order,
};
self.app_store.save_state(&snapshot)?;
self.ack_pending_decrypted_deliveries_after_app_persist();
Ok(())
}
pub(super) fn clear_persistence_best_effort(&mut self) {
if let Err(error) = self.app_store.clear() {
self.push_debug_log("storage.clear_failed", error.to_string());
}
let debug_path = self.debug_snapshot_path();
if debug_path.exists() {
let _ = fs::remove_file(debug_path);
}
}
pub(super) fn persist_debug_snapshot_best_effort(&mut self) {
if self.logged_in.is_none() {
return;
}
if !debug_snapshot_file_writes_enabled() {
return;
}
if self.debug_snapshot.write_inflight {
self.debug_snapshot.write_dirty = true;
return;
}
let now_ms = unix_now_ms();
if now_ms.saturating_sub(self.debug_snapshot.last_built_at_ms)
< DEBUG_SNAPSHOT_MIN_INTERVAL_MS
{
self.debug_snapshot.write_dirty = true;
return;
}
let snapshot = self.build_runtime_debug_snapshot();
self.debug_snapshot.build_count = self.debug_snapshot.build_count.saturating_add(1);
self.debug_snapshot.last_built_at_ms = now_ms;
let path = self.debug_snapshot_path();
let data_dir = self.data_dir.clone();
#[cfg(target_os = "ios")]
{
if let Ok(bytes) = serde_json::to_vec_pretty(&snapshot) {
let _ = fs::create_dir_all(&data_dir);
let _ = fs::write(path, bytes);
}
return;
}
#[cfg(not(target_os = "ios"))]
{
self.debug_snapshot.write_inflight = true;
self.debug_snapshot.write_dirty = false;
self.debug_snapshot.write_generation =
self.debug_snapshot.write_generation.wrapping_add(1);
let generation = self.debug_snapshot.write_generation;
let tx = self.core_sender.clone();
self.runtime.spawn_blocking(move || {
if let Ok(bytes) = serde_json::to_vec_pretty(&snapshot) {
let _ = fs::create_dir_all(&data_dir);
let _ = fs::write(path, bytes);
}
let _ = tx.send(CoreMsg::Internal(Box::new(
InternalEvent::DebugSnapshotWriteFinished { generation },
)));
});
}
}
pub(crate) fn debug_snapshot_build_count(&self) -> u64 {
self.debug_snapshot.build_count
}
#[cfg(not(target_os = "ios"))]
pub(super) fn handle_debug_snapshot_write_finished(&mut self, generation: u64) {
if generation != self.debug_snapshot.write_generation {
return;
}
self.debug_snapshot.write_inflight = false;
if self.debug_snapshot.write_dirty {
self.debug_snapshot.write_dirty = false;
self.persist_debug_snapshot_best_effort();
}
}
}
pub(super) fn apply_persisted_preferences(
preferences: &mut PreferencesSnapshot,
persisted: &PersistedPreferences,
) {
preferences.voice_calls_enabled = persisted.voice_calls_enabled;
preferences.video_calls_enabled = persisted.video_calls_enabled;
preferences.call_quality = if matches!(
persisted.call_quality.as_str(),
"auto" | "high" | "data" | "custom"
) {
persisted.call_quality.clone()
} else {
"auto".into()
};
preferences.call_max_bitrate_bps = if persisted.call_max_bitrate_bps == 0 {
2_000_000
} else {
persisted.call_max_bitrate_bps.clamp(100_000, 10_000_000)
};
preferences.send_typing_indicators = persisted.send_typing_indicators;
preferences.send_read_receipts = persisted.send_read_receipts;
preferences.allow_message_deletion_by_others = persisted.allow_message_deletion_by_others;
preferences.hide_blocked_group_messages = persisted.hide_blocked_group_messages;
preferences.desktop_notifications_enabled = persisted.desktop_notifications_enabled;
preferences.invite_acceptance_notifications_enabled =
persisted.invite_acceptance_notifications_enabled;
preferences.startup_at_login_enabled = persisted.startup_at_login_enabled;
preferences.nearby_enabled = persisted.nearby_enabled;
preferences.nearby_bluetooth_enabled = persisted.nearby_bluetooth_enabled;
preferences.nearby_lan_enabled = persisted.nearby_lan_enabled;
preferences.nearby_show_in_chat_list = persisted.nearby_show_in_chat_list;
preferences.nearby_mailbag_enabled = persisted.nearby_mailbag_enabled;
preferences.nostr_relay_urls = normalize_nostr_relay_urls(&persisted.nostr_relay_urls);
preferences.image_proxy_enabled = persisted.image_proxy_enabled;
preferences.image_proxy_fallback_enabled = persisted.image_proxy_fallback_enabled;
preferences.image_proxy_url = persisted.image_proxy_url.clone();
preferences.image_proxy_key_hex = persisted.image_proxy_key_hex.clone();
preferences.image_proxy_salt_hex = persisted.image_proxy_salt_hex.clone();
preferences.mobile_push_server_url = persisted.mobile_push_server_url.clone();
preferences.debug_logging_enabled = persisted.debug_logging_enabled;
preferences.accept_unknown_direct_messages = persisted.accept_unknown_direct_messages;
preferences.accept_social_graph_direct_messages = persisted.accept_social_graph_direct_messages;
preferences.accept_overmuted_direct_messages = persisted.accept_overmuted_direct_messages;
preferences.muted_chat_ids = persisted.muted_chat_ids.clone();
preferences.muted_chat_ids.sort();
preferences.muted_chat_ids.dedup();
preferences.timed_chat_mutes = persisted.timed_chat_mutes.clone();
preferences.silent_mention_chat_ids = persisted.silent_mention_chat_ids.clone();
preferences
.timed_chat_mutes
.retain(|mute| mute.until_secs > unix_now().get());
chat_settings::normalize_timed_chat_mutes(&mut preferences.timed_chat_mutes);
preferences.pinned_chat_ids = persisted.pinned_chat_ids.clone();
preferences.pinned_chat_ids.sort();
preferences.pinned_chat_ids.dedup();
preferences.blocked_owner_pubkeys = persisted.blocked_owner_pubkeys.clone();
preferences.blocked_owner_pubkeys.sort();
preferences.blocked_owner_pubkeys.dedup();
preferences.accepted_owner_pubkeys = persisted.accepted_owner_pubkeys.clone();
preferences.accepted_owner_pubkeys.sort();
preferences.accepted_owner_pubkeys.dedup();
}