refactor: extract block state helper
This commit is contained in:
@@ -3,7 +3,12 @@
|
||||
//! 本模块只承接拖拽命中所需的窄 helper,不处理 Leptos signal,
|
||||
//! 也不分发 editor command;调用方负责保留编辑器状态编排。
|
||||
|
||||
use crate::editor_runtime::block_hover_state::{DropIndicatorState, DropPlacement};
|
||||
use crate::{
|
||||
editor_runtime::block_hover_state::{
|
||||
block_label_for_element, DropIndicatorState, DropPlacement, HoveredBlockState,
|
||||
},
|
||||
editor_root_element, editor_stage_element,
|
||||
};
|
||||
use web_sys::{window, Element, EventTarget};
|
||||
|
||||
pub(crate) struct HandleCorridorGeometry {
|
||||
@@ -124,6 +129,78 @@ pub(crate) fn drop_indicator_from_block_rects(
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn block_state_from_index(index: usize) -> Option<HoveredBlockState> {
|
||||
let root = editor_root_element()?;
|
||||
let stage = editor_stage_element()?;
|
||||
let block = root.children().item(index as u32)?;
|
||||
let block_rect = block.get_bounding_client_rect();
|
||||
let stage_rect = stage.get_bounding_client_rect();
|
||||
let block_height = if block_rect.height() > 0.0 {
|
||||
block_rect.height()
|
||||
} else {
|
||||
28.0
|
||||
};
|
||||
|
||||
Some(HoveredBlockState {
|
||||
index,
|
||||
label: block_label_for_element(&block),
|
||||
top: block_rect.top() - stage_rect.top(),
|
||||
height: block_height,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn pointer_in_handle_corridor(
|
||||
client_x: i32,
|
||||
client_y: i32,
|
||||
block: &HoveredBlockState,
|
||||
handle_selector: &str,
|
||||
handle_left_fallback: f64,
|
||||
handle_width: f64,
|
||||
) -> bool {
|
||||
let Some(stage) = editor_stage_element() else {
|
||||
return false;
|
||||
};
|
||||
let Some(root) = editor_root_element() else {
|
||||
return false;
|
||||
};
|
||||
let Some(block_element) = root.children().item(block.index as u32) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let stage_rect = stage.get_bounding_client_rect();
|
||||
let block_rect = block_element.get_bounding_client_rect();
|
||||
let handle_rect = window()
|
||||
.and_then(|win| win.document())
|
||||
.and_then(|document| document.query_selector(handle_selector).ok().flatten())
|
||||
.map(|handle| handle.get_bounding_client_rect());
|
||||
|
||||
let block_left = block_rect.left() - stage_rect.left();
|
||||
let block_top = block_rect.top() - stage_rect.top();
|
||||
let block_bottom = block_rect.bottom() - stage_rect.top();
|
||||
let handle_left = handle_rect
|
||||
.as_ref()
|
||||
.map(|rect| rect.left() - stage_rect.left())
|
||||
.unwrap_or(handle_left_fallback);
|
||||
let handle_right = handle_rect
|
||||
.as_ref()
|
||||
.map(|rect| rect.right() - stage_rect.left())
|
||||
.unwrap_or_else(|| handle_left + handle_width);
|
||||
|
||||
pointer_in_handle_corridor_geometry(
|
||||
client_x,
|
||||
client_y,
|
||||
&HandleCorridorGeometry {
|
||||
stage_left: stage_rect.left(),
|
||||
stage_top: stage_rect.top(),
|
||||
block_left,
|
||||
block_top,
|
||||
block_bottom,
|
||||
handle_left,
|
||||
handle_right,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn top_level_block_index(root: &Element, block: &Element) -> Option<usize> {
|
||||
let children = root.children();
|
||||
(0..children.length()).find_map(|index| {
|
||||
|
||||
@@ -22,9 +22,9 @@ use web_sys::{
|
||||
|
||||
use editor_runtime::attachment_upload::dispatch_editor_upload_request;
|
||||
use editor_runtime::block_dnd::{
|
||||
direct_block_from_element, direct_block_index_from_element,
|
||||
drop_indicator_from_block_rects, element_within_handle_shell, event_target_from_point,
|
||||
pointer_in_handle_corridor_geometry, top_level_block_index, HandleCorridorGeometry,
|
||||
block_state_from_index as block_state_from_index_runtime, direct_block_from_element,
|
||||
direct_block_index_from_element, drop_indicator_from_block_rects, element_within_handle_shell,
|
||||
event_target_from_point, top_level_block_index,
|
||||
};
|
||||
use editor_runtime::block_menu_overlay;
|
||||
use editor_runtime::block_menu_document::{
|
||||
@@ -34,8 +34,7 @@ use editor_runtime::block_menu_legacy_html::{
|
||||
duplicate_top_level_block_html, reorder_top_level_block_html,
|
||||
};
|
||||
use editor_runtime::block_hover_state::{
|
||||
block_label_for_element, BlockMenuLayout, DropIndicatorState, HoveredBlockState,
|
||||
PendingDragState,
|
||||
BlockMenuLayout, DropIndicatorState, HoveredBlockState, PendingDragState,
|
||||
};
|
||||
use editor_runtime::command_sync::{
|
||||
read_editor_snapshot, sync_editor_outputs, sync_persisted_editor_command,
|
||||
@@ -4867,23 +4866,7 @@ fn hovered_block_from_selection() -> Option<HoveredBlockState> {
|
||||
}
|
||||
|
||||
fn block_state_from_index(index: usize) -> Option<HoveredBlockState> {
|
||||
let root = editor_root_element()?;
|
||||
let stage = editor_stage_element()?;
|
||||
let block = root.children().item(index as u32)?;
|
||||
let block_rect = block.get_bounding_client_rect();
|
||||
let stage_rect = stage.get_bounding_client_rect();
|
||||
let block_height = if block_rect.height() > 0.0 {
|
||||
block_rect.height()
|
||||
} else {
|
||||
28.0
|
||||
};
|
||||
|
||||
Some(HoveredBlockState {
|
||||
index,
|
||||
label: block_label_for_element(&block),
|
||||
top: block_rect.top() - stage_rect.top(),
|
||||
height: block_height,
|
||||
})
|
||||
block_state_from_index_runtime(index)
|
||||
}
|
||||
|
||||
fn prosemirror_node_size(node: &Value) -> Option<u32> {
|
||||
@@ -5046,56 +5029,6 @@ fn image_element_from_target(target: web_sys::EventTarget) -> Option<Element> {
|
||||
.flatten()
|
||||
}
|
||||
|
||||
fn pointer_in_handle_corridor(client_x: i32, client_y: i32, block: &HoveredBlockState) -> bool {
|
||||
let Some(stage) = editor_stage_element() else {
|
||||
return false;
|
||||
};
|
||||
let Some(root) = editor_root_element() else {
|
||||
return false;
|
||||
};
|
||||
let Some(block_element) = root.children().item(block.index as u32) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let stage_rect = stage.get_bounding_client_rect();
|
||||
let block_rect = block_element.get_bounding_client_rect();
|
||||
let handle_rect = window()
|
||||
.and_then(|win| win.document())
|
||||
.and_then(|document| {
|
||||
document
|
||||
.query_selector(HANDLE_SHELL_SELECTOR)
|
||||
.ok()
|
||||
.flatten()
|
||||
})
|
||||
.map(|handle| handle.get_bounding_client_rect());
|
||||
|
||||
let block_left = block_rect.left() - stage_rect.left();
|
||||
let block_top = block_rect.top() - stage_rect.top();
|
||||
let block_bottom = block_rect.bottom() - stage_rect.top();
|
||||
let handle_left = handle_rect
|
||||
.as_ref()
|
||||
.map(|rect| rect.left() - stage_rect.left())
|
||||
.unwrap_or_else(|| handle_lane_left(stage_rect.width()));
|
||||
let handle_right = handle_rect
|
||||
.as_ref()
|
||||
.map(|rect| rect.right() - stage_rect.left())
|
||||
.unwrap_or_else(|| handle_left + HANDLE_TRIGGER_WIDTH);
|
||||
|
||||
pointer_in_handle_corridor_geometry(
|
||||
client_x,
|
||||
client_y,
|
||||
&HandleCorridorGeometry {
|
||||
stage_left: stage_rect.left(),
|
||||
stage_top: stage_rect.top(),
|
||||
block_left,
|
||||
block_top,
|
||||
block_bottom,
|
||||
handle_left,
|
||||
handle_right,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn drop_indicator_from_target(
|
||||
target: web_sys::EventTarget,
|
||||
client_y: i32,
|
||||
@@ -7794,7 +7727,18 @@ fn App(mount_options: MountOptions) -> impl IntoView {
|
||||
}
|
||||
|
||||
if let Some(current_block) = hovered_block.get_untracked() {
|
||||
if pointer_in_handle_corridor(event.client_x(), event.client_y(), ¤t_block) {
|
||||
if editor_runtime::block_dnd::pointer_in_handle_corridor(
|
||||
event.client_x(),
|
||||
event.client_y(),
|
||||
¤t_block,
|
||||
HANDLE_SHELL_SELECTOR,
|
||||
handle_lane_left(
|
||||
editor_stage_element()
|
||||
.map(|stage| stage.get_bounding_client_rect().width())
|
||||
.unwrap_or(0.0),
|
||||
),
|
||||
HANDLE_TRIGGER_WIDTH,
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -7818,7 +7762,18 @@ fn App(mount_options: MountOptions) -> impl IntoView {
|
||||
return;
|
||||
}
|
||||
if let Some(current_block) = hovered_block.get_untracked() {
|
||||
if pointer_in_handle_corridor(event.client_x(), event.client_y(), ¤t_block) {
|
||||
if editor_runtime::block_dnd::pointer_in_handle_corridor(
|
||||
event.client_x(),
|
||||
event.client_y(),
|
||||
¤t_block,
|
||||
HANDLE_SHELL_SELECTOR,
|
||||
handle_lane_left(
|
||||
editor_stage_element()
|
||||
.map(|stage| stage.get_bounding_client_rect().width())
|
||||
.unwrap_or(0.0),
|
||||
),
|
||||
HANDLE_TRIGGER_WIDTH,
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user