kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Move form hooks into their own files
rodzic
eb055339d8
commit
f3727440ff
|
@ -1,13 +1,13 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import Icon from 'soapbox/components/icon';
|
import Icon from 'soapbox/components/icon';
|
||||||
import { Avatar, Button, Column, Form, FormActions, FormGroup, HStack, Input, Spinner, Text, Textarea } from 'soapbox/components/ui';
|
import { Avatar, Button, Column, Form, FormActions, FormGroup, HStack, Input, Spinner, Text, Textarea } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useInstance } from 'soapbox/hooks';
|
import { useAppSelector, useInstance } from 'soapbox/hooks';
|
||||||
import { useGroup, useUpdateGroup } from 'soapbox/hooks/api';
|
import { useGroup, useUpdateGroup } from 'soapbox/hooks/api';
|
||||||
|
import { useImageField, useTextField } from 'soapbox/hooks/forms';
|
||||||
import { isDefaultAvatar, isDefaultHeader } from 'soapbox/utils/accounts';
|
import { isDefaultAvatar, isDefaultHeader } from 'soapbox/utils/accounts';
|
||||||
import resizeImage from 'soapbox/utils/resize-image';
|
|
||||||
|
|
||||||
import type { List as ImmutableList } from 'immutable';
|
import type { List as ImmutableList } from 'immutable';
|
||||||
|
|
||||||
|
@ -178,61 +178,4 @@ const EditGroup: React.FC<IEditGroup> = ({ params: { id: groupId } }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function usePreview(file: File | null | undefined): string | undefined {
|
|
||||||
return useMemo(() => {
|
|
||||||
if (file) {
|
|
||||||
return URL.createObjectURL(file);
|
|
||||||
}
|
|
||||||
}, [file]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function useTextField(initialValue: string | undefined) {
|
|
||||||
const [value, setValue] = useState(initialValue);
|
|
||||||
const hasInitialValue = typeof initialValue === 'string';
|
|
||||||
|
|
||||||
const onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement> = (e) => {
|
|
||||||
setValue(e.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (hasInitialValue) {
|
|
||||||
setValue(initialValue);
|
|
||||||
}
|
|
||||||
}, [hasInitialValue]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
value,
|
|
||||||
onChange,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UseImageFieldOpts {
|
|
||||||
maxPixels?: number
|
|
||||||
preview?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
function useImageField(opts: UseImageFieldOpts = {}) {
|
|
||||||
const [file, setFile] = useState<File>();
|
|
||||||
const src = usePreview(file) || opts.preview;
|
|
||||||
|
|
||||||
const onChange: React.ChangeEventHandler<HTMLInputElement> = ({ target: { files } }) => {
|
|
||||||
const file = files?.item(0) || undefined;
|
|
||||||
if (file) {
|
|
||||||
if (typeof opts.maxPixels === 'number') {
|
|
||||||
resizeImage(file, opts.maxPixels)
|
|
||||||
.then((f) => setFile(f))
|
|
||||||
.catch(console.error);
|
|
||||||
} else {
|
|
||||||
setFile(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
src,
|
|
||||||
file,
|
|
||||||
onChange,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default EditGroup;
|
export default EditGroup;
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export { useImageField } from './useImageField';
|
||||||
|
export { useTextField } from './useTextField';
|
||||||
|
export { usePreview } from './usePreview';
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import resizeImage from 'soapbox/utils/resize-image';
|
||||||
|
|
||||||
|
import { usePreview } from './usePreview';
|
||||||
|
|
||||||
|
interface UseImageFieldOpts {
|
||||||
|
/** Resize the image to the max dimensions, if defined. */
|
||||||
|
maxPixels?: number
|
||||||
|
/** Fallback URL before a file is uploaded. */
|
||||||
|
preview?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handle image, and optionally resize it. */
|
||||||
|
function useImageField(opts: UseImageFieldOpts = {}) {
|
||||||
|
const [file, setFile] = useState<File>();
|
||||||
|
const src = usePreview(file) || opts.preview;
|
||||||
|
|
||||||
|
const onChange: React.ChangeEventHandler<HTMLInputElement> = ({ target: { files } }) => {
|
||||||
|
const file = files?.item(0) || undefined;
|
||||||
|
if (file) {
|
||||||
|
if (typeof opts.maxPixels === 'number') {
|
||||||
|
resizeImage(file, opts.maxPixels)
|
||||||
|
.then((f) => setFile(f))
|
||||||
|
.catch(console.error);
|
||||||
|
} else {
|
||||||
|
setFile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
src,
|
||||||
|
file,
|
||||||
|
onChange,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useImageField };
|
||||||
|
export type { UseImageFieldOpts };
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
/** Return a preview URL for a file. */
|
||||||
|
function usePreview(file: File | null | undefined): string | undefined {
|
||||||
|
return useMemo(() => {
|
||||||
|
if (file) {
|
||||||
|
return URL.createObjectURL(file);
|
||||||
|
}
|
||||||
|
}, [file]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { usePreview };
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
function useTextField(initialValue: string | undefined) {
|
||||||
|
const [value, setValue] = useState(initialValue);
|
||||||
|
const hasInitialValue = typeof initialValue === 'string';
|
||||||
|
|
||||||
|
const onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement> = (e) => {
|
||||||
|
setValue(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (hasInitialValue) {
|
||||||
|
setValue(initialValue);
|
||||||
|
}
|
||||||
|
}, [hasInitialValue]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useTextField };
|
Ładowanie…
Reference in New Issue