Add display option to hide emojis in usernames

This commit is contained in:
hzrd149 2024-04-25 10:15:23 -05:00
parent 779d7de2d1
commit 686285450c
22 changed files with 88 additions and 63 deletions

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add display option to hide emojis in usernames

View File

@ -52,6 +52,7 @@
"dayjs": "^1.11.9",
"debug": "^4.3.4",
"easymde": "^2.18.0",
"emoji-regex": "^10.3.0",
"emojilib": "^3",
"framer-motion": "^10.16.0",
"hls.js": "^1.4.14",

View File

@ -26,7 +26,7 @@ import useSingleEvent from "../../hooks/use-single-event";
import useReplaceableEvent from "../../hooks/use-replaceable-event";
import { useReadRelays } from "../../hooks/use-client-relays";
import useSubject from "../../hooks/use-subject";
import { Kind0ParsedContent, getUserDisplayName, parseMetadataContent } from "../../helpers/nostr/user-metadata";
import { Kind0ParsedContent, getDisplayName, parseMetadataContent } from "../../helpers/nostr/user-metadata";
import { MetadataAvatar } from "../user/user-avatar";
import HoverLinkOverlay from "../hover-link-overlay";
import ArrowRight from "../icons/arrow-right";
@ -79,7 +79,7 @@ function AppHandler({ app, decoded }: { app: NostrEvent; decoded: nip19.DecodeRe
<MetadataAvatar metadata={metadata} />
<Box overflow="hidden">
<HoverLinkOverlay fontWeight="bold" href={link} isExternal>
{getUserDisplayName(metadata, app.pubkey)}
{getDisplayName(metadata, app.pubkey)}
</HoverLinkOverlay>
<Text noOfLines={3}>{metadata.about}</Text>
</Box>
@ -112,7 +112,7 @@ export default function AppHandlerModal({
if (search.length > 1) {
try {
const parsed = JSON.parse(app.content) as Kind0ParsedContent;
if (getUserDisplayName(parsed, app.pubkey).toLowerCase().includes(search.toLowerCase())) {
if (getDisplayName(parsed, app.pubkey).toLowerCase().includes(search.toLowerCase())) {
return true;
}
} catch (error) {}

View File

@ -16,14 +16,14 @@ import { Link as RouterLink } from "react-router-dom";
import { nip19 } from "nostr-tools";
import UserAvatar from "./user/user-avatar";
import { getUserDisplayName } from "../helpers/nostr/user-metadata";
import { getDisplayName } from "../helpers/nostr/user-metadata";
import useUserMetadata from "../hooks/use-user-metadata";
function UserTag({ pubkey, ...props }: { pubkey: string } & Omit<TagProps, "children">) {
const metadata = useUserMetadata(pubkey);
const npub = nip19.npubEncode(pubkey);
const displayName = getUserDisplayName(metadata, pubkey);
const displayName = getDisplayName(metadata, pubkey);
return (
<Tag as={RouterLink} to={`/u/${npub}`} {...props}>

View File

@ -2,7 +2,7 @@ import { CloseIcon } from "@chakra-ui/icons";
import { useNavigate } from "react-router-dom";
import { Box, Button, Flex, IconButton, Text, useDisclosure } from "@chakra-ui/react";
import { getUserDisplayName } from "../../helpers/nostr/user-metadata";
import { getDisplayName } from "../../helpers/nostr/user-metadata";
import useSubject from "../../hooks/use-subject";
import useUserMetadata from "../../hooks/use-user-metadata";
import accountService, { Account } from "../../services/account";
@ -25,7 +25,7 @@ function AccountItem({ account, onClick }: { account: Account; onClick?: () => v
<Flex as="button" onClick={handleClick} flex={1} gap="2" overflow="hidden" alignItems="center">
<UserAvatar pubkey={pubkey} size="md" />
<Flex direction="column" overflow="hidden" alignItems="flex-start">
<Text isTruncated>{getUserDisplayName(metadata, pubkey)}</Text>
<Text isTruncated>{getDisplayName(metadata, pubkey)}</Text>
<AccountInfoBadge fontSize="0.7em" account={account} />
</Flex>
</Flex>
@ -67,7 +67,7 @@ export default function AccountSwitcher() {
>
<UserAvatar pubkey={account.pubkey} noProxy size="md" />
<Text whiteSpace="nowrap" fontWeight="bold" fontSize="lg" isTruncated>
{getUserDisplayName(metadata, account.pubkey)}
{getDisplayName(metadata, account.pubkey)}
</Text>
<Flex ml="auto" alignItems="center" justifyContent="center" aspectRatio={1} h="3rem">
{isOpen ? <ChevronUpIcon fontSize="1.5rem" /> : <ChevronDownIcon fontSize="1.5rem" />}

View File

@ -5,10 +5,12 @@ import { nip19 } from "nostr-tools";
import { useUserSearchDirectoryContext } from "../providers/global/user-directory-provider";
import userMetadataService from "../services/user-metadata";
import { getUserDisplayName } from "../helpers/nostr/user-metadata";
import { getDisplayName } from "../helpers/nostr/user-metadata";
import useAppSettings from "../hooks/use-app-settings";
const NpubAutocomplete = forwardRef<HTMLInputElement, InputProps>(({ value, ...props }, ref) => {
const getDirectory = useUserSearchDirectoryContext();
const { removeEmojisInUsernames } = useAppSettings();
const { value: users } = useAsync(async () => {
const dir = await getDirectory();
@ -24,7 +26,7 @@ const NpubAutocomplete = forwardRef<HTMLInputElement, InputProps>(({ value, ...p
.filter((p) => !!p.metadata)
.map(({ metadata, pubkey }) => (
<option key={pubkey} value={nip19.npubEncode(pubkey)}>
{getUserDisplayName(metadata, pubkey)}
{getDisplayName(metadata, pubkey, removeEmojisInUsernames)}
</option>
))}
</datalist>

View File

@ -8,7 +8,7 @@ import { nip19 } from "nostr-tools";
import { useUserSearchDirectoryContext } from "../../providers/global/user-directory-provider";
import UserAvatar from "../user/user-avatar";
import useUserMetadata from "../../hooks/use-user-metadata";
import { getUserDisplayName } from "../../helpers/nostr/user-metadata";
import { getDisplayName } from "../../helpers/nostr/user-metadata";
function UserOption({ pubkey }: { pubkey: string }) {
const metadata = useUserMetadata(pubkey);
@ -16,7 +16,7 @@ function UserOption({ pubkey }: { pubkey: string }) {
return (
<Flex as={RouterLink} to={`/u/${nip19.npubEncode(pubkey)}`} p="2" gap="2" alignItems="center">
<UserAvatar pubkey={pubkey} size="sm" />
<Text fontWeight="bold">{getUserDisplayName(metadata, pubkey)}</Text>
<Text fontWeight="bold">{getDisplayName(metadata, pubkey)}</Text>
</Flex>
);
}

View File

@ -5,7 +5,7 @@ import { useAsync } from "react-use";
import useUserMetadata from "../../hooks/use-user-metadata";
import { getIdenticon } from "../../helpers/identicon";
import { safeUrl } from "../../helpers/parse";
import { Kind0ParsedContent, getUserDisplayName } from "../../helpers/nostr/user-metadata";
import { Kind0ParsedContent, getDisplayName } from "../../helpers/nostr/user-metadata";
import useAppSettings from "../../hooks/use-app-settings";
import useCurrentAccount from "../../hooks/use-current-account";
import { buildImageProxyURL } from "../../helpers/image";
@ -103,7 +103,7 @@ export const MetadataAvatar = forwardRef<HTMLDivElement, MetadataAvatarProps>(
src={picture}
icon={pubkey ? <UserIdenticon pubkey={pubkey} /> : undefined}
// overflow="hidden"
title={getUserDisplayName(metadata, pubkey ?? "")}
title={getDisplayName(metadata, pubkey ?? "")}
ref={ref}
{...props}
>

View File

@ -2,7 +2,7 @@ import { Link, LinkProps } from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom";
import { nip19 } from "nostr-tools";
import { getUserDisplayName } from "../../helpers/nostr/user-metadata";
import { getDisplayName } from "../../helpers/nostr/user-metadata";
import useUserMetadata from "../../hooks/use-user-metadata";
import useAppSettings from "../../hooks/use-app-settings";
import useCurrentAccount from "../../hooks/use-current-account";
@ -16,12 +16,12 @@ export type UserLinkProps = LinkProps & {
export default function UserLink({ pubkey, showAt, tab, ...props }: UserLinkProps) {
const metadata = useUserMetadata(pubkey);
const account = useCurrentAccount();
const { hideUsernames } = useAppSettings();
const { hideUsernames, removeEmojisInUsernames } = useAppSettings();
return (
<Link as={RouterLink} to={`/u/${nip19.npubEncode(pubkey)}` + (tab ? "/" + tab : "")} whiteSpace="nowrap" {...props}>
{showAt && "@"}
{hideUsernames && pubkey !== account?.pubkey ? "Anon" : getUserDisplayName(metadata, pubkey)}
{hideUsernames && pubkey !== account?.pubkey ? "Anon" : getDisplayName(metadata, pubkey, removeEmojisInUsernames)}
</Link>
);
}

View File

@ -1,16 +1,19 @@
import { memo } from "react";
import { Text, TextProps } from "@chakra-ui/react";
import { getUserDisplayName } from "../../helpers/nostr/user-metadata";
import { getDisplayName } from "../../helpers/nostr/user-metadata";
import useUserMetadata from "../../hooks/use-user-metadata";
import useAppSettings from "../../hooks/use-app-settings";
export default function UserName({ pubkey, ...props }: Omit<TextProps, "children"> & { pubkey: string }) {
function UserName({ pubkey, ...props }: Omit<TextProps, "children"> & { pubkey: string }) {
const metadata = useUserMetadata(pubkey);
const { hideUsernames } = useAppSettings();
const { hideUsernames, removeEmojisInUsernames } = useAppSettings();
return (
<Text as="span" whiteSpace="nowrap" fontWeight="bold" {...props}>
{hideUsernames ? "Anon" : getUserDisplayName(metadata, pubkey)}
{hideUsernames ? "Anon" : getDisplayName(metadata, pubkey, removeEmojisInUsernames)}
</Text>
);
}
export default memo(UserName);

View File

@ -1,4 +1,5 @@
import { NostrEvent, nip19 } from "nostr-tools";
import emojiRegex from "emoji-regex";
import { truncatedId } from "./event";
export type Kind0ParsedContent = {
@ -39,8 +40,16 @@ export function getSearchNames(metadata: Kind0ParsedContent) {
return [metadata.displayName, metadata.display_name, metadata.name].filter(Boolean) as string[];
}
export function getUserDisplayName(metadata: Kind0ParsedContent | undefined, pubkey: string) {
return metadata?.displayName || metadata?.display_name || metadata?.name || truncatedId(nip19.npubEncode(pubkey));
const matchEmoji = emojiRegex();
export function getDisplayName(metadata: Kind0ParsedContent | undefined, pubkey: string, removeEmojis = false) {
let displayName = metadata?.displayName || metadata?.display_name || metadata?.name;
if (displayName) {
if (removeEmojis) displayName = displayName.replaceAll(matchEmoji, "");
return displayName;
}
return truncatedId(nip19.npubEncode(pubkey));
}
export function fixWebsiteUrl(website: string) {

View File

@ -20,7 +20,7 @@ import { PropsWithChildren, createContext, useCallback, useContext, useEffect, u
import dayjs from "dayjs";
import { useInterval } from "react-use";
import { getUserDisplayName } from "../../helpers/nostr/user-metadata";
import { getDisplayName } from "../../helpers/nostr/user-metadata";
import useUserMetadata from "../../hooks/use-user-metadata";
import useCurrentAccount from "../../hooks/use-current-account";
import {
@ -70,7 +70,7 @@ function MuteModal({ pubkey, onClose, ...props }: Omit<ModalProps, "children"> &
<Modal onClose={onClose} size="lg" {...props}>
<ModalOverlay />
<ModalContent>
<ModalHeader p="4">Mute {getUserDisplayName(metadata, pubkey)} for:</ModalHeader>
<ModalHeader p="4">Mute {getDisplayName(metadata, pubkey)} for:</ModalHeader>
<ModalCloseButton />
<ModalBody px="4" py="0">
<SimpleGrid columns={3} spacing="2">

View File

@ -36,20 +36,22 @@ export type AppSettingsV5 = Omit<AppSettingsV4, "version"> & { version: 5; hideU
export type AppSettingsV6 = Omit<AppSettingsV5, "version"> & { version: 6; noteDifficulty: number | null };
export type AppSettingsV7 = Omit<AppSettingsV6, "version"> & { version: 7; autoDecryptDMs: boolean };
export type AppSettingsV8 = Omit<AppSettingsV7, "version"> & {
version: 7;
version: 8;
mediaUploadService: "nostr.build" | "blossom";
};
export type AppSettingsV9 = Omit<AppSettingsV8, "version"> & { version: 9; removeEmojisInUsernames: boolean };
export type AppSettings = AppSettingsV8;
export type AppSettings = AppSettingsV9;
export const defaultSettings: AppSettings = {
version: 7,
version: 9,
theme: "default",
colorMode: "system",
defaultRelays: ["wss://relay.damus.io", "wss://nostr.wine", "wss://nos.lol", "wss://welcome.nostr.wine"],
maxPageWidth: "none",
blurImages: true,
hideUsernames: false,
removeEmojisInUsernames: false,
autoShowMedia: true,
proxyUserMedia: false,
loadOpenGraphData: true,
@ -76,7 +78,7 @@ export const defaultSettings: AppSettings = {
};
export function upgradeSettings(settings: { version: number }): AppSettings | null {
return { ...defaultSettings, ...settings, version: 7 };
return { ...defaultSettings, ...settings, version: 9 };
}
export function parseAppSettings(event: NostrEvent): AppSettings {

View File

@ -3,7 +3,7 @@ import { Link as RouterLink } from "react-router-dom";
import { nip19 } from "nostr-tools";
import useUserMetadata from "../../../hooks/use-user-metadata";
import { getUserDisplayName } from "../../../helpers/nostr/user-metadata";
import { getDisplayName } from "../../../helpers/nostr/user-metadata";
import { AddressPointer } from "nostr-tools/lib/types/nip19";
import useDVMMetadata from "../../../hooks/use-dvm-metadata";
@ -19,7 +19,7 @@ export function DVMName({
return (
<Text as={as} {...props}>
{dvmMetadata?.name || getUserDisplayName(metadata, pointer.pubkey)}
{dvmMetadata?.name || getDisplayName(metadata, pointer.pubkey)}
</Text>
);
}

View File

@ -3,7 +3,6 @@ import { Link as RouterLink } from "react-router-dom";
import { nip19 } from "nostr-tools";
import useUserMetadata from "../../../hooks/use-user-metadata";
import { getUserDisplayName } from "../../../helpers/nostr/user-metadata";
import UserAvatar from "../../../components/user/user-avatar";
import UserDnsIdentity from "../../../components/user/user-dns-identity";
import { NostrEvent } from "../../../types/nostr-event";
@ -12,6 +11,7 @@ import { listRemovePerson } from "../../../helpers/nostr/lists";
import useCurrentAccount from "../../../hooks/use-current-account";
import { UserFollowButton } from "../../../components/user/user-follow-button";
import { usePublishEvent } from "../../../providers/global/publish-provider";
import UserName from "../../../components/user/user-name";
export type UserCardProps = { pubkey: string; relay?: string; list: NostrEvent } & Omit<CardProps, "children">;
@ -26,13 +26,13 @@ export default function UserCard({ pubkey, relay, list, ...props }: UserCardProp
}, [list, publish]);
return (
<Card>
<Card {...props}>
<CardBody p="2" display="flex" alignItems="center" overflow="hidden" gap="2">
<UserAvatar pubkey={pubkey} />
<Flex direction="column" flex={1} overflow="hidden">
<Link as={RouterLink} to={`/u/${nip19.npubEncode(pubkey)}`}>
<Heading size="sm" whiteSpace="nowrap" isTruncated>
{getUserDisplayName(metadata, pubkey)}
<UserName as="span" pubkey={pubkey} />
</Heading>
</Link>
<UserDnsIdentity pubkey={pubkey} />

View File

@ -91,7 +91,7 @@ export default function DisplaySettings() {
<FormControl>
<Flex alignItems="center">
<FormLabel htmlFor="hideUsernames" mb="0">
Hide Usernames (anon mode)
Hide usernames (anon mode)
</FormLabel>
<Switch id="hideUsernames" {...register("hideUsernames")} />
</Flex>
@ -108,6 +108,17 @@ export default function DisplaySettings() {
</span>
</FormHelperText>
</FormControl>
<FormControl>
<Flex alignItems="center">
<FormLabel htmlFor="removeEmojisInUsernames" mb="0">
Hide Emojis in usernames
</FormLabel>
<Switch id="removeEmojisInUsernames" {...register("removeEmojisInUsernames")} />
</Flex>
<FormHelperText>
<span>Enabled: Removes all emojis in other users usernames and display names</span>
</FormHelperText>
</FormControl>
<FormControl>
<Flex alignItems="center">
<FormLabel htmlFor="show-content-warning" mb="0">

View File

@ -1,6 +1,7 @@
import { CloseIcon } from "@chakra-ui/icons";
import { Box, IconButton, Text } from "@chakra-ui/react";
import { getUserDisplayName } from "../../../helpers/nostr/user-metadata";
import { getDisplayName } from "../../../helpers/nostr/user-metadata";
import useUserMetadata from "../../../hooks/use-user-metadata";
import accountService, { Account } from "../../../services/account";
import UserAvatar from "../../../components/user/user-avatar";
@ -26,7 +27,7 @@ export default function AccountCard({ account }: { account: Account }) {
<UserAvatar pubkey={pubkey} size="md" noProxy />
<Box flex={1}>
<Text isTruncated fontWeight="bold">
{getUserDisplayName(metadata, pubkey)}
{getDisplayName(metadata, pubkey)}
</Text>
<AccountInfoBadge account={account} />
</Box>

View File

@ -19,7 +19,6 @@ import {
} from "@chakra-ui/react";
import { nip19 } from "nostr-tools";
import { getUserDisplayName } from "../../../helpers/nostr/user-metadata";
import { getLudEndpoint } from "../../../helpers/lnurl";
import { EmbedableContent, embedUrls } from "../../../helpers/embeds";
import { truncatedId } from "../../../helpers/nostr/event";
@ -39,7 +38,7 @@ import { CopyIconButton } from "../../../components/copy-icon-button";
import { QrIconButton } from "../components/share-qr-button";
import UserDnsIdentity from "../../../components/user/user-dns-identity";
import UserAvatar from "../../../components/user/user-avatar";
import { ChatIcon, QuestionIcon } from "@chakra-ui/icons";
import { ChatIcon } from "@chakra-ui/icons";
import { UserFollowButton } from "../../../components/user/user-follow-button";
import UserZapButton from "../components/user-zap-button";
import { UserProfileMenu } from "../components/user-profile-menu";
@ -50,6 +49,7 @@ import UserPinnedEvents from "./user-pinned-events";
import UserStatsAccordion from "./user-stats-accordion";
import UserJoinedChanneled from "./user-joined-channels";
import { getTextColor } from "../../../helpers/color";
import UserName from "../../../components/user/user-name";
function buildDescriptionContent(description: string) {
let content: EmbedableContent = [description.trim()];
@ -109,7 +109,9 @@ export default function UserAboutTab() {
>
<UserAvatar pubkey={pubkey} size={["lg", "lg", "xl"]} noProxy />
<Box overflow="hidden">
<Heading isTruncated>{getUserDisplayName(metadata, pubkey)}</Heading>
<Heading isTruncated>
<UserName pubkey={pubkey} />
</Heading>
<UserDnsIdentity pubkey={pubkey} />
</Box>

View File

@ -4,13 +4,13 @@ import { useNavigate } from "react-router-dom";
import { EditIcon, GhostIcon } from "../../../components/icons";
import UserAvatar from "../../../components/user/user-avatar";
import UserDnsIdentity from "../../../components/user/user-dns-identity";
import { getUserDisplayName } from "../../../helpers/nostr/user-metadata";
import useCurrentAccount from "../../../hooks/use-current-account";
import useUserMetadata from "../../../hooks/use-user-metadata";
import { UserProfileMenu } from "./user-profile-menu";
import { UserFollowButton } from "../../../components/user/user-follow-button";
import accountService from "../../../services/account";
import { useBreakpointValue } from "../../../providers/global/breakpoint-provider";
import UserName from "../../../components/user/user-name";
export default function Header({
pubkey,
@ -34,7 +34,7 @@ export default function Header({
<Flex gap="2" alignItems="center">
<UserAvatar pubkey={pubkey} size="sm" noProxy mr="2" />
<Heading size="md" isTruncated>
{getUserDisplayName(metadata, pubkey)}
<UserName pubkey={pubkey} />
</Heading>
<UserDnsIdentity pubkey={pubkey} onlyIcon={showFullNip05} />
<Spacer />

View File

@ -1,4 +1,4 @@
import { MenuItem, useConst, useDisclosure, useToast } from "@chakra-ui/react";
import { MenuItem, useDisclosure, useToast } from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom";
import { nip19 } from "nostr-tools";
@ -16,10 +16,8 @@ import {
} from "../../../components/icons";
import accountService from "../../../services/account";
import useUserMetadata from "../../../hooks/use-user-metadata";
import { getUserDisplayName } from "../../../helpers/nostr/user-metadata";
import UserDebugModal from "../../../components/debug-modal/user-debug-modal";
import { useSharableProfileId } from "../../../hooks/use-shareable-profile-id";
import { truncatedId } from "../../../helpers/nostr/event";
import useUserMuteActions from "../../../hooks/use-user-mute-actions";
import useCurrentAccount from "../../../hooks/use-current-account";
import userMailboxesService from "../../../services/user-mailboxes";
@ -67,7 +65,7 @@ export const UserProfileMenu = ({
Direct messages
</MenuItem>
<MenuItem icon={<SpyIcon fontSize="1.5em" />} onClick={() => loginAsUser()}>
Login as {truncatedId(getUserDisplayName(metadata, pubkey))}
Login as user
</MenuItem>
<MenuItem
onClick={() => {

View File

@ -29,7 +29,7 @@ import { kinds } from "nostr-tools";
import { Outlet, useMatches, useNavigate } from "react-router-dom";
import useUserMetadata from "../../hooks/use-user-metadata";
import { getUserDisplayName } from "../../helpers/nostr/user-metadata";
import { getDisplayName } from "../../helpers/nostr/user-metadata";
import { useAppTitle } from "../../hooks/use-app-title";
import { useReadRelays } from "../../hooks/use-client-relays";
import relayScoreboardService from "../../services/relay-scoreboard";
@ -82,7 +82,7 @@ const UserView = () => {
const readRelays = unique([...userTopRelays, ...pointerRelays]);
const metadata = useUserMetadata(pubkey, userTopRelays, { alwaysRequest: true });
useAppTitle(getUserDisplayName(metadata, pubkey));
useAppTitle(getDisplayName(metadata, pubkey));
const hasTorrents = useEventExists({ kinds: [TORRENT_KIND], authors: [pubkey] }, readRelays);
const hasGoals = useEventExists({ kinds: [GOAL_KIND], authors: [pubkey] }, readRelays);

View File

@ -3046,13 +3046,6 @@
dependencies:
"@types/react" "*"
"@types/react-portal@^4.0.7":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@types/react-portal/-/react-portal-4.0.7.tgz#c7436c5039e74ec80d488fbe5c98dbcc6469bf44"
integrity sha512-3zQJL6Pqcq7d73+cakVkZDqAYGFBo37XXPfahjhdScr9EdYPlf9evYilL38Fpzs1YGWz7F2SkPtN6+ygTO7ymg==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^16.9.35", "@types/react@^18.2.22", "@types/react@^18.2.45":
version "18.2.55"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.55.tgz#38141821b7084404b5013742bc4ae08e44da7a67"
@ -4250,6 +4243,11 @@ electron-to-chromium@^1.4.648:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.657.tgz#8a07ee3faa552976970843a80a1c94088ea59c9a"
integrity sha512-On2ymeleg6QbRuDk7wNgDdXtNqlJLM2w4Agx1D/RiTmItiL+a9oq5p7HUa2ZtkAtGBe/kil2dq/7rPfkbe0r5w==
emoji-regex@^10.3.0:
version "10.3.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23"
integrity sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
@ -6434,7 +6432,7 @@ pretty-bytes@^6.1.1:
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-6.1.1.tgz#38cd6bb46f47afbf667c202cfc754bffd2016a3b"
integrity sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==
prop-types@15, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.8.1:
prop-types@15, prop-types@^15.6.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@ -6669,13 +6667,6 @@ react-photo-album@^2.3.0:
resolved "https://registry.yarnpkg.com/react-photo-album/-/react-photo-album-2.3.1.tgz#f597f1d16d13f386b25c135d1f9b9d1895d2c94c"
integrity sha512-c7ofDx2DAbQa9AW9wUWOBX9zUKf/QjvdQK+fPNKEiKprks/n8t4c2viyBZ6EWpQLFLU0ad3yVBTgFvxEZ46/Iw==
react-portal@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-4.2.2.tgz#bff1e024147d6041ba8c530ffc99d4c8248f49fa"
integrity sha512-vS18idTmevQxyQpnde0Td6ZcUlv+pD8GTyR42n3CHUQq9OHi1C4jDE4ZWEbEsrbrLRhSECYiao58cvocwMtP7Q==
dependencies:
prop-types "^15.5.8"
react-qr-barcode-scanner@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/react-qr-barcode-scanner/-/react-qr-barcode-scanner-1.0.6.tgz#1df7ac3f3cb839ad673e8b619e0e93b4bdddc4e3"