diff --git a/src/components/atoms/Avatar/Avatar.tsx b/src/components/atoms/Avatar/Avatar.tsx index 74dc71b..7357a40 100644 --- a/src/components/atoms/Avatar/Avatar.tsx +++ b/src/components/atoms/Avatar/Avatar.tsx @@ -3,7 +3,7 @@ import { ReactSVG } from 'react-svg'; import { ASSETS } from 'helpers/config'; import { getTxEndpoint } from 'helpers/endpoints'; -import { checkAddress } from 'helpers/utils'; +import { checkValidAddress } from 'helpers/utils'; import * as S from './styles'; import { IProps } from './types'; @@ -12,7 +12,7 @@ export default function Avatar(props: IProps) { const [hasError, setHasError] = React.useState(false); const avatar = React.useMemo(() => { - if (!hasError && props.owner && props.owner.avatar && checkAddress(props.owner.avatar)) { + if (!hasError && props.owner && props.owner.avatar && checkValidAddress(props.owner.avatar)) { return setHasError(true)} />; } else return ; }, [props.owner, hasError]); diff --git a/src/components/molecules/AssetInfoLicense/AssetInfoLicense.tsx b/src/components/molecules/AssetInfoLicense/AssetInfoLicense.tsx index c4f7d05..cd21a38 100644 --- a/src/components/molecules/AssetInfoLicense/AssetInfoLicense.tsx +++ b/src/components/molecules/AssetInfoLicense/AssetInfoLicense.tsx @@ -3,7 +3,7 @@ import { ReactSVG } from 'react-svg'; import { Button } from 'components/atoms/Button'; import { TxAddress } from 'components/atoms/TxAddress'; import { ASSETS, REDIRECTS } from 'helpers/config'; -import { checkAddress, getDisplayValue, splitLicenseTag } from 'helpers/utils'; +import { checkValidAddress, getDisplayValue, splitLicenseTag } from 'helpers/utils'; import { useLanguageProvider } from 'providers/LanguageProvider'; import * as S from './styles'; @@ -44,7 +44,7 @@ export default function AssetDetailLicenses(props: IProps) { ); } else { - if (checkAddress(props.asset.license[element])) { + if (checkValidAddress(props.asset.license[element])) { return ( { (async function () { - if (props.id && checkAddress(props.id) && listingModalOpen && !collection) { + if (props.id && checkValidAddress(props.id) && listingModalOpen && !collection) { setFetchingCollection(true); try { const fetchResponse = await readHandler({ diff --git a/src/components/organisms/ProfileManage/ProfileManage.tsx b/src/components/organisms/ProfileManage/ProfileManage.tsx index 54ee49b..72275c9 100644 --- a/src/components/organisms/ProfileManage/ProfileManage.tsx +++ b/src/components/organisms/ProfileManage/ProfileManage.tsx @@ -13,7 +13,7 @@ import { TextArea } from 'components/atoms/TextArea'; import { AO, ASSETS, GATEWAYS, TAGS } from 'helpers/config'; import { getTxEndpoint } from 'helpers/endpoints'; import { NotificationType } from 'helpers/types'; -import { checkAddress, getBase64Data, getDataURLContentType } from 'helpers/utils'; +import { checkValidAddress, getBase64Data, getDataURLContentType } from 'helpers/utils'; import { useArweaveProvider } from 'providers/ArweaveProvider'; import { useLanguageProvider } from 'providers/LanguageProvider'; import { WalletBlock } from 'wallet/WalletBlock'; @@ -22,6 +22,7 @@ import * as S from './styles'; import { IProps } from './types'; const MAX_BIO_LENGTH = 500; +const MAX_IMAGE_SIZE = 100000; const ALLOWED_BANNER_TYPES = 'image/png, image/jpeg, image/gif'; const ALLOWED_AVATAR_TYPES = 'image/png, image/jpeg, image/gif'; @@ -48,8 +49,8 @@ export default function ProfileManage(props: IProps) { setUsername(props.profile.username ?? ''); setName(props.profile.displayName ?? ''); setBio(props.profile.bio ?? ''); - setBanner(props.profile.banner && checkAddress(props.profile.banner) ? props.profile.banner : null); - setAvatar(props.profile.avatar && checkAddress(props.profile.avatar) ? props.profile.avatar : null); + setBanner(props.profile.banner && checkValidAddress(props.profile.banner) ? props.profile.banner : null); + setAvatar(props.profile.avatar && checkValidAddress(props.profile.avatar) ? props.profile.avatar : null); } }, [props.profile]); @@ -70,7 +71,7 @@ export default function ProfileManage(props: IProps) { let bannerTx: any = null; if (banner) { - if (checkAddress(banner)) { + if (checkValidAddress(banner)) { bannerTx = banner; } else { try { @@ -91,7 +92,7 @@ export default function ProfileManage(props: IProps) { let avatarTx: any = null; if (avatar) { - if (checkAddress(avatar)) { + if (checkValidAddress(avatar)) { avatarTx = avatar; } else { try { @@ -251,6 +252,20 @@ export default function ProfileManage(props: IProps) { } } + function getImageSizeMessage() { + if (!avatar && !banner) return null; + if (checkValidAddress(avatar) && checkValidAddress(banner)) return null; + + const avatarSize = avatar ? (avatar.length * 3) / 4 : 0; + const bannerSize = banner ? (banner.length * 3) / 4 : 0; + + console.log(avatarSize); + + if (avatarSize > MAX_IMAGE_SIZE || bannerSize > MAX_IMAGE_SIZE) + return One or more images exceeds max size of 100KB; + return null; + } + function getInvalidBio() { if (bio && bio.length > MAX_BIO_LENGTH) { return { @@ -289,7 +304,7 @@ export default function ProfileManage(props: IProps) { } function getBannerWrapper() { - if (banner) return ; + if (banner) return ; return ( <> @@ -299,7 +314,7 @@ export default function ProfileManage(props: IProps) { } function getAvatarWrapper() { - if (avatar) return ; + if (avatar) return ; return ( <> @@ -360,9 +375,12 @@ export default function ProfileManage(props: IProps) { disabled={loading || !banner} /> + + Images have a max size of 100KB + - + + {getImageSizeMessage() && {getImageSizeMessage()}} {profileResponse && ( diff --git a/src/components/organisms/ProfileManage/styles.ts b/src/components/organisms/ProfileManage/styles.ts index bc262c6..6c6c2b0 100644 --- a/src/components/organisms/ProfileManage/styles.ts +++ b/src/components/organisms/ProfileManage/styles.ts @@ -37,7 +37,6 @@ export const Form = styled.div` export const TForm = styled.div` margin: 20px 0 30px 0; - padding: 20px; > * { &:last-child { margin: 20px 0 0 0; @@ -261,6 +260,18 @@ export const PActions = styled.div` } `; +export const PInfoMessage = styled.div` + margin: 15px 0 0 0; + display: flex; + justify-content: flex-end; + span { + color: ${(props) => props.theme.colors.font.alt1}; + font-size: ${(props) => props.theme.typography.size.xSmall}; + font-weight: ${(props) => props.theme.typography.weight.medium}; + line-height: 1.5; + } +`; + export const SAction = styled.div` width: 100%; display: flex; @@ -304,3 +315,19 @@ export const MActions = styled.div` flex-wrap: wrap; gap: 15px; `; + +export const MInfoWrapper = styled.div` + width: fit-content; + margin: 10px 0 0 auto; + span { + background: ${(props) => props.theme.colors.warning}; + color: ${(props) => props.theme.colors.font.light1}; + font-size: ${(props) => props.theme.typography.size.xxSmall}; + font-weight: ${(props) => props.theme.typography.weight.bold}; + border-radius: ${STYLING.dimensions.radius.alt2}; + text-align: center; + display: block; + padding: 2.5px 12.5px; + margin: 0 0 7.5px 0; + } +`; diff --git a/src/gql/search.ts b/src/gql/search.ts index 0fbbe32..395b082 100644 --- a/src/gql/search.ts +++ b/src/gql/search.ts @@ -2,7 +2,7 @@ import { getGQLData, getProfiles, structureAsset } from 'gql'; import { GATEWAYS, TAGS } from 'helpers/config'; import { AGQLResponseType, AssetGQLResponseType, AssetType, CursorEnum, GQLNodeResponseType } from 'helpers/types'; -import { checkAddress, getTagValue } from 'helpers/utils'; +import { checkValidAddress, getTagValue } from 'helpers/utils'; export async function search(args: { term: string; cursor: string | null }): Promise { const emptyResponseObject = { @@ -12,7 +12,7 @@ export async function search(args: { term: string; cursor: string | null }): Pro previousCursor: null, }; try { - const addressCheck = checkAddress(args.term); + const addressCheck = checkValidAddress(args.term); const gqlResponse: AGQLResponseType = await getGQLData({ gateway: GATEWAYS.goldsky, diff --git a/src/helpers/utils.ts b/src/helpers/utils.ts index e7fd9a3..0af461d 100644 --- a/src/helpers/utils.ts +++ b/src/helpers/utils.ts @@ -3,7 +3,7 @@ import Arweave from 'arweave'; import { API_CONFIG, GATEWAYS, STORAGE } from './config'; import { DateType, ProfileType } from './types'; -export function checkAddress(address: string | null) { +export function checkValidAddress(address: string | null) { if (!address) return false; return /^[a-z0-9_-]{43}$/i.test(address); } @@ -14,7 +14,7 @@ export function getUniqueAddresses(addresses: string[]) { export function formatAddress(address: string | null, wrap: boolean) { if (!address) return ''; - if (!checkAddress(address)) return address; + if (!checkValidAddress(address)) return address; const formattedAddress = address.substring(0, 5) + '...' + address.substring(36, address.length); return wrap ? `(${formattedAddress})` : formattedAddress; } diff --git a/src/views/Landing/Profile/Profile.tsx b/src/views/Landing/Profile/Profile.tsx index e7b7b2c..fa0d447 100644 --- a/src/views/Landing/Profile/Profile.tsx +++ b/src/views/Landing/Profile/Profile.tsx @@ -13,7 +13,7 @@ import { ProfileManage } from 'components/organisms/ProfileManage'; import { ASSETS, REDIRECTS, URLS } from 'helpers/config'; import { getTxEndpoint } from 'helpers/endpoints'; import { ProfileHeaderType } from 'helpers/types'; -import { checkAddress, formatAddress } from 'helpers/utils'; +import { checkValidAddress, formatAddress } from 'helpers/utils'; import { useArweaveProvider } from 'providers/ArweaveProvider'; import { useLanguageProvider } from 'providers/LanguageProvider'; @@ -48,7 +48,7 @@ export default function Profile(props: { address: string }) { React.useEffect(() => { (async function () { - if (props.address && checkAddress(props.address)) { + if (props.address && checkValidAddress(props.address)) { setLoading(true); try { const currentProfile = await getProfile({ address: props.address }); @@ -62,7 +62,7 @@ export default function Profile(props: { address: string }) { }, [props.address, arProvider.profile]); function getAvatar() { - if (fullProfile && fullProfile.avatar && checkAddress(fullProfile.avatar)) + if (fullProfile && fullProfile.avatar && checkValidAddress(fullProfile.avatar)) return ; return ; } diff --git a/src/views/Upload/UploadSteps/UploadStepsLicense/UploadStepsLicenseFull/UploadStepsLicenseFull.tsx b/src/views/Upload/UploadSteps/UploadStepsLicense/UploadStepsLicenseFull/UploadStepsLicenseFull.tsx index f7f8b8d..2ff9fe6 100644 --- a/src/views/Upload/UploadSteps/UploadStepsLicense/UploadStepsLicenseFull/UploadStepsLicenseFull.tsx +++ b/src/views/Upload/UploadSteps/UploadStepsLicense/UploadStepsLicenseFull/UploadStepsLicenseFull.tsx @@ -6,7 +6,7 @@ import { FormField } from 'components/atoms/FormField'; import { Select } from 'components/atoms/Select'; import { ASSETS } from 'helpers/config'; import { SelectOptionType } from 'helpers/types'; -import { checkAddress, concatLicenseTag } from 'helpers/utils'; +import { checkValidAddress, concatLicenseTag } from 'helpers/utils'; import { useArweaveProvider } from 'providers/ArweaveProvider'; import { useLanguageProvider } from 'providers/LanguageProvider'; import { RootState } from 'store'; @@ -247,7 +247,7 @@ export default function UploadStepsLicenseFull(props: IProps) { dataModelTrainingTermAmount <= 0) || (paymentMode && paymentMode.id === concatLicenseTag(licenseParams.paymentMode.single) && - !checkAddress(paymentRecipient)) + !checkValidAddress(paymentRecipient)) ) { dispatch(uploadActions.setStepDisabled(true)); } else { @@ -393,7 +393,7 @@ export default function UploadStepsLicenseFull(props: IProps) { label={language.recipient} value={paymentRecipient} onChange={(e: any) => setPaymentRecipient(e.target.value)} - invalid={{ status: paymentRecipient ? !checkAddress(paymentRecipient) : true, message: null }} + invalid={{ status: paymentRecipient ? !checkValidAddress(paymentRecipient) : true, message: null }} disabled={disabled} hideErrorMessage required diff --git a/src/wallet/WalletConnect/WalletConnect.tsx b/src/wallet/WalletConnect/WalletConnect.tsx index 11531e7..91c5119 100644 --- a/src/wallet/WalletConnect/WalletConnect.tsx +++ b/src/wallet/WalletConnect/WalletConnect.tsx @@ -84,7 +84,7 @@ export default function WalletConnect(_props: { callback?: () => void }) { {showWalletDropdown && ( - + diff --git a/src/wallet/WalletConnect/styles.ts b/src/wallet/WalletConnect/styles.ts index e453268..c3228d7 100644 --- a/src/wallet/WalletConnect/styles.ts +++ b/src/wallet/WalletConnect/styles.ts @@ -51,7 +51,7 @@ export const FlexAction = styled.div` `; export const Dropdown = styled.ul` - width: 350px; + width: 315px; max-width: 90vw; padding: 20px 0 10px 0; position: absolute; @@ -88,8 +88,8 @@ export const DHeader = styled.div` export const BWrapper = styled.div` margin: 20px 0 0 0; padding: 15px; - border-top: 1px solid ${(props) => props.theme.colors.border.primary}; - border-bottom: 1px solid ${(props) => props.theme.colors.border.primary}; + border-top: 1px solid ${(props) => props.theme.colors.border.alt4}; + border-bottom: 1px solid ${(props) => props.theme.colors.border.alt4}; p { color: ${(props) => props.theme.colors.font.primary}; font-size: ${(props) => props.theme.typography.size.small}; @@ -156,6 +156,6 @@ export const DBodyWrapper = styled.ul` export const DFooterWrapper = styled(DBodyWrapper)` padding: 10px 0 0 0; - border-top: 1px solid ${(props) => props.theme.colors.border.primary}; + border-top: 1px solid ${(props) => props.theme.colors.border.alt4}; border-bottom: none; `;