//! Serde shapes for the local store. Output structs mirror the JSON the frontend //! already consumes (frontend/src/stores/*.ts) so the same components render whether //! the data comes from REST or from these Tauri commands. Field names/optionality //! match the TypeScript interfaces exactly. use serde::{Deserialize, Serialize}; #[derive(Serialize)] pub struct Note { pub id: String, /// The note's NAME: its first non-blank body line, else its first checklist item. /// Always present, so every note has something to be called. Derived at read time, /// never stored. pub display_title: String, pub body: String, pub position: i64, pub pinned: bool, pub archived: bool, pub trashed: bool, /// When it was trashed (null unless trashed). Named for the server's field so the /// shared frontend counts down the retention window identically either way. pub deleted_at: Option, pub remind_at: Option, pub recurrence: Option, pub labels: Vec, pub items: Vec, pub attachments: Vec, pub previews: Vec, pub created_at: Option, pub updated_at: Option, /// How this account holds the note (#5175): `owner`, or `edit`/`view` for one /// someone shared with it. Named and valued as the server's, so the shared /// frontend gates the editor identically either way. pub permission: String, /// Whether the owner has shared it with anyone. pub shared: bool, /// Who shared it with us; null on our own notes. pub shared_by: Option, } #[derive(Serialize)] pub struct SharedBy { pub id: String, pub display_name: String, } #[derive(Serialize)] pub struct NoteLabel { pub id: String, pub name: String, pub color: String, /// True when attached because of a `#tag` in the body (kept in sync with the text). pub via_tag: bool, } #[derive(Serialize)] pub struct ChecklistItem { pub id: String, pub text: String, pub checked: bool, pub position: i64, } #[derive(Serialize)] pub struct Attachment { pub id: String, pub url: String, pub filename: Option, pub mime: String, pub size: Option, pub sha256: Option, /// Why the server refused a file attached on this device, in words to show on it. /// Absent for everything else, including a file still waiting to upload. #[serde(skip_serializing_if = "Option::is_none")] pub upload_error: Option, } #[derive(Serialize)] pub struct LinkPreview { pub id: String, pub url: String, pub title: Option, pub description: Option, pub image_url: Option, pub site_name: Option, } #[derive(Serialize)] pub struct NoteRevision { pub id: String, pub body: String, pub created_at: Option, } #[derive(Serialize)] pub struct Label { pub id: String, pub name: String, pub color: String, // Note count is only meaningful in listings; omitted elsewhere so the frontend // preserves the count it already holds (matches the REST single-label responses). #[serde(skip_serializing_if = "Option::is_none")] pub count: Option, } #[derive(Serialize)] pub struct TitleEntry { pub id: String, pub title: String, } /// A reminder that has come due, as the desktop's reminder worker needs it. #[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub struct DueReminder { pub id: String, pub title: String, /// `remind_at` as stored. It names the occurrence: completing or snoozing a /// reminder changes it, and that is how an announcer tells a new occurrence /// from one it has already announced. pub remind_at: String, /// The same instant, in milliseconds since the epoch. pub due_ms: i64, } #[derive(Serialize)] pub struct PublicConfig { pub site_name: String, pub allow_registration: bool, pub version: String, pub enable_url_unfurl: bool, pub trash_retention_days: u32, } /// The synthetic single user the offline core reports, so the app's auth-gated /// router resolves without a login. There is no real account offline. #[derive(Serialize)] pub struct User { pub id: String, pub email: String, pub display_name: String, pub is_admin: bool, } #[derive(Deserialize)] pub struct NoteCreateInput { #[serde(default)] pub body: String, #[serde(default)] pub items: Option>, } /// The board query (mirrors adapters/repo.ts NoteListQuery). `labelId` is camelCase /// on the wire; the facet fields are snake_case, matching NoteFacets. #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct ListQuery { pub view: String, #[serde(default)] pub label_id: Option, #[serde(default)] pub facets: Option, #[serde(default)] pub sort: Option, } #[derive(Deserialize)] pub struct Facets { #[serde(default)] pub q: Option, #[serde(default)] pub label: Option>, #[serde(default)] pub has_attachment: Option, #[serde(default)] pub created_after: Option, #[serde(default)] pub created_before: Option, /// `with_me`: only notes someone else shared with this account. #[serde(default)] pub shared: Option, }