diff --git a/src/components/furni-editor/FurniEditorView.tsx b/src/components/furni-editor/FurniEditorView.tsx index 6133b9b..c36ed09 100644 --- a/src/components/furni-editor/FurniEditorView.tsx +++ b/src/components/furni-editor/FurniEditorView.tsx @@ -19,7 +19,7 @@ export const FurniEditorView: FC<{}> = () => selectedItem, setSelectedItem, furniDataEntry, interactions, searchItems, loadDetail, loadBySpriteId, updateItem, deleteItem, loadInteractions, - updateFurnidata, revertFurnidata + updateFurnidata, revertFurnidata, importText, importResult } = useFurniEditor(); const isMod = useHasPermission('acc_catalogfurni'); @@ -158,6 +158,8 @@ export const FurniEditorView: FC<{}> = () => onBack={ handleBack } onUpdateFurnidata={ updateFurnidata } onRevertFurnidata={ revertFurnidata } + onImportText={ importText } + importResult={ importResult } /> } diff --git a/src/components/furni-editor/views/FurniEditorEditView.tsx b/src/components/furni-editor/views/FurniEditorEditView.tsx index 4110fe7..4fb7cb7 100644 --- a/src/components/furni-editor/views/FurniEditorEditView.tsx +++ b/src/components/furni-editor/views/FurniEditorEditView.tsx @@ -14,6 +14,8 @@ interface FurniEditorEditViewProps onBack: () => void; onUpdateFurnidata: (id: number, name: string, description: string) => void; onRevertFurnidata: (id: number) => void; + onImportText: (id: number) => void; + importResult: { found: boolean; name: string; description: string; classname: string; nonce: number } | null; } const FIELD_TIPS: Record = { @@ -110,7 +112,7 @@ const CopyValue: FC<{ value: string | number }> = ({ value }) => export const FurniEditorEditView: FC = props => { - const { item, furniDataEntry, interactions, loading, onUpdate, onDelete, onBack, onUpdateFurnidata, onRevertFurnidata } = props; + const { item, furniDataEntry, interactions, loading, onUpdate, onDelete, onBack, onUpdateFurnidata, onRevertFurnidata, onImportText, importResult } = props; const saveRef = useRef<() => void>(null); const [ form, setForm ] = useState({ @@ -139,6 +141,8 @@ export const FurniEditorEditView: FC = props => const [ furniName, setFurniName ] = useState(''); const [ furniDescription, setFurniDescription ] = useState(''); const [ confirmFurnidata, setConfirmFurnidata ] = useState(false); + const [ importNote, setImportNote ] = useState(''); + const appliedImportNonce = useRef(0); useEffect(() => { @@ -170,6 +174,7 @@ export const FurniEditorEditView: FC = props => setFurniName(String(furniDataEntry?.name ?? '')); setFurniDescription(String(furniDataEntry?.description ?? '')); setConfirmFurnidata(false); + setImportNote(''); }, [ item, furniDataEntry ]); const setField = useCallback((key: string, value: unknown) => @@ -238,6 +243,27 @@ export const FurniEditorEditView: FC = props => furniName !== String(furniDataEntry?.name ?? '') || furniDescription !== String(furniDataEntry?.description ?? ''), [ furniName, furniDescription, furniDataEntry ]); + // Apply an "Import from Habbo" result into the editable fields (review then Save). + useEffect(() => + { + if(!importResult || importResult.nonce === appliedImportNonce.current) return; + appliedImportNonce.current = importResult.nonce; + + // Ignore a result that belongs to a different furni (user navigated away). + if(importResult.classname && importResult.classname.trim().toLowerCase() !== String(item?.itemName ?? '').trim().toLowerCase()) return; + + if(importResult.found) + { + setFurniName(importResult.name); + setFurniDescription(importResult.description); + setImportNote('Imported from Habbo — review and Save'); + } + else + { + setImportNote('Not found on Habbo for this classname'); + } + }, [ importResult, item ]); + const handleSave = useCallback(() => { if(!isValid) return; @@ -336,10 +362,22 @@ export const FurniEditorEditView: FC = props => setFurniDescription(e.target.value) } maxLength={ 256 } /> - + + + { importNote && + { importNote } } ) : (
diff --git a/src/hooks/furni-editor/useFurniEditor.ts b/src/hooks/furni-editor/useFurniEditor.ts index 98d6e9e..3cd8ec8 100644 --- a/src/hooks/furni-editor/useFurniEditor.ts +++ b/src/hooks/furni-editor/useFurniEditor.ts @@ -1,4 +1,4 @@ -import { FurniEditorBySpriteComposer, FurniEditorDeleteComposer, FurniEditorDetailComposer, FurniEditorDetailResultEvent, FurniEditorInteractionsComposer, FurniEditorInteractionsResultEvent, FurniEditorResultEvent, FurniEditorRevertFurnidataComposer, FurniEditorSearchComposer, FurniEditorSearchResultEvent, FurniEditorUpdateComposer, FurniEditorUpdateFurnidataComposer } from '@nitrots/nitro-renderer'; +import { FurniEditorBySpriteComposer, FurniEditorDeleteComposer, FurniEditorDetailComposer, FurniEditorDetailResultEvent, FurniEditorInteractionsComposer, FurniEditorInteractionsResultEvent, FurniEditorResultEvent, FurniEditorRevertFurnidataComposer, FurniEditorSearchComposer, FurniEditorSearchResultEvent, FurniEditorUpdateComposer, FurniEditorUpdateFurnidataComposer, FurniEditorImportTextComposer, FurniEditorImportTextResultEvent } from '@nitrots/nitro-renderer'; import { useCallback, useRef, useState } from 'react'; import { NotificationAlertType, SendMessageComposer } from '../../api'; import { useMessageEvent, useNotification } from '../../hooks'; @@ -61,6 +61,8 @@ export const useFurniEditor = () => const [ interactions, setInteractions ] = useState([]); const [ furniDataEntry, setFurniDataEntry ] = useState | null>(null); const pendingActionRef = useRef<{ action: string; itemId: number } | null>(null); + const [ importResult, setImportResult ] = useState<{ found: boolean; name: string; description: string; classname: string; nonce: number } | null>(null); + const importNonceRef = useRef(0); const { simpleAlert = null } = useNotification(); const clearError = useCallback(() => setError(null), []); @@ -264,6 +266,28 @@ export const useFurniEditor = () => SendMessageComposer(new FurniEditorRevertFurnidataComposer(id)); }, []); + const importText = useCallback((id: number) => + { + setLoading(true); + setError(null); + SendMessageComposer(new FurniEditorImportTextComposer(id)); + }, []); + + useMessageEvent(FurniEditorImportTextResultEvent, (event: FurniEditorImportTextResultEvent) => + { + const parser = event.getParser(); + + setLoading(false); + importNonceRef.current += 1; + setImportResult({ + found: parser.found, + name: parser.name, + description: parser.description, + classname: parser.classname, + nonce: importNonceRef.current + }); + }); + const loadInteractions = useCallback(() => { SendMessageComposer(new FurniEditorInteractionsComposer()); @@ -274,6 +298,6 @@ export const useFurniEditor = () => selectedItem, setSelectedItem, catalogItems, furniDataEntry, interactions, searchItems, loadDetail, loadBySpriteId, updateItem, deleteItem, loadInteractions, - updateFurnidata, revertFurnidata + updateFurnidata, revertFurnidata, importText, importResult }; };