From 8042a9d92ef61db962ceef3810e002b10491091b Mon Sep 17 00:00:00 2001 From: wangdl Date: Sat, 30 May 2026 20:22:16 +0800 Subject: [PATCH] feat: core data models - MaterialType, DocumentBlock, ReadingPosition, ReadingEvent, NoteAnchor, SearchResult, DocumentError --- crates/xtask/Cargo.toml | 2 +- crates/zx_document_core/Cargo.toml | 4 +- crates/zx_document_core/src/anchors.rs | 31 +++++++++++++++ crates/zx_document_core/src/blocks.rs | 42 ++++++++++++++++++++ crates/zx_document_core/src/document.rs | 15 +++++++ crates/zx_document_core/src/error.rs | 30 ++++++++++++++ crates/zx_document_core/src/events.rs | 32 +++++++++++++++ crates/zx_document_core/src/material_type.rs | 22 ++++++++++ crates/zx_document_core/src/progress.rs | 30 ++++++++++++++ crates/zx_document_core/src/search.rs | 10 +++++ crates/zx_document_ffi/Cargo.toml | 2 +- 11 files changed, 217 insertions(+), 3 deletions(-) diff --git a/crates/xtask/Cargo.toml b/crates/xtask/Cargo.toml index e240aec..337bfe3 100644 --- a/crates/xtask/Cargo.toml +++ b/crates/xtask/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "xtask" version = "0.1.0" -edition = "2024" +edition = "2021" [dependencies] diff --git a/crates/zx_document_core/Cargo.toml b/crates/zx_document_core/Cargo.toml index cbac6a4..48372f4 100644 --- a/crates/zx_document_core/Cargo.toml +++ b/crates/zx_document_core/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "zx_document_core" version = "0.1.0" -edition = "2024" +edition = "2021" [dependencies] +serde = { version = "1", features = ["derive"] } +serde_json = "1" diff --git a/crates/zx_document_core/src/anchors.rs b/crates/zx_document_core/src/anchors.rs index e69de29..eb35ce7 100644 --- a/crates/zx_document_core/src/anchors.rs +++ b/crates/zx_document_core/src/anchors.rs @@ -0,0 +1,31 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum NoteAnchor { + Material { + material_id: String, + }, + MarkdownBlock { + material_id: String, + block_id: String, + }, + TextLine { + material_id: String, + line_number: u32, + }, + PdfPage { + material_id: String, + page_number: u32, + }, + Image { + material_id: String, + }, + EpubChapter { + material_id: String, + chapter_id: String, + }, + KnowledgeItem { + knowledge_item_id: String, + }, +} diff --git a/crates/zx_document_core/src/blocks.rs b/crates/zx_document_core/src/blocks.rs index e69de29..5f285c4 100644 --- a/crates/zx_document_core/src/blocks.rs +++ b/crates/zx_document_core/src/blocks.rs @@ -0,0 +1,42 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum DocumentBlock { + Heading { + id: String, + level: u8, + text: String, + }, + Paragraph { + id: String, + text: String, + }, + List { + id: String, + ordered: bool, + items: Vec, + }, + CodeBlock { + id: String, + language: Option, + code: String, + }, + Quote { + id: String, + text: String, + }, + Table { + id: String, + headers: Vec, + rows: Vec>, + }, + Image { + id: String, + src: String, + alt: Option, + }, + HorizontalRule { + id: String, + }, +} diff --git a/crates/zx_document_core/src/document.rs b/crates/zx_document_core/src/document.rs index e69de29..ba3b732 100644 --- a/crates/zx_document_core/src/document.rs +++ b/crates/zx_document_core/src/document.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +use crate::material_type::{MaterialType, PreviewMode}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DocumentInfo { + pub material_id: String, + pub title: String, + pub material_type: MaterialType, + pub preview_mode: PreviewMode, + pub file_size: u64, + pub page_count: Option, + pub word_count: Option, + pub created_at: Option, +} diff --git a/crates/zx_document_core/src/error.rs b/crates/zx_document_core/src/error.rs index e69de29..b3a0b5c 100644 --- a/crates/zx_document_core/src/error.rs +++ b/crates/zx_document_core/src/error.rs @@ -0,0 +1,30 @@ +use std::fmt; + +#[derive(Debug)] +pub enum DocumentError { + FileNotFound(String), + UnsupportedFormat(String), + ParseError(String), + InvalidEncoding, + IoError(std::io::Error), +} + +impl fmt::Display for DocumentError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + DocumentError::FileNotFound(path) => write!(f, "file not found: {path}"), + DocumentError::UnsupportedFormat(msg) => write!(f, "unsupported format: {msg}"), + DocumentError::ParseError(msg) => write!(f, "parse error: {msg}"), + DocumentError::InvalidEncoding => write!(f, "invalid encoding"), + DocumentError::IoError(e) => write!(f, "io error: {e}"), + } + } +} + +impl std::error::Error for DocumentError {} + +impl From for DocumentError { + fn from(e: std::io::Error) -> Self { + DocumentError::IoError(e) + } +} diff --git a/crates/zx_document_core/src/events.rs b/crates/zx_document_core/src/events.rs index e69de29..ffab57c 100644 --- a/crates/zx_document_core/src/events.rs +++ b/crates/zx_document_core/src/events.rs @@ -0,0 +1,32 @@ +use serde::{Deserialize, Serialize}; + +use crate::progress::ReadingPosition; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum ReadingEvent { + MaterialOpened { + material_id: String, + timestamp_ms: i64, + }, + MaterialClosed { + material_id: String, + timestamp_ms: i64, + active_seconds: u32, + }, + PositionChanged { + material_id: String, + position: ReadingPosition, + timestamp_ms: i64, + }, + Heartbeat { + material_id: String, + active_seconds: u32, + position: Option, + timestamp_ms: i64, + }, + MarkedAsRead { + material_id: String, + timestamp_ms: i64, + }, +} diff --git a/crates/zx_document_core/src/material_type.rs b/crates/zx_document_core/src/material_type.rs index e69de29..85ca0a1 100644 --- a/crates/zx_document_core/src/material_type.rs +++ b/crates/zx_document_core/src/material_type.rs @@ -0,0 +1,22 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum MaterialType { + Markdown, + Text, + Pdf, + Image, + Epub, + Word, + Excel, + PowerPoint, + Unknown, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum PreviewMode { + NativeReader, + PlatformPreview, + ExternalOpen, + Unsupported, +} diff --git a/crates/zx_document_core/src/progress.rs b/crates/zx_document_core/src/progress.rs index e69de29..bcea440 100644 --- a/crates/zx_document_core/src/progress.rs +++ b/crates/zx_document_core/src/progress.rs @@ -0,0 +1,30 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum ReadingPosition { + Markdown { + block_id: String, + scroll_progress: f32, + }, + Text { + line_number: u32, + scroll_progress: f32, + }, + Pdf { + page_number: u32, + page_progress: f32, + overall_progress: f32, + }, + Image { + zoom_scale: f32, + offset_x: f32, + offset_y: f32, + }, + Epub { + chapter_id: String, + chapter_progress: f32, + overall_progress: f32, + }, + Unknown, +} diff --git a/crates/zx_document_core/src/search.rs b/crates/zx_document_core/src/search.rs index e69de29..2994046 100644 --- a/crates/zx_document_core/src/search.rs +++ b/crates/zx_document_core/src/search.rs @@ -0,0 +1,10 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SearchResult { + pub block_id: String, + pub line_number: Option, + pub snippet: String, + pub match_start: usize, + pub match_end: usize, +} diff --git a/crates/zx_document_ffi/Cargo.toml b/crates/zx_document_ffi/Cargo.toml index 494eb8c..ac07d56 100644 --- a/crates/zx_document_ffi/Cargo.toml +++ b/crates/zx_document_ffi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zx_document_ffi" version = "0.1.0" -edition = "2024" +edition = "2021" [dependencies]