diff --git a/src/app/features/settings/account/Profile.tsx b/src/app/features/settings/account/Profile.tsx index 60150827..7cf1214e 100644 --- a/src/app/features/settings/account/Profile.tsx +++ b/src/app/features/settings/account/Profile.tsx @@ -60,7 +60,7 @@ function IdentityProviderSettings({ authMetadata }: { authMetadata: ValidatedAut } > - Change profile settings in your homeserver's account dashboard. + Change profile settings in your homeserver's account dashboard. ); diff --git a/src/app/features/settings/account/fields/ProfileFieldContext.tsx b/src/app/features/settings/account/fields/ProfileFieldContext.tsx index 0e5da3e6..4045d3cb 100644 --- a/src/app/features/settings/account/fields/ProfileFieldContext.tsx +++ b/src/app/features/settings/account/fields/ProfileFieldContext.tsx @@ -1,26 +1,43 @@ -import React, { FunctionComponent, ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; +import React, { + FunctionComponent, + ReactNode, + useCallback, + useEffect, + useMemo, + useState, +} from 'react'; import { ExtendedProfile } from '../../../../hooks/useExtendedProfile'; type ExtendedProfileKeys = keyof { - [Property in keyof ExtendedProfile as string extends Property ? never : Property]: ExtendedProfile[Property] -} + [Property in keyof ExtendedProfile as string extends Property + ? never + : Property]: ExtendedProfile[Property]; +}; type ProfileFieldElementRawProps = { - defaultValue: V, - value: V, - setValue: (value: V) => void, -} & C + defaultValue: V; + value: V; + setValue: (value: V) => void; +} & C; -export type ProfileFieldElementProps = ProfileFieldElementRawProps; +export type ProfileFieldElementProps< + K extends ExtendedProfileKeys, + C +> = ProfileFieldElementRawProps; type ProfileFieldElements = { [Property in ExtendedProfileKeys]?: FunctionComponent>; -} +}; type ProfileFieldContextProps = { fieldDefaults: ExtendedProfile; fieldElements: ProfileFieldElements; - children: (reset: () => void, hasChanges: boolean, fields: ExtendedProfile, fieldElements: ReactNode) => ReactNode; + children: ( + reset: () => void, + hasChanges: boolean, + fields: ExtendedProfile, + fieldElements: ReactNode + ) => ReactNode; context: C; }; @@ -28,7 +45,7 @@ export function ProfileFieldContext({ fieldDefaults, fieldElements: fieldElementConstructors, children, - context + context, }: ProfileFieldContextProps): ReactNode { const [fields, setFields] = useState(fieldDefaults); @@ -37,7 +54,7 @@ export function ProfileFieldContext({ }, [fieldDefaults]); useEffect(() => { - reset() + reset(); }, [reset]); const setField = useCallback( @@ -51,28 +68,36 @@ export function ProfileFieldContext({ ); const hasChanges = useMemo( - () => Object.entries(fields).find(([key, value]) => fieldDefaults[key as keyof ExtendedProfile] !== value) !== undefined, + () => + Object.entries(fields).find( + ([key, value]) => + // this is a hack but ExtendedProfile is always valid JSON anyway + JSON.stringify(fieldDefaults[key as keyof ExtendedProfile]) !== JSON.stringify(value) + ) !== undefined, [fields, fieldDefaults] ); - const createElement = useCallback((key: K, element: ProfileFieldElements[K]) => { - const props: ProfileFieldElementRawProps = { - ...context, - defaultValue: fieldDefaults[key], - value: fields[key], - setValue: (value) => setField(key, value), - key, - }; - if (element !== undefined) { - return React.createElement(element, props); - } - return undefined; - }, [context, fieldDefaults, fields, setField]); + const createElement = useCallback( + (key: K, element: ProfileFieldElements[K]) => { + const props: ProfileFieldElementRawProps = { + ...context, + defaultValue: fieldDefaults[key], + value: fields[key], + setValue: (value) => setField(key, value), + key, + }; + if (element !== undefined) { + return React.createElement(element, props); + } + return undefined; + }, + [context, fieldDefaults, fields, setField] + ); - const fieldElements = Object.entries(fieldElementConstructors).map(([key, element]) => + const fieldElements = Object.entries(fieldElementConstructors).map(([key, element]) => // @ts-expect-error TypeScript doesn't quite understand the magic going on here createElement(key, element) ); return children(reset, hasChanges, fields, fieldElements); -} \ No newline at end of file +}