Skip to content

Commit f1a61e8

Browse files
committed
add image size checks to profile manage
1 parent 49878d7 commit f1a61e8

File tree

11 files changed

+77
-31
lines changed

11 files changed

+77
-31
lines changed

src/components/atoms/Avatar/Avatar.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ReactSVG } from 'react-svg';
33

44
import { ASSETS } from 'helpers/config';
55
import { getTxEndpoint } from 'helpers/endpoints';
6-
import { checkAddress } from 'helpers/utils';
6+
import { checkValidAddress } from 'helpers/utils';
77

88
import * as S from './styles';
99
import { IProps } from './types';
@@ -12,7 +12,7 @@ export default function Avatar(props: IProps) {
1212
const [hasError, setHasError] = React.useState(false);
1313

1414
const avatar = React.useMemo(() => {
15-
if (!hasError && props.owner && props.owner.avatar && checkAddress(props.owner.avatar)) {
15+
if (!hasError && props.owner && props.owner.avatar && checkValidAddress(props.owner.avatar)) {
1616
return <img src={getTxEndpoint(props.owner.avatar)} onError={() => setHasError(true)} />;
1717
} else return <ReactSVG src={ASSETS.user} />;
1818
}, [props.owner, hasError]);

src/components/molecules/AssetInfoLicense/AssetInfoLicense.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ReactSVG } from 'react-svg';
33
import { Button } from 'components/atoms/Button';
44
import { TxAddress } from 'components/atoms/TxAddress';
55
import { ASSETS, REDIRECTS } from 'helpers/config';
6-
import { checkAddress, getDisplayValue, splitLicenseTag } from 'helpers/utils';
6+
import { checkValidAddress, getDisplayValue, splitLicenseTag } from 'helpers/utils';
77
import { useLanguageProvider } from 'providers/LanguageProvider';
88

99
import * as S from './styles';
@@ -44,7 +44,7 @@ export default function AssetDetailLicenses(props: IProps) {
4444
</S.LFlex>
4545
);
4646
} else {
47-
if (checkAddress(props.asset.license[element])) {
47+
if (checkValidAddress(props.asset.license[element])) {
4848
return (
4949
<TxAddress
5050
address={props.asset.license[element]}

src/components/organisms/CollectionsTable/CollectionsTable.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { Modal } from 'components/molecules/Modal';
1313
import { Table } from 'components/molecules/Table';
1414
import { AO, ASSETS, PAGINATORS, REDIRECTS, URLS } from 'helpers/config';
1515
import { AlignType, CollectionType } from 'helpers/types';
16-
import { checkAddress, formatAddress } from 'helpers/utils';
16+
import { checkValidAddress, formatAddress } from 'helpers/utils';
1717
import { useArweaveProvider } from 'providers/ArweaveProvider';
1818
import { useLanguageProvider } from 'providers/LanguageProvider';
1919
import { RootState } from 'store';
@@ -43,7 +43,7 @@ function CollectionDropdown(props: { id: string; title: string }) {
4343

4444
React.useEffect(() => {
4545
(async function () {
46-
if (props.id && checkAddress(props.id) && listingModalOpen && !collection) {
46+
if (props.id && checkValidAddress(props.id) && listingModalOpen && !collection) {
4747
setFetchingCollection(true);
4848
try {
4949
const fetchResponse = await readHandler({

src/components/organisms/ProfileManage/ProfileManage.tsx

+28-9
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { TextArea } from 'components/atoms/TextArea';
1313
import { AO, ASSETS, GATEWAYS, TAGS } from 'helpers/config';
1414
import { getTxEndpoint } from 'helpers/endpoints';
1515
import { NotificationType } from 'helpers/types';
16-
import { checkAddress, getBase64Data, getDataURLContentType } from 'helpers/utils';
16+
import { checkValidAddress, getBase64Data, getDataURLContentType } from 'helpers/utils';
1717
import { useArweaveProvider } from 'providers/ArweaveProvider';
1818
import { useLanguageProvider } from 'providers/LanguageProvider';
1919
import { WalletBlock } from 'wallet/WalletBlock';
@@ -22,6 +22,7 @@ import * as S from './styles';
2222
import { IProps } from './types';
2323

2424
const MAX_BIO_LENGTH = 500;
25+
const MAX_IMAGE_SIZE = 100000;
2526
const ALLOWED_BANNER_TYPES = 'image/png, image/jpeg, image/gif';
2627
const ALLOWED_AVATAR_TYPES = 'image/png, image/jpeg, image/gif';
2728

@@ -48,8 +49,8 @@ export default function ProfileManage(props: IProps) {
4849
setUsername(props.profile.username ?? '');
4950
setName(props.profile.displayName ?? '');
5051
setBio(props.profile.bio ?? '');
51-
setBanner(props.profile.banner && checkAddress(props.profile.banner) ? props.profile.banner : null);
52-
setAvatar(props.profile.avatar && checkAddress(props.profile.avatar) ? props.profile.avatar : null);
52+
setBanner(props.profile.banner && checkValidAddress(props.profile.banner) ? props.profile.banner : null);
53+
setAvatar(props.profile.avatar && checkValidAddress(props.profile.avatar) ? props.profile.avatar : null);
5354
}
5455
}, [props.profile]);
5556

@@ -70,7 +71,7 @@ export default function ProfileManage(props: IProps) {
7071

7172
let bannerTx: any = null;
7273
if (banner) {
73-
if (checkAddress(banner)) {
74+
if (checkValidAddress(banner)) {
7475
bannerTx = banner;
7576
} else {
7677
try {
@@ -91,7 +92,7 @@ export default function ProfileManage(props: IProps) {
9192

9293
let avatarTx: any = null;
9394
if (avatar) {
94-
if (checkAddress(avatar)) {
95+
if (checkValidAddress(avatar)) {
9596
avatarTx = avatar;
9697
} else {
9798
try {
@@ -251,6 +252,20 @@ export default function ProfileManage(props: IProps) {
251252
}
252253
}
253254

255+
function getImageSizeMessage() {
256+
if (!avatar && !banner) return null;
257+
if (checkValidAddress(avatar) && checkValidAddress(banner)) return null;
258+
259+
const avatarSize = avatar ? (avatar.length * 3) / 4 : 0;
260+
const bannerSize = banner ? (banner.length * 3) / 4 : 0;
261+
262+
console.log(avatarSize);
263+
264+
if (avatarSize > MAX_IMAGE_SIZE || bannerSize > MAX_IMAGE_SIZE)
265+
return <span>One or more images exceeds max size of 100KB</span>;
266+
return null;
267+
}
268+
254269
function getInvalidBio() {
255270
if (bio && bio.length > MAX_BIO_LENGTH) {
256271
return {
@@ -289,7 +304,7 @@ export default function ProfileManage(props: IProps) {
289304
}
290305

291306
function getBannerWrapper() {
292-
if (banner) return <img src={checkAddress(banner) ? getTxEndpoint(banner) : banner} />;
307+
if (banner) return <img src={checkValidAddress(banner) ? getTxEndpoint(banner) : banner} />;
293308
return (
294309
<>
295310
<ReactSVG src={ASSETS.media} />
@@ -299,7 +314,7 @@ export default function ProfileManage(props: IProps) {
299314
}
300315

301316
function getAvatarWrapper() {
302-
if (avatar) return <img src={checkAddress(avatar) ? getTxEndpoint(avatar) : avatar} />;
317+
if (avatar) return <img src={checkValidAddress(avatar) ? getTxEndpoint(avatar) : avatar} />;
303318
return (
304319
<>
305320
<ReactSVG src={ASSETS.user} />
@@ -360,9 +375,12 @@ export default function ProfileManage(props: IProps) {
360375
disabled={loading || !banner}
361376
/>
362377
</S.PActions>
378+
<S.PInfoMessage>
379+
<span>Images have a max size of 100KB</span>
380+
</S.PInfoMessage>
363381
</S.PWrapper>
364382
<S.Form>
365-
<S.TForm className={'border-wrapper-alt2'}>
383+
<S.TForm>
366384
<FormField
367385
label={language.name}
368386
value={name}
@@ -409,10 +427,11 @@ export default function ProfileManage(props: IProps) {
409427
type={'alt1'}
410428
label={language.save}
411429
handlePress={handleSubmit}
412-
disabled={!username || !name || loading}
430+
disabled={!username || !name || loading || getImageSizeMessage() !== null}
413431
loading={loading}
414432
/>
415433
</S.SAction>
434+
{getImageSizeMessage() && <S.MInfoWrapper>{getImageSizeMessage()}</S.MInfoWrapper>}
416435
</S.Body>
417436
</S.Wrapper>
418437
{profileResponse && (

src/components/organisms/ProfileManage/styles.ts

+28-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ export const Form = styled.div`
3737

3838
export const TForm = styled.div`
3939
margin: 20px 0 30px 0;
40-
padding: 20px;
4140
> * {
4241
&:last-child {
4342
margin: 20px 0 0 0;
@@ -261,6 +260,18 @@ export const PActions = styled.div`
261260
}
262261
`;
263262

263+
export const PInfoMessage = styled.div`
264+
margin: 15px 0 0 0;
265+
display: flex;
266+
justify-content: flex-end;
267+
span {
268+
color: ${(props) => props.theme.colors.font.alt1};
269+
font-size: ${(props) => props.theme.typography.size.xSmall};
270+
font-weight: ${(props) => props.theme.typography.weight.medium};
271+
line-height: 1.5;
272+
}
273+
`;
274+
264275
export const SAction = styled.div`
265276
width: 100%;
266277
display: flex;
@@ -304,3 +315,19 @@ export const MActions = styled.div`
304315
flex-wrap: wrap;
305316
gap: 15px;
306317
`;
318+
319+
export const MInfoWrapper = styled.div`
320+
width: fit-content;
321+
margin: 10px 0 0 auto;
322+
span {
323+
background: ${(props) => props.theme.colors.warning};
324+
color: ${(props) => props.theme.colors.font.light1};
325+
font-size: ${(props) => props.theme.typography.size.xxSmall};
326+
font-weight: ${(props) => props.theme.typography.weight.bold};
327+
border-radius: ${STYLING.dimensions.radius.alt2};
328+
text-align: center;
329+
display: block;
330+
padding: 2.5px 12.5px;
331+
margin: 0 0 7.5px 0;
332+
}
333+
`;

src/gql/search.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { getGQLData, getProfiles, structureAsset } from 'gql';
22

33
import { GATEWAYS, TAGS } from 'helpers/config';
44
import { AGQLResponseType, AssetGQLResponseType, AssetType, CursorEnum, GQLNodeResponseType } from 'helpers/types';
5-
import { checkAddress, getTagValue } from 'helpers/utils';
5+
import { checkValidAddress, getTagValue } from 'helpers/utils';
66

77
export async function search(args: { term: string; cursor: string | null }): Promise<AssetGQLResponseType | null> {
88
const emptyResponseObject = {
@@ -12,7 +12,7 @@ export async function search(args: { term: string; cursor: string | null }): Pro
1212
previousCursor: null,
1313
};
1414
try {
15-
const addressCheck = checkAddress(args.term);
15+
const addressCheck = checkValidAddress(args.term);
1616

1717
const gqlResponse: AGQLResponseType = await getGQLData({
1818
gateway: GATEWAYS.goldsky,

src/helpers/utils.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Arweave from 'arweave';
33
import { API_CONFIG, GATEWAYS, STORAGE } from './config';
44
import { DateType, ProfileType } from './types';
55

6-
export function checkAddress(address: string | null) {
6+
export function checkValidAddress(address: string | null) {
77
if (!address) return false;
88
return /^[a-z0-9_-]{43}$/i.test(address);
99
}
@@ -14,7 +14,7 @@ export function getUniqueAddresses(addresses: string[]) {
1414

1515
export function formatAddress(address: string | null, wrap: boolean) {
1616
if (!address) return '';
17-
if (!checkAddress(address)) return address;
17+
if (!checkValidAddress(address)) return address;
1818
const formattedAddress = address.substring(0, 5) + '...' + address.substring(36, address.length);
1919
return wrap ? `(${formattedAddress})` : formattedAddress;
2020
}

src/views/Landing/Profile/Profile.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { ProfileManage } from 'components/organisms/ProfileManage';
1313
import { ASSETS, REDIRECTS, URLS } from 'helpers/config';
1414
import { getTxEndpoint } from 'helpers/endpoints';
1515
import { ProfileHeaderType } from 'helpers/types';
16-
import { checkAddress, formatAddress } from 'helpers/utils';
16+
import { checkValidAddress, formatAddress } from 'helpers/utils';
1717
import { useArweaveProvider } from 'providers/ArweaveProvider';
1818
import { useLanguageProvider } from 'providers/LanguageProvider';
1919

@@ -48,7 +48,7 @@ export default function Profile(props: { address: string }) {
4848

4949
React.useEffect(() => {
5050
(async function () {
51-
if (props.address && checkAddress(props.address)) {
51+
if (props.address && checkValidAddress(props.address)) {
5252
setLoading(true);
5353
try {
5454
const currentProfile = await getProfile({ address: props.address });
@@ -62,7 +62,7 @@ export default function Profile(props: { address: string }) {
6262
}, [props.address, arProvider.profile]);
6363

6464
function getAvatar() {
65-
if (fullProfile && fullProfile.avatar && checkAddress(fullProfile.avatar))
65+
if (fullProfile && fullProfile.avatar && checkValidAddress(fullProfile.avatar))
6666
return <img src={getTxEndpoint(fullProfile.avatar)} />;
6767
return <ReactSVG src={ASSETS.user} />;
6868
}

src/views/Upload/UploadSteps/UploadStepsLicense/UploadStepsLicenseFull/UploadStepsLicenseFull.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { FormField } from 'components/atoms/FormField';
66
import { Select } from 'components/atoms/Select';
77
import { ASSETS } from 'helpers/config';
88
import { SelectOptionType } from 'helpers/types';
9-
import { checkAddress, concatLicenseTag } from 'helpers/utils';
9+
import { checkValidAddress, concatLicenseTag } from 'helpers/utils';
1010
import { useArweaveProvider } from 'providers/ArweaveProvider';
1111
import { useLanguageProvider } from 'providers/LanguageProvider';
1212
import { RootState } from 'store';
@@ -247,7 +247,7 @@ export default function UploadStepsLicenseFull(props: IProps) {
247247
dataModelTrainingTermAmount <= 0) ||
248248
(paymentMode &&
249249
paymentMode.id === concatLicenseTag(licenseParams.paymentMode.single) &&
250-
!checkAddress(paymentRecipient))
250+
!checkValidAddress(paymentRecipient))
251251
) {
252252
dispatch(uploadActions.setStepDisabled(true));
253253
} else {
@@ -393,7 +393,7 @@ export default function UploadStepsLicenseFull(props: IProps) {
393393
label={language.recipient}
394394
value={paymentRecipient}
395395
onChange={(e: any) => setPaymentRecipient(e.target.value)}
396-
invalid={{ status: paymentRecipient ? !checkAddress(paymentRecipient) : true, message: null }}
396+
invalid={{ status: paymentRecipient ? !checkValidAddress(paymentRecipient) : true, message: null }}
397397
disabled={disabled}
398398
hideErrorMessage
399399
required

src/wallet/WalletConnect/WalletConnect.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export default function WalletConnect(_props: { callback?: () => void }) {
8484
<Avatar owner={arProvider.profile} dimensions={{ wrapper: 32.5, icon: 21.5 }} callback={handlePress} />
8585
</S.PWrapper>
8686
{showWalletDropdown && (
87-
<S.Dropdown className={'border-wrapper-primary'}>
87+
<S.Dropdown className={'border-wrapper-alt2'}>
8888
<S.DHeaderWrapper>
8989
<S.DHeaderFlex>
9090
<Avatar owner={arProvider.profile} dimensions={{ wrapper: 35, icon: 23.5 }} callback={null} />

src/wallet/WalletConnect/styles.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const FlexAction = styled.div`
5151
`;
5252

5353
export const Dropdown = styled.ul`
54-
width: 350px;
54+
width: 315px;
5555
max-width: 90vw;
5656
padding: 20px 0 10px 0;
5757
position: absolute;
@@ -88,8 +88,8 @@ export const DHeader = styled.div`
8888
export const BWrapper = styled.div`
8989
margin: 20px 0 0 0;
9090
padding: 15px;
91-
border-top: 1px solid ${(props) => props.theme.colors.border.primary};
92-
border-bottom: 1px solid ${(props) => props.theme.colors.border.primary};
91+
border-top: 1px solid ${(props) => props.theme.colors.border.alt4};
92+
border-bottom: 1px solid ${(props) => props.theme.colors.border.alt4};
9393
p {
9494
color: ${(props) => props.theme.colors.font.primary};
9595
font-size: ${(props) => props.theme.typography.size.small};
@@ -156,6 +156,6 @@ export const DBodyWrapper = styled.ul`
156156

157157
export const DFooterWrapper = styled(DBodyWrapper)`
158158
padding: 10px 0 0 0;
159-
border-top: 1px solid ${(props) => props.theme.colors.border.primary};
159+
border-top: 1px solid ${(props) => props.theme.colors.border.alt4};
160160
border-bottom: none;
161161
`;

0 commit comments

Comments
 (0)