Commit active native text before saving with keyboard shortcuts
studio CI and deployment / verify-and-deploy (push) Successful in 5m32s
studio CI and deployment / verify-and-deploy (push) Successful in 5m32s
This commit is contained in:
@@ -18,10 +18,11 @@ function CurvedCopy({layout,slot,value,style,spacing=0}:{layout:Layout;slot:Slot
|
||||
export function LayoutWorkbench({layout,design:initialDesign}:LayoutPageProps){
|
||||
const [params,setParams]=useState<Parameters>(initialDesign?.parameters||emptyParameters()),[design,setDesign]=useState(initialDesign),[editing,setEditing]=useState(false),[selected,setSelected]=useState<string|null>(null),[name,setName]=useState(initialDesign?.name||layout.name),[status,setStatus]=useState(''),[busy,setBusy]=useState(false),[dirty,setDirty]=useState(false),[history,setHistory]=useState<Parameters[]>([]),[future,setFuture]=useState<Parameters[]>([]),[zoom,setZoom]=useState(1),[panel,setPanel]=useState<'layers'|'properties'|null>(null),[textEditing,setTextEditing]=useState<string|null>(null),[conflict,setConflict]=useState(false);
|
||||
const canvas=useRef<HTMLElement>(null),viewport=useRef<HTMLDivElement>(null);
|
||||
const paramsRef=useRef(params);paramsRef.current=params;
|
||||
const elements=[...layout.elements,...(params.added||[])];
|
||||
const upload=useRef<HTMLInputElement>(null),slot=elements.find(s=>s.id===selected);
|
||||
useEffect(()=>{const warn=(event:BeforeUnloadEvent)=>{if(dirty){event.preventDefault();event.returnValue=''}};window.addEventListener('beforeunload',warn);return()=>window.removeEventListener('beforeunload',warn)},[dirty]);
|
||||
function patch(next:Parameters){try{const valid=parameters(layout,next);setHistory(old=>[...old.slice(-39),params]);setFuture([]);setParams(valid);setDirty(true);setStatus('')}catch(e){setStatus(e instanceof Error?e.message:'修改失败')}}
|
||||
function patch(next:Parameters){try{const valid=parameters(layout,next);setHistory(old=>[...old.slice(-39),params]);setFuture([]);paramsRef.current=valid;setParams(valid);setDirty(true);setStatus('')}catch(e){setStatus(e instanceof Error?e.message:'修改失败')}}
|
||||
function updateText(s:Slot,changes:Partial<Parameters['texts'][string]>){patch({...params,texts:{...params.texts,[s.id]:{...params.texts[s.id],value:params.texts[s.id]?.value??defaultText(layout,s),...changes}}})}
|
||||
function layer(s:Slot):LayerValue{return params.layers?.[s.id]||{}}
|
||||
function updateLayer(s:Slot,changes:LayerValue){patch({...params,layers:{...params.layers,[s.id]:{...layer(s),...changes}}})}
|
||||
@@ -39,8 +40,10 @@ export function LayoutWorkbench({layout,design:initialDesign}:LayoutPageProps){
|
||||
function reset(s:Slot){const group=s.kind==='text'?'texts':s.kind==='image'?'images':'decorations',values={...params[group]};delete values[s.id];patch({...params,[group]:values})}
|
||||
function keySelect(e:KeyboardEvent,s:Slot){if(e.key==='ContextMenu'||(e.shiftKey&&e.key==='F10')){e.preventDefault();select(s)}if(e.key==='Escape')setSelected(null)}
|
||||
async function save(copy=false){
|
||||
// Commit an active native text edit before keyboard-triggered saving.
|
||||
if(document.activeElement instanceof HTMLElement)document.activeElement.blur();
|
||||
setBusy(true);try{
|
||||
const valid=parameters(layout,params),updating=design&&!copy;
|
||||
const valid=parameters(layout,paramsRef.current),updating=design&&!copy;
|
||||
const response=await fetch('/api/studio/designs'+(updating?'/'+design.id:''),{method:updating?'PATCH':'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(updating?{name,parameters:valid,revision:design.revision}:{name,layoutId:layout.id,parameters:valid})});
|
||||
const data=await response.json();if(!response.ok){if(response.status===409)setConflict(true);throw Error(data.error||'保存失败')};setConflict(false);
|
||||
setDesign(data.design);setDirty(false);setStatus('已保存,当前网址可直接打开此页面');
|
||||
|
||||
Reference in New Issue
Block a user