shared/domain/module/body/
cover.rs
use crate::domain::module::{
body::{Body, BodyConvert, BodyExt, StepExt, ThemeId, _groups::design::*},
ModuleKind,
};
use serde::{de::IntoDeserializer, Deserialize, Serialize};
use std::collections::HashSet;
use super::Audio;
#[derive(Clone, Serialize, Deserialize, Debug, Default)]
pub struct ModuleData {
pub content: Option<Content>,
}
impl BodyExt<(), Step> for ModuleData {
fn as_body(&self) -> Body {
Body::Cover(self.clone())
}
fn is_complete(&self) -> bool {
self.content.is_some()
}
fn kind() -> ModuleKind {
ModuleKind::Cover
}
fn new_with_mode_and_theme(_mode: (), theme: ThemeId) -> Self {
ModuleData {
content: Some(Content {
base: BaseContent {
theme,
..Default::default()
},
..Default::default()
}),
..Default::default()
}
}
fn mode(&self) -> Option<()> {
None
}
fn requires_choose_mode(&self) -> bool {
false
}
fn set_editor_state_step(&mut self, step: Step) {
if let Some(content) = self.content.as_mut() {
content.editor_state.step = step;
}
}
fn set_editor_state_steps_completed(&mut self, steps_completed: HashSet<Step>) {
if let Some(content) = self.content.as_mut() {
content.editor_state.steps_completed = steps_completed;
}
}
fn get_editor_state_step(&self) -> Option<Step> {
self.content
.as_ref()
.map(|content| content.editor_state.step)
}
fn get_editor_state_steps_completed(&self) -> Option<HashSet<Step>> {
self.content
.as_ref()
.map(|content| content.editor_state.steps_completed.clone())
}
fn set_theme(&mut self, theme_id: ThemeId) {
if let Some(content) = self.content.as_mut() {
content.base.theme = theme_id;
}
}
fn get_theme(&self) -> Option<ThemeId> {
self.content.as_ref().map(|content| content.base.theme)
}
}
impl BodyConvert for ModuleData {}
impl TryFrom<Body> for ModuleData {
type Error = &'static str;
fn try_from(body: Body) -> Result<Self, Self::Error> {
match body {
Body::Cover(data) => Ok(data),
_ => Err("cannot convert body to cover!"),
}
}
}
#[derive(Default, Clone, Serialize, Deserialize, Debug)]
pub struct Content {
pub editor_state: EditorState,
pub base: BaseContent,
#[serde(default)]
pub audio: Option<Audio>,
#[serde(default)]
pub play_settings: PlaySettings,
}
#[derive(Default, Clone, Serialize, Deserialize, Debug)]
pub struct EditorState {
pub step: Step,
pub steps_completed: HashSet<Step>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(remote = "Step")]
pub enum Step {
One,
Two,
Three,
Four,
}
impl<'de> Deserialize<'de> for Step {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = String::deserialize(deserializer)?;
if value == "Four" {
Ok(Self::Three)
} else {
Step::deserialize(value.into_deserializer())
}
}
}
impl Serialize for Step {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
Step::serialize(&self, serializer)
}
}
impl Default for Step {
fn default() -> Self {
Self::One
}
}
impl StepExt for Step {
fn next(&self) -> Option<Self> {
match self {
Self::One => Some(Self::Two),
Self::Two => Some(Self::Three),
Self::Three => Some(Self::Four),
Self::Four => None,
}
}
fn as_number(&self) -> usize {
match self {
Self::One => 1,
Self::Two => 2,
Self::Three => 3,
Self::Four => 4,
}
}
fn label(&self) -> &'static str {
const STR_DESIGN: &'static str = "Design";
const STR_CONTENT: &'static str = "Content";
const STR_SETTINGS: &'static str = "Settings";
const STR_PREVIEW: &'static str = "Preview";
match self {
Self::One => STR_DESIGN,
Self::Two => STR_CONTENT,
Self::Three => STR_SETTINGS,
Self::Four => STR_PREVIEW,
}
}
fn get_list() -> Vec<Self> {
vec![Self::One, Self::Two, Self::Three, Self::Four]
}
fn get_preview() -> Self {
Self::Four
}
}
#[derive(Clone, Default, Serialize, Deserialize, Debug)]
pub struct PlaySettings {
pub next: Next,
}
#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
pub enum Next {
Auto,
AfterAudio,
ClickNext,
}
impl Default for Next {
fn default() -> Self {
Self::Auto
}
}