docs(canvas): clarify editing guards and projection lifetimes
This commit is contained in:
@@ -41,12 +41,14 @@ export const NodeEditing = createContext<Omit<typeof defaultEditing, GestureHook
|
||||
export function useScopedNodeEditing(id:string,rendered?:RenderedTarget){
|
||||
// 只有rendered.id匹配当前节点才采用incarnation;有新版scope却缺少合法rendered身份时拒绝编辑。
|
||||
const editing=useContext(NodeEditing),scope=useContext(CanvasOverlays),incarnation=rendered?.id===id?rendered.incarnation:undefined,owner=rendered?.ownerCanvasId,canvas=rendered?.canvasId;
|
||||
// current 在动作触发时读取快照,不建立订阅;后续状态变化不会仅因这个检查而触发组件重渲染。
|
||||
// 无新版scope直接返回旧接口;否则只在接口、视图作用域或目标身份变化时重建包装。
|
||||
return useMemo(()=>{if(!scope)return editing;
|
||||
// 动作当刻检查engine未关闭、视图仍存在且仍在原canvas、元素生命周期与owner未变。
|
||||
// candidate必须是本节点(或允许的空参数),阻止一个节点的包装替其它目标发起操作。
|
||||
const current=(candidate:string|null|undefined=id)=>{const durability=scope.engine.getDurability(),view=scope.engine.sessions.getSnapshot().views.get(scope.index.viewId),record=scope.engine.getSnapshot().document.elements.get(id);return !durability.closing&&!durability.closed&&!!view&&view.canvasId===canvas&&incarnation!==undefined&&record?.incarnation===incarnation&&record.ownerCanvasId===owner&&(candidate===undefined||candidate===null||candidate===id);};
|
||||
// finish/cancel没有id参数,额外确认当前手势属于本视图,且目标列表含本id/incarnation。
|
||||
// 这里不捕获 gesture token;同视图同目标的新手势也能通过,精确手势身份须由创建者的租约保护。
|
||||
const ownGesture=()=>scope.engine.sessions.getSnapshot().gesture?.viewId===scope.index.viewId&&scope.engine.sessions.getSnapshot().gesture?.targets.some(target=>target.id===id&&target.incarnation===incarnation);
|
||||
// 拷贝展示信息,仅替换动作入口;文本/样式/几何等动作逐次检查,不缓存“曾经有效”的结论。
|
||||
const scoped:typeof editing={...editing,
|
||||
@@ -61,7 +63,7 @@ export function useScopedNodeEditing(id:string,rendered?:RenderedTarget){
|
||||
// begin取得的租约由创建者管理;这里不把旧事件转给当前另一个手势。
|
||||
if(editing.beginTransform)scoped.beginTransform=candidate=>current(candidate)?editing.beginTransform!(candidate):false;
|
||||
if(editing.endEditing)scoped.endEditing=candidate=>{if(current(candidate))editing.endEditing!(candidate);};
|
||||
// 结束手势要同时通过对象有效性与手势归属检查,防止迟到的pointerup结束新交互。
|
||||
// 结束手势要同时通过对象有效性与归属检查;这不是对任意迟到事件的完整 token 隔离。
|
||||
if(editing.finishTransform)scoped.finishTransform=()=>{if(current()&&ownGesture())editing.finishTransform!();};
|
||||
if(editing.cancelTransform)scoped.cancelTransform=()=>{if(current()&&ownGesture())editing.cancelTransform!();};
|
||||
// 包装只负责入口检查;事务合法性、持久化和失败报告仍由Provider对应的动作实现负责。
|
||||
|
||||
Reference in New Issue
Block a user