feat(ios): improve share preview (#15538)

#### PR Dependency Tree

* **PR #15538** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added rich link previews to mobile and iOS sharing, including images,
metadata, transcripts, and selected text.
* Share imports can now create structured content blocks, embeds,
bookmarks, and transcript callouts.
* Added workspace-aware preview handling for cloud, self-hosted, and
signed-out modes.
* **Accessibility**
* Improved collapse/expand controls with semantic buttons and ARIA
relationships.
* **Bug Fixes**
  * Enhanced URL and error sanitization in server logs.
* Improved link-preview CORS support, validation, and request handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-08-28 03:32:26 +08:00
committed by GitHub
parent 329839e467
commit b6de0ad51b
36 changed files with 3152 additions and 372 deletions
@@ -36,7 +36,7 @@ pub(in crate::runtime::backend_runtime::search) async fn sweep_generation_orphan
"query":{"match_all":{}},
"fields":["workspace_id"],
"size":GENERATION_GC_BATCH,
"sort":if remote.is_some() { json!([{"doc_id":"asc"},{"_id":"asc"}]) } else { json!(["doc_id","id"]) }
"sort":provider_page_sort(table, remote.is_some())
});
if let Some(cursor) = cursor.as_deref() {
dsl["cursor"] = json!(cursor);
@@ -334,7 +334,7 @@ async fn provider_document_page(
"query":{"term":{"workspace_id":{"value":workspace_id}}},
"fields":["doc_id"],
"size":RECONCILE_BATCH,
"sort":if remote.is_some() { json!([{"doc_id":"asc"},{"_id":"asc"}]) } else { json!(["doc_id","id"]) }
"sort":provider_page_sort(table, remote.is_some())
});
if let Some(cursor) = cursor {
dsl["cursor"] = json!(cursor);
@@ -351,6 +351,17 @@ async fn provider_document_page(
Ok((doc_ids, next_cursor))
}
fn provider_page_sort(table: SearchTable, remote: bool) -> Value {
if !remote {
return json!(["doc_id", "id"]);
}
let mut fields = vec!["workspace_id", "doc_id", "source_version", "permission_version"];
if table == SearchTable::Block {
fields.push("block_id");
}
json!(fields.into_iter().map(|field| json!({field:"asc"})).collect::<Vec<_>>())
}
fn provider_field_string(node: &Value, field: &str) -> Option<String> {
node
.pointer(&format!("/fields/{field}/0"))
@@ -582,7 +593,7 @@ mod tests {
use super::*;
#[test]
fn block_projection_check_rejects_missing_or_stale_rows() {
fn anti_entropy_provider_contracts_are_stable() {
let expected = HashSet::from(["one".to_string(), "two".to_string()]);
let complete = vec![
json!({"_source":{"block_id":"one","source_version":7,"permission_version":3}}),
@@ -599,5 +610,15 @@ mod tests {
7,
3,
));
assert_eq!(
provider_page_sort(SearchTable::Doc, true),
json!([
{"workspace_id":"asc"},
{"doc_id":"asc"},
{"source_version":"asc"},
{"permission_version":"asc"}
])
);
assert_eq!(provider_page_sort(SearchTable::Block, false), json!(["doc_id", "id"]));
}
}