From 9e2b7fcc617bb36f3c15220a3d503308be0bc94b Mon Sep 17 00:00:00 2001 From: Mahmoud Hemaid Date: Thu, 29 May 2025 02:05:22 +0300 Subject: [PATCH] feat: Add support for participant name, metadata, and attributes (#142) --- src/components/config/AttributesEditor.tsx | 93 ++++++++++++++++++++++ src/components/playground/Playground.tsx | 48 ++++++++++- src/hooks/useConfig.tsx | 8 ++ src/hooks/useConnection.tsx | 34 ++++++-- src/lib/types.ts | 6 ++ src/pages/api/token.ts | 26 +++++- 6 files changed, 204 insertions(+), 11 deletions(-) create mode 100644 src/components/config/AttributesEditor.tsx diff --git a/src/components/config/AttributesEditor.tsx b/src/components/config/AttributesEditor.tsx new file mode 100644 index 0000000..bfead72 --- /dev/null +++ b/src/components/config/AttributesEditor.tsx @@ -0,0 +1,93 @@ +import React from 'react'; +import { ConnectionState } from 'livekit-client'; +import { AttributeItem } from '@/lib/types'; + + +interface AttributesEditorProps { + attributes: AttributeItem[]; + onAttributesChange: (attributes: AttributeItem[]) => void; + themeColor: string; + disabled?: boolean; + connectionState?: ConnectionState; +} + +export const AttributesEditor: React.FC = ({ + attributes, + onAttributesChange, + themeColor, + disabled = false, + connectionState +}) => { + const handleKeyChange = (id: string, newKey: string) => { + const updatedAttributes = attributes.map(attr => + attr.id === id ? { ...attr, key: newKey } : attr + ); + onAttributesChange(updatedAttributes); + }; + + const handleValueChange = (id: string, newValue: string) => { + const updatedAttributes = attributes.map(attr => + attr.id === id ? { ...attr, value: newValue } : attr + ); + onAttributesChange(updatedAttributes); + }; + + const handleRemoveAttribute = (id: string) => { + const updatedAttributes = attributes.filter(attr => attr.id !== id); + onAttributesChange(updatedAttributes); + }; + + const handleAddAttribute = () => { + const newId = `attr_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + const updatedAttributes = [...attributes, { id: newId, key: "", value: "" }]; + onAttributesChange(updatedAttributes); + }; + + return ( +
+ {attributes.map((attribute) => ( +
+ handleKeyChange(attribute.id, e.target.value)} + className="flex-1 min-w-0 text-white text-sm bg-transparent border border-gray-800 rounded-sm px-3 py-1" + placeholder="Key" + disabled={disabled} + /> + handleValueChange(attribute.id, e.target.value)} + className="flex-1 min-w-0 text-white text-sm bg-transparent border border-gray-800 rounded-sm px-3 py-1" + placeholder="Value" + disabled={disabled} + /> + +
+ ))} + + +
+ ); +}; \ No newline at end of file diff --git a/src/components/playground/Playground.tsx b/src/components/playground/Playground.tsx index ec1db3d..fec3894 100644 --- a/src/components/playground/Playground.tsx +++ b/src/components/playground/Playground.tsx @@ -30,6 +30,7 @@ import { QRCodeSVG } from "qrcode.react"; import { ReactNode, useCallback, useEffect, useMemo, useState } from "react"; import tailwindTheme from "../../lib/tailwindTheme.preval"; import { EditableNameValueRow } from "@/components/config/NameValueRow"; +import { AttributesEditor } from "@/components/config/AttributesEditor"; export interface PlaygroundMeta { name: string; @@ -260,9 +261,23 @@ export default function Playground({ editable={roomState !== ConnectionState.Connected} /> { + const newSettings = { ...config.settings }; + newSettings.participant_id = value; + setUserSettings(newSettings); + }} + placeholder="Enter participant id" + editable={roomState !== ConnectionState.Connected} + /> + { @@ -270,10 +285,39 @@ export default function Playground({ newSettings.participant_name = value; setUserSettings(newSettings); }} - placeholder="Enter participant id" + placeholder="Enter participant name" editable={roomState !== ConnectionState.Connected} /> + +
+
Metadata
+