address review comments
This commit is contained in:
parent
8ca9a2157c
commit
710bb10083
@ -1,5 +1,6 @@
|
|||||||
import { ReactNode } from "react";
|
import { useState, ReactNode } from "react";
|
||||||
|
|
||||||
|
import ChevronDown from "Icons/ChevronDown";
|
||||||
import ShowMore from "Element/ShowMore";
|
import ShowMore from "Element/ShowMore";
|
||||||
|
|
||||||
interface CollapsedProps {
|
interface CollapsedProps {
|
||||||
@ -36,4 +37,26 @@ export const CollapsedIcon = ({ icon, children, collapsed }: CollapsedIconProps)
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface CollapsedSectionProps {
|
||||||
|
title: ReactNode;
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CollapsedSection = ({ title, children }: CollapsedSectionProps) => {
|
||||||
|
const [collapsed, setCollapsed] = useState(true);
|
||||||
|
const icon = (
|
||||||
|
<div className={`collapse-icon ${collapsed ? "" : "flip"}`} onClick={() => setCollapsed(!collapsed)}>
|
||||||
|
<ChevronDown />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div className="collapsable-section">
|
||||||
|
<h3 onClick={() => setCollapsed(!collapsed)}>{title}</h3>
|
||||||
|
<CollapsedIcon icon={icon} collapsed={collapsed}>
|
||||||
|
{children}
|
||||||
|
</CollapsedIcon>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default Collapsed;
|
export default Collapsed;
|
||||||
|
@ -5,10 +5,6 @@
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nip05.failed {
|
|
||||||
text-decoration: line-through;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nip05 .domain {
|
.nip05 .domain {
|
||||||
color: var(--font-secondary-color);
|
color: var(--font-secondary-color);
|
||||||
background-color: var(--font-secondary-color);
|
background-color: var(--font-secondary-color);
|
||||||
|
@ -29,14 +29,18 @@ async function fetchNip05Pubkey(name: string, domain: string) {
|
|||||||
const VERIFICATION_CACHE_TIME = 24 * 60 * 60 * 1000;
|
const VERIFICATION_CACHE_TIME = 24 * 60 * 60 * 1000;
|
||||||
const VERIFICATION_STALE_TIMEOUT = 10 * 60 * 1000;
|
const VERIFICATION_STALE_TIMEOUT = 10 * 60 * 1000;
|
||||||
|
|
||||||
export function useIsVerified(pubkey: HexKey, nip05?: string) {
|
export function useIsVerified(pubkey: HexKey, nip05?: string, bypassCheck?: boolean) {
|
||||||
const [name, domain] = nip05 ? nip05.split("@") : [];
|
const [name, domain] = nip05 ? nip05.split("@") : [];
|
||||||
const { isError, isSuccess, data } = useQuery(["nip05", nip05], () => fetchNip05Pubkey(name, domain), {
|
const { isError, isSuccess, data } = useQuery(
|
||||||
retry: false,
|
["nip05", nip05],
|
||||||
retryOnMount: false,
|
() => (bypassCheck ? Promise.resolve(pubkey) : fetchNip05Pubkey(name, domain)),
|
||||||
cacheTime: VERIFICATION_CACHE_TIME,
|
{
|
||||||
staleTime: VERIFICATION_STALE_TIMEOUT,
|
retry: false,
|
||||||
});
|
retryOnMount: false,
|
||||||
|
cacheTime: VERIFICATION_CACHE_TIME,
|
||||||
|
staleTime: VERIFICATION_STALE_TIMEOUT,
|
||||||
|
}
|
||||||
|
);
|
||||||
const isVerified = isSuccess && data === pubkey;
|
const isVerified = isSuccess && data === pubkey;
|
||||||
const cantVerify = isSuccess && data !== pubkey;
|
const cantVerify = isSuccess && data !== pubkey;
|
||||||
return { isVerified, couldNotVerify: isError || cantVerify };
|
return { isVerified, couldNotVerify: isError || cantVerify };
|
||||||
@ -45,12 +49,13 @@ export function useIsVerified(pubkey: HexKey, nip05?: string) {
|
|||||||
export interface Nip05Params {
|
export interface Nip05Params {
|
||||||
nip05?: string;
|
nip05?: string;
|
||||||
pubkey: HexKey;
|
pubkey: HexKey;
|
||||||
|
verifyNip?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Nip05 = (props: Nip05Params) => {
|
const Nip05 = ({ nip05, pubkey, verifyNip = true }: Nip05Params) => {
|
||||||
const [name, domain] = props.nip05 ? props.nip05.split("@") : [];
|
const [name, domain] = nip05 ? nip05.split("@") : [];
|
||||||
const isDefaultUser = name === "_";
|
const isDefaultUser = name === "_";
|
||||||
const { isVerified, couldNotVerify } = useIsVerified(props.pubkey, props.nip05);
|
const { isVerified, couldNotVerify } = useIsVerified(pubkey, nip05, !verifyNip);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`flex nip05${couldNotVerify ? " failed" : ""}`} onClick={ev => ev.stopPropagation()}>
|
<div className={`flex nip05${couldNotVerify ? " failed" : ""}`} onClick={ev => ev.stopPropagation()}>
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState, ChangeEvent } from "react";
|
||||||
import { useIntl, FormattedMessage } from "react-intl";
|
import { useIntl, FormattedMessage } from "react-intl";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { unwrap } from "Util";
|
||||||
|
import { formatShort } from "Number";
|
||||||
import {
|
import {
|
||||||
ServiceProvider,
|
ServiceProvider,
|
||||||
ServiceConfig,
|
ServiceConfig,
|
||||||
@ -29,11 +32,14 @@ type Nip05ServiceProps = {
|
|||||||
link: string;
|
link: string;
|
||||||
supportLink: string;
|
supportLink: string;
|
||||||
helpText?: boolean;
|
helpText?: boolean;
|
||||||
|
autoUpdate?: boolean;
|
||||||
|
onChange?(h: string): void;
|
||||||
|
onSuccess?(h: string): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Nip5Service(props: Nip05ServiceProps) {
|
export default function Nip5Service(props: Nip05ServiceProps) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { helpText = true } = props;
|
const { helpText = true, autoUpdate = true } = props;
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const pubkey = useSelector((s: RootState) => s.login.publicKey);
|
const pubkey = useSelector((s: RootState) => s.login.publicKey);
|
||||||
const user = useUserProfile(pubkey);
|
const user = useUserProfile(pubkey);
|
||||||
@ -48,6 +54,22 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
|||||||
const [showInvoice, setShowInvoice] = useState<boolean>(false);
|
const [showInvoice, setShowInvoice] = useState<boolean>(false);
|
||||||
const [registerStatus, setRegisterStatus] = useState<CheckRegisterResponse>();
|
const [registerStatus, setRegisterStatus] = useState<CheckRegisterResponse>();
|
||||||
|
|
||||||
|
const onHandleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const h = e.target.value.toLowerCase();
|
||||||
|
setHandle(h);
|
||||||
|
if (props.onChange) {
|
||||||
|
props.onChange(`${h}@${domain}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDomainChange = (e: ChangeEvent<HTMLSelectElement>) => {
|
||||||
|
const d = e.target.value;
|
||||||
|
setDomain(d);
|
||||||
|
if (props.onChange) {
|
||||||
|
props.onChange(`${handle}@${d}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const domainConfig = useMemo(() => serviceConfig?.domains.find(a => a.name === domain), [domain, serviceConfig]);
|
const domainConfig = useMemo(() => serviceConfig?.domains.find(a => a.name === domain), [domain, serviceConfig]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -113,6 +135,9 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
|||||||
setRegisterStatus(status);
|
setRegisterStatus(status);
|
||||||
setRegisterResponse(undefined);
|
setRegisterResponse(undefined);
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
|
if (autoUpdate) {
|
||||||
|
updateProfile(handle, domain);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 2_000);
|
}, 2_000);
|
||||||
@ -151,12 +176,16 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
|||||||
|
|
||||||
async function updateProfile(handle: string, domain: string) {
|
async function updateProfile(handle: string, domain: string) {
|
||||||
if (user) {
|
if (user) {
|
||||||
|
const nip05 = `${handle}@${domain}`;
|
||||||
const newProfile = {
|
const newProfile = {
|
||||||
...user,
|
...user,
|
||||||
nip05: `${handle}@${domain}`,
|
nip05,
|
||||||
} as UserMetadata;
|
} as UserMetadata;
|
||||||
const ev = await publisher.metadata(newProfile);
|
const ev = await publisher.metadata(newProfile);
|
||||||
publisher.broadcast(ev);
|
publisher.broadcast(ev);
|
||||||
|
if (props.onSuccess) {
|
||||||
|
props.onSuccess(nip05);
|
||||||
|
}
|
||||||
if (helpText) {
|
if (helpText) {
|
||||||
navigate("/settings");
|
navigate("/settings");
|
||||||
}
|
}
|
||||||
@ -185,14 +214,9 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
|||||||
{error && <b className="error">{error.error}</b>}
|
{error && <b className="error">{error.error}</b>}
|
||||||
{!registerStatus && (
|
{!registerStatus && (
|
||||||
<div className="flex mb10">
|
<div className="flex mb10">
|
||||||
<input
|
<input type="text" placeholder={formatMessage(messages.Handle)} value={handle} onChange={onHandleChange} />
|
||||||
type="text"
|
|
||||||
placeholder={formatMessage(messages.Handle)}
|
|
||||||
value={handle}
|
|
||||||
onChange={e => setHandle(e.target.value.toLowerCase())}
|
|
||||||
/>
|
|
||||||
@
|
@
|
||||||
<select value={domain} onChange={e => setDomain(e.target.value)}>
|
<select value={domain} onChange={onDomainChange}>
|
||||||
{serviceConfig?.domains.map(a => (
|
{serviceConfig?.domains.map(a => (
|
||||||
<option key={a.name}>{a.name}</option>
|
<option key={a.name}>{a.name}</option>
|
||||||
))}
|
))}
|
||||||
@ -202,7 +226,10 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
|||||||
{availabilityResponse?.available && !registerStatus && (
|
{availabilityResponse?.available && !registerStatus && (
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="mr10">
|
<div className="mr10">
|
||||||
<FormattedMessage {...messages.Sats} values={{ n: availabilityResponse.quote?.price }} />
|
<FormattedMessage
|
||||||
|
{...messages.Sats}
|
||||||
|
values={{ n: formatShort(unwrap(availabilityResponse.quote?.price)) }}
|
||||||
|
/>
|
||||||
<br />
|
<br />
|
||||||
<small>{availabilityResponse.quote?.data.type}</small>
|
<small>{availabilityResponse.quote?.data.type}</small>
|
||||||
</div>
|
</div>
|
||||||
@ -256,12 +283,16 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
|||||||
<FormattedMessage {...messages.AccountPage} />
|
<FormattedMessage {...messages.AccountPage} />
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<h4>
|
{!autoUpdate && (
|
||||||
<FormattedMessage {...messages.ActivateNow} />
|
<>
|
||||||
</h4>
|
<h4>
|
||||||
<AsyncButton onClick={() => updateProfile(handle, domain)}>
|
<FormattedMessage {...messages.ActivateNow} />
|
||||||
<FormattedMessage {...messages.AddToProfile} />
|
</h4>
|
||||||
</AsyncButton>
|
<AsyncButton onClick={() => updateProfile(handle, domain)}>
|
||||||
|
<FormattedMessage {...messages.AddToProfile} />
|
||||||
|
</AsyncButton>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -15,12 +15,22 @@ export interface ProfileImageProps {
|
|||||||
showUsername?: boolean;
|
showUsername?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
link?: string;
|
link?: string;
|
||||||
|
defaultNip?: string;
|
||||||
|
verifyNip?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProfileImage({ pubkey, subHeader, showUsername = true, className, link }: ProfileImageProps) {
|
export default function ProfileImage({
|
||||||
|
pubkey,
|
||||||
|
subHeader,
|
||||||
|
showUsername = true,
|
||||||
|
className,
|
||||||
|
link,
|
||||||
|
defaultNip,
|
||||||
|
verifyNip,
|
||||||
|
}: ProfileImageProps) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const user = useUserProfile(pubkey);
|
const user = useUserProfile(pubkey);
|
||||||
const nip05 = user?.nip05;
|
const nip05 = defaultNip || user?.nip05;
|
||||||
|
|
||||||
const name = useMemo(() => {
|
const name = useMemo(() => {
|
||||||
return getDisplayName(user, pubkey);
|
return getDisplayName(user, pubkey);
|
||||||
@ -36,7 +46,7 @@ export default function ProfileImage({ pubkey, subHeader, showUsername = true, c
|
|||||||
<div className="username">
|
<div className="username">
|
||||||
<Link className="display-name" key={pubkey} to={link ?? profileLink(pubkey)}>
|
<Link className="display-name" key={pubkey} to={link ?? profileLink(pubkey)}>
|
||||||
{name}
|
{name}
|
||||||
{nip05 && <Nip05 nip05={nip05} pubkey={pubkey} />}
|
{nip05 && <Nip05 nip05={nip05} pubkey={pubkey} verifyNip={verifyNip} />}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="subheader">{subHeader}</div>
|
<div className="subheader">{subHeader}</div>
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
|
import { useState } from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
import { services } from "Pages/Verification";
|
import { services } from "Pages/Verification";
|
||||||
import Nip5Service from "Element/Nip5Service";
|
import Nip5Service from "Element/Nip5Service";
|
||||||
import ProfileImage from "Element/ProfileImage";
|
import ProfileImage from "Element/ProfileImage";
|
||||||
|
import type { RootState } from "State/Store";
|
||||||
|
import { useUserProfile } from "Feed/ProfileFeed";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
|
|
||||||
export default function GetVerified() {
|
export default function GetVerified() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { publicKey } = useSelector((s: RootState) => s.login);
|
||||||
|
const user = useUserProfile(publicKey);
|
||||||
|
const [isVerified, setIsVerified] = useState(true);
|
||||||
|
const [nip05, setNip05] = useState(`${user?.name || "nostrich"}@snort.social`);
|
||||||
|
|
||||||
const onNext = async () => {
|
const onNext = async () => {
|
||||||
navigate("/new/import");
|
navigate("/new/import");
|
||||||
@ -26,7 +34,7 @@ export default function GetVerified() {
|
|||||||
<FormattedMessage {...messages.PreviewOnSnort} />
|
<FormattedMessage {...messages.PreviewOnSnort} />
|
||||||
</h4>
|
</h4>
|
||||||
<div className="profile-preview-nip">
|
<div className="profile-preview-nip">
|
||||||
<ProfileImage pubkey="63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed" />
|
{user?.pubkey && <ProfileImage pubkey={user?.pubkey} defaultNip={nip05} verifyNip={false} />}
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
<FormattedMessage {...messages.IdentifierHelp} />
|
<FormattedMessage {...messages.IdentifierHelp} />
|
||||||
@ -45,28 +53,55 @@ export default function GetVerified() {
|
|||||||
<p className="warning">
|
<p className="warning">
|
||||||
<FormattedMessage {...messages.NameSquatting} />
|
<FormattedMessage {...messages.NameSquatting} />
|
||||||
</p>
|
</p>
|
||||||
<h2>
|
{!isVerified && (
|
||||||
<FormattedMessage {...messages.GetSnortId} />
|
<>
|
||||||
</h2>
|
<h2>
|
||||||
<p>
|
<FormattedMessage {...messages.GetSnortId} />
|
||||||
<FormattedMessage {...messages.GetSnortIdHelp} />
|
</h2>
|
||||||
</p>
|
<p>
|
||||||
<div className="nip-container">
|
<FormattedMessage {...messages.GetSnortIdHelp} />
|
||||||
<Nip5Service key="snort" {...services[0]} helpText={false} />
|
</p>
|
||||||
</div>
|
<div className="nip-container">
|
||||||
<h2>
|
<Nip5Service
|
||||||
<FormattedMessage {...messages.GetPartnerId} />
|
key="snort"
|
||||||
</h2>
|
{...services[0]}
|
||||||
<p>
|
helpText={false}
|
||||||
<FormattedMessage {...messages.GetPartnerIdHelp} />
|
onChange={setNip05}
|
||||||
</p>
|
onSuccess={() => setIsVerified(true)}
|
||||||
<div className="nip-container">
|
/>
|
||||||
<Nip5Service key="nostrplebs" {...services[1]} helpText={false} />
|
</div>
|
||||||
</div>
|
</>
|
||||||
|
)}
|
||||||
|
{!isVerified && (
|
||||||
|
<>
|
||||||
|
<h2>
|
||||||
|
<FormattedMessage {...messages.GetPartnerId} />
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
<FormattedMessage {...messages.GetPartnerIdHelp} />
|
||||||
|
</p>
|
||||||
|
<div className="nip-container">
|
||||||
|
<Nip5Service
|
||||||
|
key="nostrplebs"
|
||||||
|
{...services[1]}
|
||||||
|
helpText={false}
|
||||||
|
onChange={setNip05}
|
||||||
|
onSuccess={() => setIsVerified(true)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<div className="next-actions">
|
<div className="next-actions">
|
||||||
<button type="button" className="transparent" onClick={onNext}>
|
{!isVerified && (
|
||||||
<FormattedMessage {...messages.Skip} />
|
<button type="button" className="transparent" onClick={onNext}>
|
||||||
</button>
|
<FormattedMessage {...messages.Skip} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{isVerified && (
|
||||||
|
<button type="button" onClick={onNext}>
|
||||||
|
<FormattedMessage {...messages.Next} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,38 +1,14 @@
|
|||||||
import { useState, ReactNode } from "react";
|
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import ChevronDown from "Icons/ChevronDown";
|
import { CollapsedSection } from "Element/Collapsed";
|
||||||
import { CollapsedIcon } from "Element/Collapsed";
|
|
||||||
import Copy from "Element/Copy";
|
import Copy from "Element/Copy";
|
||||||
import { RootState } from "State/Store";
|
import { RootState } from "State/Store";
|
||||||
import { hexToBech32 } from "Util";
|
import { hexToBech32 } from "Util";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
|
|
||||||
interface CollapsedSectionProps {
|
|
||||||
title: ReactNode;
|
|
||||||
children: ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CollapsedSection = ({ title, children }: CollapsedSectionProps) => {
|
|
||||||
const [collapsed, setCollapsed] = useState(true);
|
|
||||||
const icon = (
|
|
||||||
<div className={`collapse-icon ${collapsed ? "" : "flip"}`} onClick={() => setCollapsed(!collapsed)}>
|
|
||||||
<ChevronDown />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<div className="faq">
|
|
||||||
<h3 onClick={() => setCollapsed(!collapsed)}>{title}</h3>
|
|
||||||
<CollapsedIcon icon={icon} collapsed={collapsed}>
|
|
||||||
{children}
|
|
||||||
</CollapsedIcon>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const WhatIsSnort = () => {
|
const WhatIsSnort = () => {
|
||||||
return (
|
return (
|
||||||
<CollapsedSection title={<FormattedMessage {...messages.WhatIsSnort} />}>
|
<CollapsedSection title={<FormattedMessage {...messages.WhatIsSnort} />}>
|
||||||
|
@ -112,27 +112,6 @@
|
|||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-user .faq {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.new-user .faq h3,
|
|
||||||
.new-user .faq svg {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.new-user .faq .collapse-icon {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
transition: transform 300ms ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.new-user .faq .collapse-icon.flip {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
transition: transform 300ms ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.new-user input {
|
.new-user input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 568px;
|
max-width: 568px;
|
||||||
|
@ -44,7 +44,7 @@ export default defineMessages({
|
|||||||
EasierToFind: "Make your profile easier to find and share",
|
EasierToFind: "Make your profile easier to find and share",
|
||||||
Funding: "Fund developers and platforms providing NIP-05 verification services",
|
Funding: "Fund developers and platforms providing NIP-05 verification services",
|
||||||
NameSquatting:
|
NameSquatting:
|
||||||
"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your verification (not your account - nobody can take that away) for violating this rule.",
|
"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.",
|
||||||
PreviewOnSnort: "Preview on snort",
|
PreviewOnSnort: "Preview on snort",
|
||||||
GetSnortId: "Get a Snort identifier",
|
GetSnortId: "Get a Snort identifier",
|
||||||
GetSnortIdHelp:
|
GetSnortIdHelp:
|
||||||
|
@ -549,3 +549,24 @@ body.scroll-lock {
|
|||||||
button.tall {
|
button.tall {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collapsable-section {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapsable-section h3,
|
||||||
|
.collapsable-section svg {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapsable-section .collapse-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
transition: transform 300ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapsable-section .collapse-icon.flip {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
transition: transform 300ms ease-in-out;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user