Skip to content

Commit 2638865

Browse files
authored
Refactor components for improved readability and performance (#72)
- Replaced `img` with `Image` component in multiple files for better image handling. - Simplified `useMemo` dependencies in `message.tsx`. - Adjusted formatting and spacing in `session-view.tsx` and `welcome-view.tsx` for consistency. - Cleaned up unnecessary imports and improved JSX structure across various components.
1 parent 16b00e4 commit 2638865

4 files changed

Lines changed: 49 additions & 37 deletions

File tree

complex-agents/avatars/anam/frontend/components/agents-ui/react-shader-toy.tsx

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React, { useEffect, useRef, type ComponentPropsWithoutRef } from 'react';
1+
import React, { type ComponentPropsWithoutRef, useEffect, useRef } from 'react';
2+
23
const PRECISIONS = ['lowp', 'mediump', 'highp'];
34
const FS_MAIN_SHADER = `\nvoid main(void){
45
vec4 color = vec4(0.0,0.0,0.0,1.0);
@@ -40,7 +41,7 @@ const processUniform = <T extends UniformType>(
4041
gl: WebGLRenderingContext,
4142
location: WebGLUniformLocation,
4243
t: T,
43-
value: number | number[],
44+
value: number | number[]
4445
) => {
4546
if (isVectorType(t, value)) {
4647
switch (t) {
@@ -134,18 +135,14 @@ const uniformTypeToGLSLType = (t: string) => {
134135
return 'mat4';
135136
default:
136137
console.error(
137-
log(`The uniform type "${t}" is not valid, please make sure your uniform type is valid`),
138+
log(`The uniform type "${t}" is not valid, please make sure your uniform type is valid`)
138139
);
139140
}
140141
};
141142

142143
const LinearFilter = 9729;
143144
const NearestFilter = 9728;
144145
const LinearMipMapLinearFilter = 9987;
145-
const NearestMipMapLinearFilter = 9986;
146-
const LinearMipMapNearestFilter = 9985;
147-
const NearestMipMapNearestFilter = 9984;
148-
const MirroredRepeatWrapping = 33648;
149146
const ClampToEdgeWrapping = 33071;
150147
const RepeatWrapping = 10497;
151148

@@ -198,15 +195,15 @@ class Texture {
198195
this.height = video.videoHeight || 0;
199196
checkReady();
200197
},
201-
true,
198+
true
202199
);
203200
video.addEventListener(
204201
'timeupdate',
205202
() => {
206203
timeupdate = true;
207204
checkReady();
208205
},
209-
true,
206+
true
210207
);
211208
video.src = url;
212209
return video;
@@ -224,8 +221,8 @@ class Texture {
224221
context?.drawImage(image, 0, 0, this.pow2canvas.width, this.pow2canvas.height);
225222
console.warn(
226223
log(
227-
`Image is not power of two ${image.width} x ${image.height}. Resized to ${this.pow2canvas.width} x ${this.pow2canvas.height};`,
228-
),
224+
`Image is not power of two ${image.width} x ${image.height}. Resized to ${this.pow2canvas.width} x ${this.pow2canvas.height};`
225+
)
229226
);
230227
return this.pow2canvas as T;
231228
}
@@ -236,16 +233,14 @@ class Texture {
236233
const { url, wrapS, wrapT, minFilter, magFilter, flipY = -1 }: TextureParams = textureArgs;
237234
if (!url) {
238235
return Promise.reject(
239-
new Error(
240-
log('Missing url, please make sure to pass the url of your texture { url: ... }'),
241-
),
236+
new Error(log('Missing url, please make sure to pass the url of your texture { url: ... }'))
242237
);
243238
}
244239
const isImage = /(\.jpg|\.jpeg|\.png|\.gif|\.bmp)$/i.exec(url);
245240
const isVideo = /(\.mp4|\.3gp|\.webm|\.ogv)$/i.exec(url);
246241
if (isImage === null && isVideo === null) {
247242
return Promise.reject(
248-
new Error(log(`Please upload a video or an image with a valid format (url: ${url})`)),
243+
new Error(log(`Please upload a video or an image with a valid format (url: ${url})`))
249244
);
250245
}
251246
Object.assign(this, { url, wrapS, wrapT, minFilter, magFilter, flipY });
@@ -268,7 +263,7 @@ class Texture {
268263
border,
269264
srcFormat,
270265
srcType,
271-
pixel,
266+
pixel
272267
);
273268
if (isVideo) {
274269
const video = this.setupVideo(url);
@@ -320,7 +315,7 @@ class Texture {
320315
gl.texParameteri(
321316
gl.TEXTURE_2D,
322317
gl.TEXTURE_MIN_FILTER,
323-
this.minFilter || LinearMipMapLinearFilter,
318+
this.minFilter || LinearMipMapLinearFilter
324319
);
325320
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.magFilter || LinearFilter);
326321
this._webglTexture = texture;
@@ -501,7 +496,7 @@ export function ReactShaderToy({
501496
glRef.current = (canvasRef.current.getContext('webgl', contextAttributes) ||
502497
canvasRef.current.getContext(
503498
'experimental-webgl',
504-
contextAttributes,
499+
contextAttributes
505500
)) as WebGLRenderingContext | null;
506501
glRef.current?.getExtension('OES_standard_derivatives');
507502
glRef.current?.getExtension('EXT_shader_texture_lod');
@@ -619,15 +614,15 @@ export function ReactShaderToy({
619614
if (!gl.getProgramParameter(shaderProgramRef.current, gl.LINK_STATUS)) {
620615
onError?.(
621616
log(
622-
`Unable to initialize the shader program: ${gl.getProgramInfoLog(shaderProgramRef.current)}`,
623-
),
617+
`Unable to initialize the shader program: ${gl.getProgramInfoLog(shaderProgramRef.current)}`
618+
)
624619
);
625620
return;
626621
}
627622
gl.useProgram(shaderProgramRef.current);
628623
vertexPositionAttributeRef.current = gl.getAttribLocation(
629624
shaderProgramRef.current,
630-
'aVertexPosition',
625+
'aVertexPosition'
631626
);
632627
gl.enableVertexAttribArray(vertexPositionAttributeRef.current);
633628
};
@@ -693,8 +688,8 @@ export function ReactShaderToy({
693688
if (!isValidPrecision) {
694689
onWarning?.(
695690
log(
696-
`wrong precision type ${precision}, please make sure to pass one of a valid precision lowp, mediump, highp, by default you shader precision will be set to highp.`,
697-
),
691+
`wrong precision type ${precision}, please make sure to pass one of a valid precision lowp, mediump, highp, by default you shader precision will be set to highp.`
692+
)
698693
);
699694
}
700695
let fragmentShader = precisionString
@@ -707,7 +702,7 @@ export function ReactShaderToy({
707702
fragmentShader = insertStringAtIndex(
708703
fragmentShader,
709704
`uniform ${u.type} ${uniform}${u.arraySize || ''}; \n`,
710-
fragmentShader.lastIndexOf(precisionString) + precisionString.length,
705+
fragmentShader.lastIndexOf(precisionString) + precisionString.length
711706
);
712707
u.isNeeded = true;
713708
}
@@ -735,7 +730,7 @@ export function ReactShaderToy({
735730
gl,
736731
customUniformLocation,
737732
currentUniform.type as UniformType,
738-
currentUniform.value,
733+
currentUniform.value
739734
);
740735
}
741736
}
@@ -747,18 +742,18 @@ export function ReactShaderToy({
747742
if (uniformsRef.current.iChannelResolution?.isNeeded) {
748743
const channelResUniform = gl.getUniformLocation(
749744
shaderProgramRef.current,
750-
UNIFORM_CHANNELRESOLUTION,
745+
UNIFORM_CHANNELRESOLUTION
751746
);
752747
gl.uniform3fv(channelResUniform, uniformsRef.current.iChannelResolution.value as number[]);
753748
}
754749
if (uniformsRef.current.iDeviceOrientation?.isNeeded) {
755750
const deviceOrientationUniform = gl.getUniformLocation(
756751
shaderProgramRef.current,
757-
UNIFORM_DEVICEORIENTATION,
752+
UNIFORM_DEVICEORIENTATION
758753
);
759754
gl.uniform4fv(
760755
deviceOrientationUniform,
761-
uniformsRef.current.iDeviceOrientation.value as number[],
756+
uniformsRef.current.iDeviceOrientation.value as number[]
762757
);
763758
}
764759
if (uniformsRef.current.iTime?.isNeeded) {

complex-agents/avatars/anam/frontend/components/ai-elements/message.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
'use client';
22

33
import type { ComponentProps, HTMLAttributes, ReactElement } from 'react';
4-
import { createContext, memo, useContext, useEffect, useState } from 'react';
4+
import { createContext, memo, useContext, useEffect, useMemo, useState } from 'react';
5+
import Image from 'next/image';
56
import type { FileUIPart, UIMessage } from 'ai';
67
import { ChevronLeftIcon, ChevronRightIcon, PaperclipIcon, XIcon } from 'lucide-react';
78
import { Streamdown } from 'streamdown';
@@ -155,9 +156,11 @@ export type MessageBranchContentProps = HTMLAttributes<HTMLDivElement>;
155156

156157
export const MessageBranchContent = ({ children, ...props }: MessageBranchContentProps) => {
157158
const { currentBranch, setBranches, branches } = useMessageBranch();
158-
const childrenArray = Array.isArray(children) ? children : [children];
159+
const childrenArray = useMemo(
160+
() => (Array.isArray(children) ? children : [children]),
161+
[children]
162+
);
159163

160-
// Use useEffect to update branches when they change
161164
useEffect(() => {
162165
if (branches.length !== childrenArray.length) {
163166
setBranches(childrenArray);
@@ -187,16 +190,19 @@ export const MessageBranchSelector = ({
187190
from,
188191
...props
189192
}: MessageBranchSelectorProps) => {
193+
void from; // reserved for future use (e.g. styling by role)
190194
const { totalBranches } = useMessageBranch();
191195

192-
// Don't render if there's only one branch
193196
if (totalBranches <= 1) {
194197
return null;
195198
}
196199

197200
return (
198201
<ButtonGroup
199-
className="[&>*:not(:first-child)]:rounded-l-md [&>*:not(:last-child)]:rounded-r-md"
202+
className={cn(
203+
'[&>*:not(:first-child)]:rounded-l-md [&>*:not(:last-child)]:rounded-r-md',
204+
className
205+
)}
200206
orientation="horizontal"
201207
{...props}
202208
/>
@@ -231,6 +237,7 @@ export const MessageBranchNext = ({ children, className, ...props }: MessageBran
231237
return (
232238
<Button
233239
aria-label="Next branch"
240+
className={className}
234241
disabled={totalBranches <= 1}
235242
onClick={goToNext}
236243
size="icon-sm"
@@ -288,12 +295,13 @@ export function MessageAttachment({ data, className, onRemove, ...props }: Messa
288295
<div className={cn('group relative size-24 overflow-hidden rounded-lg', className)} {...props}>
289296
{isImage ? (
290297
<>
291-
<img
298+
<Image
292299
alt={filename || 'attachment'}
293300
className="size-full object-cover"
294301
height={100}
295302
src={data.url}
296303
width={100}
304+
unoptimized
297305
/>
298306
{onRemove && (
299307
<Button

complex-agents/avatars/anam/frontend/components/app/session-view.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ interface SessionViewProps {
1414

1515
const POST_SUBMIT_FALLBACK_MS = 90_000;
1616

17-
export const SessionView = ({ appConfig, ...props }: React.ComponentProps<'section'> & SessionViewProps) => {
17+
export const SessionView = ({
18+
appConfig,
19+
...props
20+
}: React.ComponentProps<'section'> & SessionViewProps) => {
21+
void appConfig; // passed for type/API consistency; may be used later
1822
const { end, room, isConnected } = useSessionContext();
1923
const agent = useAgent();
2024
const [formData, setFormData] = useState<IntakeFormData>(EMPTY_FORM_DATA);

complex-agents/avatars/anam/frontend/components/app/welcome-view.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import Image from 'next/image';
12
import { Button } from '@/components/ui/button';
23

34
function WelcomeImage() {
45
return (
56
<div className="mb-4 size-64 overflow-hidden rounded-lg border-4 border-gray-200 dark:border-gray-800">
6-
<img
7+
<Image
78
src="/liv.jpg"
89
alt="Liv AI assistant"
10+
width={256}
11+
height={256}
912
className="size-full object-cover"
1013
/>
1114
</div>
@@ -28,7 +31,9 @@ export const WelcomeView = ({
2831
<WelcomeImage />
2932

3033
<p className="text-foreground max-w-prose pt-1 leading-6 font-medium">
31-
Complete your healthcare intake<br />Powered by Anam + LiveKit
34+
Complete your healthcare intake
35+
<br />
36+
Powered by Anam + LiveKit
3237
</p>
3338

3439
<Button

0 commit comments

Comments
 (0)