use std::sync::Arc;
use serde::{Serialize, Serializer};
use crate::runtime::handle::ExtensionHandle;
use crate::runtime::handlers::SingleEntryContext;
use crate::runtime::state::{MessageTabContentHandler, MessageTabHandlers, MessageTabVisibilityHandler};
use crate::error::Error;
#[derive(Serialize, Clone, Copy, Debug, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum Language {
Text,
Json,
Xml,
Html,
Css,
JavaScript,
Yaml,
}
#[derive(Serialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TabContent {
text: String,
language: Language,
}
impl TabContent {
pub fn new(text: impl Into<String>, language: Language) -> Self {
Self {
text: text.into(),
language,
}
}
pub fn plain(text: impl Into<String>) -> Self {
Self::new(text, Language::Text)
}
pub fn json(text: impl Into<String>) -> Self {
Self::new(text, Language::Json)
}
pub fn xml(text: impl Into<String>) -> Self {
Self::new(text, Language::Xml)
}
pub fn html(text: impl Into<String>) -> Self {
Self::new(text, Language::Html)
}
pub fn css(text: impl Into<String>) -> Self {
Self::new(text, Language::Css)
}
pub fn javascript(text: impl Into<String>) -> Self {
Self::new(text, Language::JavaScript)
}
pub fn yaml(text: impl Into<String>) -> Self {
Self::new(text, Language::Yaml)
}
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MessageTab {
id: String,
label: String,
#[serde(skip)]
content: MessageTabContentHandler,
#[serde(rename = "isConditional", serialize_with = "serialize_is_some")]
visibility: Option<MessageTabVisibilityHandler>,
}
impl MessageTab {
pub fn new<F, Fut>(id: impl Into<String>, label: impl Into<String>, content: F) -> Self
where
F: Fn(SingleEntryContext, ExtensionHandle) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<TabContent, Error>> + Send + 'static,
{
Self {
id: id.into(),
label: label.into(),
content: Arc::new(move |ctx, handle| {
let fut = content(ctx, handle);
Box::pin(async move { fut.await.map_err(Error::into_jrpc) })
}),
visibility: None,
}
}
pub fn visible_when<F, Fut>(mut self, visibility: F) -> Self
where
F: Fn(SingleEntryContext, ExtensionHandle) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<bool, Error>> + Send + 'static,
{
self.visibility = Some(Arc::new(move |ctx, handle| {
let fut = visibility(ctx, handle);
Box::pin(async move { fut.await.map_err(Error::into_jrpc) })
}));
self
}
pub(crate) fn extract_handlers(&self) -> (String, MessageTabHandlers) {
(
self.id.clone(),
MessageTabHandlers {
content: Arc::clone(&self.content),
visibility: self.visibility.as_ref().map(Arc::clone),
},
)
}
}
fn serialize_is_some<S: Serializer>(
visibility: &Option<MessageTabVisibilityHandler>,
serializer: S,
) -> Result<S::Ok, S::Error> {
serializer.serialize_bool(visibility.is_some())
}