shared/domain/
animation.rs1use crate::api::endpoints::PathPart;
4
5use super::{meta::AnimationStyleId, Publish};
6use chrono::{DateTime, Utc};
7use macros::make_path_parts;
8use serde::{Deserialize, Serialize};
9#[cfg(feature = "backend")]
10use sqlx::postgres::PgRow;
11
12#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
14#[cfg_attr(feature = "backend", derive(sqlx::Type))]
15#[repr(i16)]
16pub enum AnimationKind {
17 Gif = 0,
19 Spritesheet = 1,
21}
22
23impl AnimationKind {
24 #[must_use]
26 pub const fn to_str(self) -> &'static str {
27 match self {
28 Self::Gif => "gif",
29 Self::Spritesheet => "spritesheet",
30 }
31 }
32}
33
34wrap_uuid! {
35 pub struct AnimationId
37}
38
39make_path_parts!(AnimationGetPath => "/v1/animation/{}" => AnimationId);
40
41#[derive(Serialize, Deserialize, Debug)]
43pub struct AnimationResponse {
44 pub metadata: AnimationMetadata,
46}
47
48#[derive(Serialize, Deserialize, Debug)]
50pub struct AnimationMetadata {
51 pub id: AnimationId,
53
54 pub name: String,
56
57 pub description: String,
59
60 pub is_premium: bool,
62
63 pub publish_at: Option<DateTime<Utc>>,
65
66 pub styles: Vec<AnimationStyleId>,
68
69 pub kind: AnimationKind,
71
72 pub is_looping: bool,
74
75 pub created_at: DateTime<Utc>,
77
78 pub updated_at: Option<DateTime<Utc>>,
80}
81
82#[cfg(feature = "backend")]
84impl<'r> sqlx::FromRow<'r, PgRow> for AnimationMetadata {
85 fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
86 let DbAnimation {
87 id,
88 kind,
89 name,
90 description,
91 is_premium,
92 publish_at,
93 styles,
94 is_looping,
95 created_at,
96 updated_at,
97 } = DbAnimation::from_row(row)?;
98
99 Ok(Self {
100 id,
101 kind,
102 name,
103 description,
104 is_premium,
105 publish_at,
106 styles: styles.into_iter().map(|(it,)| it).collect(),
107 is_looping,
108 created_at,
109 updated_at,
110 })
111 }
112}
113
114#[cfg_attr(feature = "backend", derive(sqlx::FromRow))]
115#[cfg(feature = "backend")]
116struct DbAnimation {
117 pub id: AnimationId,
118 pub kind: AnimationKind,
119 pub name: String,
120 pub description: String,
121 pub is_premium: bool,
122 pub publish_at: Option<DateTime<Utc>>,
123 pub styles: Vec<(AnimationStyleId,)>,
124 pub is_looping: bool,
125 pub created_at: DateTime<Utc>,
126 pub updated_at: Option<DateTime<Utc>>,
127}
128
129make_path_parts!(AnimationCreatePath => "/v1/animation");
130
131#[derive(Serialize, Deserialize, Debug)]
134pub struct AnimationCreateRequest {
135 pub name: String,
137
138 pub description: String,
140
141 pub is_premium: bool,
143
144 pub publish_at: Option<Publish>,
148
149 pub styles: Vec<AnimationStyleId>,
151
152 pub kind: AnimationKind,
154
155 pub is_looping: bool,
157}
158
159make_path_parts!(AnimationUploadPath => "/v1/animation/{}/raw" => AnimationId);
160
161#[derive(Serialize, Deserialize, Debug)]
163pub struct AnimationUploadRequest {
164 pub file_size: usize,
166}
167
168#[derive(Serialize, Deserialize, Debug)]
170pub struct AnimationUploadResponse {
171 pub session_uri: String,
173}
174
175make_path_parts!(AnimationDeletePath => "/v1/animation/{}" => AnimationId);