Update limits for GroupDescriptionInput

This commit is contained in:
Fedor Indutny 2021-10-05 11:47:47 -07:00 committed by GitHub
parent f974490ff0
commit d479427d88
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 25 deletions

View file

@ -37,6 +37,10 @@ export function toString(data: Uint8Array): string {
return bytes.toString(data); return bytes.toString(data);
} }
export function byteLength(value: string): number {
return bytes.byteLength(value);
}
export function concatenate(list: ReadonlyArray<Uint8Array>): Uint8Array { export function concatenate(list: ReadonlyArray<Uint8Array>): Uint8Array {
return bytes.concatenate(list); return bytes.concatenate(list);
} }

View file

@ -22,10 +22,11 @@ export const GroupDescriptionInput = forwardRef<HTMLInputElement, PropsType>(
i18n={i18n} i18n={i18n}
onChange={onChangeValue} onChange={onChangeValue}
placeholder={i18n('setGroupMetadata__group-description-placeholder')} placeholder={i18n('setGroupMetadata__group-description-placeholder')}
maxLengthCount={256} maxLengthCount={480}
maxByteCount={8192}
ref={ref} ref={ref}
value={value} value={value}
whenToShowRemainingCount={150} whenToShowRemainingCount={380}
/> />
); );
} }

View file

@ -16,15 +16,18 @@ import * as grapheme from '../util/grapheme';
import { LocalizerType } from '../types/Util'; import { LocalizerType } from '../types/Util';
import { getClassNamesFor } from '../util/getClassNamesFor'; import { getClassNamesFor } from '../util/getClassNamesFor';
import { refMerger } from '../util/refMerger'; import { refMerger } from '../util/refMerger';
import { byteLength } from '../Bytes';
export type PropsType = { export type PropsType = {
countLength?: (value: string) => number; countLength?: (value: string) => number;
countBytes?: (value: string) => number;
disabled?: boolean; disabled?: boolean;
expandable?: boolean; expandable?: boolean;
hasClearButton?: boolean; hasClearButton?: boolean;
i18n: LocalizerType; i18n: LocalizerType;
icon?: ReactNode; icon?: ReactNode;
maxLengthCount?: number; maxLengthCount?: number;
maxByteCount?: number;
moduleClassName?: string; moduleClassName?: string;
onChange: (value: string) => unknown; onChange: (value: string) => unknown;
placeholder: string; placeholder: string;
@ -56,12 +59,14 @@ export const Input = forwardRef<
( (
{ {
countLength = grapheme.count, countLength = grapheme.count,
countBytes = byteLength,
disabled, disabled,
expandable, expandable,
hasClearButton, hasClearButton,
i18n, i18n,
icon, icon,
maxLengthCount = 0, maxLengthCount = 0,
maxByteCount = 0,
moduleClassName, moduleClassName,
onChange, onChange,
placeholder, placeholder,
@ -114,8 +119,9 @@ export const Input = forwardRef<
const newValue = inputEl.value; const newValue = inputEl.value;
const newLengthCount = maxLengthCount ? countLength(newValue) : 0; const newLengthCount = maxLengthCount ? countLength(newValue) : 0;
const newByteCount = maxByteCount ? countBytes(newValue) : 0;
if (newLengthCount <= maxLengthCount) { if (newLengthCount <= maxLengthCount && newByteCount <= maxByteCount) {
onChange(newValue); onChange(newValue);
} else { } else {
inputEl.value = valueOnKeydownRef.current; inputEl.value = valueOnKeydownRef.current;
@ -124,12 +130,19 @@ export const Input = forwardRef<
} }
maybeSetLarge(); maybeSetLarge();
}, [countLength, maxLengthCount, maybeSetLarge, onChange]); }, [
countLength,
countBytes,
maxLengthCount,
maxByteCount,
maybeSetLarge,
onChange,
]);
const handlePaste = useCallback( const handlePaste = useCallback(
(event: ClipboardEvent<HTMLInputElement | HTMLTextAreaElement>) => { (event: ClipboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const inputEl = innerRef.current; const inputEl = innerRef.current;
if (!inputEl || !maxLengthCount) { if (!inputEl || !maxLengthCount || !maxByteCount) {
return; return;
} }
@ -145,14 +158,25 @@ export const Input = forwardRef<
countLength(textBeforeSelection) + countLength(textBeforeSelection) +
countLength(pastedText) + countLength(pastedText) +
countLength(textAfterSelection); countLength(textAfterSelection);
const newByteCount =
countBytes(textBeforeSelection) +
countBytes(pastedText) +
countBytes(textAfterSelection);
if (newLengthCount > maxLengthCount) { if (newLengthCount > maxLengthCount || newByteCount > maxByteCount) {
event.preventDefault(); event.preventDefault();
} }
maybeSetLarge(); maybeSetLarge();
}, },
[countLength, maxLengthCount, maybeSetLarge, value] [
countLength,
countBytes,
maxLengthCount,
maxByteCount,
maybeSetLarge,
value,
]
); );
useEffect(() => { useEffect(() => {

View file

@ -161,20 +161,6 @@ export const ProfileEditor = ({
[onProfileChanged, stagedProfile] [onProfileChanged, stagedProfile]
); );
const getTextEncoder = useCallback(() => new TextEncoder(), []);
const countByteLength = useCallback(
(str: string) => getTextEncoder().encode(str).byteLength,
[getTextEncoder]
);
const calculateLengthCount = useCallback(
(name = '') => {
return 256 - countByteLength(name);
},
[countByteLength]
);
const getFullNameText = () => { const getFullNameText = () => {
return [fullName.firstName, fullName.familyName].filter(Boolean).join(' '); return [fullName.firstName, fullName.familyName].filter(Boolean).join(' ');
}; };
@ -225,9 +211,9 @@ export const ProfileEditor = ({
content = ( content = (
<> <>
<Input <Input
countLength={countByteLength}
i18n={i18n} i18n={i18n}
maxLengthCount={calculateLengthCount(stagedProfile.familyName)} maxLengthCount={26}
maxByteCount={128}
whenToShowRemainingCount={0} whenToShowRemainingCount={0}
onChange={newFirstName => { onChange={newFirstName => {
setStagedProfile(profileData => ({ setStagedProfile(profileData => ({
@ -240,9 +226,9 @@ export const ProfileEditor = ({
value={stagedProfile.firstName} value={stagedProfile.firstName}
/> />
<Input <Input
countLength={countByteLength}
i18n={i18n} i18n={i18n}
maxLengthCount={calculateLengthCount(stagedProfile.firstName)} maxLengthCount={26}
maxByteCount={128}
whenToShowRemainingCount={0} whenToShowRemainingCount={0}
onChange={newFamilyName => { onChange={newFamilyName => {
setStagedProfile(profileData => ({ setStagedProfile(profileData => ({
@ -323,6 +309,7 @@ export const ProfileEditor = ({
</div> </div>
} }
maxLengthCount={140} maxLengthCount={140}
maxByteCount={512}
moduleClassName="ProfileEditor__about-input" moduleClassName="ProfileEditor__about-input"
onChange={value => { onChange={value => {
if (value) { if (value) {

View file

@ -40,6 +40,10 @@ export class Bytes {
return Buffer.from(data).toString(); return Buffer.from(data).toString();
} }
public byteLength(value: string): number {
return Buffer.byteLength(value);
}
public concatenate(list: ReadonlyArray<Uint8Array>): Uint8Array { public concatenate(list: ReadonlyArray<Uint8Array>): Uint8Array {
return Buffer.concat(list); return Buffer.concat(list);
} }