diff --git a/src/components/views/settings/AvatarSetting.tsx b/src/components/views/settings/AvatarSetting.tsx index 81f1cd5201c..0e95deed382 100644 --- a/src/components/views/settings/AvatarSetting.tsx +++ b/src/components/views/settings/AvatarSetting.tsx @@ -170,6 +170,7 @@ const AvatarSetting: React.FC = ({ aria-labelledby={disabled ? undefined : a11yId} // Inhibit tab stop as we have explicit upload/remove buttons tabIndex={-1} + disabled={disabled} > @@ -184,6 +185,7 @@ const AvatarSetting: React.FC = ({ onClick={uploadAvatar} // Inhibit tab stop as we have explicit upload/remove buttons tabIndex={-1} + disabled={disabled} /> ); } diff --git a/src/components/views/settings/UserProfileSettings.tsx b/src/components/views/settings/UserProfileSettings.tsx index bd61f762ff5..6d1bccb30e9 100644 --- a/src/components/views/settings/UserProfileSettings.tsx +++ b/src/components/views/settings/UserProfileSettings.tsx @@ -55,10 +55,17 @@ const UsernameBox: React.FC = ({ username }) => { ); }; +interface UserProfileSettingsProps { + // Whether the homeserver allows the user to set their display name. + canSetDisplayName: boolean; + // Whether the homeserver allows the user to set their avatar. + canSetAvatar: boolean; +} + /** * A group of settings views to allow the user to set their profile information. */ -const UserProfileSettings: React.FC = () => { +const UserProfileSettings: React.FC = ({ canSetDisplayName, canSetAvatar }) => { const [avatarURL, setAvatarURL] = useState(OwnProfileStore.instance.avatarMxc); const [displayName, setDisplayName] = useState(OwnProfileStore.instance.displayName ?? ""); const [initialDisplayName, setInitialDisplayName] = useState(OwnProfileStore.instance.displayName ?? ""); @@ -143,10 +150,16 @@ const UserProfileSettings: React.FC = () => { [client], ); + const someFieldsDisabled = !canSetDisplayName || !canSetAvatar; + return (

{_t("common|profile")}

-
{_t("settings|general|profile_subtitle")}
+
+ {someFieldsDisabled + ? _t("settings|general|profile_subtitle_oidc") + : _t("settings|general|profile_subtitle")} +
{ removeAvatar={avatarURL ? onAvatarRemove : undefined} placeholderName={displayName} placeholderId={client.getUserId() ?? ""} + disabled={!canSetAvatar} /> { onCancel={onDisplayNameCancel} onSave={onDisplayNameSave} error={displayNameError ? _t("settings|general|display_name_error") : undefined} + disabled={!canSetDisplayName} />
{avatarError && ( diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx index 3b53e5f2f19..ef90077f2d4 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx @@ -56,6 +56,8 @@ interface IState { idServerName?: string; externalAccountManagementUrl?: string; canMake3pidChanges: boolean; + canSetDisplayName: boolean; + canSetAvatar: boolean; } export default class GeneralUserSettingsTab extends React.Component { @@ -72,6 +74,8 @@ export default class GeneralUserSettingsTab extends React.Component { const cli = this.context.client!; - const capabilities = await cli.getCapabilities(); // this is cached + const capabilities = (await cli.getCapabilities()) ?? {}; const changePasswordCap = capabilities["m.change_password"]; // You can change your password so long as the capability isn't explicitly disabled. The implicit @@ -110,7 +114,17 @@ export default class GeneralUserSettingsTab extends React.Component { @@ -309,7 +323,10 @@ export default class GeneralUserSettingsTab extends React.Component - + {this.renderAccountSection()} {this.renderLanguageSection()} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index de8e33927f2..6667df57883 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2527,6 +2527,7 @@ "password_change_success": "Your password was successfully changed.", "personal_info": "Personal info", "profile_subtitle": "This is how you appear to others on the app.", + "profile_subtitle_oidc": "Your account is managed separately by an identity provider and so some of your personal information can’t be changed here.", "remove_email_prompt": "Remove %(email)s?", "remove_msisdn_prompt": "Remove %(phone)s?", "spell_check_locale_placeholder": "Choose a locale", diff --git a/test/components/views/settings/UserProfileSettings-test.tsx b/test/components/views/settings/UserProfileSettings-test.tsx index fd727729772..6b7f278e5a2 100644 --- a/test/components/views/settings/UserProfileSettings-test.tsx +++ b/test/components/views/settings/UserProfileSettings-test.tsx @@ -67,7 +67,7 @@ const renderProfileSettings = (toastRack: Partial, client: MatrixClie return render( - + , ); diff --git a/test/test-utils/client.ts b/test/test-utils/client.ts index 00f5aa3f7b8..43d8392a150 100644 --- a/test/test-utils/client.ts +++ b/test/test-utils/client.ts @@ -129,7 +129,7 @@ export const mockClientMethodsEvents = () => ({ export const mockClientMethodsServer = (): Partial, unknown>> => ({ getIdentityServerUrl: jest.fn(), getHomeserverUrl: jest.fn(), - getCapabilities: jest.fn().mockReturnValue({}), + getCapabilities: jest.fn().mockResolvedValue({}), getClientWellKnown: jest.fn().mockReturnValue({}), waitForClientWellKnown: jest.fn().mockResolvedValue({}), doesServerSupportUnstableFeature: jest.fn().mockResolvedValue(false),