mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-04 14:30:29 +03:00
Add a setting for user pronouns
This commit is contained in:
parent
c7f6e33a2b
commit
c5b59ea122
1 changed files with 138 additions and 6 deletions
|
|
@ -1,5 +1,8 @@
|
|||
import React, {
|
||||
ChangeEventHandler,
|
||||
FormEventHandler,
|
||||
KeyboardEventHandler,
|
||||
MouseEventHandler,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
|
|
@ -26,9 +29,14 @@ import {
|
|||
Dialog,
|
||||
Header,
|
||||
MenuItem,
|
||||
Chip,
|
||||
PopOut,
|
||||
RectCords,
|
||||
Menu,
|
||||
} from 'folds';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { UserEvent } from 'matrix-js-sdk';
|
||||
import { isKeyHotkey } from 'is-hotkey';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import { SettingTile } from '../../../components/setting-tile';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
|
|
@ -203,7 +211,6 @@ function ProfileTextField<K extends keyof FilterByValues<ExtendedProfile, string
|
|||
onChange={handleChange}
|
||||
variant="Secondary"
|
||||
radii="300"
|
||||
style={{ paddingRight: config.space.S200 }}
|
||||
readOnly={disabled}
|
||||
after={
|
||||
hasChanges &&
|
||||
|
|
@ -227,6 +234,130 @@ function ProfileTextField<K extends keyof FilterByValues<ExtendedProfile, string
|
|||
);
|
||||
}
|
||||
|
||||
function ProfilePronouns() {
|
||||
const { busy, value, setValue } = useProfileField('io.fsky.nyx.pronouns');
|
||||
const disabled = !useProfileFieldAllowed('io.fsky.nyx.pronouns') || busy;
|
||||
|
||||
const [menuCords, setMenuCords] = useState<RectCords>();
|
||||
const [pendingPronoun, setPendingPronoun] = useState('');
|
||||
|
||||
const handleRemovePronoun = (index: number) => {
|
||||
const newPronouns = [...(value ?? [])];
|
||||
newPronouns.splice(index, 1);
|
||||
if (newPronouns.length > 0) {
|
||||
setValue(newPronouns);
|
||||
} else {
|
||||
setValue(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit: FormEventHandler<HTMLFormElement> = (evt) => {
|
||||
evt.preventDefault();
|
||||
setMenuCords(undefined);
|
||||
if (pendingPronoun.length > 0) {
|
||||
setValue([...(value ?? []), { language: 'en', summary: pendingPronoun }]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = (evt) => {
|
||||
if (isKeyHotkey('escape', evt)) {
|
||||
evt.stopPropagation();
|
||||
setMenuCords(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOpenMenu: MouseEventHandler<HTMLSpanElement> = (evt) => {
|
||||
setPendingPronoun('');
|
||||
setMenuCords(evt.currentTarget.getBoundingClientRect());
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingTile
|
||||
title={
|
||||
<Text as="span" size="L400">
|
||||
Pronouns
|
||||
</Text>
|
||||
}
|
||||
>
|
||||
<Box alignItems="Center" gap="200" wrap="Wrap">
|
||||
{value?.map(({ summary }, index) => (
|
||||
<Chip
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
key={index}
|
||||
variant="Secondary"
|
||||
radii="Pill"
|
||||
after={<Icon src={Icons.Cross} size="100" />}
|
||||
onClick={() => handleRemovePronoun(index)}
|
||||
disabled={disabled}
|
||||
>
|
||||
<Text size="T200" truncate>
|
||||
{summary}
|
||||
</Text>
|
||||
</Chip>
|
||||
))}
|
||||
<Chip
|
||||
variant="Secondary"
|
||||
radii="Pill"
|
||||
disabled={disabled}
|
||||
after={<Icon src={menuCords ? Icons.ChevronRight : Icons.Plus} size="100" />}
|
||||
onClick={handleOpenMenu}
|
||||
>
|
||||
<Text size="T200">Add</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
<PopOut
|
||||
anchor={menuCords}
|
||||
offset={5}
|
||||
position="Right"
|
||||
align="Center"
|
||||
content={
|
||||
<FocusTrap
|
||||
focusTrapOptions={{
|
||||
onDeactivate: () => setMenuCords(undefined),
|
||||
clickOutsideDeactivates: true,
|
||||
isKeyForward: (evt: KeyboardEvent) =>
|
||||
evt.key === 'ArrowDown' || evt.key === 'ArrowRight',
|
||||
isKeyBackward: (evt: KeyboardEvent) =>
|
||||
evt.key === 'ArrowUp' || evt.key === 'ArrowLeft',
|
||||
escapeDeactivates: stopPropagation,
|
||||
}}
|
||||
>
|
||||
<Menu
|
||||
variant="SurfaceVariant"
|
||||
style={{
|
||||
padding: config.space.S200,
|
||||
}}
|
||||
>
|
||||
<Box as="form" onSubmit={handleSubmit} direction="Row" gap="200">
|
||||
<Input
|
||||
variant="Secondary"
|
||||
placeholder="they/them"
|
||||
inputSize={10}
|
||||
radii="300"
|
||||
size="300"
|
||||
outlined
|
||||
value={pendingPronoun}
|
||||
onChange={(evt) => setPendingPronoun(evt.currentTarget.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
size="300"
|
||||
variant="Success"
|
||||
radii="300"
|
||||
before={<Icon size="100" src={Icons.Plus} />}
|
||||
>
|
||||
<Text size="B300">Add</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Menu>
|
||||
</FocusTrap>
|
||||
}
|
||||
/>
|
||||
</SettingTile>
|
||||
);
|
||||
}
|
||||
|
||||
function ProfileTimezone() {
|
||||
const { busy, value, setValue } = useProfileField('us.cloke.msc4175.tz');
|
||||
const disabled = !useProfileFieldAllowed('us.cloke.msc4175.tz') || busy;
|
||||
|
|
@ -392,7 +523,7 @@ export function Profile() {
|
|||
const extendedProfile =
|
||||
extendedProfileState.status === AsyncStatus.Success ? extendedProfileState.data : undefined;
|
||||
|
||||
const [fieldDefaults, setFieldDefaults] = useState<ExtendedProfile>({})
|
||||
const [fieldDefaults, setFieldDefaults] = useState<ExtendedProfile>({});
|
||||
useLayoutEffect(() => {
|
||||
if (extendedProfile !== undefined) {
|
||||
setFieldDefaults(extendedProfile);
|
||||
|
|
@ -471,14 +602,15 @@ export function Profile() {
|
|||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="300"
|
||||
radii='0'
|
||||
radii="0"
|
||||
outlined
|
||||
style={{ borderLeftWidth: "0", borderRightWidth: "0", borderBottomWidth: "0" }}
|
||||
style={{ borderLeftWidth: '0', borderRightWidth: '0', borderBottomWidth: '0' }}
|
||||
>
|
||||
<ProfileAvatar />
|
||||
<ProfileTextField field="displayname" label="Display Name" />
|
||||
<ProfilePronouns />
|
||||
<ProfileTimezone />
|
||||
<Box gap="300" alignItems='Center'>
|
||||
<Box gap="300" alignItems="Center">
|
||||
<Button
|
||||
type="submit"
|
||||
size="300"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue