shared/domain/module/body/
video.rs1use crate::domain::module::{
2 body::{Body, BodyExt, ModeExt, StepExt, ThemeId, _groups::design::*},
3 ModuleKind,
4};
5use serde::{Deserialize, Serialize};
6use std::collections::HashSet;
7
8use super::BodyConvert;
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::Video(self.clone())
20 }
21
22 fn is_complete(&self) -> bool {
23 self.content.is_some()
24 }
25
26 fn kind() -> ModuleKind {
27 ModuleKind::Video
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::Video(data) => Ok(data),
93 _ => Err("cannot convert body to video!"),
94 }
95 }
96}
97
98#[derive(Default, Clone, Serialize, Deserialize, Debug)]
100pub struct Content {
101 pub editor_state: EditorState,
103
104 pub mode: Mode,
106
107 pub base: BaseContent,
109}
110
111#[derive(Default, Clone, Serialize, Deserialize, Debug)]
113pub struct EditorState {
114 pub step: Step,
116
117 pub steps_completed: HashSet<Step>,
119}
120
121#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
122pub enum Mode {
124 Introduction,
126 Story,
128 Song,
130 Howto,
132}
133
134impl Default for Mode {
135 fn default() -> Self {
136 Self::Introduction
137 }
138}
139
140impl ModeExt for Mode {
141 fn get_list() -> Vec<Self> {
142 vec![Self::Introduction, Self::Story, Self::Song, Self::Howto]
143 }
144
145 fn as_str_id(&self) -> &'static str {
146 match self {
147 Self::Introduction => "introduction",
148 Self::Story => "story",
149 Self::Song => "song",
150 Self::Howto => "howto",
151 }
152 }
153
154 fn label(&self) -> &'static str {
155 const STR_INTRODUCTION_LABEL: &'static str = "Introduce Your Topic";
156 const STR_STORY_LABEL: &'static str = "Tell a Story";
157 const STR_SONG_LABEL: &'static str = "Play a Song";
158 const STR_HOWTO_LABEL: &'static str = "How to";
159
160 match self {
161 Self::Introduction => STR_INTRODUCTION_LABEL,
162 Self::Story => STR_STORY_LABEL,
163 Self::Song => STR_SONG_LABEL,
164 Self::Howto => STR_HOWTO_LABEL,
165 }
166 }
167}
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
171pub enum Step {
172 One,
174 Two,
176 Three,
178 Four,
180}
181
182impl Default for Step {
183 fn default() -> Self {
184 Self::One
185 }
186}
187
188impl StepExt for Step {
189 fn next(&self) -> Option<Self> {
190 match self {
191 Self::One => Some(Self::Two),
192 Self::Two => Some(Self::Three),
193 Self::Three => Some(Self::Four),
194 Self::Four => None,
195 }
196 }
197
198 fn as_number(&self) -> usize {
199 match self {
200 Self::One => 1,
201 Self::Two => 2,
202 Self::Three => 3,
203 Self::Four => 4,
204 }
205 }
206
207 fn label(&self) -> &'static str {
208 const STR_BACKGROUND: &'static str = "Design";
210 const STR_CONTENT: &'static str = "Content";
211 const STR_SETTINGS: &'static str = "Settings";
212 const STR_PREVIEW: &'static str = "Preview";
213
214 match self {
215 Self::One => STR_BACKGROUND,
216 Self::Two => STR_CONTENT,
217 Self::Three => STR_SETTINGS,
218 Self::Four => STR_PREVIEW,
219 }
220 }
221
222 fn get_list() -> Vec<Self> {
223 vec![Self::One, Self::Two, Self::Three, Self::Four]
224 }
225 fn get_preview() -> Self {
226 Self::Four
227 }
228}