imsg_session/live/models.rs
1//! Lean read models for the live-query path.
2//!
3//! Device-derived message/thread/body shapes carrying no store-only fields (no `rowid`,
4//! `synced_at`, or `outgoing_status`, which have no device source). Only these models leave
5//! `imsg-session`; the `map_core` protocol types they are normalized from do not.
6
7/// Message direction relative to this device.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum Direction {
10 /// Inbound — received from the peer.
11 Received,
12 /// Outbound — sent from this device.
13 Sent,
14}
15
16/// One message from a live folder listing, body text fetched on demand.
17///
18/// `list`-path carrier. `timestamp_ms` is always present (taken from the listing entry, falling
19/// back to fetch time only on a malformed datetime). `read` is the device-reported read state.
20/// Carries no direction — the list renderer does not use it.
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct LiveMessage {
23 /// Opaque MAP message handle.
24 pub handle: String,
25 /// Message datetime in epoch milliseconds.
26 pub timestamp_ms: i64,
27 /// Resolved peer address: sender for received, recipient for sent.
28 pub address: String,
29 /// MAP folder name (`inbox`/`sent`/`outbox`/`deleted`).
30 pub folder: String,
31 /// Device-reported read state.
32 pub read: bool,
33 /// Decoded message body text.
34 pub text: String,
35}
36
37/// Per-contact thread summary aggregated from live folder listings.
38///
39/// Counts are approximate: aggregated over the device's bounded listing window, not the full
40/// corpus, so they differ from the store's full-corpus `GROUP BY`. No delivery badge — outgoing
41/// status is outbox-only with no device source.
42#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct LiveThread {
44 /// Peer address grouping the thread; never empty (empty-address entries are dropped).
45 pub address: String,
46 /// Most recent message datetime in epoch milliseconds across listed folders.
47 pub latest_ms: i64,
48 /// Total messages seen for this address across listed folders.
49 pub total: u32,
50 /// Count of unread received messages (`!sent && !read`).
51 pub unread: u32,
52}
53
54/// One MAP message folder from a live folder listing.
55///
56/// The name is a single path segment relative to `telecom/msg` (e.g. `inbox`), as the device
57/// reported it — no normalisation, no full path.
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct LiveFolder {
60 /// Folder name from the listing XML `name` attribute.
61 pub name: String,
62}
63
64/// One message body fetched live by handle.
65///
66/// `get`-path carrier. Structurally carries no timestamp — a `BMessage` has no datetime — and
67/// carries `direction` because the `get` renderer prints a `From:`/`To:` label from it.
68#[derive(Debug, Clone, PartialEq, Eq)]
69pub struct LiveBody {
70 /// Opaque MAP message handle the body was fetched by.
71 pub handle: String,
72 /// Direction derived from the bMessage folder.
73 pub direction: Direction,
74 /// Resolved peer address: originator for received, first recipient for sent.
75 pub address: String,
76 /// MAP folder string from the bMessage (e.g. `telecom/msg/inbox`).
77 pub folder: String,
78 /// Device-reported read state.
79 pub read: bool,
80 /// Decoded message body text.
81 pub text: String,
82}