diff --git a/crates/web/src/components/styled_rte.rs b/crates/web/src/components/styled_rte.rs index 6ee2c5ea..33a2e217 100644 --- a/crates/web/src/components/styled_rte.rs +++ b/crates/web/src/components/styled_rte.rs @@ -100,6 +100,9 @@ pub enum RteMsg { InsertCode(bool), CodeChanged(String), InjectCode, + + StoreSelection(web_sys::Selection), + ClearSelection, } impl RteMsg { @@ -212,6 +215,7 @@ pub struct StyledRteState { pub identifier: uuid::Uuid, pub heading_state: StyledSelectState, range: Option, + selection: Option, } impl StyledRteState { @@ -228,6 +232,7 @@ impl StyledRteState { range: None, identifier: uuid::Uuid::new_v4(), heading_state: StyledSelectState::new(field_id, vec![]), + selection: None, } } @@ -237,6 +242,13 @@ impl StyledRteState { let m = match msg { Msg::Rte(field, m) if field == &self.field_id => m, + Msg::StyledSelectChanged(id, StyledSelectChanged::Changed(Some(n))) + if id == &self.field_id => + { + let size = HeadingSize::from_u32(*n); + self.try_wrap_into(size.as_str()); + return; + } _ => return, }; @@ -313,7 +325,7 @@ impl StyledRteState { if self.restore_range().is_err() { return; } - let doc = seed::html_document(); + let doc = html_document(); let r = match self.range.as_ref() { Some(r) => r, _ => return, @@ -327,6 +339,12 @@ impl StyledRteState { error!(e); } } + RteMsg::StoreSelection(sel) => { + self.selection = Some(sel.clone()); + } + RteMsg::ClearSelection => { + self.selection = None; + } }; // orders.skip().send_msg(Msg::StrInputChanged( // self.field_id.clone(), @@ -376,7 +394,12 @@ impl StyledRteState { } fn try_wrap_into(&self, name: &str) -> Option<()> { - let sel = document().get_selection().ok()??; + tracing::info!(">>>> {:?}", self.selection); + + let sel = self + .selection + .clone() + .or(document().get_selection().ok().flatten())?; let r = sel.get_range_at(0).ok()?; let start = r.start_container(); @@ -427,7 +450,7 @@ impl StyledRteState { if start == end && start - .dyn_ref::() + .dyn_ref::() .filter(|x| x.tag_name() == name) .is_some() { @@ -438,10 +461,10 @@ impl StyledRteState { ); } let start = start.parent_element()?; - let start_parent = start.dyn_ref::()?; + let start_parent = start.dyn_ref::()?; let end = end.parent_element()?; - let end_parent = end.dyn_ref::()?; + let end_parent = end.dyn_ref::()?; if start_parent == end_parent && start_parent.tag_name().as_str() == name { Some(start) @@ -451,8 +474,13 @@ impl StyledRteState { } fn is_in_rte(&self) -> Option { + tracing::info!(">>>> {:?}", self.selection); + let id = self.identifier.to_string(); - let sel = document().get_selection().ok()??; + let sel = self + .selection + .clone() + .or(document().get_selection().ok().flatten())?; let r = sel.get_range_at(0).ok()?; let mut current: web_sys::Node = r.start_container().ok()?; while let Some(c) = current.parent_element() { @@ -614,12 +642,32 @@ impl<'outer> StyledRte<'outer> { let first_row = self.first_row(click_handler.clone()); - let click_detect_font_style = mouse_ev(Ev::Click, |ev| { - let target = ev.target()?; - let el = to_html_el(&target); - tracing::info!("{:?} {:?}", el.tag_name(), el.id()); - None as Option - }); + let click_detect_font_style = { + let s = self.heading_state.unwrap().values.clone(); + let id = self.field_id.clone(); + mouse_ev(Ev::Click, move |ev| { + let target = ev.target()?; + let el = to_html_el(&target); + find_head_type(el.clone(), &s).map(|size| { + Msg::StyledSelectChanged(id, StyledSelectChanged::Changed(Some(size.as_u32()))) + }) + }) + }; + + let store_selection = { + let id = self.field_id.clone(); + ev(Ev::Blur, move |_e| { + window() + .get_selection() + .ok() + .flatten() + .map(|sel| Msg::Rte(id, RteMsg::StoreSelection(sel))) + }) + }; + let clear_selection = { + let id = self.field_id.clone(); + ev(Ev::Focus, move |_e| Msg::Rte(id, RteMsg::ClearSelection)) + }; div![ C!["styledRte"], @@ -631,7 +679,9 @@ impl<'outer> StyledRte<'outer> { Tag::from("bq-rte"), C!["editor", self.field_id.to_str()], attrs![At::ContentEditable => true], - click_detect_font_style + click_detect_font_style, + store_selection, + clear_selection, ] ] ] @@ -1002,3 +1052,35 @@ impl<'outer> StyledRte<'outer> { span![C!["styledRteButton"], attrs![At::Title => title], button] } } + +fn find_head_type(mut el: HtmlElement, selected: &[u32]) -> Option { + let mut tag_name; + + loop { + tag_name = el.tag_name(); + if &tag_name == "BQ-RTE" && matches!(selected, &[] | &[0]) { + return None; + } + if &tag_name == "BODY" { + return None; + } + + match tag_name.as_str() { + "H1" => return Some(HeadingSize::H1), + "H2" => return Some(HeadingSize::H2), + "H3" => return Some(HeadingSize::H3), + "H4" => return Some(HeadingSize::H4), + "H5" => return Some(HeadingSize::H5), + "H6" => return Some(HeadingSize::H6), + "BQ-RTE" if matches!(selected, &[] | &[0]) => return None, + "BQ-RTE" => return Some(HeadingSize::Normal), + "BODY" => return None, + _ => (), + } + let Some(parent) = el.parent_element() else { + break; + }; + el = parent.dyn_into().unwrap(); + } + None +} diff --git a/crates/web/src/modals/issues_create/view.rs b/crates/web/src/modals/issues_create/view.rs index 123a1129..173cb86a 100644 --- a/crates/web/src/modals/issues_create/view.rs +++ b/crates/web/src/modals/issues_create/view.rs @@ -25,7 +25,7 @@ use crate::{BuildMsg, FieldId, Msg}; pub struct CloseCreateIssueModal; impl BuildMsg for CloseCreateIssueModal { - fn build(&self, element: &Option) -> Option { + fn build(&self, _element: &Option) -> Option { Some(Msg::ModalDropped) } diff --git a/crates/web/src/pages/profile_page/view.rs b/crates/web/src/pages/profile_page/view.rs index f68af253..e4289163 100644 --- a/crates/web/src/pages/profile_page/view.rs +++ b/crates/web/src/pages/profile_page/view.rs @@ -82,7 +82,7 @@ pub fn view(model: &Model) -> Node { avatar, username_field, email_field, - editor_mode_select(page), + // editor_mode_select(page), current_project, submit_field, ], @@ -148,7 +148,7 @@ fn project_select_option(project: &Project) -> StyledSelectOption<'_> { } } -#[inline(always)] +#[allow(dead_code)] fn editor_mode_select(page: &ProfilePage) -> Node { let time_tracking = StyledCheckbox { options: Some( @@ -171,7 +171,7 @@ fn editor_mode_select(page: &ProfilePage) -> Node { .render() } -#[inline(always)] +#[allow(dead_code)] fn editor_mode_checkbox_option<'l>( tem: TextEditorMode, state: &StyledCheckboxState,