refactor(block-h): message block types resolve via plugin-contributable registry
This commit is contained in:
@@ -6,14 +6,8 @@ import ImageBlock from './ImageBlock';
|
||||
import AudioBlock from './AudioBlock';
|
||||
import VideoBlock from './VideoBlock';
|
||||
import FileBlock from './FileBlock';
|
||||
import ActionCardBlock from './ActionCardBlock';
|
||||
import ContactCardBlock from './ContactCardBlock';
|
||||
import MiniAppBlock from './MiniAppBlock';
|
||||
import AgentResultBlock from './AgentResultBlock';
|
||||
import ApprovalRequestBlock from './ApprovalRequestBlock';
|
||||
import TaskCardBlock from './TaskCardBlock';
|
||||
import WorkflowCardBlock from './WorkflowCardBlock';
|
||||
import KnowledgeCardBlock from './KnowledgeCardBlock';
|
||||
import { getBlockComponent } from './registry';
|
||||
import './registrations'; // plugin-contributed block registrations
|
||||
|
||||
interface BlockRendererProps {
|
||||
blocks: MessageBlock[];
|
||||
@@ -51,29 +45,20 @@ const BlockRenderer: React.FC<BlockRendererProps> = ({ blocks }) => {
|
||||
return <VideoBlock block={block} />;
|
||||
case 'file':
|
||||
return <FileBlock block={block} />;
|
||||
case 'action_card':
|
||||
return <ActionCardBlock block={block} />;
|
||||
case 'contact_card':
|
||||
return <ContactCardBlock block={block} />;
|
||||
case 'miniapp':
|
||||
return <MiniAppBlock block={block} />;
|
||||
case 'agent_result':
|
||||
return <AgentResultBlock block={block} />;
|
||||
case 'approval_request':
|
||||
return <ApprovalRequestBlock block={block} />;
|
||||
case 'task_card':
|
||||
return <TaskCardBlock block={block} />;
|
||||
case 'workflow_card':
|
||||
return <WorkflowCardBlock block={block} />;
|
||||
case 'knowledge_card':
|
||||
return <KnowledgeCardBlock block={block} />;
|
||||
default:
|
||||
default: {
|
||||
// Plugin-contributed block types (Block H / HC-F)
|
||||
const Contributed = getBlockComponent(block.block_type);
|
||||
if (Contributed) {
|
||||
const ContributedBlock = Contributed as React.FC<{ block: MessageBlock }>;
|
||||
return <ContributedBlock block={block} />;
|
||||
}
|
||||
// Fallback for unknown block types
|
||||
return (
|
||||
<div className="text-xs text-secondary-400 italic p-2 rounded bg-secondary-50">
|
||||
Unbekannter Block-Typ: {block.block_type}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Plugin block registrations.
|
||||
*
|
||||
* Currently a static import list; the dynamic plugin loader (ARCH-019 fix)
|
||||
* will replace this file with manifest-driven registration. Plugins register
|
||||
* their block renderers via ``registerBlockType`` with an owner tag so that
|
||||
* ``unregisterBlockTypes(owner)`` can clean up on deactivation.
|
||||
*/
|
||||
import { registerBlockType } from './registry';
|
||||
import ActionCardBlock from './ActionCardBlock';
|
||||
import ContactCardBlock from './ContactCardBlock';
|
||||
import MiniAppBlock from './MiniAppBlock';
|
||||
import AgentResultBlock from './AgentResultBlock';
|
||||
import ApprovalRequestBlock from './ApprovalRequestBlock';
|
||||
import TaskCardBlock from './TaskCardBlock';
|
||||
import WorkflowCardBlock from './WorkflowCardBlock';
|
||||
import KnowledgeCardBlock from './KnowledgeCardBlock';
|
||||
|
||||
registerBlockType('action_card', ActionCardBlock, 'core-comm');
|
||||
registerBlockType('contact_card', ContactCardBlock, 'contacts');
|
||||
registerBlockType('miniapp', MiniAppBlock, 'kommunikation');
|
||||
registerBlockType('agent_result', AgentResultBlock, 'automation');
|
||||
registerBlockType('approval_request', ApprovalRequestBlock, 'core-approvals');
|
||||
registerBlockType('task_card', TaskCardBlock, 'tasks');
|
||||
registerBlockType('workflow_card', WorkflowCardBlock, 'workflows');
|
||||
registerBlockType('knowledge_card', KnowledgeCardBlock, 'knowledge');
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Message block type registry.
|
||||
*
|
||||
* Core owns the base block types; plugins can contribute additional block
|
||||
* renderers via ``registerBlockType`` / ``unregisterBlockTypes`` during their
|
||||
* frontend activation lifecycle (Block H / HC-F).
|
||||
*/
|
||||
import type { ComponentType } from 'react';
|
||||
import type { MessageBlock } from '@/store/commStore';
|
||||
|
||||
export type BlockComponent = ComponentType<{ block: MessageBlock }>;
|
||||
|
||||
const _registry = new Map<string, BlockComponent>();
|
||||
|
||||
export function registerBlockType(blockType: string, component: BlockComponent, owner = ''): void {
|
||||
if (_registry.has(blockType)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`[blockRegistry] block type '${blockType}' re-registered by '${owner || 'unknown'}' — overwriting`);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(component as any).__block_owner__ = owner;
|
||||
_registry.set(blockType, component);
|
||||
}
|
||||
|
||||
export function unregisterBlockTypes(owner: string): void {
|
||||
for (const [key, component] of _registry.entries()) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
if ((component as any).__block_owner__ === owner) {
|
||||
_registry.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getBlockComponent(blockType: string): BlockComponent | undefined {
|
||||
return _registry.get(blockType);
|
||||
}
|
||||
Reference in New Issue
Block a user