chore: cleanups and refactorings for cleaner code
This commit is contained in:
757
crates/bds-ui/src/app/editor_handlers.rs
Normal file
757
crates/bds-ui/src/app/editor_handlers.rs
Normal file
@@ -0,0 +1,757 @@
|
||||
use super::*;
|
||||
|
||||
impl BdsApp {
|
||||
pub(super) fn handle_post_editor_msg(&mut self, msg: PostEditorMsg) -> Task<Message> {
|
||||
enum DeferredPostAction {
|
||||
None,
|
||||
SyncEmbeddedPreview,
|
||||
Analyze(String),
|
||||
AnalyzeTaxonomy(String),
|
||||
DetectLanguage(String),
|
||||
OpenTranslate(String),
|
||||
TranslateTo {
|
||||
post_id: String,
|
||||
target_language: String,
|
||||
},
|
||||
Save(String),
|
||||
Publish(String),
|
||||
Duplicate(String),
|
||||
Discard(String),
|
||||
ShowDelete {
|
||||
tab_id: String,
|
||||
name: String,
|
||||
},
|
||||
OpenInsertLink(String),
|
||||
OpenInsertMedia {
|
||||
post_id: String,
|
||||
link_only: bool,
|
||||
},
|
||||
OpenGallery(String),
|
||||
OpenLinkedMedia(String),
|
||||
UnlinkLinkedMedia {
|
||||
post_id: String,
|
||||
media_id: String,
|
||||
},
|
||||
InsertSelectedLink {
|
||||
post_id: String,
|
||||
linked_post_id: String,
|
||||
},
|
||||
CreateLinkedPost(String),
|
||||
InsertSelectedMedia {
|
||||
post_id: String,
|
||||
media_id: String,
|
||||
},
|
||||
SetLinkTab(modal::PostInsertLinkTab),
|
||||
SetLinkSearch(String),
|
||||
SetExternalUrl(String),
|
||||
SetExternalText(String),
|
||||
InsertExternalLink,
|
||||
SetMediaSearch(String),
|
||||
SelectGalleryImage(usize),
|
||||
GalleryPrevious,
|
||||
GalleryNext,
|
||||
GalleryCloseLightbox,
|
||||
}
|
||||
|
||||
let mut deferred = DeferredPostAction::None;
|
||||
let mut refresh_linked_media: Option<(String, String)> = None;
|
||||
if let Some(tab_id) = self.active_tab.clone()
|
||||
&& let Some(state) = self.post_editors.get_mut(&tab_id)
|
||||
{
|
||||
match msg {
|
||||
PostEditorMsg::ToggleQuickActions => {
|
||||
state.quick_actions_open = !state.quick_actions_open;
|
||||
}
|
||||
PostEditorMsg::AnalyzeWithAi => {
|
||||
state.quick_actions_open = false;
|
||||
deferred = DeferredPostAction::Analyze(tab_id.clone());
|
||||
}
|
||||
PostEditorMsg::AnalyzeTaxonomy => {
|
||||
state.quick_actions_open = false;
|
||||
deferred = DeferredPostAction::AnalyzeTaxonomy(tab_id.clone());
|
||||
}
|
||||
PostEditorMsg::SwitchEditorMode(mode) => {
|
||||
state.set_editor_mode(&mode);
|
||||
deferred = DeferredPostAction::SyncEmbeddedPreview;
|
||||
}
|
||||
PostEditorMsg::DetectLanguage => {
|
||||
state.quick_actions_open = false;
|
||||
deferred = DeferredPostAction::DetectLanguage(tab_id.clone());
|
||||
}
|
||||
PostEditorMsg::Translate => {
|
||||
state.quick_actions_open = false;
|
||||
deferred = DeferredPostAction::OpenTranslate(tab_id.clone());
|
||||
}
|
||||
PostEditorMsg::TranslateTo(target_language) => {
|
||||
deferred = DeferredPostAction::TranslateTo {
|
||||
post_id: tab_id.clone(),
|
||||
target_language,
|
||||
};
|
||||
}
|
||||
PostEditorMsg::TitleChanged(s) => {
|
||||
state.title = s;
|
||||
state.mark_dirty();
|
||||
}
|
||||
PostEditorMsg::SlugChanged(s) => {
|
||||
state.slug = s;
|
||||
state.mark_dirty();
|
||||
}
|
||||
PostEditorMsg::ExcerptChanged(s) => {
|
||||
state.excerpt = s;
|
||||
state.mark_dirty();
|
||||
}
|
||||
PostEditorMsg::ContentChanged(new_text) => {
|
||||
state.content = new_text;
|
||||
state.mark_dirty();
|
||||
refresh_linked_media = Some((state.post_id.clone(), state.content.clone()));
|
||||
}
|
||||
PostEditorMsg::AuthorChanged(s) => {
|
||||
state.author = s;
|
||||
state.mark_dirty();
|
||||
}
|
||||
PostEditorMsg::LanguageChanged(s) => {
|
||||
state.language = s;
|
||||
state.mark_dirty();
|
||||
}
|
||||
PostEditorMsg::TemplateSlugChanged(s) => {
|
||||
state.template_slug = s;
|
||||
state.mark_dirty();
|
||||
}
|
||||
PostEditorMsg::ToggleDoNotTranslate(b) => {
|
||||
state.do_not_translate = b;
|
||||
state.mark_dirty();
|
||||
}
|
||||
PostEditorMsg::ToggleMetadata => {
|
||||
state.metadata_expanded = !state.metadata_expanded;
|
||||
}
|
||||
PostEditorMsg::ToggleExcerpt => {
|
||||
state.excerpt_expanded = !state.excerpt_expanded;
|
||||
}
|
||||
PostEditorMsg::SwitchLanguage(lang) => {
|
||||
state.switch_language(&lang);
|
||||
if state.editor_mode == "preview" {
|
||||
deferred = DeferredPostAction::SyncEmbeddedPreview;
|
||||
}
|
||||
}
|
||||
PostEditorMsg::TagsInputChanged(s) => {
|
||||
state.tags_input = s;
|
||||
}
|
||||
PostEditorMsg::TagsInputSubmit => {
|
||||
let tag = state.tags_input.trim().to_string();
|
||||
if !tag.is_empty() && !state.tags.contains(&tag) {
|
||||
state.tags.push(tag);
|
||||
state.mark_dirty();
|
||||
}
|
||||
state.tags_input.clear();
|
||||
}
|
||||
PostEditorMsg::RemoveTag(tag) => {
|
||||
state.tags.retain(|t| t != &tag);
|
||||
state.mark_dirty();
|
||||
}
|
||||
PostEditorMsg::CategoriesInputChanged(s) => {
|
||||
state.categories_input = s;
|
||||
}
|
||||
PostEditorMsg::CategoriesInputSubmit => {
|
||||
let cat = state.categories_input.trim().to_string();
|
||||
if !cat.is_empty() && !state.categories.contains(&cat) {
|
||||
state.categories.push(cat);
|
||||
state.mark_dirty();
|
||||
}
|
||||
state.categories_input.clear();
|
||||
}
|
||||
PostEditorMsg::RemoveCategory(cat) => {
|
||||
state.categories.retain(|c| c != &cat);
|
||||
state.mark_dirty();
|
||||
}
|
||||
PostEditorMsg::Save => {
|
||||
deferred = DeferredPostAction::Save(tab_id.clone());
|
||||
}
|
||||
PostEditorMsg::Publish => {
|
||||
deferred = DeferredPostAction::Publish(tab_id.clone());
|
||||
}
|
||||
PostEditorMsg::Duplicate => {
|
||||
deferred = DeferredPostAction::Duplicate(tab_id.clone());
|
||||
}
|
||||
PostEditorMsg::Discard => {
|
||||
deferred = DeferredPostAction::Discard(tab_id.clone());
|
||||
}
|
||||
PostEditorMsg::Delete => {
|
||||
deferred = DeferredPostAction::ShowDelete {
|
||||
tab_id: tab_id.clone(),
|
||||
name: state.title.clone(),
|
||||
};
|
||||
}
|
||||
PostEditorMsg::InsertLink => {
|
||||
deferred = DeferredPostAction::OpenInsertLink(state.post_id.clone());
|
||||
}
|
||||
PostEditorMsg::InsertMedia => {
|
||||
deferred = DeferredPostAction::OpenInsertMedia {
|
||||
post_id: state.post_id.clone(),
|
||||
link_only: false,
|
||||
};
|
||||
}
|
||||
PostEditorMsg::Gallery => {
|
||||
deferred = DeferredPostAction::OpenGallery(state.post_id.clone());
|
||||
}
|
||||
PostEditorMsg::LinkExistingMedia => {
|
||||
deferred = DeferredPostAction::OpenInsertMedia {
|
||||
post_id: state.post_id.clone(),
|
||||
link_only: true,
|
||||
};
|
||||
}
|
||||
PostEditorMsg::OpenLinkedMedia(media_id) => {
|
||||
deferred = DeferredPostAction::OpenLinkedMedia(media_id);
|
||||
}
|
||||
PostEditorMsg::UnlinkLinkedMedia(media_id) => {
|
||||
deferred = DeferredPostAction::UnlinkLinkedMedia {
|
||||
post_id: state.post_id.clone(),
|
||||
media_id,
|
||||
};
|
||||
}
|
||||
PostEditorMsg::PostInsertLinkSelected(linked_post_id) => {
|
||||
deferred = DeferredPostAction::InsertSelectedLink {
|
||||
post_id: state.post_id.clone(),
|
||||
linked_post_id,
|
||||
};
|
||||
}
|
||||
PostEditorMsg::PostInsertLinkCreate => {
|
||||
deferred = DeferredPostAction::CreateLinkedPost(state.post_id.clone());
|
||||
}
|
||||
PostEditorMsg::PostInsertMediaSelected(media_id) => {
|
||||
deferred = DeferredPostAction::InsertSelectedMedia {
|
||||
post_id: state.post_id.clone(),
|
||||
media_id,
|
||||
};
|
||||
}
|
||||
PostEditorMsg::PostGalleryImageSelected(index) => {
|
||||
deferred = DeferredPostAction::SelectGalleryImage(index);
|
||||
}
|
||||
PostEditorMsg::PostInsertLinkTabSwitch(tab) => {
|
||||
deferred = DeferredPostAction::SetLinkTab(tab);
|
||||
}
|
||||
PostEditorMsg::PostInsertLinkSearch(query) => {
|
||||
deferred = DeferredPostAction::SetLinkSearch(query);
|
||||
}
|
||||
PostEditorMsg::PostInsertLinkUrlChanged(url) => {
|
||||
deferred = DeferredPostAction::SetExternalUrl(url);
|
||||
}
|
||||
PostEditorMsg::PostInsertLinkTextChanged(text) => {
|
||||
deferred = DeferredPostAction::SetExternalText(text);
|
||||
}
|
||||
PostEditorMsg::PostInsertLinkExternalInsert => {
|
||||
deferred = DeferredPostAction::InsertExternalLink;
|
||||
}
|
||||
PostEditorMsg::PostInsertMediaSearch(query) => {
|
||||
deferred = DeferredPostAction::SetMediaSearch(query);
|
||||
}
|
||||
PostEditorMsg::PostGalleryPrevious => {
|
||||
deferred = DeferredPostAction::GalleryPrevious;
|
||||
}
|
||||
PostEditorMsg::PostGalleryNext => {
|
||||
deferred = DeferredPostAction::GalleryNext;
|
||||
}
|
||||
PostEditorMsg::PostGalleryCloseLightbox => {
|
||||
deferred = DeferredPostAction::GalleryCloseLightbox;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(tab) = self.tabs.iter_mut().find(|t| t.id == state.post_id) {
|
||||
tab.is_dirty = state.is_dirty;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((post_id, content)) = refresh_linked_media {
|
||||
let linked_media = self.load_post_media_items(&post_id, Some(&content));
|
||||
if let Some(state) = self.post_editors.get_mut(&post_id) {
|
||||
state.linked_media = linked_media;
|
||||
}
|
||||
}
|
||||
|
||||
match deferred {
|
||||
DeferredPostAction::None => Task::none(),
|
||||
DeferredPostAction::SyncEmbeddedPreview => self.sync_embedded_preview_for_active_post(),
|
||||
DeferredPostAction::Analyze(tab_id) => self.run_post_ai_analysis(&tab_id),
|
||||
DeferredPostAction::AnalyzeTaxonomy(tab_id) => self.run_post_taxonomy_analysis(&tab_id),
|
||||
DeferredPostAction::DetectLanguage(tab_id) => self.detect_post_language(&tab_id),
|
||||
DeferredPostAction::OpenTranslate(tab_id) => self.open_post_translation_modal(&tab_id),
|
||||
DeferredPostAction::TranslateTo {
|
||||
post_id,
|
||||
target_language,
|
||||
} => self.translate_post_to(&post_id, &target_language),
|
||||
DeferredPostAction::Save(tab_id) => self.save_post_editor(&tab_id),
|
||||
DeferredPostAction::Publish(tab_id) => self.publish_post_editor(&tab_id),
|
||||
DeferredPostAction::Duplicate(tab_id) => self.duplicate_post_editor(&tab_id),
|
||||
DeferredPostAction::Discard(tab_id) => self.discard_post_editor(&tab_id),
|
||||
DeferredPostAction::ShowDelete { tab_id, name } => {
|
||||
Task::done(Message::ShowModal(modal::ModalState::ConfirmDelete {
|
||||
entity_name: name,
|
||||
references: Vec::new(),
|
||||
on_confirm: modal::ConfirmAction::DeletePost(tab_id),
|
||||
}))
|
||||
}
|
||||
DeferredPostAction::OpenInsertLink(post_id) => self.insert_link_modal(&post_id),
|
||||
DeferredPostAction::OpenInsertMedia { post_id, link_only } => {
|
||||
self.insert_media_modal(&post_id, link_only)
|
||||
}
|
||||
DeferredPostAction::OpenGallery(post_id) => self.post_gallery(&post_id),
|
||||
DeferredPostAction::OpenLinkedMedia(media_id) => {
|
||||
let title = self
|
||||
.db
|
||||
.as_ref()
|
||||
.and_then(|db| {
|
||||
bds_core::db::queries::media::get_media_by_id(db.conn(), &media_id)
|
||||
.ok()
|
||||
.map(|media| media.title.unwrap_or(media.original_name))
|
||||
})
|
||||
.unwrap_or_else(|| media_id.clone());
|
||||
Task::done(Message::OpenTab(Tab {
|
||||
id: media_id,
|
||||
tab_type: TabType::Media,
|
||||
title,
|
||||
is_transient: false,
|
||||
is_dirty: false,
|
||||
}))
|
||||
}
|
||||
DeferredPostAction::UnlinkLinkedMedia { post_id, media_id } => {
|
||||
if let (Some(db), Some(data_dir)) = (&self.db, &self.data_dir) {
|
||||
if let Err(err) = engine::post_media::unlink_media_from_post(
|
||||
db.conn(),
|
||||
data_dir,
|
||||
&post_id,
|
||||
&media_id,
|
||||
) {
|
||||
self.notify_operation_failed("editor.unlinkMedia", err);
|
||||
return Task::none();
|
||||
}
|
||||
self.refresh_post_relationships(&post_id);
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
DeferredPostAction::InsertSelectedLink {
|
||||
post_id,
|
||||
linked_post_id,
|
||||
} => self.insert_selected_post_link(&post_id, &linked_post_id),
|
||||
DeferredPostAction::CreateLinkedPost(post_id) => {
|
||||
self.insert_created_post_link(&post_id)
|
||||
}
|
||||
DeferredPostAction::InsertSelectedMedia { post_id, media_id } => {
|
||||
self.insert_selected_media(&post_id, &media_id)
|
||||
}
|
||||
DeferredPostAction::SetLinkTab(tab) => {
|
||||
self.refresh_post_insert_link_modal(Some(tab), None, None, None);
|
||||
Task::none()
|
||||
}
|
||||
DeferredPostAction::SetLinkSearch(query) => {
|
||||
self.refresh_post_insert_link_modal(None, Some(query), None, None);
|
||||
Task::none()
|
||||
}
|
||||
DeferredPostAction::SetExternalUrl(url) => {
|
||||
self.refresh_post_insert_link_modal(None, None, Some(url), None);
|
||||
Task::none()
|
||||
}
|
||||
DeferredPostAction::SetExternalText(text) => {
|
||||
self.refresh_post_insert_link_modal(None, None, None, Some(text));
|
||||
Task::none()
|
||||
}
|
||||
DeferredPostAction::InsertExternalLink => {
|
||||
if let Some(modal::ModalState::PostInsertLink {
|
||||
post_id,
|
||||
external_url,
|
||||
external_text,
|
||||
..
|
||||
}) = self.active_modal.clone()
|
||||
{
|
||||
if let Some(markdown) =
|
||||
modal::external_link_markdown(&external_url, &external_text)
|
||||
{
|
||||
self.insert_markdown_into_post(&post_id, &markdown)
|
||||
} else {
|
||||
self.notify(
|
||||
ToastLevel::Error,
|
||||
&t(self.ui_locale, "modal.postInsertLink.urlRequired"),
|
||||
);
|
||||
Task::none()
|
||||
}
|
||||
} else {
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
DeferredPostAction::SetMediaSearch(query) => {
|
||||
self.refresh_insert_media_modal(query);
|
||||
Task::none()
|
||||
}
|
||||
DeferredPostAction::SelectGalleryImage(index) => {
|
||||
self.update_gallery_selection(Some(index));
|
||||
Task::none()
|
||||
}
|
||||
DeferredPostAction::GalleryPrevious => {
|
||||
self.step_gallery_selection(-1);
|
||||
Task::none()
|
||||
}
|
||||
DeferredPostAction::GalleryNext => {
|
||||
self.step_gallery_selection(1);
|
||||
Task::none()
|
||||
}
|
||||
DeferredPostAction::GalleryCloseLightbox => {
|
||||
self.update_gallery_selection(None);
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn handle_media_editor_msg(&mut self, msg: MediaEditorMsg) -> Task<Message> {
|
||||
enum DeferredMediaAction {
|
||||
None,
|
||||
Analyze(String),
|
||||
DetectLanguage(String),
|
||||
OpenTranslate(String),
|
||||
TranslateTo {
|
||||
media_id: String,
|
||||
target_language: String,
|
||||
},
|
||||
LinkPost {
|
||||
media_id: String,
|
||||
post_id: String,
|
||||
},
|
||||
OpenLinkedPost(String),
|
||||
UnlinkPost {
|
||||
media_id: String,
|
||||
post_id: String,
|
||||
},
|
||||
Save(String),
|
||||
Replace(String),
|
||||
Delete {
|
||||
tab_id: String,
|
||||
name: String,
|
||||
},
|
||||
}
|
||||
|
||||
let mut deferred = DeferredMediaAction::None;
|
||||
let mut picker_refresh: Option<(String, String)> = None;
|
||||
if let Some(tab_id) = self.active_tab.clone()
|
||||
&& let Some(state) = self.media_editors.get_mut(&tab_id)
|
||||
{
|
||||
match msg {
|
||||
MediaEditorMsg::AnalyzeWithAi => {
|
||||
deferred = DeferredMediaAction::Analyze(tab_id.clone());
|
||||
}
|
||||
MediaEditorMsg::DetectLanguage => {
|
||||
deferred = DeferredMediaAction::DetectLanguage(tab_id.clone());
|
||||
}
|
||||
MediaEditorMsg::TranslateMetadata => {
|
||||
deferred = DeferredMediaAction::OpenTranslate(tab_id.clone());
|
||||
}
|
||||
MediaEditorMsg::TranslateTo(target_language) => {
|
||||
deferred = DeferredMediaAction::TranslateTo {
|
||||
media_id: tab_id.clone(),
|
||||
target_language,
|
||||
};
|
||||
}
|
||||
MediaEditorMsg::TitleChanged(s) => {
|
||||
state.title = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
MediaEditorMsg::AltChanged(s) => {
|
||||
state.alt = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
MediaEditorMsg::CaptionChanged(s) => {
|
||||
state.caption = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
MediaEditorMsg::AuthorChanged(s) => {
|
||||
state.author = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
MediaEditorMsg::LanguageChanged(s) => {
|
||||
state.language = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
MediaEditorMsg::TagsChanged(s) => {
|
||||
state.tags_input = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
MediaEditorMsg::SwitchLanguage(lang) => {
|
||||
state.switch_language(&lang);
|
||||
}
|
||||
MediaEditorMsg::TogglePostPicker => {
|
||||
let next_open = !state.post_picker_open;
|
||||
state.post_picker_open = next_open;
|
||||
if !next_open {
|
||||
state.post_picker_results.clear();
|
||||
} else {
|
||||
picker_refresh =
|
||||
Some((state.media_id.clone(), state.post_picker_search.clone()));
|
||||
}
|
||||
}
|
||||
MediaEditorMsg::PostPickerSearchChanged(search) => {
|
||||
state.post_picker_search = search;
|
||||
if state.post_picker_open {
|
||||
picker_refresh =
|
||||
Some((state.media_id.clone(), state.post_picker_search.clone()));
|
||||
}
|
||||
}
|
||||
MediaEditorMsg::LinkPost(post_id) => {
|
||||
deferred = DeferredMediaAction::LinkPost {
|
||||
media_id: state.media_id.clone(),
|
||||
post_id,
|
||||
};
|
||||
}
|
||||
MediaEditorMsg::OpenLinkedPost(post_id) => {
|
||||
deferred = DeferredMediaAction::OpenLinkedPost(post_id);
|
||||
}
|
||||
MediaEditorMsg::UnlinkPost(post_id) => {
|
||||
deferred = DeferredMediaAction::UnlinkPost {
|
||||
media_id: state.media_id.clone(),
|
||||
post_id,
|
||||
};
|
||||
}
|
||||
MediaEditorMsg::Save => {
|
||||
deferred = DeferredMediaAction::Save(tab_id.clone());
|
||||
}
|
||||
MediaEditorMsg::ReplaceFile => {
|
||||
deferred = DeferredMediaAction::Replace(tab_id.clone());
|
||||
}
|
||||
MediaEditorMsg::Delete => {
|
||||
deferred = DeferredMediaAction::Delete {
|
||||
tab_id: tab_id.clone(),
|
||||
name: state.title.clone(),
|
||||
};
|
||||
}
|
||||
}
|
||||
if let Some(tab) = self
|
||||
.tabs
|
||||
.iter_mut()
|
||||
.find(|t| t.id == *state.media_id.as_str())
|
||||
{
|
||||
tab.is_dirty = state.is_dirty;
|
||||
}
|
||||
}
|
||||
if let Some((media_id, search)) = picker_refresh {
|
||||
let results = self.query_media_post_picker_results(&media_id, &search);
|
||||
if let Some(state) = self.media_editors.get_mut(&media_id) {
|
||||
state.post_picker_results = results;
|
||||
}
|
||||
}
|
||||
match deferred {
|
||||
DeferredMediaAction::None => Task::none(),
|
||||
DeferredMediaAction::Analyze(media_id) => self.run_media_ai_analysis(&media_id),
|
||||
DeferredMediaAction::DetectLanguage(media_id) => self.detect_media_language(&media_id),
|
||||
DeferredMediaAction::OpenTranslate(media_id) => {
|
||||
self.open_media_translation_modal(&media_id)
|
||||
}
|
||||
DeferredMediaAction::TranslateTo {
|
||||
media_id,
|
||||
target_language,
|
||||
} => self.translate_media_to(&media_id, &target_language),
|
||||
DeferredMediaAction::LinkPost { media_id, post_id } => {
|
||||
self.link_media_to_post(&media_id, &post_id)
|
||||
}
|
||||
DeferredMediaAction::OpenLinkedPost(post_id) => {
|
||||
let title = self
|
||||
.db
|
||||
.as_ref()
|
||||
.and_then(|db| {
|
||||
bds_core::db::queries::post::get_post_by_id(db.conn(), &post_id).ok()
|
||||
})
|
||||
.map(|post| post.title)
|
||||
.unwrap_or_else(|| post_id.clone());
|
||||
Task::done(Message::OpenTab(Tab {
|
||||
id: post_id,
|
||||
tab_type: TabType::Post,
|
||||
title,
|
||||
is_transient: false,
|
||||
is_dirty: false,
|
||||
}))
|
||||
}
|
||||
DeferredMediaAction::UnlinkPost { media_id, post_id } => {
|
||||
self.unlink_media_from_post(&media_id, &post_id)
|
||||
}
|
||||
DeferredMediaAction::Save(tab_id) => self.save_media_editor(&tab_id),
|
||||
DeferredMediaAction::Replace(media_id) => {
|
||||
crate::platform::dialog::pick_media_replacement(
|
||||
media_id,
|
||||
t(self.ui_locale, "dialog.replaceMedia"),
|
||||
t(self.ui_locale, "dialog.imageFilter"),
|
||||
)
|
||||
}
|
||||
DeferredMediaAction::Delete { tab_id, name } => {
|
||||
Task::done(Message::ShowModal(modal::ModalState::ConfirmDelete {
|
||||
entity_name: name,
|
||||
references: Vec::new(),
|
||||
on_confirm: modal::ConfirmAction::DeleteMedia(tab_id),
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn handle_template_editor_msg(&mut self, msg: TemplateEditorMsg) -> Task<Message> {
|
||||
if let Some(tab_id) = self.active_tab.clone()
|
||||
&& let Some(state) = self.template_editors.get_mut(&tab_id)
|
||||
{
|
||||
match msg {
|
||||
TemplateEditorMsg::TitleChanged(s) => {
|
||||
state.title = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
TemplateEditorMsg::SlugChanged(s) => {
|
||||
state.slug = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
TemplateEditorMsg::KindChanged(k) => {
|
||||
state.kind = k.0;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
TemplateEditorMsg::EnabledChanged(b) => {
|
||||
state.enabled = b;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
TemplateEditorMsg::ContentChanged(new_text) => {
|
||||
state.content = new_text;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
TemplateEditorMsg::Save => {
|
||||
return self.save_template_editor(&tab_id);
|
||||
}
|
||||
TemplateEditorMsg::Validate => {
|
||||
if let Some(st) = self.template_editors.get_mut(&tab_id) {
|
||||
match engine::template::validate_template(&st.content) {
|
||||
Ok(()) => {
|
||||
st.validation_error = None;
|
||||
}
|
||||
Err(e) => {
|
||||
st.validation_error = Some(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TemplateEditorMsg::Delete => {
|
||||
return self.show_template_delete_confirmation(&tab_id);
|
||||
}
|
||||
}
|
||||
if let Some(st) = self.template_editors.get(&tab_id)
|
||||
&& let Some(tab) = self.tabs.iter_mut().find(|t| t.id == tab_id)
|
||||
{
|
||||
tab.is_dirty = st.is_dirty;
|
||||
}
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
pub(super) fn handle_script_editor_msg(&mut self, msg: ScriptEditorMsg) -> Task<Message> {
|
||||
let mut run_request = None;
|
||||
if let Some(tab_id) = self.active_tab.clone()
|
||||
&& let Some(state) = self.script_editors.get_mut(&tab_id)
|
||||
{
|
||||
match msg {
|
||||
ScriptEditorMsg::TitleChanged(s) => {
|
||||
state.title = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
ScriptEditorMsg::SlugChanged(s) => {
|
||||
state.slug = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
ScriptEditorMsg::KindChanged(k) => {
|
||||
state.kind = k.0;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
ScriptEditorMsg::EntrypointChanged(s) => {
|
||||
state.entrypoint = s;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
ScriptEditorMsg::EnabledChanged(b) => {
|
||||
state.enabled = b;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
ScriptEditorMsg::ContentChanged(new_text) => {
|
||||
state.discovered_entrypoints = engine::script::discover_entrypoints(&new_text);
|
||||
state.content = new_text;
|
||||
state.is_dirty = true;
|
||||
}
|
||||
ScriptEditorMsg::Save => {
|
||||
return self.save_script_editor(&tab_id);
|
||||
}
|
||||
ScriptEditorMsg::CheckSyntax => {
|
||||
if let Some(st) = self.script_editors.get_mut(&tab_id) {
|
||||
match engine::script::validate_script_syntax(&st.content) {
|
||||
Ok(()) => {
|
||||
st.validation_error = None;
|
||||
}
|
||||
Err(e) => {
|
||||
st.validation_error = Some(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ScriptEditorMsg::Run => {
|
||||
run_request = Some((
|
||||
state.content.clone(),
|
||||
state.entrypoint.clone(),
|
||||
state.kind.clone(),
|
||||
));
|
||||
}
|
||||
ScriptEditorMsg::Delete => {
|
||||
let name = state.title.clone();
|
||||
return Task::done(Message::ShowModal(modal::ModalState::ConfirmDelete {
|
||||
entity_name: name,
|
||||
references: Vec::new(),
|
||||
on_confirm: modal::ConfirmAction::DeleteScript(tab_id),
|
||||
}));
|
||||
}
|
||||
}
|
||||
if let Some(st) = self.script_editors.get(&tab_id)
|
||||
&& let Some(tab) = self.tabs.iter_mut().find(|t| t.id == tab_id)
|
||||
{
|
||||
tab.is_dirty = st.is_dirty;
|
||||
}
|
||||
}
|
||||
if let Some((source, entrypoint, kind)) = run_request {
|
||||
return self.spawn_engine_task(
|
||||
"engine.runScript",
|
||||
move |_db_path, _project_id, _data_dir, task_manager, task_id| {
|
||||
let execution_kind = match kind {
|
||||
bds_core::model::ScriptKind::Macro => {
|
||||
bds_core::scripting::ExecutionKind::Macro
|
||||
}
|
||||
bds_core::model::ScriptKind::Utility => {
|
||||
bds_core::scripting::ExecutionKind::Utility
|
||||
}
|
||||
bds_core::model::ScriptKind::Transform => {
|
||||
bds_core::scripting::ExecutionKind::Transform
|
||||
}
|
||||
};
|
||||
let result = bds_core::scripting::execute(
|
||||
&source,
|
||||
&entrypoint,
|
||||
&serde_json::json!({}),
|
||||
execution_kind,
|
||||
&bds_core::scripting::ExecutionControl::default(),
|
||||
)?;
|
||||
for progress in &result.progress {
|
||||
let percent = progress.total.and_then(|total| {
|
||||
(total > 0.0).then_some((progress.current / total) as f32)
|
||||
});
|
||||
task_manager.report_progress(task_id, percent, progress.message.clone());
|
||||
}
|
||||
let mut lines = result.output;
|
||||
lines.extend(
|
||||
result
|
||||
.toasts
|
||||
.into_iter()
|
||||
.map(|message| format!("toast: {message}")),
|
||||
);
|
||||
if result.value != serde_json::Value::Null {
|
||||
lines.push(result.value.to_string());
|
||||
}
|
||||
Ok(if lines.is_empty() {
|
||||
"completed".to_string()
|
||||
} else {
|
||||
lines.join("\n")
|
||||
})
|
||||
},
|
||||
);
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user