shared/domain/module/body/
poster.rs1use crate::domain::module::{
2 body::{Body, BodyConvert, BodyExt, ModeExt, StepExt, ThemeId, _groups::design::*},
3 ModuleKind,
4};
5use serde::{Deserialize, Serialize};
6use std::collections::HashSet;
7
8use super::Audio;
9
10#[derive(Default, Clone, Serialize, Deserialize, Debug)]
12pub struct ModuleData {
13 pub content: Option<Content>,
15}
16
17impl BodyExt<Mode, Step> for ModuleData {
18 fn as_body(&self) -> Body {
19 Body::Poster(self.clone())
20 }
21
22 fn is_complete(&self) -> bool {
23 self.content.is_some()
24 }
25
26 fn kind() -> ModuleKind {
27 ModuleKind::Poster
28 }
29
30 fn new_with_mode_and_theme(mode: Mode, theme: ThemeId) -> Self {
31 ModuleData {
32 content: Some(Content {
33 mode,
34 base: BaseContent {
35 theme,
36 ..Default::default()
37 },
38 ..Default::default()
39 }),
40 }
41 }
42
43 fn mode(&self) -> Option<Mode> {
44 self.content.as_ref().map(|c| c.mode.clone())
45 }
46
47 fn requires_choose_mode(&self) -> bool {
48 self.content.is_none()
49 }
50
51 fn set_editor_state_step(&mut self, step: Step) {
52 if let Some(content) = self.content.as_mut() {
53 content.editor_state.step = step;
54 }
55 }
56 fn set_editor_state_steps_completed(&mut self, steps_completed: HashSet<Step>) {
57 if let Some(content) = self.content.as_mut() {
58 content.editor_state.steps_completed = steps_completed;
59 }
60 }
61
62 fn get_editor_state_step(&self) -> Option<Step> {
63 self.content
64 .as_ref()
65 .map(|content| content.editor_state.step)
66 }
67
68 fn get_editor_state_steps_completed(&self) -> Option<HashSet<Step>> {
69 self.content
70 .as_ref()
71 .map(|content| content.editor_state.steps_completed.clone())
72 }
73
74 fn set_theme(&mut self, theme_id: ThemeId) {
75 if let Some(content) = self.content.as_mut() {
76 content.base.theme = theme_id;
77 }
78 }
79
80 fn get_theme(&self) -> Option<ThemeId> {
81 self.content.as_ref().map(|content| content.base.theme)
82 }
83}
84
85impl BodyConvert for ModuleData {}
86
87impl TryFrom<Body> for ModuleData {
88 type Error = &'static str;
89
90 fn try_from(body: Body) -> Result<Self, Self::Error> {
91 match body {
92 Body::Poster(data) => Ok(data),
93 _ => Err("cannot convert body to poster!"),
94 }
95 }
96}
97
98#[derive(Default, Clone, Serialize, Deserialize, Debug)]
100pub struct Content {
101 pub editor_state: EditorState,
103 pub mode: Mode,
105 #[serde(default)]
107 pub audio: Option<Audio>,
108 pub base: BaseContent,
110 #[serde(default)]
112 pub play_settings: PlaySettings,
113}
114
115#[derive(Default, Clone, Serialize, Deserialize, Debug)]
117pub struct EditorState {
118 pub step: Step,
120
121 pub steps_completed: HashSet<Step>,
123}
124
125#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
126pub enum Mode {
128 Printables,
130 TalkingPictures,
132 TeachAWord,
134 StoryTime,
136 Map,
138 Poster,
140 HearASong,
142}
143
144impl Default for Mode {
145 fn default() -> Self {
146 Self::Poster
147 }
148}
149
150impl ModeExt for Mode {
151 fn get_list() -> Vec<Self> {
152 vec![
153 Self::Printables,
154 Self::TalkingPictures,
155 Self::TeachAWord,
156 Self::StoryTime,
157 Self::Map,
158 Self::Poster,
159 Self::HearASong,
160 ]
161 }
162
163 fn as_str_id(&self) -> &'static str {
164 match self {
165 Self::Printables => "printables",
166 Self::TalkingPictures => "talking-pictures",
167 Self::TeachAWord => "teach-a-word",
168 Self::StoryTime => "story-time",
169 Self::Map => "map",
170 Self::Poster => "poster",
171 Self::HearASong => "hear-a-song",
172 }
173 }
174
175 fn label(&self) -> &'static str {
176 const STR_PRINTABLES_LABEL: &'static str = "Printables";
177 const STR_TALKING_PICTURES_LABEL: &'static str = "Talking Picture";
178 const STR_TEACH_A_WORD_LABEL: &'static str = "Teach a Word";
179 const STR_STORY_TIME_LABEL: &'static str = "Storytime";
180 const STR_MAP_LABEL: &'static str = "Map";
181 const STR_POSTER_LABEL: &'static str = "Poster";
182 const STR_HEAR_A_SONG_LABEL: &'static str = "Hear a song";
183
184 match self {
185 Self::Printables => STR_PRINTABLES_LABEL,
186 Self::TalkingPictures => STR_TALKING_PICTURES_LABEL,
187 Self::TeachAWord => STR_TEACH_A_WORD_LABEL,
188 Self::StoryTime => STR_STORY_TIME_LABEL,
189 Self::Map => STR_MAP_LABEL,
190 Self::Poster => STR_POSTER_LABEL,
191 Self::HearASong => STR_HEAR_A_SONG_LABEL,
192 }
193 }
194}
195
196#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
198pub enum Step {
199 One,
201 Two,
203 Three,
205 Four,
207}
208
209impl Default for Step {
210 fn default() -> Self {
211 Self::One
212 }
213}
214
215impl StepExt for Step {
216 fn next(&self) -> Option<Self> {
217 match self {
218 Self::One => Some(Self::Two),
219 Self::Two => Some(Self::Three),
220 Self::Three => Some(Self::Four),
221 Self::Four => None,
222 }
223 }
224
225 fn as_number(&self) -> usize {
226 match self {
227 Self::One => 1,
228 Self::Two => 2,
229 Self::Three => 3,
230 Self::Four => 4,
231 }
232 }
233
234 fn label(&self) -> &'static str {
235 const STR_DESIGN: &'static str = "Design";
236 const STR_CONTENT: &'static str = "Content";
237 const STR_SETTINGS: &'static str = "Settings";
238 const STR_PREVIEW: &'static str = "Preview";
239
240 match self {
241 Self::One => STR_DESIGN,
242 Self::Two => STR_CONTENT,
243 Self::Three => STR_SETTINGS,
244 Self::Four => STR_PREVIEW,
245 }
246 }
247
248 fn get_list() -> Vec<Self> {
249 vec![Self::One, Self::Two, Self::Three, Self::Four]
250 }
251 fn get_preview() -> Self {
252 Self::Four
253 }
254}
255
256#[derive(Clone, Default, Serialize, Deserialize, Debug)]
258pub struct PlaySettings {
259 pub next: Next,
261}
262
263#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
265pub enum Next {
266 AfterAudio,
268 ClickNext,
270}
271
272impl Default for Next {
273 fn default() -> Self {
274 Self::ClickNext
275 }
276}