Skip to main content

mimick/library/
asset_object.rs

1//! GObject subclass representing a single asset in the library grid.
2//!
3//! Uses the `glib::Properties` derive macro so every field is a proper GObject property,
4//! enabling `gtk::SortListModel`, expression bindings, and signal-based reactivity
5//! without a future migration from `BoxedAnyObject`.
6
7use glib::prelude::*;
8use glib::subclass::prelude::*;
9use std::cell::{Cell, RefCell};
10
11mod imp {
12    use super::*;
13    use glib::Properties;
14
15    #[derive(Properties, Default)]
16    #[properties(wrapper_type = super::AssetObject)]
17    pub struct AssetObject {
18        /// Immich asset UUID.
19        #[property(get, set)]
20        id: RefCell<String>,
21
22        /// Original filename on the server.
23        #[property(get, set)]
24        filename: RefCell<String>,
25
26        /// MIME type (e.g. "image/jpeg").
27        #[property(get, set)]
28        mime_type: RefCell<String>,
29
30        /// ISO 8601 creation timestamp from file metadata.
31        #[property(get, set)]
32        created_at: RefCell<String>,
33
34        /// "IMAGE" or "VIDEO".
35        #[property(get, set)]
36        asset_type: RefCell<String>,
37
38        /// Sync state indicator: 0 = remote only, 1 = local only, 2 = both.
39        #[property(get, set)]
40        sync_state: Cell<u32>,
41
42        /// Optional thumbhash for placeholder rendering (base64-encoded).
43        #[property(get, set)]
44        thumbhash: RefCell<Option<String>>,
45
46        /// Absolute path to the local copy on disk (LocalAsset, or matched
47        /// remote with a local sibling); empty string when none.
48        #[property(get, set)]
49        local_path: RefCell<String>,
50
51        /// Immich asset id when this row corresponds to a remote asset (or
52        /// has been matched to one via checksum); empty string otherwise.
53        #[property(get, set)]
54        remote_id: RefCell<String>,
55
56        /// Native pixel width of the asset; 0 = unknown (settled later from
57        /// thumbnail decode for sources without EXIF metadata).
58        #[property(get, set)]
59        width: Cell<u32>,
60
61        /// Native pixel height of the asset; 0 = unknown.
62        #[property(get, set)]
63        height: Cell<u32>,
64    }
65
66    #[glib::object_subclass]
67    impl ObjectSubclass for AssetObject {
68        const NAME: &'static str = "MimickAssetObject";
69        type Type = super::AssetObject;
70    }
71
72    #[glib::derived_properties]
73    impl ObjectImpl for AssetObject {}
74}
75
76glib::wrapper! {
77    /// A single library asset exposed as a full GObject for use in `gio::ListStore`.
78    pub struct AssetObject(ObjectSubclass<imp::AssetObject>);
79}
80
81/// Constructor parameters for a remote `AssetObject`.
82/// Pass `width` / `height` as 0 when unknown.
83pub struct AssetInit<'a> {
84    pub id: &'a str,
85    pub filename: &'a str,
86    pub mime_type: &'a str,
87    pub created_at: &'a str,
88    pub asset_type: &'a str,
89    pub sync_state: u32,
90    pub thumbhash: Option<&'a str>,
91    pub width: u32,
92    pub height: u32,
93}
94
95impl AssetObject {
96    pub fn new(init: AssetInit<'_>) -> Self {
97        glib::Object::builder()
98            .property("id", init.id)
99            .property("filename", init.filename)
100            .property("mime-type", init.mime_type)
101            .property("created-at", init.created_at)
102            .property("asset-type", init.asset_type)
103            .property("sync-state", init.sync_state)
104            .property("thumbhash", init.thumbhash)
105            .property("local-path", "")
106            .property("remote-id", init.id)
107            .property("width", init.width)
108            .property("height", init.height)
109            .build()
110    }
111
112    /// Build an AssetObject for a purely local asset (LocalOnly state).
113    /// `id` is a synthetic row identity (use the absolute path) so the
114    /// existing `id` plumbing in the grid factory keeps working.
115    pub fn new_local(
116        id: &str,
117        filename: &str,
118        mime_type: &str,
119        created_at: &str,
120        asset_type: &str,
121        local_path: &str,
122    ) -> Self {
123        glib::Object::builder()
124            .property("id", id)
125            .property("filename", filename)
126            .property("mime-type", mime_type)
127            .property("created-at", created_at)
128            .property("asset-type", asset_type)
129            .property("sync-state", 1u32)
130            .property("thumbhash", None::<String>)
131            .property("local-path", local_path)
132            .property("remote-id", "")
133            .property("width", 0u32)
134            .property("height", 0u32)
135            .build()
136    }
137}