Feed pagination, duplicate identity detection, pkarr leak fix, Android SAF
Feed pagination: - Cursor-based pagination: get_feed_page/get_all_posts_page (20 posts/page) - Batched engagement queries (3 bulk SQL queries instead of 4 per post) - IntersectionObserver for infinite scroll (sentinel at midpoint) - Viewport-based media loading (blobs only load when post enters view) - Pre-fetch next page immediately after current page renders Duplicate identity detection: - Anchor detects when a NodeId is already mesh-connected during initial exchange and sets duplicate_active flag in response - Client skips sync tasks when duplicate detected - Frontend shows red warning banner Privacy: - Fixed pkarr leak: clear_address_lookup() removes default dns.iroh.link publishing. Only mDNS (local network) discovery enabled. Android: - SAF integration via tauri-plugin-android-fs: exports open native "Save As" dialog so users can save to Downloads/Drive/etc. - Download/export paths use app data dir on Android (writable) - File picker gated behind desktop cfg (blocking_pick not on Android) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5e7eed9638
commit
288b53ffb1
12 changed files with 910 additions and 120 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use std::net::SocketAddr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::atomic::{AtomicU64, Ordering as AtomicOrdering};
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering as AtomicOrdering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use tracing::{debug, info, warn};
|
||||
|
|
@ -30,6 +30,8 @@ pub struct Node {
|
|||
pub blob_store: Arc<BlobStore>,
|
||||
secret_seed: [u8; 32],
|
||||
bootstrap_anchors: tokio::sync::Mutex<Vec<(NodeId, iroh::EndpointAddr)>>,
|
||||
/// True if an anchor reported another instance of this identity is already active
|
||||
pub duplicate_detected: Arc<AtomicBool>,
|
||||
#[allow(dead_code)]
|
||||
profile: DeviceProfile,
|
||||
pub activity_log: Arc<std::sync::Mutex<ActivityLog>>,
|
||||
|
|
@ -136,6 +138,7 @@ impl Node {
|
|||
blob_store,
|
||||
secret_seed,
|
||||
bootstrap_anchors: tokio::sync::Mutex::new(Vec::new()),
|
||||
duplicate_detected: Arc::new(AtomicBool::new(false)),
|
||||
profile,
|
||||
activity_log: activity_log_ref,
|
||||
last_rebalance_ms,
|
||||
|
|
@ -927,6 +930,34 @@ impl Node {
|
|||
Ok(self.decrypt_posts(raw, &group_seeds))
|
||||
}
|
||||
|
||||
pub async fn get_feed_page(
|
||||
&self,
|
||||
before_ms: Option<u64>,
|
||||
limit: usize,
|
||||
) -> anyhow::Result<Vec<(PostId, Post, PostVisibility, Option<String>)>> {
|
||||
let (raw, group_seeds) = {
|
||||
let storage = self.storage.get().await;
|
||||
let posts = storage.get_feed_page(before_ms, limit)?;
|
||||
let seeds = storage.get_all_group_seeds_map().unwrap_or_default();
|
||||
(posts, seeds)
|
||||
};
|
||||
Ok(self.decrypt_posts(raw, &group_seeds))
|
||||
}
|
||||
|
||||
pub async fn get_all_posts_page(
|
||||
&self,
|
||||
before_ms: Option<u64>,
|
||||
limit: usize,
|
||||
) -> anyhow::Result<Vec<(PostId, Post, PostVisibility, Option<String>)>> {
|
||||
let (raw, group_seeds) = {
|
||||
let storage = self.storage.get().await;
|
||||
let posts = storage.list_posts_page(before_ms, limit)?;
|
||||
let seeds = storage.get_all_group_seeds_map().unwrap_or_default();
|
||||
(posts, seeds)
|
||||
};
|
||||
Ok(self.decrypt_posts(raw, &group_seeds))
|
||||
}
|
||||
|
||||
fn decrypt_posts(
|
||||
&self,
|
||||
posts: Vec<(PostId, Post, PostVisibility)>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue