diff --git a/assets/default-images/tns-profile-cover.png b/assets/default-images/tns-profile-cover.png new file mode 100644 index 0000000000..81cfe808d0 Binary files /dev/null and b/assets/default-images/tns-profile-cover.png differ diff --git a/assets/icons/upload-cloud.svg b/assets/icons/upload-cloud.svg new file mode 100644 index 0000000000..99540948f5 --- /dev/null +++ b/assets/icons/upload-cloud.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/package.json b/package.json index 59359bce07..6c1bb445ba 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "expo": "^49.0.16", "expo-av": "~13.4.1", "expo-barcode-scanner": "~12.5.3", + "expo-document-picker": "~11.5.4", "expo-font": "~11.4.0", "expo-linear-gradient": "~12.3.0", "expo-optimize": "^0.2.20", diff --git a/packages/components/OptimizedImage.tsx b/packages/components/OptimizedImage.tsx index 7baade4989..87ef21296f 100644 --- a/packages/components/OptimizedImage.tsx +++ b/packages/components/OptimizedImage.tsx @@ -1,5 +1,5 @@ import { CID } from "multiformats"; -import React, { memo } from "react"; +import React, { memo, useEffect } from "react"; import { Image, ImageProps, View, StyleSheet, PixelRatio } from "react-native"; import { neutral33 } from "../utils/style/colors"; @@ -22,12 +22,27 @@ export const OptimizedImage: React.FC< const sourceWidth = PixelRatio.getPixelSizeForLayoutSize(width); const sourceHeight = PixelRatio.getPixelSizeForLayoutSize(height); + useEffect(() => { + setIsError(false); + }, [baseSourceURI]); + + useEffect(() => { + setIsFallbackError(false); + }, [fallbackURI]); + if ((shouldUseFallback && !fallbackURI) || isFallbackError) { return ( extends Omit { label: string; variant?: "regular" | "labelOutside" | "noStyle"; iconSVG?: React.FC; + onPressChildren?: () => void; placeHolder?: string; squaresBackgroundColor?: string; style?: StyleProp; @@ -139,6 +143,7 @@ export const TextInputCustom = ({ subtitle, labelStyle, iconSVG, + onPressChildren, hideLabel, valueModifier, errorStyle, @@ -292,9 +297,10 @@ export const TextInputCustom = ({ {...restProps} /> - {isLoading ? ( + ) : onPressChildren ? ( + {children} ) : ( <>{children} )} diff --git a/packages/components/modals/teritoriNameService/TNSNameFinderModal.tsx b/packages/components/modals/teritoriNameService/TNSNameFinderModal.tsx index d8ededb4d1..b4ee13a381 100644 --- a/packages/components/modals/teritoriNameService/TNSNameFinderModal.tsx +++ b/packages/components/modals/teritoriNameService/TNSNameFinderModal.tsx @@ -120,7 +120,7 @@ export const TNSNameFinderModal: React.FC<{ } width={372} > diff --git a/packages/components/teritoriNameService/MediaPreview.tsx b/packages/components/teritoriNameService/MediaPreview.tsx new file mode 100644 index 0000000000..07f85e7c4c --- /dev/null +++ b/packages/components/teritoriNameService/MediaPreview.tsx @@ -0,0 +1,182 @@ +import * as DocumentPicker from "expo-document-picker"; +import { DocumentPickerResult } from "expo-document-picker"; +import React, { Dispatch, SetStateAction, useState } from "react"; +import { ActivityIndicator, View, ViewStyle } from "react-native"; +import { useSelector } from "react-redux"; + +import tnsProfileAvatar from "../../../assets/default-images/default-name-nft.png"; +import tnsProfileCover from "../../../assets/default-images/tns-profile-cover.png"; +import uploadCloudIcon from "../../../assets/icons/upload-cloud.svg"; +import { useFeedbacks } from "../../context/FeedbacksProvider"; +import { Metadata } from "../../contracts-clients/teritori-name-service/TeritoriNameService.types"; +import { PinataFileProps, useIpfs } from "../../hooks/useIpfs"; +import { useSelectedNetworkInfo } from "../../hooks/useSelectedNetwork"; +import useSelectedWallet from "../../hooks/useSelectedWallet"; +import { selectNFTStorageAPI } from "../../store/slices/settings"; +import { generateIpfsKey } from "../../utils/ipfs"; +import { + neutral00, + neutral17, + neutral33, + secondaryColor, +} from "../../utils/style/colors"; +import { layout } from "../../utils/style/layout"; +import { OptimizedImage } from "../OptimizedImage"; +import { SVG } from "../SVG"; +import { TextInputCustom } from "../inputs/TextInputCustom"; + +export const MediaPreview: React.FC<{ + style: ViewStyle; + avatarImageUrl: string; + setAvatarImageUrl: Dispatch>; + bannerImageUrl: string; + setBannerImageUrl: Dispatch>; +}> = ({ + style, + avatarImageUrl, + setAvatarImageUrl, + bannerImageUrl, + setBannerImageUrl, +}) => { + const selectedNetwork = useSelectedNetworkInfo(); + const selectedWallet = useSelectedWallet(); + const { setToastError } = useFeedbacks(); + const { pinataPinFileToIPFS } = useIpfs(); + const userId = selectedWallet?.userId; + const [isAvatarImageUploadLoading, setAvatarImageUploadLoading] = + useState(false); + const [isBannerImageUploadLoading, setBannerImageUploadLoading] = + useState(false); + const userIPFSKey = useSelector(selectNFTStorageAPI); + + const upload = async ( + callback: Dispatch>, + documentPickerResult: DocumentPickerResult, + ) => { + const pinataJWTKey = + userIPFSKey || (await generateIpfsKey(selectedNetwork?.id || "", userId)); + if (!pinataJWTKey) { + console.error("upload file err : No Pinata JWT"); + setToastError({ + title: "File upload failed", + message: "No Pinata JWT", + }); + return; + } + if (documentPickerResult.output) { + const fileIpfsHash = await pinataPinFileToIPFS({ + pinataJWTKey, + file: { file: documentPickerResult.output[0] }, + } as PinataFileProps); + callback(`ipfs://${fileIpfsHash}`); + } + }; + + const onPressUploadAvatar = async () => { + const documentPickerResult = await DocumentPicker.getDocumentAsync({ + multiple: false, + }); + setAvatarImageUploadLoading(true); + await upload(setAvatarImageUrl, documentPickerResult); + setAvatarImageUploadLoading(false); + }; + + const onPressUploadBanner = async () => { + const documentPickerResult = await DocumentPicker.getDocumentAsync({ + multiple: false, + }); + setBannerImageUploadLoading(true); + await upload(setBannerImageUrl, documentPickerResult); + setBannerImageUploadLoading(false); + }; + + return ( + + + name="image" + style={style} + label="Avatar URL" + noBrokenCorners + variant="labelOutside" + placeHolder="https://website.com/avatar.jpg" + onPressChildren={onPressUploadAvatar} + value={avatarImageUrl} + onChangeText={setAvatarImageUrl} + squaresBackgroundColor={neutral17} + > + {isAvatarImageUploadLoading ? ( + + ) : ( + + )} + + + + name="public_profile_header" + style={style} + label="Cover Image URL" + noBrokenCorners + onPressChildren={onPressUploadBanner} + variant="labelOutside" + placeHolder="https://website.com/coverimage.jpg" + value={bannerImageUrl} + onChangeText={setBannerImageUrl} + squaresBackgroundColor={neutral17} + > + {isBannerImageUploadLoading ? ( + + ) : ( + + )} + + + + + + + + ); +}; diff --git a/packages/components/teritoriNameService/NameData.tsx b/packages/components/teritoriNameService/NameData.tsx deleted file mode 100644 index 35f2eca1ea..0000000000 --- a/packages/components/teritoriNameService/NameData.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import React from "react"; -import { View, ViewStyle } from "react-native"; - -import { neutral17, neutral77 } from "../../utils/style/colors"; -import { imageDisplayLabel, prettyTokenData } from "../../utils/teritori"; -import { BrandText } from "../BrandText"; -import { ExternalLink } from "../ExternalLink"; -import { LegacyTertiaryBox } from "../boxes/LegacyTertiaryBox"; - -export const NameData: React.FC<{ - token: any; - name: string; - style?: ViewStyle; -}> = ({ token, name, style }) => { - const width = 396; - - return ( - - {token ? ( - <> - - - Name - - - {name} - - - - - {prettyTokenData(token) - // We display only the raw if there is a value - .filter((data) => data.value) - .map((data, i) => ( - - - {data.displayLabel} - - {/*---- We want some style depending on the data type*/} - {data.displayLabel === imageDisplayLabel ? ( - - {data.value} - - ) : ( - - {data.value} - - )} - - ))} - - - ) : ( - Loading - )} - - ); -}; diff --git a/packages/components/teritoriNameService/NameDataForm.tsx b/packages/components/teritoriNameService/NameDataForm.tsx index 4f72753a14..8d0b1b5040 100644 --- a/packages/components/teritoriNameService/NameDataForm.tsx +++ b/packages/components/teritoriNameService/NameDataForm.tsx @@ -1,15 +1,15 @@ import React, { useEffect, useState } from "react"; import { View, ViewStyle } from "react-native"; +import { MediaPreview } from "./MediaPreview"; import { Metadata } from "../../contracts-clients/teritori-name-service/TeritoriNameService.types"; import { neutral17, neutral77 } from "../../utils/style/colors"; +import { layout } from "../../utils/style/layout"; import { BrandText } from "../BrandText"; import { ExternalLink } from "../ExternalLink"; import { PrimaryButton } from "../buttons/PrimaryButton"; import { TextInputCustom } from "../inputs/TextInputCustom"; -// TODO: Later, create a reusable FormBase cpt to avoid writing too much code and call it in NameDataForm.tsx. Maybe use react-hook-form ? - export const NameDataForm: React.FC<{ isMintPath?: boolean; btnLabel: string; @@ -20,8 +20,8 @@ export const NameDataForm: React.FC<{ const [pathId, setPathId] = useState(""); const [publicName, setPublicName] = useState(""); const [public_bio, setBio] = useState(""); - const [image, setImageUrl] = useState(""); - const [bannerImage, setBannerImage] = useState(""); + const [avatarImageUrl, setAvatarImageUrl] = useState(""); + const [bannerImageUrl, setBannerImageUrl] = useState(""); const [email, setEmail] = useState(""); const [external_url, setWebsite] = useState(""); const [twitter_id, setTwitter] = useState(""); @@ -40,8 +40,8 @@ export const NameDataForm: React.FC<{ pathId, public_name: publicName, public_bio, - image, - public_profile_header: bannerImage, + image: avatarImageUrl, + public_profile_header: bannerImageUrl, email, external_url, twitter_id, @@ -54,8 +54,8 @@ export const NameDataForm: React.FC<{ // Setting initial inputs values (Pre-filled values if existing token) useEffect(() => { setBio(initialData.public_bio || ""); - setImageUrl(initialData.image || ""); - setBannerImage(initialData.public_profile_header || ""); + setAvatarImageUrl(initialData.image || ""); + setBannerImageUrl(initialData.public_profile_header || ""); setEmail(initialData.email || ""); setWebsite(initialData.external_url || ""); setTwitter(initialData.twitter_id || ""); @@ -70,6 +70,7 @@ export const NameDataForm: React.FC<{ {isMintPath ? ( @@ -97,9 +98,12 @@ export const NameDataForm: React.FC<{ . + + {/*// TODO: Refacto TextInputCustom and fix usages*/} + name="pathId" - style={inputStyle} + containerStyle={inputStyle} label="Path ID (must be unique)" placeHolder="Type path ID here" value={pathId} @@ -110,8 +114,11 @@ export const NameDataForm: React.FC<{ ) : null} name="name" - style={[inputStyle, !isMintPath && { marginTop: 4 }]} - label="NAME" + containerStyle={inputStyle} + label="Name" + rules={{ required: true }} + noBrokenCorners + variant="labelOutside" placeHolder="Type name here" value={publicName} onChangeText={setPublicName} @@ -120,35 +127,29 @@ export const NameDataForm: React.FC<{ /> name="public_bio" - style={inputStyle} - label="BIO" + containerStyle={inputStyle} + label="Bio" + noBrokenCorners + variant="labelOutside" placeHolder="Type bio here" value={public_bio} onChangeText={setBio} squaresBackgroundColor={neutral17} /> - - name="image" - style={inputStyle} - label="AVATAR IMAGE URL" - placeHolder="Insert image URL here" - value={image} - onChangeText={setImageUrl} - squaresBackgroundColor={neutral17} - /> - - name="public_profile_header" + + name="email" - style={inputStyle} - label="EMAIL" + containerStyle={inputStyle} + label="Email" + noBrokenCorners + variant="labelOutside" placeHolder="Type email here" value={email} onChangeText={setEmail} @@ -156,8 +157,10 @@ export const NameDataForm: React.FC<{ /> name="external_url" - style={inputStyle} - label="WEBSITE" + containerStyle={inputStyle} + label="Website" + noBrokenCorners + variant="labelOutside" placeHolder="Type/insert link here" value={external_url} onChangeText={setWebsite} @@ -165,8 +168,10 @@ export const NameDataForm: React.FC<{ /> name="twitter_id" - style={inputStyle} - label="TWITTER" + containerStyle={inputStyle} + label="Twitter (X)" + noBrokenCorners + variant="labelOutside" placeHolder="Link to Twitter account" value={twitter_id} onChangeText={setTwitter} @@ -174,8 +179,10 @@ export const NameDataForm: React.FC<{ /> name="discord_id" - style={inputStyle} - label="DISCORD" + containerStyle={inputStyle} + label="Discord" + noBrokenCorners + variant="labelOutside" placeHolder="Link to Discord" value={discord_id} onChangeText={setDiscord} @@ -183,8 +190,10 @@ export const NameDataForm: React.FC<{ /> name="telegram_id" - style={inputStyle} - label="TELEGRAM USERNAME" + containerStyle={inputStyle} + label="Telegram Username" + noBrokenCorners + variant="labelOutside" placeHolder="@nickname" value={telegram_id} onChangeText={setTelegrameUsername} @@ -192,8 +201,10 @@ export const NameDataForm: React.FC<{ /> name="keybase_id" - style={inputStyle} - label="KEYBASE.IO" + containerStyle={inputStyle} + label="Keybase.io" + noBrokenCorners + variant="labelOutside" placeHolder="Type/insert link here" value={keybase_id} onChangeText={setKeybaseIo} @@ -201,19 +212,21 @@ export const NameDataForm: React.FC<{ /> name="validator_operator_address" - style={inputStyle} - label="VALIDATOR OPERATOR ADDRESS" + containerStyle={inputStyle} + label="Validator Operator Address" + noBrokenCorners + variant="labelOutside" placeHolder="Type/insert link here" value={validator_operator_address} onChangeText={setValidatorOperatorAddress} squaresBackgroundColor={neutral17} /> diff --git a/packages/components/teritoriNameService/NameStatus.tsx b/packages/components/teritoriNameService/NameStatus.tsx index 3d554709de..5b37e0956b 100644 --- a/packages/components/teritoriNameService/NameStatus.tsx +++ b/packages/components/teritoriNameService/NameStatus.tsx @@ -7,7 +7,6 @@ import { BrandText } from "../BrandText"; import { SVG } from "../SVG"; import { LegacyTertiaryBox } from "../boxes/LegacyTertiaryBox"; -// A custom TextInput. You can add children (Ex: An icon or a small container) export const NameStatus: React.FC<{ available?: boolean; hasError?: boolean; diff --git a/packages/hooks/useIpfs.ts b/packages/hooks/useIpfs.ts index 30ec447eae..5a398073b5 100644 --- a/packages/hooks/useIpfs.ts +++ b/packages/hooks/useIpfs.ts @@ -5,11 +5,6 @@ import { useState } from "react"; import { LocalFileData, RemoteFileData } from "../utils/types/files"; -interface PinataFileProps { - file: LocalFileData; - pinataJWTKey: string; -} - interface UploadPostFilesToPinataParams { files: LocalFileData[]; pinataJWTKey: string; @@ -20,6 +15,11 @@ interface IPFSUploadProgress { progress: number; // 0 to 1 } +export interface PinataFileProps { + file: LocalFileData; + pinataJWTKey: string; +} + export const useIpfs = () => { const [ipfsUploadProgresses, setIpfsUploadProgresses] = useState< IPFSUploadProgress[] @@ -57,7 +57,7 @@ export const useIpfs = () => { "Content-Type": "multipart/form-data", }, }); - return responseFile.data.IpfsHash; + return CID.parse(responseFile.data.IpfsHash).toV1().toString(); } catch (err) { console.error("Error pinning " + file.fileName + " to IPFS", err); } @@ -74,9 +74,7 @@ export const useIpfs = () => { file, pinataJWTKey, }); - const url = !fileIpfsHash - ? "" - : "ipfs://" + CID.parse(fileIpfsHash).toV1().toString(); + const url = !fileIpfsHash ? "" : "ipfs://" + fileIpfsHash; if (file.thumbnailFileData) { const thumbnailFileIpfsHash = await pinataPinFileToIPFS({ @@ -85,7 +83,7 @@ export const useIpfs = () => { }); const thumbnailUrl = !thumbnailFileIpfsHash ? "" - : "ipfs://" + CID.parse(thumbnailFileIpfsHash).toV1().toString(); + : "ipfs://" + thumbnailFileIpfsHash; return { ...omit(file, "file"), @@ -128,5 +126,9 @@ export const useIpfs = () => { 0, ) / ipfsUploadProgresses.length; - return { uploadFilesToPinata, ipfsUploadProgress: finalProgress }; + return { + uploadFilesToPinata, + pinataPinFileToIPFS, + ipfsUploadProgress: finalProgress, + }; }; diff --git a/packages/screens/TeritoriNameService/TNSBurnNameScreen.tsx b/packages/screens/TeritoriNameService/TNSBurnNameScreen.tsx index 3cb2a34473..e91ec16604 100644 --- a/packages/screens/TeritoriNameService/TNSBurnNameScreen.tsx +++ b/packages/screens/TeritoriNameService/TNSBurnNameScreen.tsx @@ -16,10 +16,12 @@ import { nsNameInfoQueryKey } from "../../hooks/useNSNameInfo"; import { useNSTokensByOwner } from "../../hooks/useNSTokensByOwner"; import useSelectedWallet from "../../hooks/useSelectedWallet"; import { + getCosmosNetwork, getKeplrSigningCosmWasmClient, mustGetCosmosNetwork, } from "../../networks"; -import { neutral17 } from "../../utils/style/colors"; +import { neutral17, neutralA3 } from "../../utils/style/colors"; +import { layout } from "../../utils/style/layout"; interface TNSBurnNameScreenProps extends TNSModalCommonProps {} @@ -29,10 +31,12 @@ export const TNSBurnNameScreen: React.FC = ({ const { name } = useTNS(); const { setToastError, setToastSuccess } = useFeedbacks(); const selectedWallet = useSelectedWallet(); - const network = mustGetCosmosNetwork(selectedWallet?.networkId); + const network = getCosmosNetwork(selectedWallet?.networkId); const { tokens } = useNSTokensByOwner(selectedWallet?.userId); const walletAddress = selectedWallet?.address; - const normalizedTokenId = (name + network.nameServiceTLD || "").toLowerCase(); + const normalizedTokenId = ( + name + network?.nameServiceTLD || "" + ).toLowerCase(); const queryClient = useQueryClient(); @@ -53,6 +57,7 @@ export const TNSBurnNameScreen: React.FC = ({ } try { + const network = mustGetCosmosNetwork(selectedWallet?.networkId); if (!network.nameServiceContractAddress) { throw new Error("network not supported"); } @@ -93,6 +98,7 @@ export const TNSBurnNameScreen: React.FC = ({ onClose()} + label="Burn Name NFT" width={457} boxStyle={{ backgroundColor: neutral17, @@ -131,7 +137,7 @@ export const TNSBurnNameScreen: React.FC = ({ style={{ fontSize: 16, lineHeight: 20, - color: "#A3A3A3", + color: neutralA3, marginTop: 16, marginBottom: 20, }} @@ -145,7 +151,7 @@ export const TNSBurnNameScreen: React.FC = ({ size="XS" text="I understand, burn it" onPress={onSubmit} - style={{ marginBottom: 80 }} + style={{ marginBottom: layout.spacing_x4 }} loader /> diff --git a/packages/screens/TeritoriNameService/TNSConsultNameScreen.tsx b/packages/screens/TeritoriNameService/TNSConsultNameScreen.tsx index 551b02cea0..696a49222d 100644 --- a/packages/screens/TeritoriNameService/TNSConsultNameScreen.tsx +++ b/packages/screens/TeritoriNameService/TNSConsultNameScreen.tsx @@ -4,12 +4,10 @@ import { View } from "react-native"; import { TNSModalCommonProps } from "./TNSHomeScreen"; import { BrandText } from "../../components/BrandText"; -import { CopyToClipboard } from "../../components/CopyToClipboard"; import { PrimaryButton } from "../../components/buttons/PrimaryButton"; import { SecondaryButton } from "../../components/buttons/SecondaryButton"; import ModalBase from "../../components/modals/ModalBase"; import { TNSSendFundsModal } from "../../components/modals/teritoriNameService/TNSSendFundsModal"; -import { NameData } from "../../components/teritoriNameService/NameData"; import { NameNFT } from "../../components/teritoriNameService/NameNFT"; import { useFeedbacks } from "../../context/FeedbacksProvider"; import { useTNS } from "../../context/TNSProvider"; @@ -33,6 +31,7 @@ import { } from "../../networks"; import { useAppNavigation } from "../../utils/navigation"; import { neutral17, neutral33 } from "../../utils/style/colors"; +import { layout } from "../../utils/style/layout"; const NotOwnerActions: React.FC<{ tokenId: string; @@ -57,8 +56,8 @@ const NotOwnerActions: React.FC<{ {isPrimary && ( { onClose(); navigation.navigate("UserPublicProfile", { id: ownerId }); @@ -68,7 +67,7 @@ const NotOwnerActions: React.FC<{ setSendFundsModalVisible(true)} /> @@ -95,24 +94,25 @@ const OwnerActions: React.FC<{ style={{ flexDirection: "row", alignItems: "center", - marginBottom: 42, + justifyContent: "center", + marginBottom: layout.spacing_x3, alignSelf: "center", }} > {isPrimary && ( { + onClose(); navigation.navigate("UserPublicProfile", { id: ownerId }); }} /> )} { onClose("TNSUpdateName"); }} @@ -120,7 +120,7 @@ const OwnerActions: React.FC<{ { onClose("TNSBurnName"); }} @@ -130,7 +130,7 @@ const OwnerActions: React.FC<{ size="M" text="Set as Primary" loader - style={{ marginLeft: 24 }} + style={{ marginLeft: layout.spacing_x3 }} onPress={async () => { try { const network = mustGetCosmosNetwork(wallet?.networkId); @@ -178,11 +178,12 @@ export const TNSConsultNameScreen: React.FC = ({ const networkId = useSelectedNetworkId(); const network = getCosmosNetwork(networkId); const tokenId = (name + network?.nameServiceTLD || "").toLowerCase(); - const { nsInfo: token, notFound } = useNSNameInfo( + const { notFound } = useNSNameInfo( networkId, tokenId, !!network?.nameServiceTLD, ); + const { nameOwner } = useNSNameOwner(networkId, tokenId); const ownerId = getUserId(networkId, nameOwner); const { daos } = useDAOs({ networkId, memberAddress: wallet?.address }); @@ -213,14 +214,16 @@ export const TNSConsultNameScreen: React.FC = ({ {notFound ? ( Not found ) : ( <> - + {!notFound && (isOwnedByUser ? ( = ({ onClose={onClose} /> ))} - {!!token && !!name && ( - - {isOwnedByUser ? ( - - ) : ( - <> - {!!token.extension.contract_address && ( - - )} - - )} - - - )} )} diff --git a/packages/screens/TeritoriNameService/TNSExploreScreen.tsx b/packages/screens/TeritoriNameService/TNSExploreScreen.tsx index 924edbfa75..f98983d0e3 100644 --- a/packages/screens/TeritoriNameService/TNSExploreScreen.tsx +++ b/packages/screens/TeritoriNameService/TNSExploreScreen.tsx @@ -9,10 +9,12 @@ import { TNSSendFundsModal } from "../../components/modals/teritoriNameService/T import { FindAName } from "../../components/teritoriNameService/FindAName"; import { useTNS } from "../../context/TNSProvider"; import { useNSMintAvailability } from "../../hooks/useNSMintAvailability"; +import { useNSNameOwner } from "../../hooks/useNSNameOwner"; import { useNSTokensByOwner } from "../../hooks/useNSTokensByOwner"; import { useSelectedNetworkId } from "../../hooks/useSelectedNetwork"; import useSelectedWallet from "../../hooks/useSelectedWallet"; -import { getCosmosNetwork } from "../../networks"; +import { getCosmosNetwork, getUserId } from "../../networks"; +import { useAppNavigation } from "../../utils/navigation"; import { neutral17 } from "../../utils/style/colors"; interface TNSExploreScreenProps extends TNSModalCommonProps {} @@ -25,6 +27,11 @@ export const TNSExploreScreen: React.FC = ({ const selectedWallet = useSelectedWallet(); const networkId = useSelectedNetworkId(); const network = getCosmosNetwork(networkId); + const navigation = useAppNavigation(); + const { nameOwner } = useNSNameOwner( + networkId, + name + network?.nameServiceTLD || "", + ); const { tokens } = useNSTokensByOwner(selectedWallet?.userId); const tokenId = (name + network?.nameServiceTLD || "").toLowerCase(); const { nameAvailable, nameError, loading } = useNSMintAvailability( @@ -34,7 +41,7 @@ export const TNSExploreScreen: React.FC = ({ return ( onClose()} modalStatus={name && nameAvailable ? "success" : "danger"} @@ -66,16 +73,18 @@ export const TNSExploreScreen: React.FC = ({ { - onClose("TNSConsultName"); + navigation.navigate("UserPublicProfile", { + id: getUserId(networkId, nameOwner), + }); }} /> setSendFundsModalVisible(true)} squaresBackgroundColor={neutral17} /> diff --git a/packages/screens/TeritoriNameService/TNSRegisterScreen.tsx b/packages/screens/TeritoriNameService/TNSRegisterScreen.tsx index 8c26098d6a..e881646b16 100644 --- a/packages/screens/TeritoriNameService/TNSRegisterScreen.tsx +++ b/packages/screens/TeritoriNameService/TNSRegisterScreen.tsx @@ -29,7 +29,7 @@ export const TNSRegisterScreen: React.FC = ({ return ( onClose()} - label="Find a name" + label="Find a Name" width={457} modalStatus={name && nameAvailable ? "success" : "danger"} hideMainSeparator diff --git a/packages/screens/TeritoriNameService/TNSUpdateNameScreen.tsx b/packages/screens/TeritoriNameService/TNSUpdateNameScreen.tsx index dd8cb5f683..25d472fe8a 100644 --- a/packages/screens/TeritoriNameService/TNSUpdateNameScreen.tsx +++ b/packages/screens/TeritoriNameService/TNSUpdateNameScreen.tsx @@ -6,7 +6,6 @@ import { View } from "react-native"; import { TNSModalCommonProps } from "./TNSHomeScreen"; import ModalBase from "../../components/modals/ModalBase"; import { NameDataForm } from "../../components/teritoriNameService/NameDataForm"; -import { NameNFT } from "../../components/teritoriNameService/NameNFT"; import { useFeedbacks } from "../../context/FeedbacksProvider"; import { useTNS } from "../../context/TNSProvider"; import { TeritoriNameServiceQueryClient } from "../../contracts-clients/teritori-name-service/TeritoriNameService.client"; @@ -18,10 +17,10 @@ import { useNSNameOwner } from "../../hooks/useNSNameOwner"; import { useNSTokensByOwner } from "../../hooks/useNSTokensByOwner"; import useSelectedWallet from "../../hooks/useSelectedWallet"; import { + getCosmosNetwork, getKeplrSigningCosmWasmClient, - mustGetNonSigningCosmWasmClient, mustGetCosmosNetwork, - getCosmosNetwork, + mustGetNonSigningCosmWasmClient, } from "../../networks"; import { neutral17 } from "../../utils/style/colors"; import { defaultMetaData } from "../../utils/types/tns"; @@ -197,16 +196,16 @@ export const TNSUpdateNameScreen: React.FC = ({ onClose()} + label="Edit profile" scrollable width={457} boxStyle={{ backgroundColor: neutral17, }} > - { - const finalDatas: PrettyTokenData[] = []; - Object.entries(tokenData).map(([key, value], i) => { - switch (key) { - case "email": - finalDatas[0] = { displayLabel: "Email", value: value as string }; - break; - case "public_name": - finalDatas[1] = { - displayLabel: publicNameDisplayLabel, - value: value as string, - }; - break; - case "public_bio": - finalDatas[2] = { displayLabel: "Bio", value: value as string }; - break; - case "image": - finalDatas[3] = { - displayLabel: imageDisplayLabel, - value: value as string, - }; - break; - case "external_url": - finalDatas[4] = { - displayLabel: "External URL", - value: value as string, - }; - break; - case "discord_id": - finalDatas[5] = { - displayLabel: "Discord", - value: value as string, - }; - break; - case "twitter_id": - finalDatas[6] = { displayLabel: "Twitter", value: value as string }; - break; - case "telegram_id": - finalDatas[7] = { - displayLabel: "Telegram username", - value: value as string, - }; - break; - case "keybase_id": - finalDatas[8] = { displayLabel: "Keybase", value: value as string }; - break; - case "validator_operator_address": - finalDatas[9] = { displayLabel: "Validator", value: value as string }; - break; - } - }); - return finalDatas; -}; diff --git a/yarn.lock b/yarn.lock index 4d160c3a82..c9b183c9db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10682,6 +10682,15 @@ __metadata: languageName: node linkType: hard +"expo-document-picker@npm:~11.5.4": + version: 11.5.4 + resolution: "expo-document-picker@npm:11.5.4" + peerDependencies: + expo: "*" + checksum: a59571a356830b698ebeeb29cf1b33e42dcd05b348fe1125c5c52f0ef0bae410d9e6e57d62b7f9e9a699b38d824e90f787282d80b3feeddb35dcc319a389e546 + languageName: node + linkType: hard + "expo-file-system@npm:~15.4.0, expo-file-system@npm:~15.4.4": version: 15.4.4 resolution: "expo-file-system@npm:15.4.4" @@ -19548,6 +19557,7 @@ __metadata: expo-barcode-scanner: ~12.5.3 expo-dev-client: ~2.4.12 expo-doctor: ^1.1.3 + expo-document-picker: ~11.5.4 expo-font: ~11.4.0 expo-linear-gradient: ~12.3.0 expo-optimize: ^0.2.20