feat: invite codes
This commit is contained in:
parent
6f8e8eca0f
commit
f26155ddd8
@ -24,6 +24,7 @@
|
||||
"fuse.js": "^7.0.0",
|
||||
"highlight.js": "^11.8.0",
|
||||
"light-bolt11-decoder": "^2.1.0",
|
||||
"lottie-react": "^2.4.0",
|
||||
"marked": "^9.1.0",
|
||||
"marked-footnote": "^1.0.0",
|
||||
"match-sorter": "^6.3.1",
|
||||
|
51
packages/app/src/Element/Invite.tsx
Normal file
51
packages/app/src/Element/Invite.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
import SnortApi from "@/External/SnortApi";
|
||||
import { getCurrentRefCode, getDisplayName } from "@/SnortUtils";
|
||||
import { useUserProfile } from "@snort/system-react";
|
||||
import Lottie from "lottie-react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import Modal from "./Modal";
|
||||
import Hugs from "@/hug.json";
|
||||
|
||||
const InviteModal = () => {
|
||||
const [pubkey, setPubkey] = useState("");
|
||||
const code = getCurrentRefCode();
|
||||
const navigate = useNavigate();
|
||||
useEffect(() => {
|
||||
if (code) {
|
||||
const api = new SnortApi();
|
||||
api.getRefCodeInfo(code).then(a => setPubkey(a.pubkey));
|
||||
}
|
||||
}, []);
|
||||
const profile = useUserProfile(pubkey);
|
||||
if (!code) return;
|
||||
|
||||
function close() {
|
||||
navigate("/");
|
||||
}
|
||||
return (
|
||||
<Modal id="invite-modal" onClose={close}>
|
||||
<div className="flex flex-col gap-4 items-center">
|
||||
<Lottie animationData={Hugs} />
|
||||
<p className="text-3xl font-semibold">
|
||||
<FormattedMessage
|
||||
defaultMessage="{name} invited you to {app}"
|
||||
id="ZlmK/p"
|
||||
values={{
|
||||
name: <span className="text-primary">{getDisplayName(profile, pubkey)}</span>,
|
||||
app: CONFIG.appNameCapitalized,
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
<Link to="/login/sign-up">
|
||||
<button className="primary">
|
||||
<FormattedMessage defaultMessage="Sign Up" id="39AHJm" />
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default InviteModal;
|
7
packages/app/src/External/SnortApi.ts
vendored
7
packages/app/src/External/SnortApi.ts
vendored
@ -79,7 +79,8 @@ export interface RelayDistance {
|
||||
}
|
||||
|
||||
export interface RefCodeResponse {
|
||||
code: string
|
||||
code: string;
|
||||
pubkey: string;
|
||||
}
|
||||
|
||||
export default class SnortApi {
|
||||
@ -143,6 +144,10 @@ export default class SnortApi {
|
||||
return this.#getJsonAuthd<RefCodeResponse>("api/v1/referral", "GET");
|
||||
}
|
||||
|
||||
getRefCodeInfo(code: string) {
|
||||
return this.#getJson<RefCodeResponse>(`api/v1/referral/${code}`, "GET");
|
||||
}
|
||||
|
||||
async #getJsonAuthd<T>(
|
||||
path: string,
|
||||
method?: "GET" | string,
|
||||
|
@ -15,7 +15,7 @@ import * as utils from "@noble/curves/abstract/utils";
|
||||
import { Blasters, SnortPubKey } from "@/Const";
|
||||
import { LoginStore, UserPreferences, LoginSession, LoginSessionType, SnortAppData, Newest } from "@/Login";
|
||||
import { generateBip39Entropy, entropyToPrivateKey } from "@/nip6";
|
||||
import { bech32ToHex, dedupeById, getCountry, sanitizeRelayUrl, unwrap } from "@/SnortUtils";
|
||||
import { bech32ToHex, dedupeById, deleteRefCode, getCountry, sanitizeRelayUrl, unwrap } from "@/SnortUtils";
|
||||
import { SubscriptionEvent } from "@/Subscription";
|
||||
import { Chats, FollowsFeed, GiftsCache, Notifications } from "@/Cache";
|
||||
import { Nip7OsSigner } from "./Nip7OsSigner";
|
||||
@ -70,6 +70,7 @@ export function logout(id: string) {
|
||||
Notifications.clear();
|
||||
FollowsFeed.clear();
|
||||
Chats.clear();
|
||||
deleteRefCode();
|
||||
}
|
||||
|
||||
export function markNotificationsRead(state: LoginSession) {
|
||||
|
@ -14,7 +14,7 @@ export function ListFeedPage() {
|
||||
const { data } = useEventFeed(link);
|
||||
|
||||
if (!data) return <PageSpinner />;
|
||||
if (data.kind !== EventKind.ContactList && data.kind !== EventKind.CategorizedPeople) {
|
||||
if (data.kind !== EventKind.ContactList && data.kind !== EventKind.FollowSet) {
|
||||
return (
|
||||
<b>
|
||||
<FormattedMessage defaultMessage="Must be a contact list or pubkey list" id="vB3oQ/" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { lazy, useContext, useEffect, useState } from "react";
|
||||
import { Link, Outlet, RouteObject, useParams } from "react-router-dom";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { unixNow } from "@snort/shared";
|
||||
@ -7,7 +7,7 @@ import { SnortContext } from "@snort/system-react";
|
||||
|
||||
import Timeline from "@/Element/Feed/Timeline";
|
||||
import { TimelineSubject } from "@/Feed/TimelineFeed";
|
||||
import { debounce, getRelayName, sha256 } from "@/SnortUtils";
|
||||
import { debounce, getCurrentRefCode, getRelayName, sha256 } from "@/SnortUtils";
|
||||
import useLogin from "@/Hooks/useLogin";
|
||||
import Discover from "@/Pages/Discover";
|
||||
import TrendingUsers from "@/Element/Trending/TrendingUsers";
|
||||
@ -20,6 +20,7 @@ import { RootTabs } from "@/Element/Feed/RootTabs";
|
||||
import { DeckContext } from "@/Pages/DeckLayout";
|
||||
import { TopicsPage } from "./TopicsPage";
|
||||
import TrendingHashtags from "@/Element/Trending/TrendingHashtags";
|
||||
const InviteModal = lazy(() => import("@/Element/Invite"));
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
@ -29,6 +30,7 @@ interface RelayOption {
|
||||
}
|
||||
|
||||
export default function RootPage() {
|
||||
const code = getCurrentRefCode();
|
||||
return (
|
||||
<>
|
||||
<div className="main-content p">
|
||||
@ -37,6 +39,7 @@ export default function RootPage() {
|
||||
<div className="main-content">
|
||||
<Outlet />
|
||||
</div>
|
||||
{code && <InviteModal />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import ModerationSettings from "@/Pages/settings/Moderation";
|
||||
import { CacheSettings } from "./settings/Cache";
|
||||
|
||||
import messages from "./messages";
|
||||
import { ReferralsPage } from "./settings/Referrals";
|
||||
|
||||
export default function SettingsPage() {
|
||||
const navigate = useNavigate();
|
||||
@ -66,6 +67,10 @@ export const SettingsRoutes: RouteObject[] = [
|
||||
path: "cache",
|
||||
element: <CacheSettings />,
|
||||
},
|
||||
{
|
||||
path: "invite",
|
||||
element: <ReferralsPage />,
|
||||
},
|
||||
...ManageHandleRoutes,
|
||||
...WalletSettingsRoutes,
|
||||
],
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { FeedCache } from "@snort/shared";
|
||||
import {
|
||||
Chats,
|
||||
FollowLists,
|
||||
FollowsFeed,
|
||||
GiftsCache,
|
||||
InteractionCache,
|
||||
@ -29,6 +30,7 @@ export function CacheSettings() {
|
||||
<CacheDetails cache={PaymentsCache} name={<FormattedMessage defaultMessage="Payments" id="iYc3Ld" />} />
|
||||
<CacheDetails cache={InteractionCache} name={<FormattedMessage defaultMessage="Interactions" id="u+LyXc" />} />
|
||||
<CacheDetails cache={GiftsCache} name={<FormattedMessage defaultMessage="Gift Wraps" id="fjAcWo" />} />
|
||||
<CacheDetails cache={FollowLists} name={<FormattedMessage defaultMessage="Social Graph" id="CzHZoc" />} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
42
packages/app/src/Pages/settings/Referrals.tsx
Normal file
42
packages/app/src/Pages/settings/Referrals.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import Copy from "@/Element/Copy";
|
||||
import SnortApi from "@/External/SnortApi";
|
||||
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||
import { useEffect, useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
export function ReferralsPage() {
|
||||
const [refCode, setRefCode] = useState("");
|
||||
const { publisher } = useEventPublisher();
|
||||
|
||||
useEffect(() => {
|
||||
const api = new SnortApi(undefined, publisher);
|
||||
|
||||
api.getRefCode().then(v => setRefCode(v.code));
|
||||
}, [publisher]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>
|
||||
<FormattedMessage defaultMessage="Invite your friends" id="l3H1EK" />
|
||||
</h1>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Your referral code is {code}"
|
||||
id="UxgyeY"
|
||||
values={{
|
||||
code: <span className="font-mono text-highlight select-all">{refCode}</span>,
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Send this link to your friends and share the magic of the nostr."
|
||||
id="Ml7+RS"
|
||||
/>
|
||||
</p>
|
||||
<div className="border border-zinc-900 rounded-2xl px-3 py-2">
|
||||
<Copy text={`https://${window.location.host}?ref=${refCode}`} maxSize={Number.MAX_VALUE} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
@ -33,27 +33,40 @@ const SettingsIndex = () => {
|
||||
];
|
||||
|
||||
const menuItems = [
|
||||
{ icon: "profile", message: messages.Profile, path: "profile" },
|
||||
{ icon: "relay", message: messages.Relays, path: "relays" },
|
||||
{ icon: "key", message: "Export Keys", id: "08zn6O", path: "keys" },
|
||||
{ icon: "shield-tick", message: "Moderation", id: "wofVHy", path: "moderation" },
|
||||
{ icon: "badge", message: "Nostr Address", id: "9pMqYs", path: "handle" },
|
||||
{ icon: "gear", message: messages.Preferences, path: "preferences" },
|
||||
{ icon: "wallet", message: "Wallet", id: "3yk8fB", path: "wallet" },
|
||||
{ icon: "heart", message: messages.Donate, path: "/donate" },
|
||||
{ icon: "hard-drive", message: "Cache", id: "DBiVK1", path: "cache" },
|
||||
{ icon: "profile", message: <FormattedMessage defaultMessage="Profile" id="itPgxd" />, path: "profile" },
|
||||
{ icon: "relay", message: <FormattedMessage defaultMessage="Relays" id="RoOyAh" />, path: "relays" },
|
||||
{ icon: "key", message: <FormattedMessage defaultMessage="Export Keys" id="08zn6O" />, path: "keys" },
|
||||
{ icon: "shield-tick", message: <FormattedMessage defaultMessage="Moderation" id="wofVHy" />, path: "moderation" },
|
||||
{ icon: "badge", message: <FormattedMessage defaultMessage="Nostr Address" id="9pMqYs" />, path: "handle" },
|
||||
{ icon: "gear", message: <FormattedMessage defaultMessage="Preferences" id="PCSt5T" />, path: "preferences" },
|
||||
{ icon: "wallet", message: <FormattedMessage defaultMessage="Wallet" id="3yk8fB" />, path: "wallet" },
|
||||
{ icon: "heart", message: <FormattedMessage defaultMessage="Donate" id="2IFGap" />, path: "/donate" },
|
||||
{ icon: "hard-drive", message: <FormattedMessage defaultMessage="Cache" id="DBiVK1" />, path: "cache" },
|
||||
{ icon: "link", message: <FormattedMessage defaultMessage="Invite" id="hYOE+U" />, path: "invite" },
|
||||
];
|
||||
|
||||
if (CONFIG.features.subscriptions) {
|
||||
menuItems.push({ icon: "diamond", message: "Subscription", id: "R/6nsx", path: "/subscribe/manage" });
|
||||
menuItems.push({
|
||||
icon: "diamond",
|
||||
message: <FormattedMessage defaultMessage="Subscription" id="R/6nsx" />,
|
||||
path: "/subscribe/manage",
|
||||
});
|
||||
}
|
||||
|
||||
if (CONFIG.features.zapPool) {
|
||||
menuItems.push({ icon: "piggy-bank", message: "Zap Pool", id: "i/dBAR", path: "/zap-pool" });
|
||||
menuItems.push({
|
||||
icon: "piggy-bank",
|
||||
message: <FormattedMessage defaultMessage="Zap Pool" id="i/dBAR" />,
|
||||
path: "/zap-pool",
|
||||
});
|
||||
}
|
||||
|
||||
if (sub) {
|
||||
menuItems.push({ icon: "code-circle", message: "Account Switcher", id: "7BX/yC", path: "accounts" });
|
||||
menuItems.push({
|
||||
icon: "code-circle",
|
||||
message: <FormattedMessage defaultMessage="Accounts" id="FvanT6" />,
|
||||
path: "accounts",
|
||||
});
|
||||
}
|
||||
|
||||
const getNavLinkClass = ({ isActive }: { isActive: boolean }) => {
|
||||
@ -64,10 +77,10 @@ const SettingsIndex = () => {
|
||||
<div className="settings-nav">
|
||||
{!hideMenu && (
|
||||
<div>
|
||||
{menuItems.map(({ icon, message, id, path }) => (
|
||||
{menuItems.map(({ icon, message, path }) => (
|
||||
<NavLink to={path} key={path} className={getNavLinkClass} end>
|
||||
<Icon name={icon} size={24} />
|
||||
<FormattedMessage {...(id ? { defaultMessage: message, id } : message)} />
|
||||
{message}
|
||||
<Icon name="arrowFront" size={16} />
|
||||
</NavLink>
|
||||
))}
|
||||
|
@ -12,6 +12,7 @@ import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||
import SnortApi, { SubscriptionError, SubscriptionErrorCode } from "@/External/SnortApi";
|
||||
import SendSats from "@/Element/SendSats";
|
||||
import classNames from "classnames";
|
||||
import { getRefCode } from "@/SnortUtils";
|
||||
|
||||
export function mapPlanName(id: number) {
|
||||
switch (id) {
|
||||
@ -74,7 +75,8 @@ export function SubscribePage() {
|
||||
async function subscribe(type: number) {
|
||||
setError(undefined);
|
||||
try {
|
||||
const rsp = await api.createSubscription(type);
|
||||
const ref = getRefCode();
|
||||
const rsp = await api.createSubscription(type, ref);
|
||||
setInvoice(rsp.pr);
|
||||
} catch (e) {
|
||||
if (e instanceof SubscriptionError) {
|
||||
|
@ -536,3 +536,29 @@ export function getCountry() {
|
||||
export function trackEvent(event: string) {
|
||||
window.plausible?.(event);
|
||||
}
|
||||
|
||||
export function storeRefCode() {
|
||||
const ref = getCurrentRefCode();
|
||||
if (ref) {
|
||||
window.localStorage.setItem("ref", ref);
|
||||
}
|
||||
}
|
||||
|
||||
export function getCurrentRefCode() {
|
||||
if (window.location.search) {
|
||||
const q = new URLSearchParams(window.location.search);
|
||||
const ref = q.get("ref");
|
||||
if (ref) {
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getRefCode() {
|
||||
const r = window.localStorage.getItem("ref");
|
||||
if (r) return r;
|
||||
}
|
||||
|
||||
export function deleteRefCode() {
|
||||
window.localStorage.removeItem("ref");
|
||||
}
|
||||
|
5365
packages/app/src/hug.json
Normal file
5365
packages/app/src/hug.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -50,7 +50,7 @@
|
||||
--expired-invoice-gradient: linear-gradient(45deg, var(--gray-superdark) 50%, var(--gray), var(--gray-superdark));
|
||||
--sub-bg: #111;
|
||||
--btn-color: #fff;
|
||||
--primary-gradient: linear-gradient(90deg, rgba(239, 150, 68, 1) 0%, rgba(123, 65, 246, 1) 100%);
|
||||
--primary-gradient: linear-gradient(90deg, #ef9644 0%, #7b41f6 100%);
|
||||
--cashu-gradient: linear-gradient(90deg, #40b039, #adff2a);
|
||||
--pro: #ffdd65;
|
||||
}
|
||||
@ -153,6 +153,20 @@ a.ext {
|
||||
color: var(--pro);
|
||||
}
|
||||
|
||||
.text-snort-gradient {
|
||||
background: var(--snort-gradient);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
background: var(--primary-gradient);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.br {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import { removeUndefined, throwIfOffline } from "@snort/shared";
|
||||
|
||||
import * as serviceWorkerRegistration from "@/serviceWorkerRegistration";
|
||||
import { IntlProvider } from "@/IntlProvider";
|
||||
import { getCountry, unwrap } from "@/SnortUtils";
|
||||
import { getCountry, storeRefCode, unwrap } from "@/SnortUtils";
|
||||
import Layout from "@/Pages/Layout";
|
||||
import ProfilePage from "@/Pages/Profile/ProfilePage";
|
||||
import { RootRoutes, RootTabRoutes } from "@/Pages/Root";
|
||||
@ -183,6 +183,7 @@ serviceWorkerRegistration.register();
|
||||
|
||||
async function initSite() {
|
||||
console.debug(getCountry());
|
||||
storeRefCode();
|
||||
if (hasWasm) {
|
||||
await wasmInit(WasmPath);
|
||||
}
|
||||
|
@ -57,6 +57,9 @@
|
||||
"00LcfG": {
|
||||
"defaultMessage": "Load more"
|
||||
},
|
||||
"08zn6O": {
|
||||
"defaultMessage": "Export Keys"
|
||||
},
|
||||
"0Azlrb": {
|
||||
"defaultMessage": "Manage"
|
||||
},
|
||||
@ -162,6 +165,9 @@
|
||||
"3tVy+Z": {
|
||||
"defaultMessage": "{n} Followers"
|
||||
},
|
||||
"3yk8fB": {
|
||||
"defaultMessage": "Wallet"
|
||||
},
|
||||
"450Fty": {
|
||||
"defaultMessage": "None"
|
||||
},
|
||||
@ -470,6 +476,9 @@
|
||||
"FmXUJg": {
|
||||
"defaultMessage": "follows you"
|
||||
},
|
||||
"FvanT6": {
|
||||
"defaultMessage": "Accounts"
|
||||
},
|
||||
"G/yZLu": {
|
||||
"defaultMessage": "Remove"
|
||||
},
|
||||
@ -656,6 +665,9 @@
|
||||
"MiMipu": {
|
||||
"defaultMessage": "Set as primary Nostr address (nip05)"
|
||||
},
|
||||
"Ml7+RS": {
|
||||
"defaultMessage": "Send this link to your friends and share the magic of the nostr."
|
||||
},
|
||||
"Mrpkot": {
|
||||
"defaultMessage": "Pay for subscription"
|
||||
},
|
||||
@ -741,6 +753,9 @@
|
||||
"Qxv0B2": {
|
||||
"defaultMessage": "You currently have {number} sats in your zap pool."
|
||||
},
|
||||
"R/6nsx": {
|
||||
"defaultMessage": "Subscription"
|
||||
},
|
||||
"R81upa": {
|
||||
"defaultMessage": "People you follow"
|
||||
},
|
||||
@ -849,6 +864,9 @@
|
||||
"UrKTqQ": {
|
||||
"defaultMessage": "You have an active iris.to account"
|
||||
},
|
||||
"UxgyeY": {
|
||||
"defaultMessage": "Your referral code is {code}"
|
||||
},
|
||||
"VL900k": {
|
||||
"defaultMessage": "Recommended Relays"
|
||||
},
|
||||
@ -940,6 +958,9 @@
|
||||
"Zff6lu": {
|
||||
"defaultMessage": "Username iris.to/<b>{name}</b> is reserved for you!"
|
||||
},
|
||||
"ZlmK/p": {
|
||||
"defaultMessage": "{name} invited you to {app}"
|
||||
},
|
||||
"a5UPxh": {
|
||||
"defaultMessage": "Fund developers and platforms providing NIP-05 verification services"
|
||||
},
|
||||
@ -1140,6 +1161,9 @@
|
||||
"hY4lzx": {
|
||||
"defaultMessage": "Supports"
|
||||
},
|
||||
"hYOE+U": {
|
||||
"defaultMessage": "Invite"
|
||||
},
|
||||
"ha8JKG": {
|
||||
"defaultMessage": "Show graph"
|
||||
},
|
||||
@ -1234,6 +1258,9 @@
|
||||
"l+ikU1": {
|
||||
"defaultMessage": "Everything in {plan}"
|
||||
},
|
||||
"l3H1EK": {
|
||||
"defaultMessage": "Invite your friends"
|
||||
},
|
||||
"lCILNz": {
|
||||
"defaultMessage": "Buy Now"
|
||||
},
|
||||
|
@ -18,6 +18,7 @@
|
||||
"/d6vEc": "Make your profile easier to find and share",
|
||||
"/n5KSF": "{n} ms",
|
||||
"00LcfG": "Load more",
|
||||
"08zn6O": "Export Keys",
|
||||
"0Azlrb": "Manage",
|
||||
"0BUTMv": "Search...",
|
||||
"0HFX0T": "Use Exact Location",
|
||||
@ -53,6 +54,7 @@
|
||||
"3qnJlS": "You are voting with {amount} sats",
|
||||
"3t3kok": "{n,plural,=1{{n} new note} other{{n} new notes}}",
|
||||
"3tVy+Z": "{n} Followers",
|
||||
"3yk8fB": "Wallet",
|
||||
"450Fty": "None",
|
||||
"47FYwb": "Cancel",
|
||||
"4IPzdn": "Primary Developers",
|
||||
@ -155,6 +157,7 @@
|
||||
"FdhSU2": "Claim Now",
|
||||
"FfYsOb": "An error has occured!",
|
||||
"FmXUJg": "follows you",
|
||||
"FvanT6": "Accounts",
|
||||
"G/yZLu": "Remove",
|
||||
"G1BGCg": "Select Wallet",
|
||||
"GFOoEE": "Salt",
|
||||
@ -216,6 +219,7 @@
|
||||
"MP54GY": "Wallet password",
|
||||
"MWTx65": "Default Page",
|
||||
"MiMipu": "Set as primary Nostr address (nip05)",
|
||||
"Ml7+RS": "Send this link to your friends and share the magic of the nostr.",
|
||||
"Mrpkot": "Pay for subscription",
|
||||
"MuVeKe": "Buy nostr address",
|
||||
"MzRYWH": "Buying {item}",
|
||||
@ -244,6 +248,7 @@
|
||||
"QDFTjG": "{n} Relays",
|
||||
"QWhotP": "Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)",
|
||||
"Qxv0B2": "You currently have {number} sats in your zap pool.",
|
||||
"R/6nsx": "Subscription",
|
||||
"R81upa": "People you follow",
|
||||
"RSr2uB": "Username must only contain lowercase letters and numbers",
|
||||
"RahCRH": "Expired",
|
||||
@ -279,6 +284,7 @@
|
||||
"Ub+AGc": "Sign In",
|
||||
"Up5U7K": "Block",
|
||||
"UrKTqQ": "You have an active iris.to account",
|
||||
"UxgyeY": "Your referral code is {code}",
|
||||
"VL900k": "Recommended Relays",
|
||||
"VN0+Fz": "Balance: {amount} sats",
|
||||
"VOjC1i": "Pick which upload service you want to upload attachments to",
|
||||
@ -309,6 +315,7 @@
|
||||
"ZLmyG9": "Contributors",
|
||||
"ZS+jRE": "Send zap splits to",
|
||||
"Zff6lu": "Username iris.to/<b>{name}</b> is reserved for you!",
|
||||
"ZlmK/p": "{name} invited you to {app}",
|
||||
"a5UPxh": "Fund developers and platforms providing NIP-05 verification services",
|
||||
"a7TDNm": "Notes will stream in real time into global and notes tab",
|
||||
"aHje0o": "Name or nym",
|
||||
@ -375,6 +382,7 @@
|
||||
"hMzcSq": "Messages",
|
||||
"hRTfTR": "PRO",
|
||||
"hY4lzx": "Supports",
|
||||
"hYOE+U": "Invite",
|
||||
"ha8JKG": "Show graph",
|
||||
"hicxcO": "Show replies",
|
||||
"hmZ3Bz": "Media",
|
||||
@ -406,6 +414,7 @@
|
||||
"kc79d3": "Topics",
|
||||
"kuPHYE": "{n,plural,=0{{name} liked} other{{name} & {n} others liked}}",
|
||||
"l+ikU1": "Everything in {plan}",
|
||||
"l3H1EK": "Invite your friends",
|
||||
"lCILNz": "Buy Now",
|
||||
"lD3+8a": "Pay",
|
||||
"lPWASz": "Snort nostr address",
|
||||
|
20
yarn.lock
20
yarn.lock
@ -2924,6 +2924,7 @@ __metadata:
|
||||
fuse.js: ^7.0.0
|
||||
highlight.js: ^11.8.0
|
||||
light-bolt11-decoder: ^2.1.0
|
||||
lottie-react: ^2.4.0
|
||||
marked: ^9.1.0
|
||||
marked-footnote: ^1.0.0
|
||||
match-sorter: ^6.3.1
|
||||
@ -7799,6 +7800,25 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lottie-react@npm:^2.4.0":
|
||||
version: 2.4.0
|
||||
resolution: "lottie-react@npm:2.4.0"
|
||||
dependencies:
|
||||
lottie-web: ^5.10.2
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
checksum: e9ea4a89be90a29bde4a83956f76a80d1f8031882f18ea38ef5271d2aafd8e68348ae6297f185ed85b149ca4896fe33aee7faf9780b88a1b289b8e146f477448
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lottie-web@npm:^5.10.2":
|
||||
version: 5.12.2
|
||||
resolution: "lottie-web@npm:5.12.2"
|
||||
checksum: af5bc3bc405fd760de8b17a36158d5a8c3e8c586c711d0c63681ddf056b65bc6b54ea36b1fcad782fb02dbe12e696a40e0ba72daf41b8f10ab5b5d1113793636
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"loupe@npm:^2.3.6":
|
||||
version: 2.3.7
|
||||
resolution: "loupe@npm:2.3.7"
|
||||
|
Loading…
x
Reference in New Issue
Block a user